Skip to content

🌐 新增翻译完整性机械检查 (check:i18n)#1606

Open
cyfung1031 wants to merge 4 commits into
scriptscat:mainfrom
cyfung1031:claude/missing-translation-checker-6b27d1
Open

🌐 新增翻译完整性机械检查 (check:i18n)#1606
cyfung1031 wants to merge 4 commits into
scriptscat:mainfrom
cyfung1031:claude/missing-translation-checker-6b27d1

Conversation

@cyfung1031

@cyfung1031 cyfung1031 commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Checklist / 检查清单

  • Fixes mentioned issues / 修复已提及的问题
  • Code reviewed by human / 代码通过人工检查
  • Changes tested / 已完成测试

背景

#1587(pt-BR 翻译)合并后,评审中发现该 PR 遗漏了 messages.json(chrome.i18n 商店信息)与 Monaco 编辑器语言(editorLangs),当时没有机制能自动拦截这类遗漏("we don't have a solid mechanism to prevent this")。本 PR 为此补上一个机械检查脚本,并在本地提交与 CI 两处强制执行。

本次改动

新增 scripts/check-i18n.mjs,并通过新增的 pnpm run check:i18n 接入 pnpm lint / pnpm lint:ci。针对 src/locales/ 下的每个 locale,以 en-US 为基准做以下校验:

  1. src/locales/<locale>/*.json:每个命名空间文件的 key 是否与 en-US 一一对应,缺失或多余都会报错。
  2. src/locales/<locale>/index.ts:是否导出了 en-US 拥有的全部命名空间。
  3. src/assets/_locales/<chrome-locale>/messages.json:与 en/messages.json 的 key 是否一致(即 Brazilian Portuguese/pt-BR Translation #1587 遗漏的部分)。chrome 目录名通过实际扫描 _locales/ 目录解析(如 ko-KRkozh-CNzh_CN),而非写死的映射表,避免映射表本身过期失效。
  4. docs/references/terminology-<locale>.md:每个 locale 必须有对应术语规范文件,缺失即报错。
  5. src/pkg/utils/monaco-editor/langs.ts(或未来拆分后的 langs/<locale>.ts + langs/index.ts):editorLangs(悬浮提示、脚本头字段提示,即 Brazilian Portuguese/pt-BR Translation #1587 遗漏的另一部分)用 TypeScript 编译器 API 解析。它是手写的 const 对象而非 JSON,部分属性引用了同文件内其他顶层常量(如 grantValuePrompts: grantValuePromptsEnUS)或跨文件 import 绑定(拆分后每个 locale 一个文件,index.ts"pt-BR": ptBR 指向 ./pt-BR.tsexport default),解析时都会展开后再与 en-US 比对 key。

同时:

  • docs/translation.md 新增"机械检查:遗漏翻译"一节并更新翻译检查清单。
  • .husky/pre-commit 中新增一段:只要暂存区包含 src/locales/**/*.jsonsrc/assets/_locales/**/*.json,本地提交前就会先跑一遍 pnpm run check:i18n,不通过直接拒绝提交——不用等推送后才在 CI 里看到红叉。范围刻意收窄为 json 文件本身(不含 terminology-*.mdlangs.ts/langs/),这样改动检查脚本本身或调整 terminology/langs 这类周边文件时不会被连带拦下;这些周边文件的完整性仍由 CI 侧的 lint:ci(覆盖全部 5 类检查)兜底。

已知限制

  • 对于第 3、5 项,如果某个 locale 尚未创建对应目录/条目(当前如 pt-BR_locales 目录、pt-BR/tr-TReditorLangs 条目),本次检查仅给出提示(warning),不会导致失败——这两处目前是可选/尽力而为的内容(参见 docs/translation.md),与项目现状一致。但只要该 locale 已经创建了对应条目,其 key 就必须与 en-US 保持一致,否则报错。这个折衷是为了不让本 PR 自身因为与本次改动无关的历史遗留缺口(tr-TR/pt-BReditorLangs)而在合并后立即变红。
  • 该脚本无法判断翻译措辞是否准确、是否符合术语规范——那部分仍需人工审阅并遵循 docs/translation.md 与对应的 terminology-<locale>.md
  • 本 PR 无法做到"检查不通过就不允许合并"pnpm run check:i18n 已经接入 pnpm lint:ci.github/workflows/test.ymlLint job),失败时 PR 上会有红叉,本地 pre-commit 也会提前拦截;但真正能拦住合并按钮的,是仓库管理员在 main 分支的 branch protection 里把 Lint 设为 required status check——这一步需要 scriptscat/scriptcat 的仓库管理员在 GitHub 仓库设置里配置,贡献者/本 PR 都无法代为完成,只能建议。

建议审查重点

  • src/pkg/utils/monaco-editor/langs.ts 的 TypeScript AST 解析逻辑(parseModule/flattenNode):是否正确处理了对象嵌套、同文件顶层常量引用、跨文件 import 绑定与 shorthand 属性(grantValuePrompts,)。
  • src/assets/_locales 目录名解析逻辑(findChromeDirName):是否能正确覆盖未来新增的 locale,而不需要手动维护映射表。
  • 第 3、5 项"缺失整个目录/条目仅警告,但已存在则必须对齐"的严格程度是否符合预期。
  • .husky/pre-commit 只在 json 文件改动时触发是否合适:好处是不会拦住本 PR 自身、或调整 terminology/langs 文件时的提交;代价是本地提交阶段不会拦截"新增 locale 但漏配 terminology 文件/langs 条目"这类问题,这类问题仍要等 CI 才会报出来。

验证

  • pnpm run check:i18n:在当前 main 上通过,仅有两条提示性 warning(pt-BR 尚无 _locales 目录、pt-BR/tr-TR 尚无 editorLangs 条目),均为历史遗留、非阻塞。
  • pnpm run lint:ci:全部通过(prettier、tsc、check:i18n、eslint)。
  • 用 scriptscat/scriptcat 官方仓库的三个真实 PR 做了验证:
  • 反向验证(人为在 JSON 命名空间、拆分前后的 langs.ts/langs/<locale>.ts 中删除/新增 key,删除 messages.json、删除 terminology-<locale>.md)均能正确以 exit code 1 报出具体缺失/多余的 key 路径,还原后重新通过;pre-commit 钩子在暂存区包含 json 翻译文件的坏改动时也会正确拒绝提交,同时确认了它不会拦截本 PR 自身对 .husky/pre-commitscripts/check-i18n.mjs 等非 json 文件的提交。

关联

PR scriptscat#1587 (pt-BR) 合并后发现 messages.json 与 monaco 编辑器语言遗漏,且当时无机制拦截;
本次新增 scripts/check-i18n.mjs 并接入 pnpm lint / lint:ci,机械校验:

- src/locales/<locale>/*.json 各命名空间 key 是否与 en-US 一一对应(缺失/多余均报错)
- src/locales/<locale>/index.ts 是否导出全部命名空间
- src/assets/_locales/<chrome-locale>/messages.json 与 en/messages.json 的 key 是否一致
  (尚未创建该目录时仅提示,不阻塞)
- docs/references/terminology-<locale>.md 是否存在(每个 locale 必须有,缺失即报错)
- src/pkg/utils/monaco-editor/langs.ts 中 editorLangs 各 locale 的 key 是否与 en-US 一致
  (尚未创建该 locale 条目时仅提示;已创建则 key 必须对齐)

已用 scriptscat/scriptcat 官方仓库的 PR scriptscat#1568(韩语)与 scriptscat#1587(pt-BR)实际验证:
正确通过完整、正确的翻译提交,也能在人为剔除 key / 文件时正确报错。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@cyfung1031 cyfung1031 changed the title Add mechanical i18n completeness check (check:i18n) 🌐 新增翻译完整性机械检查 (check:i18n) Jul 17, 2026
用 PR scriptscat#1605 实测时发现:check-i18n.mjs 硬编码了单文件 src/pkg/utils/monaco-editor/langs.ts
路径,一旦该文件被拆分为 langs/<locale>.ts + langs/index.ts(如 scriptscat#1605 所做),检查会误报
"文件缺失"。改为先探测 langs/index.ts 是否存在,再退回单文件路径;并将 key 展开逻辑改为
按模块解析(parseModule/flattenNode),支持跨文件解析 import 绑定(如 index.ts 里
"pt-BR": ptBR 指向 ./pt-BR.ts 的 default export)与同文件 shorthand 属性
(如 pt-BR.ts 内的 grantValuePrompts,)。

已用 scriptscat#1605 的实际分支验证:新结构下 0 误报,人为在拆分后的 pt-BR.ts 中删除顶层 key 与
grantValuePrompts 子 key 均能正确报出具体路径。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
cyfung1031 and others added 2 commits July 18, 2026 03:50
CI 的 lint:ci 已经跑 check:i18n,但那只在 push/PR 之后才会看到红叉。
本次让本地 pre-commit 钩子在暂存区涉及翻译相关路径
(src/locales/、src/assets/_locales/、docs/references/terminology-*.md、
src/pkg/utils/monaco-editor/langs.ts 或 langs/ 拆分文件)时,
提前跑一遍 pnpm run check:i18n,不通过则直接拒绝提交,
不需要等到推送后在 CI 里才发现。

真正能拦住"不通过就不许合并"的还有一层:仓库 main 分支的
branch protection 需要把 Lint 设为 required status check,
这一步需要 scriptscat/scriptcat 的仓库管理员在 GitHub 设置里配置,
不是贡献者这边能做的。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
之前的触发范围包含 terminology-*.md、langs.ts/langs/* 等非 json 文件,
导致本 PR 自身改动 .husky/pre-commit、scripts/check-i18n.mjs 这类非
翻译内容的提交也可能被牵连(虽然本次未命中,但范围过宽)。收窄为只在
暂存区包含 src/locales/**/*.json 或 src/assets/_locales/**/*.json 时才
触发 pnpm run check:i18n,其余改动(含本 PR 自身)不受影响,仍可正常
提交推送。CI 侧的 lint:ci 不受影响,仍覆盖全部 5 类检查。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@cyfung1031

Copy link
Copy Markdown
Collaborator Author

manually tested

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant