The browser build fetched its Japanese fallback font only for a Japanese UI, so a Japanese design name, file name or typed text showed as tofu with the UI in English. After drawing each frame the web shell now looks through the painted text for kana, CJK ideographs and full-width forms while no CJK font is loaded, and fetches the same font once on the first hit. A failed fetch with an English UI leaves the language alone and is not retried in a loop. Sessions that never show such text download nothing extra. Fixes #720 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
52 lines
3.5 KiB
Markdown
52 lines
3.5 KiB
Markdown
# UI localization
|
|
|
|
SolidCraft embeds its translations and works offline. English and Japanese are currently
|
|
registered in `crates/ui-egui/src/i18n.rs`. Adding a language requires an embedded catalog and
|
|
one registration there; the preferences selector and validation use the same registry.
|
|
|
|
## Messages
|
|
|
|
`crates/ui-egui/src/locales/en.json` defines stable message IDs and English fallback text.
|
|
Keep IDs when changing wording. Other catalogs use the same IDs; missing messages fall back
|
|
to English. Use `app.tr("ui.preferences")` for static messages and
|
|
`Locale::format` for full sentences with named placeholders. Translate the entire sentence,
|
|
including punctuation, so a translator can reorder its arguments. Placeholder values are
|
|
inserted literally, even if a document name contains braces.
|
|
|
|
The English-label adapter (`app.tr_label`) supports existing engine and UI tables. It maps
|
|
display text to a message ID, then uses the same catalog lookup. New UI messages should use
|
|
stable IDs directly. The adapter does not change command IDs, model names, or scenario handles.
|
|
When a table's English wording changes, update the corresponding English catalog entry too.
|
|
Generated browser labels use named templates while their underlying model names stay intact.
|
|
|
|
Catalogs are parsed once and looked up through ordered maps. This is offline localization,
|
|
not a claim of zero runtime overhead. The catalog tests check registered locale IDs,
|
|
translation keys, and placeholder consistency. Run `cargo xtask ci` before submitting changes.
|
|
|
|
## Rendering and coverage
|
|
|
|
One immutable `Locale` type handles all translations. Table widgets without an app reference
|
|
use a render scope that restores the previous locale when it exits, including nested renders.
|
|
Standalone translated panels enter the same scope. Measure rendered text to size custom
|
|
widgets; UTF-8 byte lengths do not describe their displayed width.
|
|
|
|
The desktop host tries system CJK fonts across Windows, macOS and Linux, as well as an optional
|
|
`CRAFT_FONTS_DIR` font pack, and skips files that cannot be parsed. No fonts are redistributed
|
|
in native desktop distribution packages; native builds rely entirely on existing operating system fonts
|
|
or craft-fonts.
|
|
|
|
In the browser, `solidcraft-web` bundles a self-hosted Japanese font (`BIZUDPGothic-Regular.ttf`, licensed
|
|
under SIL OFL 1.1) within the web distribution artifacts only. The font is loaded asynchronously from the same
|
|
origin (`./fonts/BIZUDPGothic-Regular.ttf`) on-demand when the interface language is set to Japanese, or, with
|
|
any other interface language, the first time Japanese text (kana, kanji or full-width forms in a design name,
|
|
file name, body name or typed text) is drawn, without contacting any external CDNs or third-party servers.
|
|
A session that never shows such text downloads no font. If font loading fails with the Japanese interface,
|
|
the web interface shows English for that session only to prevent missing glyphs (tofu); the saved language
|
|
preference is kept, so the next visit tries again. This bundled font specifically targets Japanese; Korean (Hangul) and Chinese scripts are not covered.
|
|
|
|
The current messages support named substitution, not locale-specific plural selection,
|
|
number/date formatting, or right-to-left layout and shaping. Add those capabilities when
|
|
introducing messages or languages that need them; use an established message formatter for
|
|
plural rules instead of adding language branches to panels. The catalogs cover the UI surfaces
|
|
introduced by this PR, not every engine error or every newer command dialog.
|