Skip to content

fix(i18n): 一处键差异被 checkKeyParity 报成两条,且 extra 的 locale 标签指向错误一侧 #209

Description

@wxrbyte

现象

checkKeyParity()(packages/i18n/src/resources.ts:87-118)外层遍历全部 locale、内层再对 flat 与
otherFlat 各查一遍,于是同一处 en/zh 键差异会产出 2 条 issue;且 extra 分支的 locale
填的是当前 locale 而不是缺键的那一侧,标签与事实相反。

给 zh-CN 删掉 navigation.today(一处差异),跑真实脚本 bun run i18n:check:

i18n:check
  supported locales: en-US, zh-CN
  ✗ [missing zh-CN] navigation.today
  ✗ [extra zh-CN] navigation.today
  en-US: 1487 keys · zh-CN: 1486 keys
i18n:check FAILED — 2 issue(s)

第 2 行读作「zh-CN 多出一个键」,但该键其实存在于 en-US、缺失于 zh-CN——标签正好说反;
同时 failures 计数被放大一倍(scripts/i18n-check.ts:57 对每条 issue 累加一次)。

期望

一处差异产出且仅产出一条 issue,且 locale 指向有问题的那一侧。修复后同样的差异:

i18n:check
  supported locales: en-US, zh-CN
  ✗ [missing zh-CN] navigation.today
  en-US: 1487 keys · zh-CN: 1486 keys
i18n:check FAILED — 1 issue(s)

判据(取自源码自述契约)

  • packages/i18n/src/locales/keys.ts:8-9:exact parity including extras is enforced by i18n:check at CI
  • packages/i18n/src/resources.ts:4:Both locales must stay key-identical — i18n:check enforces that in CI
  • scripts/i18n-check.ts:8:key parity — every key in en-US exists in zh-CN and vice versa
  • scripts/i18n-check.ts:56-58:for (const issue of issues) fail(...) → failures 就是 issue 条数,
    并直接出现在用户可见的 i18n:check FAILED — ${failures} issue(s) 与 assertKeyParity() 抛出的
    I18N_KEY_PARITY: ${issues.length} issue(s) 里

影响

  1. CI 日志与 assertKeyParity 的报错计数把 1 处差异说成 2 处,N issue(s) 虚高一倍;
  2. [extra …] 行的 locale 指向错误一侧,排查时会去看根本没有问题的那个 locale;
  3. assertKeyParity 只打印前 8 条样本(resources.ts:125),双报会白白占掉一半样本额度;
  4. 插值不一致(interpolation-mismatch,resources.ts:99-110)同样被双报,且两条的 locale 分别是
    两个 locale —— 同一对 key 看起来像是「两边都错」。

当前 main 上键完全对齐(en-US 1487 keys ≡ zh-CN 1487 keys),checkKeyParity() 恒返回空数组,
所以该缺陷只在真正出现差异时暴露 —— 也就是 CI 变红、最需要读数准确的那一刻。

复现

# 1) 制造一处差异:在 packages/i18n/src/locales/zh-CN/navigation.ts 里删掉 `today: '今日',`
bun run i18n:check
# 修复前:i18n:check FAILED — 2 issue(s)   ([missing zh-CN] + [extra zh-CN])
# 修复后:i18n:check FAILED — 1 issue(s)   ([missing zh-CN])

建议修复方向

以 SUPPORTED_LOCALES_FOR_RESOURCES[0] 为基准 locale(reference),只对其余 locale 单向比较,
并把三类 issue 的 locale 统一为「有问题的那一侧」:

  • missing:该 locale 缺少 reference 里存在的键;
  • extra:该 locale 多出 reference 里没有的键;
  • interpolation-mismatch:该 locale 的 {{var}} 集合与 reference 不一致。

这样 issues.length 恰好等于差异处数,locale 语义在三类之间保持一致,同时保留未来增加第三个
locale 时的扩展性。

验证方式

  • 新增 3 条回归用例(一处缺失 / 一处多余 / 一处插值不一致):修复前
    bun test packages/i18n/src/resources.test.ts --isolate = 5 pass / 3 fail(三条均为
    Expected length: 1 / Received length: 2),修复后 = 8 pass / 0 fail;
  • bun test packages/i18n --isolate = 28 pass / 0 fail;
  • bun run i18n:check 在键对齐时输出 i18n:check passed ✅、exit 0;
  • bun run typecheck 五个工作区 exit 0。

Activity

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

Metadata

Metadata

Assignees

Labels

claimedClaimed by a contributor and currently in progress

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions