Uh oh!
There was an error while loading. Please reload this page.
fix(i18n): remove five dead objectView/appDesigner locale keys, add reverse sweep - #4731
Conversation
…everse sweep console.objectView.striped/bordered/virtualScroll and appDesigner.stripedRows/ bordered had no t()/tt() call site anywhere in the repo, in any of the ten packs. The console.objectView three describe grid options objectstack#7176 retired upstream and objectui stopped forwarding in #4649; the appDesigner pair was independently dead by name coincidence only. Adds scripts/check-i18n-dead-keys.mjs, a report-only reverse sweep (pack key set minus referenced key set) that reuses check-i18n-call-site-keys.mjs's own AST walk (extended, not duplicated, to also collect referenced keys/branches/ dynamic-template heads during the same pass) plus a whole-repo text safety net that demotes indirectly-referenced keys to a NEEDS-REVIEW tier instead of false-confirming them dead. Not wired into CI - report-only by design. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnQd8iMMUwXQEV1crFmQiQ
The latest updates on your projects. Learn more about Vercel for GitHub. |
yinlianghui
commented
Aug 15, 2026
Review verdict: ACCEPT (reviewer of record, PM session Verified against this PR, not the report: fifteen changed files; Will flip ready + enable auto-merge once Lint, Type Check, and Test shards 1–4 conclude Generated by Claude Code |
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#4658
What changed
Deleted five locale keys with no
t()/tt()call site anywhere in the repo,from all ten packs (
enplus the nine translations, soall-locales-key-parity.test.tsstays green):console.objectView.striped,console.objectView.bordered,console.objectView.virtualScroll— grid optionsobjectstack#7176retired upstream (maintainer-ruled 2026-08-10) and objectui stopped
declaring/forwarding in
#4649. Dead permanently, not merely dormant.appDesigner.stripedRows,appDesigner.bordered— textually similar nameonly; independently dead. No control in
AppCreationWizard.tsx, no entryin
useDesignerTranslation.ts'sDESIGNER_DEFAULT_TRANSLATIONSfallbackmap, no mention anywhere in the repo outside the locale packs.
Added
scripts/check-i18n-dead-keys.mjs, the reverse-sweep the card askedfor: pack key set minus referenced key set. Report-only — exit 0 always
unless
--strictis passed (nothing calls--strict; not wired into anyworkflow). It reuses
check-i18n-call-site-keys.mjs's own AST walk ratherthan a second parser:
analyze()was extended (not duplicated) to alsocollect, during the same pass that already classifies every call site,
referencedKeys(literal + plural-suffixed),referencedBranches(
returnObjects: trueconsumption), anddynamicHeads(template-key staticprefixes — the call-site gate's own
missing-prefixclass read in reverse).A candidate the AST pass cannot explain also gets a text safety net: one
grep -rFpass over the whole repo (not justpackages/+apps/, which isthe AST walk's scope) for the literal dotted key string, excluding the locale
packs themselves. Zero hits anywhere → CONFIRMED; some hit elsewhere (an
indirect
labelKey: 'foo.bar'property, a doc mention, a test fixture) →NEEDS-REVIEW, not confirmed dead. This is what lets the report tell a
truly-dead key apart from one only the AST pass's own blind spots (calls
outside
packages/+apps/, keys reached through a variable rather than aliteral argument) made look dead.
Premise verification (issue's mechanism assumptions)
confirmed independently three ways: (a)
check-i18n-dead-keys.mjs's ASTpass found no
t()/tt()call site; (b) the text safety net found zerotextual occurrences of any of the five dotted key strings anywhere outside
the locale packs (not even in comments/docs/tests); (c) direct greps for
the bare identifiers (
striped,bordered,virtualScroll,stripedRows) confirm the only non-locale, non-unrelated hits are theobjectql.zod.tscomment documenting the upstream retirement and theblock-config.tscomment documenting the#4649field removal — bothcorroborating evidence, neither a consumer.
check-i18n-call-site-keys.mjs's parsing machinery reused, notduplicated —
analyze()was extended in place; the new script importsanalyze()andcollectEnKeys()directly. The one place a second,independent pass was necessary (the text safety net) is documented as such
in the new script's header, with the specific gap it closes (indirect
references, and
examples//e2e/— measured empty oft()/tt()callstoday, so the AST walk's
packages/+apps/-only scope costs nothing onthis run, but is flagged as a scope note rather than silently matched).
this class — confirmed by reading each gate's own header (already
documented there, cross-checked against behavior):
all-locales-key-parityis pack-vs-pack (full parity on a key nobody wants);
check-i18n-*-keysis call-site-to-
en(asks whether a wanted key exists, never whether anexisting key is wanted);
check-i18n-en-driftfires onenVALUE change(a key that never changes never registers, and removal is explicitly
parity's business per its own output — see the
check:i18n-driftrunbelow).
Sweep report / measured false-positive rate
Run against this PR's tree (
d3d028631): 2927 pack keys, 13776 referenced.626 candidates, 384 CONFIRMED, 242 NEEDS-REVIEW (38.7%) — i.e. a naive
AST-only reverse sweep (no text safety net) would have been wrong about
2 in 5 of its own candidates. That NEEDS-REVIEW rate is this PR's answer to
"is this worth red-ifying yet": no — even with the text safety net, a
CONFIRMED verdict still needs a human before deletion, so
--strictstaysunwired.
Spot-verification beyond the five keys actually deleted here (sampled, not
exhaustive — the full 384 is far bigger than this card's scope):
workflow.*(54/58 confirmed) traces toProcessDesigner.tsx, whichhardcodes English directly and imports no translation hook at all;
publicForm.demo.*(36/36 confirmed) has zero footprint anywhere includingoutside
t()calls. Filed as#4730(unassigned,findinglabel,observation-class) rather than expanded in this PR — out of
#4658'sfive-key scope, and
#4730is not addressed here.Tests
New self-test (
scripts/__tests__/check-i18n-dead-keys.test.ts, 16 tests):positive controls for all three "still live" escape hatches (literal+plural-
suffix,
returnObjectsbranch, dynamic-template head — each must keep a keyOUT of the candidate set), a dead-key positive control (must be CONFIRMED), an
indirect-reference control (must be NEEDS-REVIEW, not CONFIRMED), and the
locale-pack self-reference exclusion (a key's own definition line in
en.tsmust never itself count as a textual hit — the one bug that would silently
empty the CONFIRMED tier entirely; caught during development when an earlier
docstring draft used a real target key as an illustrative example and
self-polluted its own report entry, fixed by not spelling a real candidate
key in the script's own comments).
All gate/test output above and in this body is from the same commit —
git rev-parse --short HEAD=d3d028631, run after the final commit(re-run if this PR gets a post-review push).
Notes
check-i18n-call-site-keys.mjswas extended, not forked:analyze()gained three new Set fields (
referencedKeys,referencedBranches,dynamicHeads), populated inline at the exact points the existing walkalready computes the underlying facts. No existing finding/counter logic
changed — pinned by the pre-existing self-test suite staying green
unmodified (97 tests, same file).
scripts/changes do not need a changeset (check-changeset-presence.mjsconfirms: 10 files under a released package's
src/, 0 under an ignoredpackage —
scripts/isn't under any package'ssrc/at all).--strictexists on the new script deliberately, so a future decision tored-ify this needs no rewrite — just wiring, once
#4730's backlog isworked down enough that CONFIRMED stops meaning "hundreds, mostly
unreviewed."
Generated by Claude Code
Generated by Claude Code