fix(i18n): 回填 perm + home 两命名空间 14 个缺失语言 key,十包补齐(#3546 切片六) - #3868
Merged
Conversation
Fixes-part-of: #3546 守卫 scripts/check-i18n-call-site-keys.mjs 实测:14 个不重复 key / 14 个调用点 (1:1,无一 key 多站点),分别落在 PermissionFacetLink(权限集授权面只读摘要 + Studio 深链,ADR-0056 P1)9 处与 usePublishAllDrafts(ADR-0038 L3 探针健康、 示例数据健康、ADR-0066 ⑨ 能力引用巡检)5 处。这两个命名空间不含 missing-prefix 家族,棘轮 missingPrefixes 保持 2 条不动。 英文一字未改:9 处静态 defaultValue 与 en 逐字节相同(9/9);另外 4 个计数标签的 defaultValue 是带英文单复数分支的模板串,改用 i18next 复数族后逐个计数渲染结果与 模板串一致(en 在 count 1/2/3/5/11/21/100 上全等)。 复数族刻意写成 key + key_one 而非 _one/_other:i18next 只按语言 CLDR 类别取一个 后缀,取不到就沿 fallbackLng 落到 en。ru(few 2-4、many 5-20)与 ar(two、 few 3-10、many 11-99)会因此在用户最先遇到的计数上显示英文;基础 key 让这些类别 落回本语言。ru 基础值取该包已用 25 次的「名词: {{count}}」写法,ar 取该包的 「{{count}} 单数(复数)」写法。 九包译文逐包取邻键证据(zh 取自本仓权限集设计器同一张表的 个对象/行级策略/ 标签页/委派管理范围;de 区分 Registerkarte 与浏览器 Tab;fr 直角撇号与冒号前空格; ru ё;ar 动作箭头保留 →)。4 处 en 同串直接复用邻键既有译文(list.none / calendar.moreEvents / topbar.designInStudio / console.ai.seedWarn)。 棘轮 31 → 17(恰减 14,按行删除);四个既有 3546 家族测试的总数钉子同步同降一次。
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Collaborator
Author
|
修订记录
值一字未改,所以正文里的分母、9/9、18 个新增路径、棘轮 31 → 17、四方向反向验证与全部验证读数均不受影响;改正后复跑本切片测试仍 Generated by Claude Code |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
Collaborator
Author
|
✅ 验收(PM,session 实物核验:头 裁定要点:
转 ready 并挂 auto-merge。#3546 棘轮余 17 key + 2 前缀,切片七候选(gantt.linkEnd. / organization.invitations.status. 前缀族等)待本片落 main 后排。越界 #3863/#3865/#3866 与 #3810/#3845 追评归分诊席。 Generated by Claude Code |
yinlianghui
marked this pull request as ready for review
August 8, 2026 22:40
This was referenced Aug 8, 2026
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.
Fixes-part-of: #3546— 切片六。本单不关闭 #3546:回填后仍余 17 个缺失 key + 2 个整族缺失前缀。分支自
origin/main@993336f7c显式 sha 切出(main其后前进五个提交,含 #3849;与本围栏零文件相交,已实测,见文末)。分母:脚本实测,不手数
node scripts/check-i18n-call-site-keys.mjs(#3530 的守卫)的analyze()实测:perm9 +home5)missing-prefix_one伴生)守卫读数,前后对照(同一命令):
解析数 +14(= 14 个调用点)、en key 数 +18(14 + 4 个
_one),与清单精确相等。棘轮 ASSERT:棘轮按行删除而非重序列化(切片四量过:重序列化会把 diff 变成全文件重排)。最终 diff:
14 deletions(-),零插入。严重度:全部是「英文可见、十语不可译」
14 处全部带内联
defaultValue,无一渲染裸 key(那类由切片一 PR #3583 收)。两个现场:PermissionFacetLink,ADR-0056 P1 —— Setup 只读展示 + 深链进 Studio 的结构化编辑器):空面的None、系统能力芯片溢出的+3 more、四个计数标签(3 objects/2 field rules/1 RLS policy/4 tab rules)、Delegated admin configured,以及深链本身的Design in Studio →与无 app 上下文时的灰态Design in Studio。usePublishAllDrafts,Home 待发布横幅与 ADR-0037 草稿预览条共用同一条治理路径):Nothing to publish.、ADR-0038 L3 探针发现问题的Published, but verification found problems.、示例数据未加载的Published, but some sample data failed to load.、带计数的Published & verified — 12 sample row(s) live.,以及 ADR-0066 ⑨ 能力引用巡检的Authoring check: 2 capability reference(s) resolve nowhere.en ↔ 内联 defaultValue:9/9 逐字节相同,另 5 处结构上不可能
无 defaultValue 的站点:0 处 —— 本切片不需要从组件语境取文案。
余下 5 处的
defaultValue是模板串:逐字节比对对模板串结构上不可能(切片五在
marketplace.org.installed上撞过同一面墙),但这次取到的等价关系更强:测试把模板串按 JS 的语义在count = 1/2/3/5/11/21/100上各渲染一遍,与包路径的输出逐个相等。也就是说英文渲染文本一字未变,只是换成 i18next 来插值和选形。模板串一移动,断言先红(expect(src).toContain(...)钉住原文)。check-i18n-en-drift.mjs独立复核了同一件事:0 en value(s) changed (18 key(s) added, 0 removed)。复数族刻意带基础 key,而不是只写
_one/_other四个计数标签需要两种英文形态,所以是 i18next 复数族。形状取
key+key_one,不是惯用的key_one+key_other,依据是实测行为而非口味:十包各自只有
_one/_other时的实测(装好的 i18next 26.3.6,与本仓createI18n配置一致,无compatibilityJSON):ru 的
few(2-4)与many(5-20)、ar 的two/few(3-10)/many(11-99) —— 恰好是用户最先遇到的计数。而给 ru 补_few/_many会被all-locales-key-parity判成"有 en 没有的 key"(该测试的不变量正是十包键名集合相同),所以那条路要先改一道共享门禁。基础 key 是不用改门禁的那条路:i18next 的查找链里基础 key 始终在列,任何未枚举的类别都落到它,留在本语言:
十语 × counts
1/2/3/5/11/21/100全量渲染断言(用Intl.PluralRules.select()预测该由哪个槽位作答,与 i18next 同一个解析器),外加 ru/ar 具名的五个未枚举槽位。detail.showEmptyRelated_one/_other没有基础 key,因此今天就有这个英文泄漏(ru 在 2-4/5-20、ar 在 2-99)。已立 #3863,含实测表与照搬本切片形状的修法;detail命名空间的欠账属后续切片,本 PR 未动。九包实译:逐包邻键取证
perm.stat.objectsSuffix=个对象、perm.rls.empty=暂无行级策略。、perm.tabs.title=标签页可见性、perm.admin.title=委派管理范围、perm.cap.none的能力—— 正是这个芯片点进去的那个界面;home.pendingDrafts.message用你与——{{count}} 个对象、已配置委派管理范围、编写检查:{{count}} 个能力引用无法解析。、已发布并验证 —— {{count}} 行示例数据已生效。appDesigner.objectManager.fieldCount={{count}} フィールド的「{{count}} + 単位」形;console.objectView.addRule=ルールを追加(rule = ルール);中間コロンは後続が単一トークンなら半角(AI 使用状況: {{status}})、日本語の文なら全角(現在の承認待ち:{{who}}。)—— 24:28 の条件式{{count}} フィールドルール、作成時チェック:…、公開するものはありません。fieldCountko ={{count}}개 필드;appDesigner.objects=오브젝트;全包 0 处全角冒号{{count}}개 오브젝트、작성 검사: …、Studio에서 디자인 →Registerkarte(console.objectView.ufTabs,4 处),Tab专留给浏览器页签(detail.openInNewTab,4 处);managedByBadge.systemWritable.body的delegierte Administration{{count}} Registerkarten-Regeln、Delegierte Administration konfiguriertadministration déléguée{{count}} règles d'onglet、Contrôle de conception : …home.pendingDrafts.*一致 usted;(s)记法随同族message(cambio(s)){{count}} fila(s) de ejemplo activa(s).、Administración delegada configuradamessage=alteração(ões) não publicada(s){{count}} linha(s) de exemplo ativa(s).、{{count}} regras de abalookup.recordCount=Записей: {{count}}、notifications.groupCount、approvalsInbox.bulkApproved…),且对任何俄语数字都正确 —— 正因如此基础 key 才能覆盖 few/many;ё 正字法(161 处)Объектов: {{count}}、Политик RLS: {{count}}、+{{count}} ещё、Публиковать нечего.fieldCount={{count}} حقل(حقول)、table.modified);动作链接的尾箭头保留→(marketplace.browseLink十包 10/10),与该包 3 处把行内左右映射镜像成←的情形区分开{{count}} كائن(كائنات)、التصميم في Studio →en 相同的字符串一律复用邻键既有译文而不另造,4 对,双向钉住(先验证两边 en 真的同字符串,再验证十包同值):
perm.facet.none←list.none;perm.facet.more←calendar.moreEvents(同为「+N more」溢出芯片,en 逐字节相同);perm.facet.designInStudioHint←topbar.designInStudio,且designInStudio= 该值 +→(十包统一按此构造);home.pendingDrafts.seedWarn←console.ai.seedWarn(AiChatPage.tsx:2152,同一句英文)。一处刻意不复用,也有断言:
console.ai.designBuiltApp的 en 同为Design in Studio,但 zh/de/ru 早已按语境分开译(zh进入 Studio 继续完善—— agent 刚建好应用后"继续完善"),本切片这条是普通导航标签,取topbar.designInStudio。这不是缺陷(两个 key 存在的意义就是可以分开),故未立单,只在测试里写明。按概念找邻键(切片五教训)已按新规执行:
RLS policies/field rules这类词在 en 里逐字节搜不到邻键,是按概念找到了设计器同一张表与fieldCount。另需说明两处确实没有仓内邻键、属新造词的:Authoring check与capability(九包一个都没有;仅 zh 有依据 —— 设计器表的能力/必需能力)。这两处的措辞在 PR 里点名,便于 review 直接推翻。反抄袭断言:精确集合是空集,靠三条防空转顶住
实测"与 en 逐字节相同"的
lang :: key对:0 / 162(十包 18 路径)。本切片确实没有一个合法同形词。空集是最容易空转的形状(切片二 B1 的教训),所以配三条:it.each);{{count}} RLS-Richtlinien、fr{{count}} politiques RLS、jaStudio でデザイン →、de 的Capability-Verweis(e);另加本切片特有的形状断言:插值恰 11 个路径带
{{count}}(按 key 具名列出,其余一律不许有洞);尾箭头十包镜像 en 且designInStudioHint不许有箭头;&只出现在 en(九包各自改写);em dash 十包为—、zh 为该包自己的——;(s)记法只出现在 de/fr/es/pt(zh/ja/ko/ru 不许引入),且该断言的正则是/\([\p{L}]{1,4}\)/u并自带反例说明为什么不能用 ASCII\w(见下 #3866)。provider-mounted 抽样钉扎(discrimination check)
usePublishAllDrafts的t由useObjectTranslation()传入(HomePage 与 DraftPreviewBar 两个调用方都断言了);PermissionFacetLink经useDetailTranslation,挂 provider 时该 hook 交出 i18next 的t—— 这就是 console 的路径。这两条前提本身也断言了(读源码),而不是假设。en/zh各解析 6 个代表 key(每个 owner 一个),断言not.toBe(key)且等于包内值;4 个对象、已发布并验证 —— 12 行示例数据已生效。);RLS/Studio两个不可避免的拉丁串都留在句中;反向验证:四处方向跑前先判,四处全中
GUARD EXIT=1;总数钉子红:en.ts(棘轮保持已删)→ 守卫报 14 条 unexpected / 14 distinct,GUARD EXIT=1,解析数回落 2297 → 2283;parity 九包各报has 18 key(s) absent from en。zh.ts(en 保留)→ 守卫仍然绿(它只看 en),parity 与本切片测试红,失败文本就是把藏了这些 key 数月的机制摆出来 —— zh 缺 key 时t()返回的是 en 的值,不是 key、不报错:_one保留)—— 本切片特有的一条,方向预判为"parity 红 + 渲染断言红且实际值是英文",命中:顺手量出、未在本 PR 修的事
detail.showEmptyRelated的复数族缺基础 key,ru 在 2-4/5-20、ar 在 2-99 渲染英文;调用点record-reference-rail.tsx:350的 count 恰是 2-4 最常见。含十语实测表与修法。createSafeTranslation的无 provider 兜底fallbackT读的是defaults[key] || key,从不读调用点的defaultValue(它只被当成一次{{defaultValue}}替换),所以表里没有的 key 在独立嵌入宿主上渲染 raw key。useDetailTranslation一个 hook 实测:146 条表 / 16 个 key 不在表内(9 个perm.facet.*+ 7 个detail.*,其中 4 个包里已有值 —— 与"缺 key"无关)。这是 258 个 t() 调用点引用的 key 在任何语言包里都不存在(#3530 守卫首跑实测),其中 8 处直接把 raw key 渲染给用户 #3546 正文那个陷阱的镜像方向:正文是"表里有、包里没有 → 真实 console 露 key,无 provider 单测绿";这里是"表里没有 → 无 provider 露 key,挂 provider 的单测绿"。本 PR 因此零组件改动:补那张表会新增一个与包并列的真源,与本单的方向相反。\w,所以 ru 的结论(0 处)是错的(实为 13 处),同一写法的断言对全部非拉丁语言包空转 #3866(新立,finding) — PR fix(i18n): 回填 marketplace + preview 两命名空间 37 个缺失语言 key 及 marketplace.disclosure.runtime. 前缀家族,十包补齐 (#3546 切片五) #3847 的「括号复数记法」普查用了 ASCII\w,ru 的结论(0 处)是错的(实为 13 处,含fieldCount={{count}} поле(й)),且marketplace-preview-namespace-3546.test.tsx里同一写法的断言对 zh/ja/ko/ru/ar 五个包恒为 false(空转)。不影响该 PR 的落值,影响后续切片的取证方法;本切片已改用\p{L}+u并把反例钉进测试。perm.*/home.*全部 153 个调用点(14 文件,不只本切片的 14 个)的普查:53 个带字面量 defaultValue,49/53 与 en 一致,4 处分歧(全在HomePage.tsx,全是已存在的 key;home.welcome包值Build your business system with AI/ 死句Welcome to {{product}})。死兜底t(key) || …/?? …:0 处。另把 (2) 的机制交给该单的选项 C 作前提。home.welcome是休眠参数的第二个实例,并且说明该单的检测判据缺了一半:它按"参数名 vsdefaultValue的洞"判定,而这一处defaultValue有洞、en 包值没有 —— key 存在时包值才是渲染的东西。建议判据分两段,该单"1 / 1055"的分母只覆盖了第一段。验证
all-locales-key-parity.test.ts含在上面 32 个文件内,已绿(它是补完 en 后立刻要求九包补齐的那道门禁)。@object-ui/i18n无工作区内依赖,自身不需要先建依赖;@object-ui/react的TranslationKeys = typeof en只是转出口,加 key 不窄化任何消费方 —— 全仓 turbo type-check 已实跑覆盖。测试命令按 AGENTS.md §9 的唯一正确写法(仓根
pnpm exec vitest run加相对仓根的路径),不用pnpm --filter 包名 test;--workspace-concurrency一律在--filter之前。围栏
17 文件:
packages/i18n/src/locales/*.ts(十包,仅新增本切片 18 个路径)、scripts/i18n-call-site-key-baseline.json(仅删本切片 14 行)、packages/i18n/src/__tests__/perm-home-namespace-3546.test.tsx(新增,49 条)、auth-+console-+marketplace-preview-+organization-namespace-3546.test.tsx(仅棘轮总数 31 → 17 —— 那个计数器每切片动一次且只降;missingPrefixes钉子保持 2 条不动,本切片不含前缀家族)、changeset(@object-ui/i18npatch)。零组件改动(本切片 key 的死兜底量出为 0)。与在飞 #3827(packages/cli)零相交;
main在分支点后落地的五个提交(#3849 / #3749 / #3738 / #3737 / #3827)与本围栏实测零文件相交 —— #3849 动的是packages/components/src/renderers/action/**与plugin-detail/src/renderers/record-quick-actions.tsx,本 PR 对 plugin-detail 只有测试里的读取(PermissionFacetLink.tsx/useDetailTranslation.ts),两者都不在其围栏内。未动content/docs/releases/**。Generated by Claude Code