feat(i18n): localize client-side JS strings via window.__lcI18n catalog (LC-361) #373
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/lc-361-js-i18n"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The last MED finding from the UI audit.
just test+just test-saasgreen.Problem
~45 user-facing strings in the client-side JS were hardcoded English and never localized - the call (
call.js), voice-channel (voice.js), upload + voice-recording (composer.html), offline-outbox (outbox.js), reminder (reminders/picker.html), and device-label (devices.js) flows. So exactly the high-stakes moments (a call failing, an upload erroring, offline queueing) stayed English foresusers, even though the static template strings are fully translated.Approach
base.htmlrenders awindow.__lcI18nobject (each value via{{ "js-..."|t }}) plus awindow.__lcS(key, fallback)helper, synchronously before the deferred asset scripts.locales/en/js.ftl+locales/es/js.ftlcarry the keys with Spanish translations, glob-loaded alongside the existing catalogs and kept in en/es lockstep for thei18n_cataloggate.%name%/%status%/%n%/%size%are literal placeholders the JS substitutes; filename substitutions use a function replacer to avoid$-in-replacement-string pitfalls.Tests
base.html) emits the catalog object + helper with a known English value.i18n_catalogconfirms every key exists in en and en/es parity holds.Closes LC-361.
~45 user-facing strings in the call (call.js), voice-channel (voice.js), upload + voice-recording (composer.html), offline-outbox (outbox.js), reminder (reminders/picker.html), and device-label (devices.js) flows were hardcoded English, so they never localized - exactly the high-stakes flows (a call failing, an upload erroring, offline queueing) stayed English for es users. base.html now renders a window.__lcI18n object (each value via `{{ "js-..."|t }}`) plus a window.__lcS(key, fallback) helper, synchronously before the deferred asset scripts. Each call site passes the English literal as the fallback, so a missing/old catalog key degrades to English rather than breaking the flow. New en/js.ftl + es/js.ftl carry the keys (Spanish translations included), glob-loaded alongside the existing catalogs and kept in en/es lockstep for the i18n_catalog gate. `%name%`/`%status%`/`%n%`/`%size%` are literal placeholders the JS substitutes (filename substitutions use a function replacer to avoid `$`-in-replacement pitfalls). Test: a full page render emits the catalog object + helper with a known English value; i18n_catalog confirms key existence + en/es parity. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>