fix(i18n): the drifted detail row mirrors the en pack, and the three defaults maps get a gate (#4401) - #4409
Merged
Merged
Conversation
…maps get a gate (#4401) `DETAIL_DEFAULT_TRANSLATIONS['detail.editFieldsInline']` said 'Edit fields inline' where all ten packs say 'Edit fields', so InlineEditSaveBar's toggle announced two different names depending on whether an I18nProvider was mounted. The pack wins. Generalizes objectui#3440's collaboration-only byte-identity test to the three ungated maps: per-key over the map/pack intersection, not a whole-map toEqual. LIST_ and DESIGNER_DEFAULT_TRANSLATIONS are exported for it, as DETAIL_ and COLLAB_ already were.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
Collaborator
Author
|
ACCEPT — PM 复核 (session
Flipping ready + arming auto-merge. Generated by Claude Code |
yinlianghui
marked this pull request as ready for review
August 12, 2026 04:08
This was referenced Aug 12, 2026
Merged
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 #4401
Both halves of the ruling in the claim comment, implemented as ruled.
1. The pack wins — the drifted row
DETAIL_DEFAULT_TRANSLATIONS['detail.editFieldsInline']saidEdit fields inlinewhere the
enpack saysEdit fields, soInlineEditSaveBar's toggle announced twodifferent names for one control: the map's on a provider-less host (standalone embeds,
the preview gallery, this package's own unit tests), the pack's in the console.
Byte-identity verified by evaluating the pack and comparing codepoints, per #4402's
method — the gate's own failure message carries them:
No pack files were touched, so the nine other locales keep their existing translations
of "Edit fields" and
check:i18n-driftreports 0 changedenvalues.Nothing pinned the old string:
git grep "Edit fields inline"found only the map rowand the call site (
InlineEditSaveBar.tsx:281,aria-label={t('detail.editFieldsInline')}).No test pins moved.
2. Generalize the gate — the three ungated maps
New suite:
packages/app-shell/src/__tests__/defaults-maps-mirror-en-pack.test.tsx,12 cases covering all three maps.
Why app-shell is the home. It cannot live in
@object-ui/i18n: every map's packagedepends on that one, so importing a map back into it inverts the dependency — the exact
reason
gantt-count-interpolation-4157.test.tsgives for assertingenvalues asliterals rather than importing
plugin-gantt.app-shellis the package that dependson all three plugins and on
@object-ui/i18n, it already hosts a cross-packageparity gate (
__tests__/spec-symbol-parity.test.ts), and it already imports a defaultsmap through a plugin barrel (
views/RecordDetailView.feedRecordScope.test.tsximports
DETAIL_DEFAULT_TRANSLATIONS). So the maps are read, not parsed out of sourcetext.
LIST_DEFAULT_TRANSLATIONSandDESIGNER_DEFAULT_TRANSLATIONSare exported for it, asDETAIL_DEFAULT_TRANSLATIONSandCOLLAB_DEFAULT_TRANSLATIONSalready were — thismakes the four maps consistent rather than introducing a new convention.
Shape. Per-key over the
map ∩ packintersection, never a whole-maptoEqual:#3440 could compare a whole namespace because the collaboration map is a namespace
slice, while these three borrow rows from other namespaces and are deliberate subsets
of their own.
The exceptions, graded on measurement — none of them exempts a row
common.resizeDrawer(detail),table.search/table.rowsPerPage(list),common.cancel/back/next/close/edit/delete(designer)enpackdetail.showEmptyRelated{,_one,_other}fallbackTindexesdefaults[key]literally, so only the base row is reachable; the suffixed rows exist so the map's key set mirrors the packs') is a claim about keys, so it is enforced as oneNon-vacuity (#4118 family standard): each map asserts rows exist, that named
sentinel rows are present (including
detail.editFieldsInlineitself and #4294'slist.sortRelationalHint), and that the compared intersection is non-empty — thelast one catches a pack rename that empties the intersection while the rows stay put.
Pre-fix red — direction predicted before running
Predicted in the suite's docblock before the first run: restoring the row turns exactly
one case red, naming that key and nothing else; the list and designer maps, both
absence cases, both non-vacuity cases and the exception cases stay green.
Observed against the unfixed tree — 1 failed / 12, and the drift list has exactly
one entry:
Reverse verification was re-run commit-then-revert (never
git stash— the stack isshared across worktrees) with the same prediction and the same result; restoring the
fix returns 12/12.
No extra drift. The card's 1-in-372 measurement reproduced exactly: rows
148 / 59 / 165, drifted 1 / 0 / 0, key-absent-from-pack 0 / 0 / 0.
3. The falsified comment
LIST_DEFAULT_TRANSLATIONS' #4294 note said "No gate compares this table toen".This PR makes that false, so it now names the new suite — while keeping the part that
is still true (that
check:i18n-keysjudges inlinet(key, { defaultValue })optionsand never a
createSafeTranslationtable; it is simply no longer the only thinglooking). All three maps' docblocks now state the byte-identity contract and point at
the gate.
Interaction with #4392, which landed mid-flight
origin/mainmoved during the work and was merged in; it carried #4392 (retiringcommon.searchfrom the packs) and #4394's newcheck:phantom-depsgate.common.search: none of the three maps has a row for that key, so theintersection is unaffected. The gate was re-run against the post-merge pack.
check:phantom-deps: the new suite's three plugin imports are already declared byapp-shell'spackage.json; the gate passes.Verification
packages/collaboration's #3440 suite is untouched and green in the run above.Type-check needed the dependency closure built first in a fresh worktree
(
pnpm --filter '...^...' build) — the same fresh-worktree artifact trap #4402 hit, nota defect. Control-byte self-scan beyond the gate over all seven touched files: clean.
Changeset:
.changeset/map-pack-mirror-gate-4401.md, patch on the three pluginpackages (user-visible: the provider-less label loses one word). Never
major, perAGENTS.md's version-alignment rule.
Out of scope
None. No unrelated defect was tripped over; the measurement that would have produced one
(rows whose key the pack lacks) came back 0 across all three maps.
Generated by Claude Code