Skip to content

check-i18n-call-site-keys value-compares inline defaultValue but never a createSafeTranslation defaults table — the same promise, one indirection away, uncompared across the whole factory population #7567

Description

@huangyiirene

Split out of #7454 by the triage seat (R+129). That card measures one drifted entry (calendar.allDay: 'all-day' in a factory table vs 'All Day' in the pack) and says the class fix — "value-compare factory defaults tables against en, the way inline defaultValue already is""is the one that closes the class". It is a different lane and a different fix, so it is a different card.

#7454 keeps the instance (align the table, delete the dead ternary) in packages/plugin-calendardomain:ui. This card is the gatedomain:devx.

The gap, measured — tree origin/main e304a4e, read 2026-09-03T22:49:30Z

scripts/check-i18n-call-site-keys.mjs already value-compares one flavour of inline default and not the other:

channel compared against en?
t(key, { defaultValue }) — inline literal ✅ yes (996 compared, 993 matching per the gate's own summary)
createSafeTranslation(DEFAULT_TRANSLATIONS, …) table entry no — classified as "module-local table" and never value-compared

Both are the same promise — "this is what the pack says" — one written at the call site, the other one indirection away in a table. #7454 is what the uncompared channel costs: a lane header that renders all-day without a provider and All Day with one, plus a structurally unreachable ternary kept alive by nothing.

⚠️ Population size: three numbers, three questions — ⛔ do not conflate them

measure count what it actually counts
the gate's own header (:92-93) 26 "all 26 such hooks are either createSafeTranslation(...) factories or thin wrappers over…"hooks
literal createSafeTranslation( sites, excl. tests/imports 33 factory invocations
files mentioning the identifier 74 files, incl. consumers of a factory's output

⛔ I did not re-derive the gate's 26 and I am not claiming it is wrong — it counts hooks under the gate's own convention, which is a narrower thing than either of my counts. ⇒ Whoever takes this should decide which population the comparison should cover and say so; the three numbers are not interchangeable and picking one silently is how the coverage claim ends up overstated.

Why pm:queue and not a ruling

Extending an existing error-level comparison to a channel the gate already classifies is a coverage fix, ⛔ not a gate-strength change — so it does not hit the human floor the way a warn→error flip does (cf. #4853).

⚠️ But the red set is unmeasured, and that is the whole risk. #7454 found one mismatch by hand; nobody knows whether turning the comparison on surfaces one more or fifty.

Stop-condition, and it is hard: measure the mismatch count before landing anything. Run the widened comparison in report-only mode and put the number in the report.

⛔ Do not add per-entry exemptions to make a red list go green. An exemption list assembled to fit today's failures is the thing the comparison exists to prevent.

What "correct" means here is not obvious either

⚠️ The comparison direction needs stating: is the pack authoritative and the table a copy that must match, or is the table a deliberate provider-less fallback allowed to differ? #7454's evidence favours the first (six of seven sibling entries match en exactly; the nine translation packs follow en), but that is one table. ⇒ Whichever the gate asserts, it should say so in its own header — the failure message is where the next author learns the rule.

Related: #7454 (the instance this came from) · #3810 (the inline-default-contradicts-pack class this belongs to) · #7443 (a live example of a deliberate divergence, in a different subsystem — the reason "always match the pack" cannot simply be assumed).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repopm:dispatchedpriority:p3tooling

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions