Skip to content

i18n: 按平台正式写法补 zh-CN 翻译包,消除中文界面下的英文对象名与列头 - #25

Merged
baozhoutao merged 1 commit into
mainfrom
issue-24-i18n-zh-bundle
Sep 3, 2026
Merged

baozhoutao merged 1 commit into
mainfrom
issue-24-i18n-zh-bundle

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

关联工作项 #24。

问题

中文界面下对象名与列头显示英文(Assessment Plan、Plan Name、Entry Sheet、Final Score…),用户已选中文仍然如此。

根因不是文案写错:元数据 label 本身就是中文,但仓库只注册了 en 翻译包、没有 zh-CN 包。平台运行时按「zh-CN 包 → en 包 → 元数据原文」查标签,zh-CN 包不存在,凡 en 包覆盖到的键一律落到英文。

改法

按平台文档(objectstack-i18n)的正式写法整改——每个支持的语言各带一个翻译包,默认语言的包由 os i18n extract 从元数据标签生成:

文件 改动
src/translations/zh-CN.objects.generated.ts 新增,529 个词条,100% 由 pnpm i18n:extract 从元数据中文 label 生成,零人工翻译、零手改
src/translations/index.ts 注册 'zh-CN' 包;en 包内容原样保留
package.json 新增 i18n:extract(生成)与 i18n:extract:check(新鲜度门禁);verify 并入门禁,元数据标签改了包必须跟着改
CLAUDE.md 项目约定中翻译包的那一句改为正式写法(只改这一句)

不改任何对象/字段 label 文案,不改 en 包内容,不动 src/data/、scripts/、docs/、README,不修改平台包。

生成命令为何带 --no-objects-only --filter=kpi_

  • 平台默认的 --objects-only 只产出 objects / globalActions 子树、不含 apps,而验收要求应用名返回「KPI 考核管理」——应用名正是被 en 包覆盖的键。
  • 加 --no-objects-only 后,工具即便同时传 --no-metadata-forms,仍会把平台 Studio 的 metadataForms 英文基线(761 词条)内联进同一文件;那份基线按平台文档属于平台包、不该由应用包分发。--filter=kpi_ 把范围收在本应用自有的 objects/apps/dashboards/pages 上。
  • 零内容损失:带与不带 filter 的两份产物逐行 diff,差异有且仅有 metadataForms 整块,其余四段逐字节相同。

命令原样写进 package.json,评审可 pnpm i18n:extract:check 或重跑 pnpm i18n:extract 对账。

验证

pnpm verify 全绿(validate + typecheck + 90 个单测 + 新鲜度门禁);os i18n check 默认语言 zh-CN 100.0%(1290/1290,missing 0);node scripts/e2e-flow.mjs 73 PASS / 0 FAIL。

API 断言(zh-CN):填报单 / 填报单名称 / 状态 / 最终得分 / KPI 考核管理 —— 逐字命中。
API 对照(en):Entry Sheet / Sheet / Status / Final Score / KPI Assessment —— 逐字未变。

UI 前后对比 6 组 12 张 + 英文对照 1 张,含「指标 / Indicator 两列并存 → 指标 / 指标名称」的点名项。

新鲜度门禁做过负向测试:人为改脏一个词条即报 out of date 并以退出码 1 失败。

📄 测试报告 · 需求符合度清单 · 截图归档 acceptance-evidence @ 8c584f20de742d6d6c35c5cb8b6be53aa38168d9

🤖 Generated with Claude Code

@baozhoutao

Copy link
Copy Markdown
Contributor Author

代码评审报告(os-project-dev-review)

档位:轻量档(依据:工作项属纯新增——生成文件 + 注册两行 + 约定一句 + 两个 npm 脚本,路径唯一、低风险;调度员派发时按 dev-issue 低风险直接开工。diff 1422 行中 1364 行为工具产物,手写代码实际仅 14 行)
评审方式:冷启动独立子 agent,只读;输入仅工作项全文、PR diff、需求符合度清单原文(未读开发自测报告与对话)。对账在临时 clone(issue-24-i18n-zh-bundle @ 312cb7a)中执行,未进入任何既有 worktree,未写入本仓库任何文件。

结论:可合并


通用质量(/code-review)

无正确性缺陷。 内置 /code-review 常规档运行完成,独立复核了生成器可重现性、过滤器无内容损失、门禁非空转、en/zh-CN 键覆盖对齐,并额外确认:

  • extractTranslations 对默认语言跳过 merge、每次重新播种,因此元数据 label 一改,--check 必然失败 —— 新鲜度门禁不是摆设;
  • 手工维护的 en 包中每一个键路径在新 zh-CN 包中都有对应词条(差集为空)——「en 有键、zh-CN 没有 → 漏成英文」这一 bug 类别对当前元数据已完全闭合;
  • 生成包内无空值;529 条目映射到 484 个唯一路径,45 处路径重合值全部一致,无静默覆盖;
  • src/views|reports|actions|dashboards|pages|apps 中无英文字面量 label,元数据侧无残留英文可漏。

产出 2 条低危健壮性提示,均不影响当前正确性,列入 ⚪ 记录级。


专属核查(四条逐条)

1 改动面越界:✅ 无越界
diff 恰为 4 个文件,与工作项范围逐一对应:CLAUDE.md(+3/-1)、package.json(+3/-1)、src/translations/index.ts(+8/-1)、src/translations/zh-CN.objects.generated.ts(新增 1364 行)。

  • CLAUDE.md:只改「用户可见文案默认中文…」这一条,前后条目一字未动;
  • package.json:只新增 i18n:extract / i18n:extract:check 两个脚本,并在 verify 尾部追加门禁,其余脚本与依赖未动;
  • index.ts:新增 import、'zh-CN' 注册、注释重写;en 对象块与 main 逐字节比对完全相同(diff 空);
  • 「不做」清单全部守住:未触及 src/objects/、src/data/、scripts/、README、docs/,未改任何 label 文案。

2 降级对账:✅ 清单相符(含一处自述偏差,核实属实且已获调度员放行)

清单条目 核实方式 结果
范围1 ⚠️ 命令带 --no-objects-only --filter=kpi_,529 词条,零手改 在临时 clone 中原地重跑 pnpm i18n:extract,git status --porcelain 输出为空 ✅ 属实——提交的生成文件与工具重新产出逐字节相同,不存在手写词条冒充生成物
偏差理由「--filter=kpi_ 零内容损失」 分别生成带 filter / 不带 filter 两份产物做全文 diff ✅ 属实——差异为单一纯新增块 1362a1363,3021,即 1363 行之后追加的 metadataForms 整段;objects / apps / dashboards / pages 四段逐字节相同。1290 = 529 + 761(metadataForms)
范围2 en 包原样保留 en: 块与 main 对拆比对 ✅ 逐字节未变
范围3 只改那一句 读 diff ✅
范围4 --check 可用、并入 verify 实跑 ✅ pnpm i18n:extract:check 报 1 bundle(s) are in sync,退出码 0
验收1 五项标签断言 在生成包中静态定位 ✅ kpi_entry_sheet.label=填报单、fields.name=填报单名称、fields.status=状态、fields.total_score=最终得分、apps.kpi_app.label=KPI 考核管理,五项逐字命中
验收2 en 不受影响 en 块未变 ✅ 结构上成立(运行期 API 断言归验收线)
验收4 verify 绿 + i18n check 默认语言零错误 实跑 ✅ pnpm verify 退出码 0(validate 通过、tsc 通过、vitest 90/90 通过、门禁 in sync);os i18n check 零 error,1252 条 warning 全为 en 非默认语言的既有缺口,结论行为「default locale is fully covered」
验收5 生成物可对账 重跑生成对账 ✅ 见范围1

无 TODO / FIXME / 被注释掉的校验 / 比需求少的分支。未发现静默降级。
(验收3 的 UI 前后对比截图属功能达标判定,归验收线,本闸门不判。)

3 三禁痕迹:✅ 无
diff 路径不含 node_modules/ 或任何平台包目录;无 patch 类文件(无 patches/、无 pnpm.patchedDependencies);未绕行平台机制自造实现——恰恰相反,本单是把原先「只发 en 包」的非正式写法改回平台 objectstack-i18n 文档的正式写法(每语言各一包、默认语言包由 os i18n extract 生成)。平台工具的行为差异按 G2 只记录、不修复。

4 硬拍板落地:✅

  • 数字字段四件套:本单未新增或修改任何字段(src/objects/ 未触及),不适用;
  • std-copy 四条红线:生成包 376 条叶子值全部含中文,零条纯英文(自动扫描结果为 0);无内部代号当 label(grep ': "(kpi_|bu_)' 无命中);无异常原文;词条均为既有元数据 label 的原样搬运,不引入新文案。CLAUDE.md 那句为开发者文档,不属用户可见文案。
  • 附:被 --filter=kpi_ 排除掉的 761 条 metadataForms 正是平台 Studio 的英文基线(label: "Object" / "Basics" / "Define the data model…")。若不排除,这批英文将被打进 zh-CN 包并由应用分发——过滤器的取舍反而是 std-copy 红线的正解,而非损失。

发现清单

级别 位置 问题 处置出口
🔴 阻塞 — 无 —
🟡 应修 — 无 —
⚪ 记录 package.json:21-22 i18n:extract 与 i18n:extract:check 逐字重复同一串五个 flag。二者必须永远保持一致,否则只改其一(如改 --filter / --out / 去掉 --no-objects-only)会让 pnpm verify 要么对着生成器原样产出的文件永久失败,要么放行一份生成器根本不会产出的文件。建议把公共 flag 抽成一个脚本供另一个复用 留痕,不阻塞合并
⚪ 记录 package.json:22 新鲜度门禁与生成用同一个 --filter=kpi_,因此对被过滤掉的东西天然失明。具体场景:将来注册一个名字/路径里没有 kpi_ 的 app/page/dashboard(CLAUDE.md 的 kpi_ 前缀规约只约束对象机器名),它拿不到 zh-CN 词条而门禁仍报 in sync;一旦有人给它补了 en 词条,本单修的失效模式就原样复现。边缘情形:平台 commands/i18n/extract.js 的 emitted 列表只收 counts > 0 的语言,万一 filter 一条都没匹配上,--check 会打印「0 bundle(s) are in sync」并以 0 退出 留痕;若认为值得跟踪,按 dev-issue「独立问题照立单」另立工作项
⚪ 记录 平台工具行为 --no-metadata-forms 在配合 --no-objects-only 时未能抑制 761 条 metadataForms 内联进单文件(实测仍全量产出),本单靠 --filter 绕开。属平台侧现象,按 G2 只上报不修复;与已上报的 objectstack-ai/objectstack 第 14882 号(os i18n check 把默认语言原文算作已覆盖)可一并归档 留痕,平台仓上报
⚪ 记录 符合度清单 验收4 表述 清单写「zh-CN 覆盖率 100.0%,1290/1290」,而随包交付的词条实为 529 条。该数字经复核确为 os i18n check 的真实输出(1290 含 761 条 metadataForms),不构成失实;但这个 100% 恰恰来自「默认语言原文算已覆盖」的口径——也就是 objectstack-ai/objectstack 第 14882 号争议本身,故它不是本单修复生效的独立证据。真正的证据是「重跑生成逐字节相同」+「en 包每个键在 zh-CN 包均有对应词条」,二者本次均已独立复现 留痕,建议后续清单改引可证伪指标

复现命令(评审侧实跑,均在临时 clone 内)

pnpm install --frozen-lockfile
pnpm i18n:extract        # 重跑后 git status 为空 → 生成物零手改
pnpm i18n:extract:check  # in sync,退出码 0
pnpm verify              # 退出码 0(validate / tsc / 90 tests / 门禁)
npx objectstack i18n check   # 零 error;default locale fully covered

评审子 agent 零代码:本报告不含任何修复提交,未改标签、未改处理人、未合并。

@baozhoutao
baozhoutao merged commit 2367ed6 into main Sep 3, 2026
1 check passed
@baozhoutao
baozhoutao deleted the issue-24-i18n-zh-bundle branch September 3, 2026 08:21
界面英文的根因是缺 zh-CN 翻译包:元数据 label 本身是中文,但仓库只注册了
en 包;运行时按「zh-CN 包 → en 包 → 元数据原文」查标签,zh-CN 包不存在,
凡 en 包覆盖到的键一律落到英文。

按 objectstack-i18n 文档的正式写法整改,每个支持语言各一个包:

- 新增 src/translations/zh-CN.objects.generated.ts —— 全部由
  `pnpm i18n:extract`(os i18n extract)从元数据中文 label 生成,529 个
  词条,零手改;
- src/translations/index.ts 注册 'zh-CN' 包,en 包内容原样不动;
- package.json 增加 i18n:extract 生成脚本与 i18n:extract:check 新鲜度
  门禁,并把门禁并入 pnpm verify,保证元数据标签改了包会跟着改;
- CLAUDE.md 项目约定中翻译包的那一句改为正式写法。

生成命令带 --no-objects-only:平台默认的 --objects-only 只产出
objects/globalActions 子树,不含 apps,而应用名「KPI 考核管理」正是被 en
包覆盖的键。带 --filter=kpi_ 把范围收在本应用自有的 objects/apps/
dashboards/pages 上——与不带 filter 的产物逐字节相同,只少了平台 Studio
的 metadataForms 英文基线(--no-metadata-forms 未能抑制它内联到单文件里,
那份基线属于平台包,不该由应用包分发)。

不改任何对象/字段 label 文案,不改 en 包,不动 src/data、scripts、docs。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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