Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions docs/i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

Register is localized with [Lingui v5](https://lingui.dev). Supported locales: **English (en),
Spanish (es), Korean (ko), Simplified Chinese (zh)**, plus a dev-only **pseudo** locale for
finding unwrapped strings. English is the default; an explicit choice is persisted to
`localStorage['register.locale']`.
finding unwrapped strings. The first visit uses the first supported locale from the browser's language
preferences, falling back to English. An explicit choice is persisted to
`localStorage['register.locale']` and takes precedence on later visits.

## The one rule: reactive vs non-reactive

Expand Down Expand Up @@ -135,7 +136,7 @@ still in plain English is unwrapped. It's the primary tool for catching missed s

```js
// in the browser console, then reload
localStorage.setItem('register.locale', 'pseudo')
localStorage.setItem('register.locale', JSON.stringify('pseudo'))
```

Pseudo is only selectable in dev (`import.meta.env.DEV`); in production the value is validated
Expand Down
6 changes: 5 additions & 1 deletion docs/wiki/log.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Log
updated: 2026-08-08
updated: 2026-08-19
type: log
---

Expand Down Expand Up @@ -129,3 +129,7 @@ Play-by-play lives in git (PRs #1053/#1054/#1055/#1063, SDK PR #27). Durable out
## 2026-08-08

- DTF Settings confirmation was globally gated by deploy-time schema validity, so unchanged on-chain values with display-rounding drift blocked unrelated governance changes even though those values were omitted from proposal calldata. The gate now scopes errors to changed settings while preserving no-change and changed-invalid guards; the E2E regression models an unchanged invalid distribution plus a valid mandate update.

## 2026-08-19

- Locale initialization now uses the first supported browser preference for visitors without a saved choice; a persisted explicit choice still wins. A clean Lingui extraction confirmed 2,543 active messages with zero missing Spanish, Korean, or Chinese translations and removed obsolete catalog entries. Live browser verification covered Spanish auto-selection plus a Korean selection surviving reload.
3 changes: 2 additions & 1 deletion docs/wiki/progress.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Progress
updated: 2026-08-10
updated: 2026-08-19
type: ledger
---

Expand All @@ -10,6 +10,7 @@ Stage ledger. One row per stage; keep entries short. Verifier = exact fresh comm

| Stage | Status | Verifier | Review | Next |
|---|---|---|---|---|
| Browser locale default and translation audit | human-review-required (base a6f20e340) | RED: browser es→expected es, got en; Traditional Chinese cases initially mapped to zh · GREEN i18n 15/15 · lint · typecheck · unit 895/895 · build:no-seo · live browser: es-ES→Español, persisted ko survives reload · catalogs es/ko/zh 2543, 0 missing | independent review found Traditional→Simplified matching risks (including Hant+region); both fixed with negative and positive BCP-47 coverage; shared locale provider/persistence default requires Engineer review | PR review/merge only after Engineer review; wiki-lint blocked by pre-existing stale design-system page |
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
| Preserve Index DTF section in cmd-k navigation | human-review-required (base ebcd6febe) | RED: proposal/rebalance both landed overview; GREEN 2/2 · gate typecheck/lint/880 unit · live Ctrl+K proposal→governance + rebalance→auctions | independent Intent + Engineering Risk PASS, no findings; shared route-selection behavior requires Engineer review | merge only after Engineer review; wiki-lint blocked by pre-existing stale design-system page |
| vote modal: address-length title overflowed the dialog | done (base 6854a370b) | lint · typecheck · test:run · e2e helper units · smoke 58 · new `vote-modal-long-title` spec desktop+mobile green · RED-verified (reverted the index-dtf modal fix → checkbox right edge 943 vs dialog 849.9) | product/correctness: self — copy + layout only, no tx path touched | — |
| Fix DTF settings confirm button | human-review-required (base 6854a370b) | RED: rounded seeded distribution blocked mandate confirm; GREEN: unit 878 incl. mapper 27/27 · focused E2E 5/5 · typecheck · lint | Dark HOLD on untested mapping → 27 exhaustive mapper tests → Dark PASS; Light PASS; CodeRabbit 2 Minor → resolved (test IDs + editable confirmed state) | PR #1084 open; Engineer review required before merge; wiki-lint blocked by pre-existing stale design-system page |
Expand Down
33 changes: 32 additions & 1 deletion src/i18n.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,37 @@ export type SupportedLocale = 'en' | 'es' | 'ko' | 'zh' | 'pseudo'

export const DEFAULT_LOCALE: SupportedLocale = 'en'

const BROWSER_LOCALES: SupportedLocale[] = ['en', 'es', 'ko']

export function getBrowserLocale(): SupportedLocale {
if (typeof navigator === 'undefined') return DEFAULT_LOCALE

const languages = navigator.languages.length ? navigator.languages : [navigator.language]

for (const language of languages) {
const subtags = language.toLowerCase().split('-')
const locale = subtags[0] as SupportedLocale

if (locale === 'zh') {
if (subtags.includes('hant')) continue

if (
subtags.length === 1 ||
subtags.includes('hans') ||
subtags.includes('cn') ||
subtags.includes('sg')
) {
return 'zh'
}
continue
}

if (BROWSER_LOCALES.includes(locale)) return locale
}

return DEFAULT_LOCALE
}

// 'pseudo' is a dev-only debugging locale that mangles every wrapped string,
// making unwrapped (untranslated) text visually obvious.
export const SUPPORTED_LOCALES: SupportedLocale[] = import.meta.env.DEV
Expand Down Expand Up @@ -48,7 +79,7 @@ export async function dynamicActivate(locale: SupportedLocale) {

const storedLocaleAtom = atomWithStorage<SupportedLocale>(
'register.locale',
DEFAULT_LOCALE,
getBrowserLocale(),
undefined,
{ getOnInit: true }
)
Expand Down
Loading
Loading