0070. The UI is English only, with a light/dark switch
Status: Accepted · Date: 2026-10-26 · Design section: UI, Roadmap phase 10
Decided: The UI has one language, English. The ja dictionary, the language selector, and language detection and storage are removed; en stays in ui/src/lib/i18n.ts behind t() / useT(); dates and sizes use Intl with en, not the browser locale; the page header carries a light/dark switch that follows prefers-color-scheme until the user chooses, then keeps the choice in localStorage
Supersedes: 0064
Context
ADR 0064 localised the UI in English and Japanese and picked the language from navigator.languages. The user asked for an English-only UI; a Japanese browser should not produce a Japanese page. The user also asked for a dark/light switch; index.css already had the dark custom variant and token block.
Decision
1. English only. ja, Lang, langs, langNames, detectLang, lang.ts, the LanguageSelector/LanguageSwitch component and the common.language key are deleted. The English strings are unchanged. t(key, params) lives in i18n.ts and replaces {name} markers; useT() stays so the roughly 220 call sites do not change, but returns t without subscribing to anything. enumName and formatBytes / formatDate / formatTimestamp lose their lang parameter and use en.
2. Light/dark switch. ui/src/lib/theme.ts has the pure chooseTheme(saved, prefersDark): a saved light or dark wins, otherwise the system preference. The choice is kept in localStorage["ichor-ui-theme"] (read and written in try/catch) and applied as the dark class on <html>. A small inline script in ui/index.html applies it before first paint to avoid a light flash. The header button is the preactcn Button and says which mode it switches to.
Consequences
- Nothing in the UI follows the browser language. Reintroducing a language means a new ADR.
- The typed-dictionary indirection remains although only one dictionary exists; it keeps strings in one place and the call sites unchanged.
- The theme logic exists twice (TypeScript and the inline script);
theme.tssays so.