fix: make locale switches atomic while lazy catalogs load - #2633
fix: make locale switches atomic while lazy catalogs load#2633Chris0Jeky wants to merge 2 commits into
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
…ted restore Review round 1 (fresh-context, D-12 sweep): app.mount ran only in the finally of the locale restore promise, so a lazy catalog request that stalled rather than failed held first paint open indefinitely. Startup now races the restore against a 1500 ms budget and mounts in English when the budget wins; the store still commits atomically if the catalog arrives later. A rejected restore is logged through the existing error reporter instead of being discarded, the garbage-stored-value test asserts preferredLocale (the validate-on-read guard it exists for), and ADR-0054 section 7 records the commit-after-load semantics.
|
Review gate (Codex review credits exhausted, SC-9; D-12 ruled 2026-09-05: the Codex session's PRs are reviewed and merged by the coordinator): one fresh-context read-only reviewer (Opus 5) on head Round 1 reviewed head Checked by reading: both race orderings in Findings and disposition:
Issue disposition: slice of |
|
Round 2 (scoped to the fix diff 6906c6a..7e9a64b only; one fresh-context read-only reviewer, Opus 5). Verdict: SHIP. Checked by reading: Promise.race settles once and a single .finally is attached to it, so app.mount runs at most once; it cannot run zero times because the restore cannot reject (the new .catch returns void) and the budget always resolves, so the race always settles within 1500 ms; when the budget wins and the catalog arrives later, localeStore.ts:109-121 commits this.locale and applyLocale (i18n.global.locale plus html lang) in one synchronous body after setLocaleMessage has already registered the messages, so no raw keys are shown, only an English first paint that flips once; logError(context, ...args) exists at errorReporting.ts:78 and is the helper the installed handlers already use; preferredLocale is declared store state (localeStore.ts:71), so the spec change compiles and is the stronger assertion; no vitest spec imports src/main.ts (scripts/check-dev-entry-graph.mjs only transforms it; tests/run-vite-dev.spec.ts writes same-named fixtures), so the timer never runs under happy-dom today. Findings and disposition (all LOW, tracked on #2003, none owed):
Not verified by the reviewer: typecheck, build and the spec run (no shell); the hosted CI run on this head is the evidence for those. |
Summary
html.lang.Refs #2003
Scope
This PR implements only
TD-2003-pending-ui. The service-worker preferred-locale warming contract and its browser/build proof remain separate follow-up work.Verification
npx vitest --run --maxWorkers=2 src/tests/store/localeStore.failure.spec.ts src/tests/i18n/lazyLocales.spec.ts src/tests/views/AppearanceSettingsView.language.spec.ts src/tests/i18n/catalogs.spec.ts— 37 passed.npm run test -- --maxWorkers=2— 371 files passed; 5,728 passed, 3 skipped.npm run typecheck— passed.npm run lint— 0 errors, 8 existing warnings.npm run build— passed; existing ineffective dynamic-import warning fortoastStore.git diff --check— passed.Not verified