Skip to content

i18n 门禁:en 文案变更时其余九包必须同批跟改(或显式挂账)——#3582/#3625 族缺陷缺的那道不变量 #3650

Description

@yinlianghui

PM 立卡,汇总三处已有记录(#3582 正文、#3625 正文「这可能才是这一族缺陷真正缺的那道门禁」、PR #3627/#3642 正文),避免第四次以散文形态重述。

缺陷族回顾(全部已实测)

两案共同成因:en 改文案的那个 PR 没有同批更新九个译文包,而现有三道门禁(键集合 parity / 调用点 key 守卫 / 棘轮基线)全部只看键集合,对「值的语义漂移」天生失明。#3582「建议 2」的非拉丁包 ASCII 抽查只能抓第一案(英文原文残留),对第二案(地道译文承载废弃语义)同样失明 — #3625 已证明。

缺的不变量

en 某 key 的值在一个 PR 里变了 → 其余九包该 key 的值必须在同一 PR 里也变,或显式挂账。

建议实现(供 dev 测量后定,非结论)

新门禁脚本(如 scripts/check-i18n-en-drift.mjs),CI 上以 merge-base 对比:

  1. 计算本分支相对 origin/main merge-base 的 en 包值变更 key 集合;
  2. 对每个变更 key,要求其余九包同 key 的值也在 diff 中变更;
  3. 否则失败并逐 key 点名 — 除非该 key 出现在挂账文件(如 scripts/i18n-en-drift-baseline.json)里;
  4. 挂账文件本身棘轮化(feat(ci): assert every t() call-site key exists in the en locale pack #3547 同款):只许减不许增,新增挂账须在 PR 里显式改该文件,评审可见;
  5. 落地时挂账清单应为空(console.objectView 的 2 个 key 在 8 个语言包里是英文原文,其中 systemViewReadonly 还是与 en 不一致的旧文案(全部门禁皆绿) #3582/view.readonlyTooltip 在 8 个语言包里译的是「duplicate to customize」这句已废弃语义 —— 因为它是真译文,任何「值是英文」判据都看不见它 #3625 已清,先全量扫一遍确认没有第三案存量 — 有则先清或入账)。

需要斟酌的点(dev 实测后在 PR 里裁,或报回分诊):

  • en 的纯排版修正(标点/空格)是否豁免 — 倾向不豁免,挂账机制本身就是豁免通道,保持规则简单;
  • 脚本对「同批跟改」的判定粒度是 key 级即可,不必比对语义;
  • 该门禁与 all-locales-key-parity 的分工写进两者头注,互相指认。

关联

#3582(第一案)、#3625(第二案)、#3517(defaultValue 掩盖)、#3530/PR #3547(调用点守卫与棘轮先例)、PR #3627/#3642(两案修复 + 单 key 机械化先例:钉 en 字面量)。

Activity

  1. self-assigned this
    on Aug 7, 2026
  2. yinlianghui commented on Aug 7, 2026

    @yinlianghui
    CollaboratorAuthor

    认领(PM 派发,立卡即派)。


    Generated by Claude Code

  3. yinlianghui commented on Aug 7, 2026

    @yinlianghui
    CollaboratorAuthor

    验收 ACCEPT → PR #3659(session_01GTRjn8xBqp75dk7kFupVRt)。en-drift 门禁落地,#3582/#3625 族缺陷的不变量自此有牙。

    已核:CI 17 项 0 失败(Type Check 绿本身即 merge-base 在 CI checkout 下解析成功的证据);预测 (a)-(e) 全中,(d3) 拆三机制的表述修正接受(照单一句会误导读者)。

    裁决记录(全部采纳并记入方法库):

    1. 挂账逐字转写机制:只有做过该改动的人写得出、只豁免那一句、每次运行对 en 现值核对 — 挂账自我过期,(e) 证明不退化成 allowlist。这是挂账类门禁的新标准形态,优于 feat(ci): assert every t() call-site key exists in the en locale pack #3547 的纯棘轮。
    2. 不豁免排版的实测论证:21 commit 历史回放代价为 0;「标点白名单是披正则外衣的语义主张」— 判词收录。
    3. 考古发现:两案肇事 commit 不在本仓(30ac2e1 带漂移整体进仓)→ 门禁不可能被历史验证,植入式语料重建 view.readonlyTooltip 在 8 个语言包里译的是「duplicate to customize」这句已废弃语义 —— 因为它是真译文,任何「值是英文」判据都看不见它 #3625 的 should-have-existed commit — 「落地即绿非空绿」的正面证法收录。
    4. AST 读 git blob + 读不懂即 throw,首跑当场兑现(跨行拼接 key)并折叠钉测;粒度两推论(键集合归 parity、en/zh-only 跳过计数)避免门禁打架。
    5. 新发现 ci-cd-pipeline.md 的 type-check 行漏了 pnpm check:i18n-keys,而 ci-cd-pipeline-doc.test.ts 的钉子按「作业」而非「步骤」判定,看不见这类漏项 #3653 入池(ci-cd-pipeline 文档钉粒度是作业级非步骤级,feat(ci): assert every t() call-site key exists in the en locale pack #3547 欠的一步 + 本单新步骤都漏 — 两账并清另派)。

    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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions