feat(i18n): wire hardcoded settings surfaces (MoA, Billing, Custom Endpoints) for all locales - #74691
Conversation
…00% coverage Russian locale catalog merged from two independent native-speaker sources: - DrMaks22's hand-reviewed catalog (PR NousResearch#72250) as the primary base - anatolijlaptev1991-ctrl's catalog with additional keys + ё-fidelity corrections Changes: - i18n/ru.ts: full Russian translation (defineLocale + defineFieldCopy, same architecture as ja.ts/ar.ts) - i18n/types.ts: add 'ru' to Locale union type - i18n/catalog.ts: register ru in TRANSLATIONS - i18n/languages.ts: add 'Русский' to LOCALE_OPTIONS + locale aliases (ru, ru-RU, ru_ru, russian, Русский, русский) - i18n/languages.test.ts: test cases for ru normalization Coverage: 2755/2755 en.ts leaf keys (100%). Locale-neutral i18n-wiring for hardcoded surfaces (MoA/Billing/Endpoints) is tracked separately in PR NousResearch#74691.
teknium1
left a comment
There was a problem hiding this comment.
Thanks for isolating the wiring work; the underlying issue is real on current main (model-settings.tsx:1004, custom-endpoints-settings.tsx:232, and billing/errors.ts:28-29 still render literals).
Problems
- The added required
Translationskeys (apps/desktop/src/i18n/types.ts:687) have no counterparts in the unchanged full Chinese catalog (apps/desktop/src/i18n/zh.ts:5). The PR head therefore cannot meet that catalog's type contract. It also removes unrelated type members such assayStopToEnd; current main still requires that member attypes.ts:198. AUTO_REFILL_GENERICis translated once at module initialization (billing/use-billing-state.ts:604).translateNow()reads the mutable runtime locale (src/i18n/runtime.ts:54-65), so this copy does not change after the user switches locale.- Several literals remain in the claimed surfaces, including the recovery suffix in
billing/errors.ts:48, AutoReloadRow copy atbilling/auto-reload-row.tsx:98, and the MoA switch aria-label atmodel-settings.tsx:1109.
Suggested changes
- Preserve existing type fields, add the new keys to every locale catalog, and translate the remaining billing/MoA literals.
- Move the auto-refill generic translation into the view-building path and add a non-English render test.
This is an automated hermes-sweeper review.
| @@ -710,6 +684,205 @@ export interface Translations { | |||
| fallbackEmpty: string | |||
| notInCatalog: string | |||
| tasks: Record<string, AuxTaskCopy> | |||
| moaTitle: string | |||
There was a problem hiding this comment.
These required additions need matching catalog entries. zh.ts declares a complete Translations object directly, but this PR does not change it and its head has no moaTitle, customEndpoints, or billing additions; preserve the existing interface members and update every locale catalog.
| } | ||
| } | ||
|
|
||
| // The generic first sentence shared by the off / absent / divergent states, | ||
| // where the concrete amounts aren't the headline. The configured state overrides | ||
| // this with the disambiguating "Charges $X … below $Y." sentence (spec §8). | ||
| const AUTO_REFILL_GENERIC = 'Keep your balance topped up when it drops below your threshold.' | ||
| const AUTO_REFILL_GENERIC = translateNow('settings.billing.state.autoRefill.genericDescription') |
There was a problem hiding this comment.
translateNow() reads the mutable runtime locale, so resolving this at module import permanently captures the initial language. Move this lookup into autoReloadRow() or otherwise recompute it when building the view.
40799b8 to
d65de92
Compare
|
Thanks for the review — all five issues are addressed in 1. Removed type fields (sayStopToEnd etc.) — 2. zh.ts missing new keys — all new keys (moa/customEndpoints/billing/state/errors, incl. 3. AUTO_REFILL_GENERIC frozen at module init — the module-level 4. Remaining literals translated:
Checks (all green):
|
d65de92 to
f674592
Compare
Follow-up: 3-independent-auditor review (0c6ad7789)After the initial sweeper feedback, ran two rounds of 3 independent auditor agents (types/contracts, literals/UX, tests/style) to scrupulously find every remaining issue. Round 1 found 5 real issues — all fixed and verified. Round 2 confirmed clean. Round 1 findings — fixed in 0c6ad7789
Verification (all green)
Round 2 — clean ✅Three fresh auditors on HEAD |
…ebased on main) Rebased the i18n wiring onto current upstream/main after the i18n architecture changed (locales now via defineLocale; new ar/ja/zh-hant catalogs added). Carries the original wiring forward: - Components (model-settings, custom-endpoints-settings, billing/*): replace every hard-coded English literal with t()/translateNow() calls. - en.ts + types.ts: add the moa*/customEndpoints/billing.* key sets the wiring consumes (thresholdAria, reloadToAria, moaDisableRef/EnableRef, provenance.customerDefault/subPin/suffix, remoteSpendingReconnect, etc.). - zh.ts: complete Chinese translations for the new key sets (strict catalog must implement Translations in full). ja/zh-hant/ar inherit via defineLocale. Verification: - tsc clean on renderer, electron, and e2e tsconfigs (0 errors) - vitest ui: i18n 28/28 passing; billing 133/135 - The 2 billing failures are pre-existing on upstream/main (verified by running the same suite on a clean main checkout: 105/107) and are unrelated to this wiring. Co-Authored-By: Anatoliy Laptev <anatolij.laptev.1991@gmail.com>
0c6ad77 to
377c49f
Compare
Rebased onto current upstream/main — conflicts resolvedThe branch was 2746 commits behind What changed
Verification (real, on the pushed commit)
Remaining gate: an approving review ( This is locale-neutral: once merged, every locale (existing or future) gets these surfaces translated automatically, complementary to any |
Summary
Three settings surfaces in the Desktop app contained hard-coded English strings that bypassed the i18n system entirely:
model-settings.tsx) — 13 literalscustom-endpoints-settings.tsx) — 28 literalsbilling/index.tsx,plans-view.tsx,current-plan-card.tsx,auto-reload-row.tsx,use-billing-state.ts,errors.ts) — 75+ literalsThese surfaces rendered English for every locale, including
zhandja. This PR wires them to the i18n system witht()/translateNow()calls and adds the corresponding keys toen.ts+ theTranslationsinterface.Locale-neutral: no
ru.ts, nocatalog.ts/languages.tschanges, no new locale registration. This benefits every existing and future locale equally.Extracted from #71573 per maintainer feedback (comment) to split the generic wiring from the Russian catalog.
Changes
model-settings.tsx— MoA: title, description, preset, enabled, setDefault, delete, newPreset, addPreset, defaultLabel, referenceN, remove, addReference, aggregatorcustom-endpoints-settings.tsx— all field labels, buttons, notifications (28 strings)billing/index.tsx+plans-view.tsx— Billing, Plan, Payment & credits, Usage, portal, auto-refill, Confirm downgradebilling/use-billing-state.ts— usage panel: subscription credits, top-up credits, monthly spend cap, does not expire, refill when low, payment method, etc. (40+ strings)billing/errors.ts— error banners: card confirmation needed, monthly spend cap reached, remote spending needs approval, session logged out, admin role required, etc. (35+ strings)en.ts— 257 new keys acrosssettings.model.moa,settings.billing.*,settings.customEndpoints.*types.ts— correspondingTranslationsinterface extensionsSweeper review (addressed)
All five issues from the hermes-sweeper review are fixed in
d65de924(rebased onmain@f3cda0ceb):sayStopToEnd,findInPage,artifactCard,quickEntry,wakeWord*) — restored frommaintype contract.types.tsrebuilt from main, then new keys added on top.moaTitle,moaDesc, etc.) with Chinese translations or English fallback.use-billing-state.ts), now reactive to locale changes.errors.ts:48recovery suffix,auto-reload-row.tsx:98,model-settings.tsx:1109aria-label — all wired.zh.ts+types.tsfully consistent.Verification (fresh, on committed
d65de924):tscclean (3 tsconfigs, 0 errors)test:ui -- i18n28/28 passedtest:ui -- billing105/107 (2 pre-existing failures on unchangedbilling-amounts.ts)Verification
tscclean on all 3 tsconfigs (renderer, electron, e2e)npm run build(vite production build) succeedst('settings.model.moa.title'))Relation to other PRs
This PR has no conflicts with any locale catalog.