Pull requests / #1427
#1427 web: Russian UI localization (dictionary + header language picker)
open · @Astemiir · 0 comments · View on GitHub
Description
## Title web: Russian UI localization (dictionary + header language picker) ## Summary Adds a Russian localization of the web UI. It is deliberately **non-invasive**: the interface code keeps its English strings, and a self-contained script translates the visible chrome from a flat JSON dictionary, so the patch does not touch app logic, needs no build step and adds no dependencies. English stays the default — the language only changes when the user picks it. ## What changed * **new `serve/web/i18n.js`** — the translator. Walks the DOM, replaces exact dictionary matches and keeps a `MutationObserver` on the body, so text the app renders later (metrics, status labels, toasts) is translated in the observer's microtask — before the frame is painted, otherwise the English word flashes first. Strings with numbers (1 token / 2 tokens / 5 tokens) go through a small rule table, since a flat dictionary cannot express Russian plurals. Model answers, code blocks and attachments are never touched: inside `#chat` only the chrome listed in `CHROME_SEL` is translated. * **new `serve/web/i18n/ru.json`** — 317 flat `"english": "russian"` pairs. The reverse direction is built by inversion, so one file works both ways; adding a language is another `<lang>.json` plus one entry in `LANGS`. * **new `serve/web/i18n.css`** — the picker button and a fixed-width slot for the status pill. The header is right-aligned and the pill changes width (`Idle` → `Reading prompt · 63 %`), so a button placed next to it kept sliding around; the invisible slot keeps the button in place while the pill still hugs its own text. * **`serve/web/index.html`** — the stylesheet link, the `En`/`Ru` button left of the status pill, the pill slot, and `i18n.js` before `app.js` (so the static header is translated before the app renders and before the first paint). * **`serve/web/monitor.html`** — the same script and a picker in the monitor window's own header, so the standalone monitor is translated as well. Dictionary directory is resolved from the script's own URL, so the same file works from `/` and from `web/monitor.html`. The choice is remembered in `localStorage` under `strata.lang` (same convention as `strata.theme`), and `document.documentElement.lang` follows it. **Coverage.** Checked by extracting every string the pages and their scripts can show: `index.html` 67/81, `monitor.html` 40/53, `app.js` 126/126, `monitor.js` 18/18. What is intentionally left in English: the brand name, the sample URLs, the dash placeholders and the sampler labels `Top-p`, `Top-k`, `Seed` (parameter names). ## Extra Notes * Unknown text simply stays English, so a missing pair never breaks a page. A dictionary that fails to load falls back to English and re-labels the button. * Known limitation: a few long sentences in the About card are split across inline tags (`<b>`, `<code>`), so their fragments would need separate pairs. If you prefer, I can switch those few to `data-i18n` keys instead of translating text nodes — your call. * Verified locally: the patch applies to a fresh copy of `main` (git apply, LF, byte-identical to the tree it was built from), and `i18n.js` was run against a small DOM harness (19 assertions: dictionary loading, translation, chat-chrome rule, observer path, language switch and back). * Happy to rename files, move the dictionary, or fold the CSS into `app.css` — whatever fits your layout. A screenshot of the Russian UI can be attached if useful.
Related on strata.com
Editorial links to help you install, pick models, or read release notes — not part of the upstream thread.