Skip to content

i18n 规范

本规范参考 momei 项目的国际化治理体系(translation-governance.md / i18n.md)适配而成,聚焦 dependfix 的 README 多语言、docs 翻译与平台 UI 国际化三条链路。

1. 目标与适用范围

本规范定义 dependfix 多语言文档与产品词条的协作规则,目标是避免出现"页面已翻译、系统链路未补齐、质量门禁未覆盖"的半完成语言。

适用范围包括:

  • README 多语言版本(README.md 中文原版 + README.en-US.md 等翻译版)
  • 文档站公开页面(docs/ 中文原版 + docs/i18n/<locale>/ 翻译版)
  • 管理平台 UI 词条(apps/platform/i18n/locales/<locale>.json
  • 与语言发布相关的回退策略与质量门禁

2. 语言发布分级

新增语言采用分级准入:

  • draft:仅允许本地验证,不进入公开语言切换入口。
  • ui-ready:完成核心 UI、语言入口、回退链和基础质量校验,可公开展示。
  • seo-ready:在 ui-ready 基础上补齐邮件、SEO、站点地图与回归检查,可作为正式全球语言发布。

发布原则:

  • 默认先接入 ui-ready,避免一次性追求全量翻译。
  • 没有通过回归校验的语言,不得升级为 seo-ready
  • 快速迭代模块允许暂时回退到中文原文,但必须在文档与待办中明确标注。

2.1 文档翻译 freshness 分层

文档翻译按页面职责分层治理,不统一按"所有页面都必须 30 天内同步"处理:

Tierfreshness 口径允许内容形态当前典型范围
must-sync30面向公开入口的操作等价翻译en-US 首页、快速开始、README
summary-sync45摘要同步,保留原文回链路线图摘要、核心高频规范页
source-only不做天数 SLA,但必须显式声明"中文事实源优先"保留 locale URL 的入口页,不承诺持续维护正文低频设计页、低频 Guide、深层 Standards

补充约束:

  1. source-only 页面必须显式提供中文原文入口,不允许保留看起来像完整翻译、实际上已长期失新的旧正文。
  2. source-only 页面不得继续占据 locale 导航和侧边栏主入口,避免用户误判维护承诺范围。
  3. summary-sync 页面允许结构摘要化,但必须覆盖本轮已经进入质量门、导航主入口或贡献流程的关键变化点。

2.2 当前 locale 文档范围

Locale当前承诺范围
en-US公开入口页保持 must-sync;路线图、开发指南与核心高频规范页保持 summary-sync;设计页、低频 Guide 降为 source-only

3. 平台 UI 国际化

3.1 语言标识规范

项目内部统一采用 BCP 47 风格区域码作为唯一业务规范:

  • zh-CN(简体中文,默认)
  • en-US(英文)

后续扩展候选:zh-TW(繁体中文)、ko-KR(韩文)、ja-JP(日文)。

规范要求:

  • apps/platform/i18n/locales/<locale>.json 文件名必须使用这套标识。
  • apps/platform/nuxt.config.tsi18n.locales 配置、语言切换器、服务端翻译装配都必须以这套标识为准。
  • 文件名使用完整区域码(en-US.json),code 字段可保持短码(en)用于 URL 前缀,两者映射见 apps/platform/i18n/localeDetector.ts

3.2 回退链

缺词时按以下回退链解析:

LocalefallbackChain
zh-CNzh-CN
en-USen-US -> zh-CN
zh-TW(未来)zh-TW -> zh-CN -> en-US
ko-KR(未来)ko-KR -> en-US -> zh-CN

zh-TWzh-CN 语义最接近,缺词优先回退简体中文;ko-KR 的 UI 缺词优先回退英文,减少机器感过强的中文兜底。

3.3 文案归属层级

  • 页面私有:只服务单一页面或单一流程的词条,保留在对应页面命名空间(如 alerts.*repos.*)。
  • 模块共享:同一业务模块下多个页面复用的词条,收敛到该模块共享命名空间(如 common.actions.*)。
  • 全局共享:跨模块稳定复用的按钮、状态、提示和壳层文案,放在 common 命名空间。
  • 禁止为了减少翻译工作量,让公共页长期引用后台页面 key,或让后台页直接复用公共页私有 key。
  • 在决定是否上收到共享命名空间前,先运行 pnpm i18n:audit:duplicates。该脚本只标记"所有扫描语言里翻译签名完全一致"的重复候选,避免因为单语种撞词就误判为可复用文案。
  • 审计结果只提供候选,不直接等于应该抽取;是否提取到共享命名空间,仍要结合组件职责、加载边界和未来演进方向逐条判断。

3.X locale 文件 insert anchor 必须用目标 locale 文本(M25.4 阶段实证)

locale 文件多段对称(zh-CN.json + en-US.json),insert anchor 必须用目标 locale 实际文本(如 en-US 段必须用 loadFailed: "Failed to load: {message}" 英文 anchor;zh-CN 段必须用 loadFailed: "加载失败:{message}" 中文 anchor)。

根因:JSON.parse 容忍重复键 last-key-wins,anchor 错位导致后续段被改写但前端无 lint 检测 i18n 字段语义。M24.1 Phase 4 B1 实证:en-US.json alerts.errors.loadFailed 被中文污染("加载失败:{message}")—— 本次 en PRCheck 段 insert anchor 用 zh-CN 中文文本,导致 en-US 段尾部被改写。集成测试 + 视觉测试前无法发现。

修复模式

  1. 双向检测(en-US ↔ zh-CN):scripts/i18n-anchor-check.mjs(M25.4 commit 80912c2 落地)覆盖 (a) 正常态——en-US/zh-CN 键集相同 + 文本不同;(b) 异常态——en-US/zh-CN anchor 用错位文本;(c) 异常态——en-US 段尾部某字段值与 zh-CN 相同(locale 错位污染);(d) 值 locale 区分度(任意 code 在 zh-CN locale 取值 ≠ en-US locale 取值是"对称态";两者相等是"错位污染")
  2. CI 集成.github/workflows/test.yml step 9 跑 pnpm run i18n:anchor-check——本批 CI 步骤新增不破坏现有 check:docs / lint:md / typecheck 链路
  3. zod-helpers 配套apps/platform/server/utils/zod-helpers.ts parseOptional<T>(schema, query, fieldName): { success: boolean, value?: T, isProvided: boolean } helper 强制三态语义(testing.md §6 失败处理后段

详见 经验归档 §六十一 M25.4 i18n-anchor-check 工具化 + 经验归档 §五十六 M24.1 教训 2/5

4. README 多语言规范

  • 中文原版固定为 README.md,翻译版使用 README.<locale>.md 命名(如 README.en-US.md)。
  • 每个语言版本头部必须包含语言切换链接区,指向全部已发布语言版本。
  • README 属于 must-sync 层级,翻译版必须跟随原版结构变化同步更新,不得长期滞后。

5. 术语约束

翻译时遵循以下约束:

  • 保留产品名、协议名、云厂商名与主流技术名:如 GitHubDependabotpnpmTypeORM
  • 同一术语在同一语言中保持统一,不允许同页混用不同译法。
  • localefallbackreadiness 等治理术语优先与现有设计文档保持一致。
  • 繁体中文必须避免残留简体字;韩语页面避免用英文占位直接暴露给 UI。

推荐在提交前抽样检查以下高风险词:

  • 文案状态词:启用、停用、发布、审核、失败、成功
  • 设置键名:仓库、凭据、扫描、告警、定时、批量、同步

6. 贡献流程

6.1 开始前

  1. 明确目标语言与阶段目标:是补齐 ui-ready,还是推进到 seo-ready
  2. 检查对应模块是否已有 locale 文件、README 版本和文档目录。
  3. todo.md 中更新当前阶段状态,避免重复劳动。

6.2 翻译中

  1. 优先补高频路径:首页、认证、设置、后台关键链路。
  2. 新增文档页时,优先同步首页、快速开始和 README。
  3. 翻译文档的物理路径统一落在 docs/i18n/<locale>/,对外文档站 URL 继续保持 /<locale>/...
  4. 合并前必须通过 pnpm docs:check:i18n;若发现旧目录(docs/<locale>/)回流,或同一翻译页同时存在于旧目录与 docs/i18n/<locale>/,视为阻塞问题,禁止继续提交。
  5. 若某页决定降为 source-only,必须同步更新页面正文、Frontmatter、locale 导航范围与翻译治理说明,不能只在脚本里豁免。
  6. 若某模块暂不翻译,需保留原文来源说明,而不是留空或放英文占位。

6.3 提交前

至少执行以下校验:

bash
pnpm lint:md:check
pnpm docs:check:i18n
pnpm lint
pnpm typecheck

涉及平台 locale 词条变更时,额外执行:

bash
pnpm i18n:audit:missing
pnpm i18n:audit:unused

涉及文档翻译时,额外执行:

bash
pnpm docs:check:i18n

6.4 Blocker 入口与最小检查矩阵

pnpm i18n:audit:missing 的口径统一为"缺词 parity blocker":

场景必跑命令blocker 判定
日常 i18n 代码改动pnpm i18n:audit:missing只要本次变更触及 apps/platform/i18n/locales/** 或共享组件命名空间,缺词就按本次 Review Gate blocker 处理
发版前 / 阶段收口CI 的 i18n:audit:missing 步骤失败直接阻断发版
docs 翻译变更pnpm docs:check:i18n旧目录回流或重复翻译页即阻塞,禁止提交

pnpm i18n:audit:unused 的口径统一为 warning / cleanup candidate,不直接阻断 release 或阶段收口。只有当本次任务目标本身就是"删除旧 key、收敛未使用文案、证明某模块可安全裁剪"时,才把 unused 结果升级为当前任务的必过检查。

i18n 相关改动的最小检查矩阵统一如下:

改动类型最小检查矩阵
仅补 locale 文案pnpm i18n:audit:missing + pnpm lint:i18n
locale 模块注册、运行时加载、共享组件跨页面复用上述命令 + pnpm i18n:audit:duplicates
文案复用 / 命名空间收敛上述命令 + pnpm i18n:audit:duplicates + pnpm i18n:audit:unused
文档翻译pnpm docs:check:i18n + pnpm lint:md:check
发版前或阶段收口CI 全部 i18n 步骤通过

7. 回归检查清单

每轮语言扩展完成后,按以下顺序回归:

  1. 语言切换入口是否可见,且能正确切换 locale。
  2. 公共页面、后台关键页面是否仍有明显未翻译占位。
  3. pnpm i18n:audit:missing 是否通过,且无缺失 key。
  4. 文档站对应语言首页与快速开始页是否可访问。
  5. pnpm docs:check:i18n 是否通过,无旧目录回流或重复翻译页。

8. PR / 交付说明建议

提交翻译相关变更时,说明中建议包含:

  • 本轮新增或补齐的语言与模块
  • 是否新增 README / 文档站翻译页面
  • 已执行的校验命令与结果
  • 仍未覆盖的模块或已知残留

Released under the MIT License.