i18n: complete Simplified Chinese catalog, Chinese font fallback and a coverage xtask (#930)
Adds a complete Simplified Chinese (zh) catalog covering every English message, a font fallback for Chinese text, and `cargo xtask i18n --check`, which checks that the complete catalogs (ja, zh) carry every English message and that every command label is translatable. Co-authored-by: Noly1990 <[email protected]>
This commit is contained in:
1 parent
587cf865b8
commit
45f92277cb
17 files changed
+2485
-52
No files matched your search
@@ -123,7 +123,7 @@ unit regardless of the design, pass an expression with one: `"value": "50 mm"` o
|
||||
| `ui.home` | `open?`: bool; `sample?`: index | the start page: show or hide it, open a built-in sample (once built); returns `open` and the recent designs |
|
||||
| `ui.shortcut` | `command`, `key?`, `replace?` | a command's key, or rebinds it (`""` clears; a key another command uses is refused unless `replace`) |
|
||||
| `ui.help` | `item?`: `about`, `shortcuts` (read only), `report` (copies diagnostics), `crashes` (the Crash Reports window) | the version, commit, build date and diagnostic text |
|
||||
| `ui.prefs` | any of `default_units`, `nav` (`fusion`, `solidworks`, `inventor`, `alias`, `tinkercad`, `openscad`), `zoom_reverse`, `zoom_to_cursor`, `smooth_wheel_zoom` (default true), `trackpad_pan` (default true: two-finger scroll pans, pinch zooms), `orbit_cursor`, `look_at_anim`, `look_at_speed`, `middle_double_click` (`home` (default), `fit`, `off`), `msaa`, `length_decimals`, `angle_decimals`, `theme` (`dark`, `light`, `system`), `language` (`en`, `ja`; see [localization](localization.md)), `ui_scale`, `up_axis` (`z`, `y`), `offer_stand_up`; `open` (a page: General, Navigation, Keyboard Shortcuts, Design, Graphics, Sketch, Selection) opens the Preferences dialog there; `button`: `ok`, `cancel`, `apply`, `defaults`; `stand_up: true` stands up a just-opened Y-up file | sets preferences (kept between runs), returns them all plus `dialog` (the open page or null), `dark` and `stand_up_offer` |
|
||||
| `ui.prefs` | any of `default_units`, `nav` (`fusion`, `solidworks`, `inventor`, `alias`, `tinkercad`, `openscad`), `zoom_reverse`, `zoom_to_cursor`, `smooth_wheel_zoom` (default true), `trackpad_pan` (default true: two-finger scroll pans, pinch zooms), `orbit_cursor`, `look_at_anim`, `look_at_speed`, `middle_double_click` (`home` (default), `fit`, `off`), `msaa`, `length_decimals`, `angle_decimals`, `theme` (`dark`, `light`, `system`), `language` (`en`, `ja`, `de`, `ko`, `zh`; see [localization](localization.md)), `ui_scale`, `up_axis` (`z`, `y`), `offer_stand_up`; `open` (a page: General, Navigation, Keyboard Shortcuts, Design, Graphics, Sketch, Selection) opens the Preferences dialog there; `button`: `ok`, `cancel`, `apply`, `defaults`; `stand_up: true` stands up a just-opened Y-up file | sets preferences (kept between runs), returns them all plus `dialog` (the open page or null), `dark` and `stand_up_offer` |
|
||||
| `ui.capture` | `action?`: `capture`, `revert`, `cancel` | answers the Capture Position question (asked when a command starts or the design is saved while components were moved without capturing); without `action`, what waits |
|
||||
| `ui.window` | `action`: minimize, maximize, restore, toggle, close | what the title bar's caption buttons do (on Windows and Linux the application bar is the title bar); close asks about unsaved designs first |
|
||||
| `ui.agent_cursor` | `show` (bool), `speed`: a number from 1 to 5 (times the normal speed) or `"instant"` (no animation: the command runs at once and the pointer jumps to where it acted), `follow_camera` (bool); all optional | the settings. While the cursor is shown, `engine.execute` first glides to the command's toolbar button and to each pick, then runs and replies; later requests wait their turn. `"animate": false` on a call skips it |
|
||||
|
||||
+47
-10
@@ -1,8 +1,9 @@
|
||||
# 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.
|
||||
SolidCraft embeds its translations and works offline. English, Japanese, German, Korean and
|
||||
Chinese 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
|
||||
|
||||
@@ -23,6 +24,37 @@ Catalogs are parsed once and looked up through ordered maps. This is offline loc
|
||||
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.
|
||||
|
||||
## Coverage
|
||||
|
||||
A message a locale never received falls back to English silently, so a gap shows up only as a row
|
||||
that looks untranslated. Two guards catch that in the build:
|
||||
|
||||
- `every_complete_catalog_carries_every_english_message` — adding a key to `en.json`
|
||||
without giving it to a complete catalog fails the tests. English is the source catalog,
|
||||
Japanese and Chinese are delivered complete; German and Korean are still partial — their
|
||||
gaps are reported by `cargo xtask i18n` without failing the build.
|
||||
- `every_toolbar_tab_and_panel_is_in_the_english_catalog` — tabs and panels reach the UI as bare
|
||||
source strings, resolved only by the English-label adapter, so a heading missing from `en.json`
|
||||
can never translate.
|
||||
|
||||
Command labels are the same case on a larger scale: every label in the engine's registry now has
|
||||
an entry under `cmd.<command id>`, and `every_command_label_is_in_the_english_catalog` fails if a
|
||||
command is added without one.
|
||||
|
||||
The context menu and the browser are the same case again, and they carry the most labels of all:
|
||||
`every_menu_label_is_in_the_english_catalog` opens every menu the app can reach, flips the state
|
||||
each conditional label branches on (origin shown, bodies locked, bodies hidden) so both branches
|
||||
are seen, and fails on any label the catalog has never seen. Unit symbols are left out of the
|
||||
sweep: `mm` is `mm` in every language, so they are not prose to translate. The sweep also asserts
|
||||
it keeps reaching a broad set of labels, so it cannot pass by finding nothing.
|
||||
|
||||
`cargo xtask i18n` prints the same picture across every locale — which messages each one is
|
||||
missing and which command labels English cannot translate. `--check` turns it into a non-zero exit
|
||||
for CI. `--add-missing` writes each uncovered label into `en.json` under `cmd.<command id>`, with
|
||||
the English label as its text, so the label adapter can find it and only the translations are left
|
||||
to do. One key per distinct label: two commands that share a label (`Trim`, `Extend`) must not both
|
||||
claim it, or the English-text lookup would silently pick one.
|
||||
|
||||
## Rendering and coverage
|
||||
|
||||
One immutable `Locale` type handles all translations. Table widgets without an app reference
|
||||
@@ -31,18 +63,23 @@ Standalone translated panels enter the same scope. Measure rendered text to size
|
||||
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.
|
||||
`CRAFT_FONTS_DIR` font pack, and skips files that cannot be parsed. Chinese uses its own fallback
|
||||
chain after the general CJK font: many Japanese CJK fonts (Hiragino Gothic, Meiryo, Yu Gothic)
|
||||
match the CJK font search but lack simplified characters, so a second fallback found by the
|
||||
Chinese font-name list (`PingFang`, `Microsoft YaHei`, `Noto Sans CJK SC`, …) covers them per
|
||||
glyph. 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
|
||||
origin (`./fonts/BIZUDPGothic-Regular.ttf`) on-demand when the interface language is a CJK one, 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.
|
||||
A session that never shows such text downloads no font. If font loading fails with a CJK 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. The bundled font specifically targets Japanese; it also
|
||||
renders the kanji Chinese shares with Japanese, while Korean (Hangul) and simplified-only Chinese characters
|
||||
are not covered, so a self-hosted SC/Korean font bundle remains follow-up work for full web coverage.
|
||||
|
||||
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
|
||||
|
||||
Reference in new issue
Block a user