Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

语言包 key 缺口:8 个语言各缺 357–359 键,74 键只存在于 zh.ts,且没有任何 parity 测试 #2872

Closed

Description

@os-zhuang

问题

packages/i18n/src/locales/ 的 10 个语言包顶层命名空间是齐的(57 个),但下一层已经烂了。而 i18n.ts:135 设了 fallbackLng: 'en',missingKeyHandler(:145)只在 dev 生效——所以线上一律静默回退,表现为"看起来只是没翻完"。

实测数据

用 flatten 后的 key 集合与 en 对比:

包 key 数 相对 en 缺失 en 中没有的
en 2243 — —
zh 2313 4 74
ja / ko / de / es 1886 357 0
fr / pt / ru / ar 1884 359 0

(a) 357–359 个 en 键在 8 个非中文包里不存在

按命名空间(以 ja 为例):console 141、gantt 58、grid 29、dashboard 25、home 19、list 18、topbar 12、layout 12、marketplace 8、capability 7,其余零散。

实际效果:德语/日语管理员看到的整个 AI 控制台(console.ai.*)、Gantt 工具栏、grid 批量选择全是英文。

(b) 74 个键只存在于 zh.ts,从没进过 en.ts

  • grid.import.* — 62 键。packages/plugin-grid/src/ImportWizard.tsx:39-45 自带一份私有 DEFAULTS 映射兜底,所以英文"碰巧"能显示——但其余 8 语拿到的是那份英文兜底,且无处可翻;两份文案还会各自漂移。
  • auth.setPassword.* — 12 键。调用点(apps/console/src/pages/auth/SetPasswordPage.tsx:55-108)传 defaultValue: 英文,同样是 en 能显示、其余 8 语无法翻译。

这两处是本仓库已经修过两次的同一形态:字符串只加进一个包,在大家日常测试的两种语言下"一切正常"。

(c) 4 个 en 键中文包缺失

console.commandPalette.title
console.ai.suggestions.metadataAssistant.buildInventory
console.ai.suggestions.metadataAssistant.buildRecruiting
help.keyboardShortcuts

缺一条测试

packages/i18n/src/__tests__/ 目前没有任何跨语言包 parity 测试。一个 flatten + keySet(en) === keySet(locale) 的断言可以一次性拦下 (a)(b)(c)。

写法可直接复用刚合入的 packages/i18n/src/__tests__/cloudConnection-locale-parity.test.ts(objectui#2865),它已按同样思路守住 cloudConnection 命名空间,并做过变异验证。

⚠️ 注意实施顺序:全量 parity 测试加进去会立刻失败(357×8 + 74 + 4)。所以必须"补齐 + 测试"同 PR,或者先落一份 baseline 允许列表再逐步收敛。只加测试会直接卡红 CI。

需要先决策的一点

补齐 (a) 意味着为 8 种语言生成约 2800 条译文。这是产品质量决策,不该默认由 agent 直接生成后发版:

  • 接受机器翻译先行、后续人工校订?
  • 还是只补齐高频命名空间(console / home / topbar / layout),其余保持英文回退?
  • 或者引入 TMS / 人工翻译流程?

(b)(c) 与这个决策无关,可以立刻做:(b) 是把已有中文补上英文原文并让其余语言可翻,(c) 是 4 条中文补全。

建议拆法

  • P1(无需决策):(c) 4 条 zh 补全 + (b) grid.import.* / auth.setPassword.* 归位到 en.ts,并消除 ImportWizard 的私有 DEFAULTS 兜底
  • P2(需决策):(a) 8 语 × ~357 键补齐策略
  • P3:全量 parity 测试落地(跟在 P1/P2 之后,或配 baseline)

发现来源

objectstack#3589 收尾时的全仓库 i18n 覆盖排查。相关:objectui#2870(P0 全屏拦截层)、objectui#2871(手搓 zh 判断绕开语言包)。

Activity

  1. os-zhuang commented on Jul 28, 2026

    @os-zhuang
    ContributorAuthor

    P1 已完成;顺带修正 P2 的规模数字

    在 main(dc334da)上重新实测:

    包 key 数 相对 en 缺失 en 中没有的
    en 2481 — —
    zh 2481 0 0
    ja / ko / de / es 2012 469 0
    fr / pt / ru / ar 2010 471 0

    (b)(c) 已关闭

    • (c) 4 条 en 键的中文补齐 ✅
    • (b) grid.import.*(134 键)与 auth.setPassword.*(12 键)已归位到 en.ts;ImportWizard 的私有 DEFAULTS 兜底由 packages/plugin-grid/src/ImportWizard.i18n-parity.test.ts 钉死到 en.grid.import,两份文案不会再各自漂移

    en ↔ zh 现在是精确对等的:2481 : 2481,双向 0 差异。

    ⚠️ P2 的规模从 ~2,800 涨到 ~3,760,这是修 (b) 的直接结果

    原 issue 记的是 357–359 键,现在是 469–471。这不是回退,而是把原本藏在组件私有兜底后面的缺口暴露出来了:

    (b) 里那 146 条字符串此前只存在于 zh.ts,英文靠 ImportWizard 组件内的 DEFAULTS 才"碰巧"能显示。它们进入 en.ts 之后,按定义就成了其余 8 语的缺口——这些语言过去同样翻不了,只是当时统计不到。

    所以 P2 的实际工作量是 469–471 键 × 8 包 ≈ 3,760 条译文。

    本轮新增命名空间未扩大缺口

    cloudConnection、auth.remediation、auth.layout、environment、excelImport、cloudOnboarding、aiModelStatus、chatbotQuota、以及 console.loadingHint,全部一次补齐 10 个语言包。相关的 parity 测试(cloudConnection-locale-parity、authRemediation-locale-parity、en-zh-key-parity)均已做过变异验证——即断言其在不变量被破坏时确实会红。

    P2 仍待决策

    三条路(机器翻译先行 / 只补高频命名空间 / 引入 TMS)是产品质量决策,等确认后再动。P3 的全量 parity 测试跟在 P2 之后落地——现在加会立刻红 469×8。


    Generated by Claude Code

  2. os-zhuang commented on Jul 28, 2026

    @os-zhuang
    ContributorAuthor

    Part (a) 第一阶段已合并(#2903):高频命名空间补齐

    按「只补高频命名空间」的策略,console / home / topbar / layout 已补齐 —— 193 键 × 8 包 = 1,544 条。

    包 之前缺失 现在
    ja / ko / de / es 469 277
    fr / pt / ru / ar 471 279
    en ↔ zh 2499 : 2499,双向 0 差异 不变

    剩余缺口按命名空间(去重后 277–279 键):

    命名空间 缺失
    grid 101
    gantt 58
    dashboard 25
    list 18
    auth 18
    fields 11
    marketplace 8
    capability 7
    其余零散 ~35
    console/home/topbar/layout 4(见下,故意保留)

    注:grid 从原 issue 记的 29 涨到 101,是 part (b) 把 grid.import.* 的 134 键归位到 en.ts 的直接结果 —— 那些文案过去同样翻不了,只是统计不到。

    ⚠️ 顺带修掉了一个我在 #2900 引入的回归

    这次为了给每个 console.ai.* 键分类(标签 vs 出站消息),发现有 4 个键根本不是标签,而是按钮发给 agent 的正文:

    console.ai.planApproveMessage
    console.ai.planApproveDefaultsMessage
    console.ai.planAnswerMessage
    console.ai.changesConfirmMessage
    

    它们是否被认作「批准」,由 cloud 的 confirm-gate.ts APPROVAL_RE 判定 —— 该正则只认中文和英文。zh.ts 里已有的注释写得很清楚:不匹配则 agent 会重新提议,而按钮看上去像失灵了,却不报任何错。

    所以 AiChatPage 是按对话语言(而非 UI 语言)选这几条的,t() 在非中文包里本就应该 miss 并回退到英文 defaultValue。

    #2900 把 changesConfirmMessage 加进了全部 10 个包,于是德/日/俄用户点「确认」时发出的是德/日/俄文,gate 匹配不上。#2903 已将其从 8 个包中移除,恢复英文回退。

    新增守卫 packages/i18n/src/__tests__/outbound-agent-messages.test.ts 双向钉住该不变量:这 4 个键必须不在 8 个包里、且必须在 en/zh 里;同时第三条断言要求其余每一个 console.ai 标签都必须被翻译 —— 避免这个窄例外被扩大成「其它标签也可以不翻」的借口。两个方向都做过变异验证。

    后续

    • P2 剩余:277–279 键 × 8,主要是 grid / gantt / dashboard。这些是数据表格/甘特图的专业术语,机器翻译出错风险高于本轮的导航类文案,建议单独判断是否值得做
    • P3 全量 parity 测试:仍需等 P2 收敛,或配 baseline 允许列表
    • 本轮译文为模型生成,术语沿用各语言包既有习惯、引号按各语言规范(「」 ja、„" de、« » fr),但建议母语者复核后再当作最终版本

    Generated by Claude Code

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions