🌐 新增翻译完整性机械检查 (check:i18n)#1606
Open
cyfung1031 wants to merge 4 commits into
Open
Conversation
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>
用 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>
3 tasks
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>
Collaborator
Author
|
manually tested |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checklist / 检查清单
背景
#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为基准做以下校验:src/locales/<locale>/*.json:每个命名空间文件的 key 是否与en-US一一对应,缺失或多余都会报错。src/locales/<locale>/index.ts:是否导出了en-US拥有的全部命名空间。src/assets/_locales/<chrome-locale>/messages.json:与en/messages.json的 key 是否一致(即 Brazilian Portuguese/pt-BR Translation #1587 遗漏的部分)。chrome 目录名通过实际扫描_locales/目录解析(如ko-KR→ko、zh-CN→zh_CN),而非写死的映射表,避免映射表本身过期失效。docs/references/terminology-<locale>.md:每个 locale 必须有对应术语规范文件,缺失即报错。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.ts的export default),解析时都会展开后再与en-US比对 key。同时:
docs/translation.md新增"机械检查:遗漏翻译"一节并更新翻译检查清单。.husky/pre-commit中新增一段:只要暂存区包含src/locales/**/*.json或src/assets/_locales/**/*.json,本地提交前就会先跑一遍pnpm run check:i18n,不通过直接拒绝提交——不用等推送后才在 CI 里看到红叉。范围刻意收窄为 json 文件本身(不含terminology-*.md、langs.ts/langs/),这样改动检查脚本本身或调整 terminology/langs 这类周边文件时不会被连带拦下;这些周边文件的完整性仍由 CI 侧的lint:ci(覆盖全部 5 类检查)兜底。已知限制
pt-BR的_locales目录、pt-BR/tr-TR的editorLangs条目),本次检查仅给出提示(warning),不会导致失败——这两处目前是可选/尽力而为的内容(参见docs/translation.md),与项目现状一致。但只要该 locale 已经创建了对应条目,其 key 就必须与en-US保持一致,否则报错。这个折衷是为了不让本 PR 自身因为与本次改动无关的历史遗留缺口(tr-TR/pt-BR的editorLangs)而在合并后立即变红。docs/translation.md与对应的terminology-<locale>.md。pnpm run check:i18n已经接入pnpm lint:ci(.github/workflows/test.yml的Lintjob),失败时 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,而不需要手动维护映射表。.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)。_locales/ko/messages.json与editorLangs["ko-KR"]均完整。langs.ts拆分为langs/<locale>.ts):零问题通过,已在 #1605 的评论里贴出结果;期间发现脚本最初硬编码单文件路径、对拆分后的目录结构会误报"文件缺失",已在本 PR 中修复(自动探测langs/index.ts,支持跨文件import解析)。langs.ts/langs/<locale>.ts中删除/新增 key,删除messages.json、删除terminology-<locale>.md)均能正确以 exit code 1 报出具体缺失/多余的 key 路径,还原后重新通过;pre-commit钩子在暂存区包含 json 翻译文件的坏改动时也会正确拒绝提交,同时确认了它不会拦截本 PR 自身对.husky/pre-commit、scripts/check-i18n.mjs等非 json 文件的提交。关联