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.

detail.showEmptyRelated 的复数族只有 _one/_other,没有基础 key —— ru 在 2-4/5-20、ar 在 2-99 直接渲染英文 #3863

Closed

Description

@yinlianghui

在 #3546 切片六(PR 回填 perm + home 14 个缺失 key)顺手量出,不在该 PR 围栏内(detail 命名空间的欠账属后续切片),单独记录。

缺陷

detail.showEmptyRelated 是本仓唯一一个既有的 i18next 复数族,十个包各自只定义两个槽位:

packages/i18n/src/locales/ru.ts   showEmptyRelated_one:   "+ {{count}} пустое"
                                  showEmptyRelated_other: "+ {{count}} пустых"

i18next 只向 Intl.PluralRules 要该语言该数字对应的那一个后缀,取不到就沿 fallbackLng 链走到 en。而 ru 的类别是 one / few / many / other,ar 是 zero / one / two / few / many / other —— 包里都没有 _few / _many / _two / _zero,于是:

语言 count CLDR 类别 实际渲染
ru 1、21、31… one + 1 пустое ✅
ru 2、3、4 few + 3 empty(英文)
ru 5–20、25–30… many + 7 empty(英文)
ar 1 one + 1 فارغ ✅
ar 2 two + 2 empty
ar 3–10 few + 5 empty
ar 11–99 many + 30 empty
fr/es/pt ≥ 1e6 many 英文(实务上够不到)
en/de 全部 one/other ✅
zh/ja/ko 全部 仅 other ✅

调用点是 record-reference-rail.tsx:350 的「+N empty」折叠按钮,count = emptyTitles.length —— 2 到 4 是最常见的取值,所以俄语用户几乎总看到英文。

实测(装好的 i18next 26.3.6,十包各自都有 _one/_other,与本仓 createI18n 的配置一致 —— 无 compatibilityJSON):

ru  0:EN_OTHER  1:RU_ONE  2:EN_OTHER  3:EN_OTHER  5:EN_OTHER  11:EN_OTHER  100:EN_OTHER
ar  0:EN_OTHER  1:AR_ONE  2:EN_OTHER  3:EN_OTHER  11:EN_OTHER  100:AR_OTHER

为什么三道门禁都看不见

这是 #3582 / #3625 / #3810 之后的又一个值域盲区,机制不同:键名集合正确、包际一致,坏在该语言需要的那个槽位不在集合里,而 parity 的设计前提正是"十包键名必须相同"—— 给 ru 补 _few/_many 会让 parity 判它"有 en 没有的 key"。

修法(#3546 切片六已在新 key 上采用,可直接照搬)

在 _one 之外定义基础 key(无后缀)作为兜底槽位:i18next 的查找链里基础 key 始终在列,所以任何未枚举的类别都落到它,留在本语言而不是掉到英文。实测:

ru  flat + _one + _other → count 3 命中 flat("RU both-flat 3"),不再是 EN

切片六的 perm.facet.objects / fields / rls / tabs 就是这个形状(key + key_one),ru 的基础值取该包已用 25 次的「名词: {{count}}」写法(Записей: {{count}} 等),对任何俄语数字都正确;ar 取该包的「{{count}} 单数(复数)」写法。packages/i18n/src/__tests__/perm-home-namespace-3546.test.tsx 里有十语 × counts 1/2/3/5/11/21/100 的全量渲染断言,反向验证(删掉 ru 基础 key)的失败文本正是本单的证据:

AssertionError: expected '3 objects' to be 'Объектов: 3'

所以本单的修复 = 给 detail.showEmptyRelated 十包各加一个基础 key(ru/ar 用计数不变的写法),并考虑把"复数族必须带基础 key"写成一条断言/门禁 —— 否则下一个复数族会重犯。

关联:#3546(切片六在新 key 上确立了基础 key 形状)、#3530(调用点守卫,PLURAL_SUFFIXES 判定)、#3650、#3810。

Activity

  1. os-zhuang commented on Aug 8, 2026

    @os-zhuang
    Contributor

    Triage: pm:queue (in-repo objectui card — no routing label by design).

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. self-assigned this
    on Aug 11, 2026
  3. yinlianghui commented on Aug 11, 2026

    @yinlianghui
    ContributorAuthor

    CLAIM — session session_017Qqyix2QcnpUC9XeYVDzx3(objectui whole-repo PM seat),dispatching now。Branch: claude/issue-3863-plural-base-key。

    按卡片 + triage 执行:给 detail.showEmptyRelated 十包各加基础 key(#3546 切片6 的既定形状:ru 用该包已用 25 次的「名词: {{count}}」计数不变写法,ar 用「{{count}} 单数(复数)」写法,其余包按各自惯例),en defaults 表同步;同 PR 落"复数族必须带基础 key"的门禁断言(卡片提案、triage 认可——否则下一个复数族重犯);十语 × 多 count 渲染断言照切片6 模板,反向验证删 ru 基础 key 复现卡片的失败文本。#3865 是同 hook 异缺陷(cross-linked,无文件重叠),不并入。locales 面自由(#4294/#4307 已落)。


    Generated by Claude Code

  4. added a commit that references this issue on Aug 11, 2026
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