Uh oh!
There was an error while loading. Please reload this page.
fix(i18n): define home.recentApps.itemType.report and .metadata in all ten packs - #6163
Merged
Merged
Conversation
…l ten packs RecentItem['type'] is a six-member union and useTrackRouteAsRecent writes both `metadata` (:105) and `report` (:148) at runtime, but the packs defined only four of the six. Ten packs missing the same member identically is full parity, so no pack-vs-pack gate saw it, and the three consumers' inline defaultValue rendered a plausible English word rather than a raw key -- objectui#3517's mechanism for hiding a missing key for months. The nine translations reuse each pack's own existing rendering of the same word (appDesigner.navReport / search.badgeReport for `Report`, layout.metadata.label for `Metadata`) rather than newly composed copy. Clears the two matching `missingMembers` entries in the call-site key baseline; that list is a ratchet, so a baselined entry whose defect is gone fails too. The baseline `note` is untouched: its `BOTH LISTS ARE NOW EMPTY` sentinel is scoped to the missingKeys/missingPrefixes pair and is asserted elsewhere. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019b5UBNMtTzKbVtZZGvFuxe
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
This was referenced Aug 24, 2026
yinlianghui-tw
marked this pull request as ready for review
August 24, 2026 22:13
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 24, 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 freeto 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#6023
All ten locale packs now define
home.recentApps.itemType.reportandhome.recentApps.itemType.metadata, and the two matchingmissingMembersentries inscripts/i18n-call-site-key-baseline.jsonare cleared.Verified at
cd8d6594d.Premise re-verified, not inherited
The card rules out narrowing
RecentItem['type'], and that ruling-out holds. Both membersare written at runtime, in
packages/app-shell/src/hooks/useTrackRouteAsRecent.ts:The union at
packages/app-shell/src/context/RecentItemsProvider.tsx:47is unchanged.Narrowing it would have shrunk the check rather than paid off the debt — the exact
resolution the gate's own hint text warns against.
The nine translations were found, not composed
Every pack already renders both words, so nothing was invented for any locale. Sources:
Reportcarried byappDesigner.navReport,appDesigner.navTypeReportandsearch.badgeReport(that last one is the closestanalogue: a type badge on a search result).
Metadatacarried bylayout.metadata.label, the nav entry for thesame
/metadata/...surface these recent items point at.One judgement call, zh
report. The pack is not unanimous: 12 uses of报表against 1of
报告(console.breadcrumb.reports). Five of the six report-valued keys, including allthree singular ones, read
报表, so报表is what the pack says. The lone报告outlier isnoted here rather than touched — out of scope for this card.
Register and capitalisation follow each pack's own four existing
itemTypemembers ratherthan English title case; the found values already matched (capitalised in de/es/fr/pt/ru,
caseless in ar/ja/ko/zh), so no case was adjusted.
Verification
The ratchet does work — the ablation pair. Keys added and baseline cleared, the gate is
green. With the two
enlines deleted and the baseline still cleared, it reddens and namesboth members. The mutation was confirmed on disk before the result was read (grep count on
each anchor line went 1 to 0, and the
itemTypeblock was printed back), and the restoreleg ran under a trap, verified clean by
git status.pnpm check:i18n-keys(fixed state) — exit0, its own verdict line:Every in-scope call-site key resolves against the en pack (2822 keys), … and every dynamic key family either checks its members against a declared vocabulary or says in writing why it has none.— with18 with a static vocabulary (112 member key(s) checked exactly).pnpm check:i18n-keys(ablated state) — exit1:2 dynamic-family findings — the head resolves, so the prefix rule is satisfied; these are about the MEMBERS behind it:followed byHomeRail.tsx:251:21 [missing-member] home.recentApps.itemType.metadataandHomeRail.tsx:251:21 [missing-member] home.recentApps.itemType.report.pnpm vitest run packages/i18n/src/__tests__(root vitest, never package-scoped) —exit
0,Test Files 54 passed (54)/Tests 898 passed (898). All ten packs passall-locales-key-parity.test.tsindividually:zh|ja|ko|de|fr|es|pt|ru|ar defines every en keyplus… defines no key that en lacks, andplaceholders match en in every pack.pnpm check:i18n-drift— exit0:Compared the ten locale packs at 7797e3b74 (merge-base with origin/main) with the working tree: 0 en value(s) changed (2 key(s) added, 0 removed …).node scripts/check-changeset-presence.mjs— exit0:✅ 10 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s).pnpm changeset:check— exit0,✅ No changeset declares a major bump.node scripts/check-control-bytes.mjs— exit0,✅ check-control-bytes: OK (scanned 5098 tracked text file(s); skipped 85 binary).pnpm turbo run type-check --filter=@object-ui/i18n— exit0,Tasks: 4 successful, 4 total.pnpm check:i18n-dead-keys— a report, not a gate; neither new key appears in it (bothare dynamic-template-reachable).
Every exit code above was captured before any pipe (redirect to a file, then read the
file), and each line quoted is the gate's own, not a bare
$?.Lint was narrowed, and here is why the narrowing is a measurement. eslint ran over the
ten changed
.tsfiles rather than the repo. (1) The universe comes from eslint's ownconfig, not a guess: run against the other two changed paths, eslint reports
File ignored because no matching configuration was supplied.for bothscripts/i18n-call-site-key-baseline.jsonand the changeset
.md, so the diff's lintable set is exactly those ten files. (2) Thecount comes from
--format json:files eslint actually linted: 10,errors: 0 warnings: 0, exit0. (3)eslint.config.jsenables no type-aware linting — itslanguageOptionscarries onlyecmaVersionandglobals, with noprojectorprojectService— so no untouched file's verdict can move because of this diff. CI runsthe full farm regardless.
Two things reported, not fixed
HomeRail.tsx:251falls back to the bare lowercaseit.typewhileRecentApps.tsx:55and
StarredApps.tsx:61both passcapitalizeFirst(item.type). Once these keys exist thefallback stops firing for
reportandmetadata, so it is moot for them — but it stayswrong for any future member, and it is the reason the English rail read
reportwhere thecards read
Report. Out of scope here; flagged for the PM to decide whether it wants acard.
The baseline
notewas left exactly as it is, per the standing instruction. Reportingone consequence rather than acting on it: the note's sentence
missingMembers is a THIRD list (objectui#4964), NOT part of that pair and NOT emptynowhas a stale clause, because this change takes
missingMembersto zero. The load-bearinghalf is untouched and still true — the
BOTH LISTS ARE NOW EMPTYsentinel is scoped to themissingKeys+missingPrefixespair, andresidue-namespaces-3546.test.tsx'sthe ratchet is empty — this is the terminal state, not a partial onepasses. Not edited;the PM decides.
Generated by Claude Code