当规范标签跨语言指向时,Hreflang 失效
一个本地化页面的规范指向其英文同级页面,会取消自身的 hreflang 注释,浏览器也无法检测到。审计数据显示哪些检查捕捉到了矛盾,以及我们自己的 9 区域前缀在哪一天未能通过其中一个检查。
一个页面可以在同一个 <head> 中携带 2 个标签,它们就同一个 URL 向同一个爬虫说出相反的话。在 https://example.com/fr/pricing 上,这表示该页面是一个集群中的法语成员:
<link rel="alternate" hreflang="fr" href="https://example.com/fr/pricing" />
这条,1 下面的行,表示该页面是应合并到英文原版的变体:
<link rel="canonical" href="https://example.com/pricing" />
真实网站会在它们拥有的每个本地化路由上,从同一模板发送两者。 这是在七月记录的失败之后仍然存在的错误——缺失 hreflang 自引用,在我们当前数据中仍有 58% 的 88 次 hreflang 评估失败。 一个网站可以关闭该循环,正确设置每个自引用,并且仍然让每个本地化页面请求被其英文同级页面替代。
一个跨语言规范要求 Google 将本地化的 URL 合并到原版中
规范标签是一次合并请求:将此 URL 视为该版本的变体,并索引该版本。 hreflang 注释是一次路由声明:此 URL 是该语言的版本。 将它们指向不同的 URL,网站就发出了一个无效自身声明的请求——集群中的法语位置被一个否认自身的页面填充。
Google 已明确表示 hreflang 只是一个提示,而非指令,规范化的工作方式相同:网站提供信号,Google 进行解析。 这种解析就是整个问题。 对于自规范化的本地化页面,发布者决定哪个 URL 为法语搜索者服务。 对于跨语言规范,发布者已将决定权交给了系统,同时认为集群已配置——随后报告的结果是一个在自身市场中排名无效的本地化页面,而英文页面则占据其位置。
产生这些的生成器是普通的。 一个基于路由定义而非请求路径的规范助手,为每个语言输出未加前缀的 URL。 一个 hreflang 设置按语言,但规范设置全局的 CMS 也会执行相同的操作。 那么迁移添加了语言前缀到 URL 并将 canonical 指向内容原始位置的做法。 在每种情况下页面都能完美渲染,view-source 中的注释看起来完整,矛盾仅在 2 属性上。
数据集
| hreflang 自引用存在 | 主页自身的 hreflang 注释缺失 | 58% 的 88 评估;59% 的 34 网站 |
| 主页 canonical 存在 | 主页根本没有声明 canonical URL | 29% 的 49 网站 |
方法论:每个域名的最新完成审计快照来自我们当前的检查集,约为 5 月 23 – August 31, 2026,已匿名化。 分母因检查而异——34 到 49 网站——因为只有当输入存在时才会运行检查:自引用检查在没有 hreflang 注释的主页上不会给出判决,这就是其站点计数较少的原因。 评估级别和站点级别的比率不同,因为某些域名在窗口内被审计多次。 样本为自选——已运行审计的所有者——并倾向于中小型,因此请将比率视为该细分市场的方向性指标。
第二行是更安静的风险。 一个没有 canonical 的页面并未与其 hreflang 注释相矛盾,但也未为注释辩护:页面中没有任何内容说明它认为哪个 URL 是权威的,因此可通过推断完全解析可在 1 个以上地址访问的语言变体。* 正确聚类的前提是先进行 canonical 卫生检查,这就是为什么我们的 canonical 指南 是hreflang 实施指南 的前置条件,而不是其伴随文件。*
矛盾仅在聚类的两端可见
单个页面无法报告自身的此类失败。 /fr/pricing 内部一致——一个 hreflang 集合,一个 canonical,均格式良好。* 当你将注释与被注释页面并排查看时,缺陷才会出现,这也是为什么验证它需要获取整个聚类,而不是只读取 1 个文档。*.
沿着每条 hreflang 注释找到其目标,并记录返回的结果:状态码、请求是否重定向、是否存在 noindex 指令,以及目标自身的 canonical 是否指向注释所指的 URL。canonical 指向另一个 URL 的目标,正是本文所讨论的跨语言 canonical。
lang 属性是第二个证人。如果一个页面的 html lang 所声明的语言与其自身 hreflang 条目声称的语言不同,它就以同样的方式自相矛盾,而这往往是本地化路由正在提供原始内容的第一个可见迹象。
无法获取的替代版本是证据缺口,并不能证明存在缺陷。应将其记录为未验证,并在判定聚类损坏之前重试。
Diagram source
graph TD
FR["/fr/pricing — html lang=fr"]
EN["/pricing — English original"]
FR -->|"hreflang=fr, self-referencing"| CLAIM["声称:向法国搜索者提供此 URL"]
FR -->|"rel=canonical"| EN
EN -->|"hreflang=fr"| FR
CLAIM --> Q{"Which URL answers a French query?"}
EN --> Q
Q -->|"the site stopped deciding"| OUT["Google 挑选 — 通常是英语 URL"]Our own locale prefixes served English until August 17, 2026
我们自己就在 seoreport.dev 上犯过这类缺陷。 Ahrefs 网站审核报告了一个 hreflang 与 HTML lang 不匹配,涉及我们自己网站的 184 个 URL。 lang 属性是症状;内容也是英文,出现在 9 个语言前缀中的每一个,这使得每个本地化的 URL 成为其英文对应的复制品——跨语言规范产生的同样结果,从相反方向得到。
原因是 1 函数边界。 文档壳从一个在 window 未定义时返回默认语言的助手中获取其语言。 在服务器上,/fr/pricing 因此渲染了 lang="en" 并为英语翻译包播种,而发出头部链接的组件——读取路径而非运行时——直接在其旁边发出了正确的 fr self-hreflang. 一个客户端效果在水化之后切换了那种语言,因此每个基于浏览器的检查通过了,和没有人看到它。 爬虫不运行那个效果。
已修复于 August 17, 2026: 壳 其 语言 从 路径 派生,已本地化的 布局 在 加载器 中 解析 本地化 包,以便 服务器 渲染 和 水合 共享 它,且 支持的 本地化 有 没有 包 抛出 而不是 悄悄地 提供 英语 在 其 前缀。 文本方向也不正确——阿拉伯语一直在服务 ltr。
回归测试是一次不运行 JavaScript 的原始 HTML 运行,因为浏览器检查对整个失败类是盲目的。 在生产环境中先运行红色检查,它报告了440失败,跨越128本地化URL,每个页面在100%英语携带。 对于已修复的构建:0失败,跨越144 URL. 对 lang 与 hreflang 进行比较,第一个会判定失败的就是我们自己的网站。
x-default 继承回退页面声明的任何内容
我们声明x-default的网站样本太小,无法发布失败率。HTML 所能证明的也比看上去少:它只显示x-default注释已被声明,而不能说明发布者打算让它服务哪些受众。可检查的事实是相邻的那些——URL形状、目标健康、相互注释和规范对齐。
机制所暗示的内容仍值得说明。 x-default 是搜索者语言未被站点服务时的回退,通常指向主要市场页面。 如果该页面携带跨语言规范,地球上每个未匹配搜索者的回退都会继承矛盾,这种矛盾会体现在目标的健康状况中,而不是体现在x-default那一行本身。
在原始HTML中按语言验证,双向
像爬虫一样获取页面并读取3内容:
curl -s -A "Googlebot" https://example.com/fr/pricing | grep -iE '<html|rel="canonical"|hreflang'
lang属性、自引用hreflang条目和规范必须在 1 个语言和 1 个URL上保持一致:
<!-- On https://example.com/fr/pricing --><html lang="fr"><link rel="canonical" href="https://example.com/fr/pricing" /><link rel="alternate" hreflang="en" href="https://example.com/pricing" /><link rel="alternate" hreflang="fr" href="https://example.com/fr/pricing" /><link rel="alternate" hreflang="x-default" href="https://example.com/pricing" />
然后在每个语言的 1 个页面上重复,并获取每个注释名称的所有URL以确认每个都规范化为自身。 规则足够简短,交给开发者:每个 hreflang 集群的成员都规范化为自身。 跨语言规范在恰好 1 种情况下是正确的——当本地化的URL根本未本地化且服务与原始相同语言时——在这种情况下URL也不属于该集群。
Search Console 的 URL 检查为每个 URL 提供权威的第二意见,说明实际选择了哪个规范 Google。付费的 SEOReport 诊断 会在整个集群中运行这一循环,并列出每个矛盾对及其被发现的页面。 seoreport.dev 上的 9 语言前缀现在通过,并且它们通过是因为我们首先在一个整个产品都在发现它的站点上发布了缺陷。