i18n: a catalog for the interface below the menu bar

The menu bar has had a catalog since #229 (keyed by `(command, English label)`); everything below
it - panel labels, buttons, field names, tooltips, the sentences a panel draws itself - was written
straight into the code and stayed English in every language (#333).

This adds `crates/ui-egui/src/i18n/ui.rs`:

- Rows are keyed by the English source string, so a panel wraps a literal it already has instead of
  inventing an id, and a row that is missing falls back to English rather than to an empty label.
- `tr("Rename")` translates a plain string; `tr_args("Proxy Use: {}", &[&quality])` fills the values
  of a row that carries them. `tr_args` writes into its own buffer, so it cannot panic on a mismatch,
  and a test keeps every row's placeholder count equal to its English source.
- The language in force is set once per frame from the resolved interface language - the same value
  the CJK fonts are installed for - and kept in a thread-local, so the panels do not have to thread
  it through every function. The render threads never draw interface text.
- Simplified and Traditional Chinese are complete (384 strings); the Japanese rows are still open,
  and the catalog takes them without any other change.

Tests: the two Chinese catalogs must list the same source strings, no empty or duplicated rows, every
row must be asked for by a converted panel, and a converted panel that gains a hard-coded string in a
common call shape fails the build.
This commit is contained in:
FeiLiuEM
2026-10-09 20:17:05 +08:00
parent d5f78f3fc0
commit cceaba0452
6 changed files with 1076 additions and 2 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -29,7 +29,7 @@ Commands (CLI, MCP, control channel):
### Settings that change behaviour
- `general.language`: interface language (`system` / `en` / `ja` / `zh-hans` / `zh-hant`), Settings ▸ General ▸ Language; menu labels change immediately. `system` (Match System, the default) follows the operating system's interface language where EffectCraft has a translation and is English otherwise: a Simplified Chinese locale (`zh`, `zh-CN`, `zh_CN.UTF-8`, `zh-Hans-CN`, `zh-SG`) selects `zh-hans`, a Traditional one (`zh-TW`, `zh-HK`, `zh-Hant`, `zh_MO`) selects `zh-hant`; the browser build stays in English with it. Native Japanese, Simplified and Traditional Chinese UI uses installed system fonts; the web host must supply a Japanese font.
- `general.language`: interface language (`system` / `en` / `ja` / `zh-hans` / `zh-hant`), Settings ▸ General ▸ Language; menu labels change immediately. `system` (Match System, the default) follows the operating system's interface language where EffectCraft has a translation and is English otherwise: a Simplified Chinese locale (`zh`, `zh-CN`, `zh_CN.UTF-8`, `zh-Hans-CN`, `zh-SG`) selects `zh-hans`, a Traditional one (`zh-TW`, `zh-HK`, `zh-Hant`, `zh_MO`) selects `zh-hant`; the browser build stays in English with it. Native Japanese, Simplified and Traditional Chinese UI uses installed system fonts; the web host must supply a Japanese font. Two catalogs back the text: the menus are keyed by `(command, English label)` (`crates/ui-egui/src/i18n.rs`), and the rest of the interface - panels, dialogs, buttons, tooltips - is keyed by its English source string (`crates/ui-egui/src/i18n/ui.rs`), where a panel writes `tr("Rename")`, or `tr_args("Proxy Use: {}", &[&quality])` when the row carries a value. A row that is missing falls back to English, so a new string shows up untranslated rather than empty; the tests in that module fail on an unused row and on a hard-coded string in a converted panel.
- `general.undoLevels`: Levels of Undo
- `general.pathPointSize`: Path Point and Handle Size
- `general.recentItems`: Recent Projects Shown