Skip to content

detail.editFieldsInline renders two different labels depending on whether an I18nProvider is mounted — the defaults map says "Edit fields inline", the en pack says "Edit fields" #4401

Description

@yinlianghui

Found while implementing #4396 (adding six missing rows to the same maps). Not fixed there: #4396's scope is adding rows, and this is an existing row whose value disagrees with the pack.

The measurement

DETAIL_DEFAULT_TRANSLATIONS (packages/plugin-detail/src/useDetailTranslation.ts) is the value createSafeTranslation's fallback serves when no provider is mounted; the en pack is what i18next serves when one is. For one key they disagree:

key defaults map en pack
detail.editFieldsInline Edit fields inline Edit fields

So the same control is labelled "Edit fields inline" on a provider-less host (standalone embedding, the preview gallery, this package's own unit tests) and "Edit fields" in the console. Each path looks correct on its own, which is why no test catches it.

Scope — this is the only one

Scanned all three maps that #4396 touched, source rows against the evaluated pack:

plugin-detail  DETAIL_DEFAULT_TRANSLATIONS    rows 148  drifted 1  key-absent-from-pack 0
plugin-list    LIST_DEFAULT_TRANSLATIONS      rows  59  drifted 0  key-absent-from-pack 0
plugin-designer DESIGNER_DEFAULT_TRANSLATIONS rows 165  drifted 0  key-absent-from-pack 0

One drifted row in 372. The maps are in much better shape than the absence of a gate would suggest — which is the argument for pinning it now rather than letting it grow.

Why nothing catches it

Each map's docblock states the byte-identity contract; for these three nothing enforces it.

Two things to decide, hence no PR attached

  1. Which side is right. "Edit fields inline" (map) vs "Edit fields" (pack) is a copy decision, not a mechanical one — and if the pack wins, nine other locale packs already carry translations of "Edit fields" and stay as they are.
  2. Whether to generalize the gate. Extending the [i18n] PresenceAvatars 三处硬编码英文(控制台头部与记录详情实际在渲染) #3440 test's shape to these three maps is cheap now that the measured drift is 1. It would have to allow the deliberate exceptions the maps already carry (borrowed common.* rows, and plugin-detail's showEmptyRelated suffixed rows kept to mirror the packs' key set — see the comment at useDetailTranslation.ts), so it is a per-key comparison over the intersection, not a whole-map toEqual.

Related: #4396 (the six missing rows, same maps), #3440 (byte-identity precedent, collaboration only), #4294 (pinned list.sortRelationalHint byte-for-byte by hand for exactly this reason), #3865 / PR #4372 (the census that surfaced the family).


Generated by Claude Code

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions