仅在 / 协商语言,并让 /en/ 和 /fr/ 等明确 URL 始终提供其指定语言的内容。本指南将向 Mac 桌面出版人员展示如何指定这种行为、保留易于发现的文档链接,并测试结果。

示例采用一个虚构的公开文档集,其中包含一份简短形状排列指南的英文版和法文版。其根页面是语言选择页,介绍文字可根据请求进行调整。所有示例地址描述的都是建议的配置,并不表示这些地址上目前托管着相应页面。

更改语言设置前,先定义 URL 行为

先制定一份简明的路由约定。在本例中,根页面帮助读者选择语言,而两个明确路径则包含完整的译文。Google 建议为不同语言版本使用单独的 URL,并建议不要根据推测的语言自动在这些版本之间重定向读者。提供可见链接,让读者自行选择。管理多地区和多语言网站。

请求的路径 预期响应 语言偏好的影响
/ 带简短介绍的语言选择页 介绍文字和推荐链接可能会变化
/en/ 完整英文文档 文档语言不变
/fr/ 完整法文文档 文档语言不变
未发布的路径 缺失页面响应 不得静默显示其他文档

将此表作为实现说明。只有确认请求指向根页面后,才应用语言选择。若某条通用规则在每次页面请求前运行,就可能覆盖明确的选择并破坏此约定。

例如,即使请求的语言偏好是英语,访问 /fr/ 的人仍应收到法文文档。在尚未决定语言的入口处,英语偏好很有用;其他位置的明确路径已经给出了选择。这是本文采用的设计建议。

在每个页面上都保留两种语言的链接。在根页面上,推荐一种语言可以让读者更容易做出第一个选择,同时不隐藏另一种选项。在完整文档中,语言切换器应直接指向对应的文档。

选择可预测的根页面语言策略

Accept-Language 表示偏好的响应语言,并可带有类似 fr;q=0.9,en;q=0.5 的质量权重。它并不要求服务器提供请求中的每一种语言。质量值为零表示不可接受。Content-Language 描述返回内容所面向的受众;它不会选择路由。RFC 9110:HTTP 语义,第 8.5、12.4.2 和 12.5.4 节。

配置之前,写明支持的语言集合和回退行为。在本例中,使用英文和法文介绍;当请求中没有可用的匹配项时,显示英文介绍并提供两种语言选项。这种回退是示例中的出版选择,并非 HTTP 要求。

使用具有明确策略的语言匹配实现。RFC 4647 区分过滤和查找:查找会选择一个结果,按优先级顺序考虑请求范围,并逐步移除子标签以寻找匹配项。它还要求使用查找的应用定义默认行为。因此,通过查找,请求 fr-CA 可以匹配受支持的通用 fr 介绍。RFC 4647:语言标签匹配,第 3.4–3.4.1 节。

不要通过搜索标头中第一次出现的 fr 或 en 来选择语言。这种简化做法会忽略权重和排除项。匹配层应解析偏好,考虑权重为零的排除项,然后应用已记录的回退行为。

根页面请求偏好 本例中的预期结果
未提供标头 英文介绍,并提供两种语言选项
fr 法文介绍,并提供两种语言选项
fr-CA,fr;q=0.9,en;q=0.5 法文介绍
en;q=0.9,fr;q=0.2 英文介绍
de 回退选择页
fr;q=0,en;q=1 英文介绍;不选择法文
*;q=0 明确定义的未匹配语言处理方式

最后一行需要有意作出决定。对于这种选择页设计,应指定:当请求排除所有语言时,返回回退选择页,因为应用选择不遵循该偏好;不要声称英语与其匹配。如果需要严格协商,就定义并测试相应的不可接受响应行为。无论采用哪种方式,都应避免误把零当成普通的低优先级。

让文档语言、链接和搜索注释保持一致

对每份 HTML 文档,将文档的 lang 属性设为其实际的主要语言:英文页面使用 en,法文页面使用 fr。WHATWG 将 lang 定义为元素内容和文本属性的主要语言;若省略,则从父元素继承。仅有语言前缀并不能完成此声明。HTML 标准:lang 和 xml:lang 属性。

检查导航链接以及页面文本。相对 URL 会根据 WHATWG URL 标准,以基准 URL 为依据进行解析。例如,若文档没有指定其他基准,https://example.com/en/ 下的 fr/ 会解析为 https://example.com/en/fr/;/fr/ 则会解析为源站的法文路径。可见的语言切换器应使用预期的绝对路径。URL 标准:URL 的编写与解析。

搜索注释有单独的用途。Google 支持通过 HTML、HTTP 标头或站点地图添加等效语言注释。选择一种易于管理的方式。每个版本都应使用完全限定的 URL 指向自身及其对应版本,并通过这些注释让各版本相互关联。根选择页可以作为 x-default 目标页面。向 Google 告知页面的本地化版本。

虚构文档集的注释映射如下:

注释 虚构目标地址
en https://example.com/en/
fr https://example.com/fr/
x-default https://example.com/

通过出版系统支持的注释机制添加这些关系。此映射是规范说明,不是可执行标记。x-default 不会配置服务器协商,也不会提供翻译。Google 还表示,它会通过算法判断页面语言,而不是使用 hreflang 或 HTML lang 来检测语言。向 Google 告知页面的本地化版本。

确保完整译文无需依赖根页面的语言调整也能访问。Google 记录称,其爬虫发送请求时不带 Accept-Language,并警告说,区域自适应页面可能导致部分变体无法被发现。可靠的回退行为和直接语言 URL 可以解决这一发现问题,无需爬虫请求不同版本的根页面介绍。Google 如何抓取区域自适应页面。

让缓存的根页面响应遵循语言选择

当根页面的选择取决于 Accept-Language 时,应在根页面响应中加入 Vary: Accept-Language,包括回退响应。保留已有的变化字段。下面是法文根页面响应中可包含的示例标头片段;它不是完整的 HTTP 消息:RFC 9110:HTTP 语义,第 12.5.5 节。

Content-Type: text/html; charset=utf-8
Content-Language: fr
Vary: Accept-Language

RFC 9111 要求缓存:在无需重新验证而重用已存储响应之前,先匹配 Vary 中列出的请求字段。这一点很重要,因为根页面 URL 保持不变,而介绍文字会变化。Vary 描述选择依据;它本身不会实现语言匹配器。RFC 9111:HTTP 缓存,第 4.1 节。

按照此设计,/en/ 和 /fr/ 的文档不会随 Accept-Language 变化。应依据路由约定检查完整的内容交付路径,包括任何共享缓存。作为实用诊断,交替发送英语和法语的根页面请求,然后反转顺序。如果根页面反复返回上一个请求的语言,就应同时检查缓存行为和路由。

在 Mac 上测试此约定

先在公开的演示源站上准备这三个虚构页面。以下测试要求该源站在 /、/en/ 和 /fr/ 处仅包含此演示文档集。它不会创建页面或配置主机。上面的示例 example.com 地址不是可用的测试环境。

打开 Mac 上的 Terminal 应用并运行 curl --version,确认 curl 可用。然后粘贴以下完整的 shell 诊断脚本。出现提示时,输入演示源站地址,其中应包含 https://,且不带路径或末尾斜杠。

printf 'Public demo origin, without a trailing slash: '
IFS= read -r demo_origin
case "$demo_origin" in
  https://*) ;;
  *) printf 'Enter an HTTPS origin.\n' >&2; exit 1 ;;
esac

for demo_path in / /en/ /fr/; do
  for demo_language in '' 'en' 'fr' 'fr-CA,fr;q=0.9,en;q=0.5' 'en;q=0.9,fr;q=0.2' 'de' 'fr;q=0,en;q=1'; do
    printf '\nPath: %s | Accept-Language: %s\n' \
      "$demo_path" "${demo_language:-absent}"
    curl --silent --show-error --connect-timeout 5 --max-time 15 \
      --dump-header - --header "Accept-Language: $demo_language" \
      "$demo_origin$demo_path" || exit 1
  done
done

此诊断脚本会打印响应标头和正文。Curl 的 --header 用于提供语言偏好;空值会移除此标头。--dump-header - 会将标头打印到标准输出,而时间限制则用于限制每次传输耗时。脚本刻意不跟随重定向,以便能看到意外的重定向。curl — 使用方法。

脚本的 shell 语法已检查;本文不声称已进行演示部署或取得实际语言路由结果。curl 传输失败时脚本会停止,但 HTTP 错误响应仍可能出现在输出中,必须进行检查。

将根页面响应与偏好表进行比较。然后检查每个 /en/ 响应是否为英文内容,以及每个 /fr/ 响应是否为法文内容,不受所提供偏好的影响。检查状态码、意外的 Location 字段、返回的语言声明和实际文档文本。标头正确但正文错误,仍然意味着结果不合格。

最后,在浏览器中打开两个明确 URL。通过每个页面的语言切换器跳转,重新加载目标页面,并检查地址栏。这样可以发现直接请求成功时可能遗漏的导航错误。单独测试一个未发布的路径,并确认它不会悄悄显示某份完整文档。

无法协商时,使用稳定的选择页

这种设计需要具备读取请求标头并选择响应能力的内容交付层。WHATWG 的文档语言和 URL 机制用于描述文档和地址;添加 lang 属性或更改链接文字本身并不会创建 HTTP 协商。依赖请求进行的选择应由 HTTP 内容交付配置实现。HTML 标准、RFC 9110:HTTP 语义。

如果出版系统不具备此类内容交付能力,就使用固定的根选择页,并提供指向完整语言页面的直接链接。这样既保留读者的选择权,也符合 Google 对独立语言 URL 和可见语言切换链接的建议。本文未假定任何特定出版产品具备协商功能。管理多地区和多语言网站。

实际验收标准很简单:语言偏好可以帮助根页面做出选择,而明确的语言链接应始终可靠地指向相应内容。最终应具备已记录的回退行为、匹配的文档声明、相互指向的语言注释,以及逐个请求证明路由约定成立的证据。

来源