Pull requests / #1204
#1204 serve: a Chinese / English language switch for the web app
open · @hogtinbao · 0 comentarios · En GitHub
BenchmarksServer & APIModels & quantsWindows
Descripción
Rebased onto the new `main` (v0.1.40.1) — this replaces #682, which GitHub closed automatically when the history was rewritten. No other change; the branch is a single commit on today's `main`. ## What this adds An optional **Chinese / English language switch** for the web app, with a `Language` button at the left of the header: **English / Simplified Chinese / Chinese + English**. It is opt-in and reversible: the stock interface is what you get until someone picks another language. ## Coverage: the whole 0.1.40.1 web interface is translated Not a partial pass — every user-facing string in the two pages of this release, including the views added in 0.1.40: - the header, the three tabs and the status pill; - **Chat**: the empty state, the composer and its buttons, the toasts, the attachments, the tool-call blocks, the per-message meta line, the export and copy labels; - **Monitor**: the state badges, the eight metric cards, the context gauge, the request table (headers, status badges, `+N% PCIe`), the totals line, and the new **Conversation cache** panel — its bars, its four facts rows and both of its notes; - **About**: the model/engine facts, the hardware facts, the API addresses, the settings; - the **sampling drawer**: thinking levels, temperature, Top-p, Top-k, Max tokens, Seed, the three switches; - the new **Model settings** view: the help sentence of all 15 editable keys (those sentences come from `runconfig.py` and are matched as data), *and* the two pieces of the form that are not sentences — the `<option>` text of its dropdowns (`default` / `on` / `off` render as 默认 / 开 / 关; an enum choice keeps its config word with the meaning beside it: `model(按模型习惯)`, `start(开头)` …) and the monospace config key beside each field, which keeps the key untouched and gets a short gloss after it (`sampling.top_p(核采样范围)`, `reasoning_budget_tokens(思考长度上限)` …). The key names and the `value` attributes are never rewritten, so what a save writes to the run config stays exactly the English keys the server expects; - and the strings only a screen reader or a hover would show: every `title`, `placeholder` and `aria-label`. How that was verified: every string literal and text node was extracted from `index.html`, `monitor.html`, `app.js`, `monitor.js` and the `EDITABLE` list in `runconfig.py` (~264 candidates), then compared against the dictionary and the rules, with HTML line-wrapping normalised; every `<option>` label the settings form can render is checked against the option and general tables, and the short enum words are asserted *absent* from the general dictionary. The remaining unlisted items are CSS class names, code fragments, Python docstrings and proper nouns (e.g. `Top-p`, `Strata`, `Tok/s`) — nothing a user reads. A new string added upstream later shows up untranslated rather than breaking anything, so this list only ever grows. ## Files | File | Change | | --- | --- | | `serve/web/i18n-zh.js` | new, self-contained | | `serve/web/index.html` | one `<script>` tag | | `serve/web/monitor.html` | one `<script>` tag | No existing function is modified, there is no new dependency, no server-side change and no API change (`/health`, `/v1/...` are untouched — only the two HTML pages load the new file). Removing the feature is deleting one line per page. ## How it works - A dictionary covers the fixed labels; a list of regex rules covers the strings the app builds at run time (token counts, `tok/s`, the request table, the `Since …` totals line, the conversation-cache statistics, the composed per-message meta line, and so on). - A `MutationObserver` re-translates after the app re-renders, so the live Monitor — the status pill included — keeps updating in the chosen language, and it does so before the next paint, so nothing flickers back to English. - The Chinese and the English text both live in the DOM; a `data-lang` attribute on `<html>` plus CSS decides which one is shown. Switching is instant and does not re-run the translation. - The button's own label and menu follow the chosen language (`Language` / `语言` / `语言 Language`), and the choice is kept in `localStorage` (`strata.lang`). ## Guarantees - **The model's output is never rewritten.** Chat text, reasoning, code blocks and MCP tool arguments and results are explicitly excluded. Checked by asking the model for an English answer and confirming the bubble, the reasoning and the code read exactly as the model produced them in every language mode. - **`English` restores the stock interface**, attributes included: every translated `title`, `placeholder` and `aria-label` keeps its original value in a `data-i18n-orig-*` attribute, and every `<option>` and `<code>` key its original text in `data-i18n-orig-text`. - Text with no dictionary entry or rule is left alone, so a partial translation never breaks the page. ## Tested On Windows 11 in a real browser against a running server (Qwen3.8-Flash-Next IQ2_XS): all three modes on the Chat, Monitor and About tabs, in the sampling drawer and in the Model settings view; switching back and forth without a reload; reloading to confirm the stored choice comes back; and the model-output check above. ## Notes - The dictionary is deliberately data rather than code: another language is another table, and the rules are shared. - Happy to rework any of it — a different button position, the dictionary split into its own file, a different default — if you would rather have it another way.
En el sitio
Enlaces a install, modelos, releases.