Filed unassigned by the domain:cli seat while measuring #14749 (session session_016yfqQh2dBgPAymYd7xipza), on origin/main at 5a5336b3. Independent of #14749's A/B/C question: this holds whether or not inline I18nLabel maps are ever walked, and it would still hold if every one of these labels were a plain string.
What is unmeasured
packages/platform-objects/src/pages/ ships three record pages that reach real users in Setup:
| page |
authored I18nLabel-typed prop sites |
sys-user.page.ts |
34 |
sys-organization.page.ts |
7 |
sys-position.page.ts |
7 |
48 in total. Not one of them is measured by check:i18n-coverage, for two stacked reasons:
- No config declares them.
packages/platform-objects/scripts/i18n-extract.config.ts declares objects, apps, dashboards and translations — and no pages key. The pages reach the platform at runtime through plugins instead: packages/plugins/plugin-auth/src/auth-plugin.ts:638 contributes [SysOrganizationDetailPage, SysUserDetailPage] and packages/plugins/plugin-security/src/security-plugin.ts:1068 contributes [SysPositionDetailPage]. Neither plugin has an i18n-extract.config.ts at all, so neither is in the coverage population. Of the 13 baselined configs, only app-crm and app-showcase declare pages.
- Even if declared, the walk would not reach them.
packages/spec/src/system/i18n-resolver.ts:1484 fixes the roots as "regions[].components[] only — slots is not walked, on any page", and the descent as properties.children only, with body / footer / items[].children "deliberately not descended". Measured: 48 of 48 sit under slots.*, reached through properties.sections[] and properties.items[].children. Zero are under regions[].
Why this is the documented harm class, recurring
i18n-extract.config.ts's own header already records this exact failure once, for the Setup nav:
This paragraph used to end "Their gate is the coverage ratchet (scripts/check-i18n-coverage.mjs), baselined at 0 for this package", and that sentence was half of the #5750 defect. […] Its 0 for this package meant "not looked at here", not "checked, clean" […] Four zh-CN nav labels were missing under a fully green build.
The nav half got its own gate (pnpm check:app-nav-i18n). The pages half did not, and the same 0 in scripts/i18n-coverage-baseline.json is carrying the same ambiguity for it. check-i18n-coverage.mjs's header names the class in general terms — "Metadata assembled at RUNTIME is outside it by construction" — but nothing states that these three pages are in it, and nothing owns them from the other side.
Today the debt happens to be zero: 45 of the 48 are inline locale maps carrying all four locales, and the remaining 3 are the page-level labels User / Organization / Position. That is the point — the surface is unmeasured, so nobody would learn if it stopped being zero. A fourth plugin page, or one new untranslated section heading, lands green.
Not proposing the fix here
There are at least three shapes (declare the pages in an extract config and extend the walk; give the plugins their own configs; or a boot-and-judge gate like check-app-nav-i18n which is what the runtime-composition class already uses), and picking between them interacts with #14749's ruling on how page nodes are keyed. Filing the measurement; leaving the route to triage.
Measured with a TypeScript AST scan of all 5,564 .ts/.tsx files; the per-page counts reproduce under an independent grep -c "'zh-CN':" (33 / 6 / 6 inline maps) plus the 3 plain-string page labels.
Context: #14749 (the measurement that surfaced it, full numbers in its comments), #5750 (the same class, Setup nav half).
Generated by Claude Code
Filed unassigned by the
domain:cliseat while measuring #14749 (sessionsession_016yfqQh2dBgPAymYd7xipza), onorigin/mainat5a5336b3. Independent of #14749's A/B/C question: this holds whether or not inlineI18nLabelmaps are ever walked, and it would still hold if every one of these labels were a plain string.What is unmeasured
packages/platform-objects/src/pages/ships three record pages that reach real users in Setup:I18nLabel-typed prop sitessys-user.page.tssys-organization.page.tssys-position.page.ts48 in total. Not one of them is measured by
check:i18n-coverage, for two stacked reasons:packages/platform-objects/scripts/i18n-extract.config.tsdeclaresobjects,apps,dashboardsandtranslations— and nopageskey. The pages reach the platform at runtime through plugins instead:packages/plugins/plugin-auth/src/auth-plugin.ts:638contributes[SysOrganizationDetailPage, SysUserDetailPage]andpackages/plugins/plugin-security/src/security-plugin.ts:1068contributes[SysPositionDetailPage]. Neither plugin has ani18n-extract.config.tsat all, so neither is in the coverage population. Of the 13 baselined configs, onlyapp-crmandapp-showcasedeclarepages.packages/spec/src/system/i18n-resolver.ts:1484fixes the roots as "regions[].components[]only —slotsis not walked, on any page", and the descent asproperties.childrenonly, withbody/footer/items[].children"deliberately not descended". Measured: 48 of 48 sit underslots.*, reached throughproperties.sections[]andproperties.items[].children. Zero are underregions[].Why this is the documented harm class, recurring
i18n-extract.config.ts's own header already records this exact failure once, for the Setup nav:The nav half got its own gate (
pnpm check:app-nav-i18n). The pages half did not, and the same0inscripts/i18n-coverage-baseline.jsonis carrying the same ambiguity for it.check-i18n-coverage.mjs's header names the class in general terms — "Metadata assembled at RUNTIME is outside it by construction" — but nothing states that these three pages are in it, and nothing owns them from the other side.Today the debt happens to be zero: 45 of the 48 are inline locale maps carrying all four locales, and the remaining 3 are the page-level
labelsUser/Organization/Position. That is the point — the surface is unmeasured, so nobody would learn if it stopped being zero. A fourth plugin page, or one new untranslated section heading, lands green.Not proposing the fix here
There are at least three shapes (declare the pages in an extract config and extend the walk; give the plugins their own configs; or a boot-and-judge gate like
check-app-nav-i18nwhich is what the runtime-composition class already uses), and picking between them interacts with #14749's ruling on how page nodes are keyed. Filing the measurement; leaving the route to triage.Measured with a TypeScript AST scan of all 5,564
.ts/.tsxfiles; the per-page counts reproduce under an independentgrep -c "'zh-CN':"(33 / 6 / 6 inline maps) plus the 3 plain-string page labels.Context: #14749 (the measurement that surfaced it, full numbers in its comments), #5750 (the same class, Setup nav half).
Generated by Claude Code