国际化(i18n)
Apothem 文档网站如何在十二种语言中声明其语言区域集合、发出 hreflang 备用语言链接并进行从右到左渲染。
本页记录 Apothem 文档网站如何处理多种语言:它声明的语言区域集合、它发出的 hreflang 机制、它的从右到左渲染,以及每种语言的页面如何接入路由。
决策摘要
- 平台:Next.js App Router + Fumadocs。 网站从
site/构建。语言区域集合在site/lib/i18n.ts中声明,备用语言链接机制位于site/lib/hreflang.ts。 - 语言区域集合:十二种语言。 由十二个语言区域组成的现代开发者集合是规范的单一事实来源,英语为源语言区域,十一个目标语言区域各自由英文页面集机器播种;各语言区域的人工审校正在进行中,而
fallbackLanguage: 'en'覆盖某个语言区域尚未编写的任何页面。 - 按语言区域路由:已在整个集合中启用。 每个语言区域都接入路由,并可在其自己的 URL 前缀下访问(
/es/、/zh-cn/、…);英语在网站根目录提供。 hreflang机制:已启用。 每个页面都会发出一组<link rel="alternate">,覆盖每个语言区域并加上一个x-default回退,因此搜索引擎能看到完整的备用语言集群。这些链接按文件从文件系统解析,因此只有当某个语言区域拥有某个页面时,该页面才会以该语言区域对外公布。- 从右到左渲染:已启用。 共享样式表全程使用逻辑 CSS 属性,因此阿拉伯语页面在
dir="rtl"下能正确渲染。 - 翻译审校:按页面跟踪。 机器播种的语言区域页面会正常提供,并在其 frontmatter 中带有
machineTranslated: true,直到有人审校为止;该标志是用于跟踪审校的元数据,页面不会显示它。对于某个语言区域缺少的任何页面,英语是回退语言。某个语言区域有 80% 的页面完成审校,是一个审校目标,而不是发布的门槛。 - 翻译新鲜度:按页面跟踪。 每个语言区域页面都会记录它所翻译自的英文文本。当英文页面之后发生变化时,翻译页面会显示一行注释,链接到英文页面,而英文页面仍具有权威性。
语言区域集合
现代开发者集合声明了十二个语言区域。英语在网站根目录提供;十一个目标语言区域各自在自己的 URL 前缀下由英文页面集机器播种,而 fallbackLanguage: 'en' 覆盖任何尚未编写的页面。
| 代码 | 路径 | 语言 | 方向 |
|---|---|---|---|
en | / | 英语 | LTR |
zh-CN | /zh-cn/ | 简体中文 | LTR |
es | /es/ | 西班牙语 | LTR |
pt-BR | /pt-br/ | 巴西葡萄牙语 | LTR |
fr | /fr/ | 法语 | LTR |
de | /de/ | 德语 | LTR |
ja | /ja/ | 日语 | LTR |
ko | /ko/ | 韩语 | LTR |
ru | /ru/ | 俄语 | LTR |
id | /id/ | 印度尼西亚语 | LTR |
ar | /ar/ | 阿拉伯语 | RTL |
hi | /hi/ | 印地语 | LTR |
该集合是单一事实来源;对它的修订须经过审慎的决策,绝不通过静默编辑进行。
hreflang 的工作方式
site/lib/hreflang.ts 构建 alternates.languages 映射,Next.js 将其渲染进每个页面的 <head>。其构建遵循一条规则:仅当某个语言区域已编写该页面时,才发出该语言区域的备用语言链接,这一点按文件从文件系统解析(site/lib/translated-pages.ts)。因此,一个完全翻译的页面会发出完整的集群:
<link rel="alternate" hreflang="en" href="https://apothem.ahmedgad.com/..." />
<link rel="alternate" hreflang="es" href="https://apothem.ahmedgad.com/es/..." />
<link rel="alternate" hreflang="ar" href="https://apothem.ahmedgad.com/ar/..." dir="rtl" />
<!-- … one per cohort locale … -->
<link rel="alternate" hreflang="x-default" href="https://apothem.ahmedgad.com/..." />页面的 canonical 链接始终是它自己的 URL——它绝不跨语言区域指向。
从右到左渲染
阿拉伯语是该集合中从右到左的语言区域,网站会正确地渲染它:
- 仅使用逻辑 CSS 属性。 共享样式表和组件使用逻辑属性(
margin-inline-start、padding-inline-end、text-align: start、inset-inline-start),而非物理属性(margin-left、text-align: left)。逻辑属性在dir="rtl"下会自动翻转,因此同一份样式表能正确地服务于两种方向。 - 方向属性。 阿拉伯语页面在
<html>元素上设置dir="rtl",并同时设置lang="ar"。 - 双向内容。 混合方向的字符串——例如阿拉伯语段落中的一条英文命令——会被包裹在
<bdi>中,使嵌入的从左到右文本段在从右到左的文本流中正确渲染。
添加或更新语言区域
集合与路由由 site/lib/i18n.ts 驱动:
- 在
content/docs/<locale>/下编写该页面,与英文源保持镜像。 - 记录它所翻译的英文文本:在
site/中运行node scripts/translation-sources.mjs --stamp <locale>/<path>.mdx,它会将英文页面的哈希写入该语言区域页面 frontmatter 中的sourceHash。 - 确认该语言区域已列在
ROUTED_LOCALES中(如今集合中的全部十二个语言区域都已接入路由)。 - 它的
hreflang链接和路由会从文件系统自动解析。
过期的翻译
语言区域页面的 sourceHash 是它所翻译自的英文页面的哈希,涵盖英文 frontmatter 和正文,但不包括参考生成器在所有语言中一次性重写的生成表格。在构建时,网站会对当前英文页面计算哈希;当两者不同时,翻译页面会显示一条注释,说明英文页面自翻译完成以来已发生变化,并附上指向它的链接。在 site/ 中运行 node scripts/translation-sources.mjs,按语言区域列出过期页面,然后更新每份翻译,并按上文第 2 步为其打上标记。某个语言区域完全未翻译的页面会以英文源提供,并标记为英文文本。
英文仍是事实来源;每个语言区域页面都逐字镜像其英文对应页面的结构、链接和代码示例。