mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-26 19:07:06 -06:00
* Update mod.rs * Update system.rs * Update live_tests.rs * Update localization.md * Italian UI translation (it) * Register Italian fully and bring the catalog up to date - LANGUAGES grows to 13 entries (the array length was still 12), with the native name Italiano. - The system-locale test expects the code `it`, not `it-IT`. - Italian joins the i18n coverage report, ATTRIBUTION.md and LICENSE-translations.txt. - Translate the strings main gained since the catalog was written, and fix two comments copied from the Spanish catalog. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
118 lines
6.3 KiB
Markdown
118 lines
6.3 KiB
Markdown
# UI localisation and live language switching
|
|
|
|
PhotoCraft uses the same Rust catalog implementation in the native egui shell and the
|
|
WebAssembly build. English source strings are lookup keys. UTF-8 TSV catalogs supply plain,
|
|
contextual, command-ID and plural translations; missing entries fall back to English.
|
|
|
|
## Supported languages
|
|
|
|
| Language | Preference code | Integer plural forms |
|
|
|---|---|---|
|
|
| English | `en` | one / other |
|
|
| 简体中文 | `zh-hans` | one form |
|
|
| 日本語 | `ja` | one form |
|
|
| 한국어 | `ko` | one form |
|
|
| Русский | `ru` | one / few / many |
|
|
| Français | `fr` | singular for 0 and 1 / plural for 2+ |
|
|
| 繁體中文 | `zh-hant` | one form |
|
|
| Español | `es` | one / other |
|
|
| Čeština | `cs` | one / few / other |
|
|
| Deutsch | `de` | one / other |
|
|
| Bahasa Indonesia | `id` | one form |
|
|
| Português (Brasil) | `pt-br` | singular for 0 and 1 / plural for 2+ |
|
|
| Italiano | `it` | one / other |
|
|
|
|
Every non-English catalog covers the current menu labels, `tl!` literals, blend mode names,
|
|
and generated preference labels. Tests enforce that coverage. This does not include every
|
|
engine error or status message: those remain English, as do automation command IDs and
|
|
user-provided document, layer and preset names.
|
|
|
|
## Switch without restarting
|
|
|
|
Open **Edit > Preferences > Interface > Language** and choose a language. The Preferences
|
|
dialog previews its title, controls and buttons in the chosen language. **Cancel** discards
|
|
the preview, **Apply** commits it without closing the dialog, and **OK** commits and closes.
|
|
The rest of the interface follows the committed preference on its next draw. Existing
|
|
documents, undo history and tools remain available throughout a language change.
|
|
|
|
The existing preference store saves the selection for future launches. `auto` follows the
|
|
native system locale; an unsupported code follows the same fallback. Regional tags such as
|
|
`fr-CA`, `ko-KR` and `zh-CN` resolve to the corresponding registered catalog. Traditional and
|
|
Simplified Chinese remain distinct. Every Portuguese locale (`pt`, `pt-BR`, `pt-PT`) uses the
|
|
Brazilian Portuguese catalog.
|
|
|
|
### First launch and system language
|
|
|
|
With no saved preference, `interface.language` defaults to `auto`, so the first rendered
|
|
window uses the first supported system UI language. An older preferences file without this
|
|
field also uses Auto. If detection fails or none of the preferred languages is registered,
|
|
the UI uses English (`en`). A saved manual language choice takes precedence on later launches;
|
|
startup never overwrites it or writes the detected language into the preference file.
|
|
|
|
The native-only, pinned `sys-locale` dependency provides safe Rust access to the platform APIs:
|
|
|
|
- **Windows:** `GetUserPreferredUILanguages`, in the user's preferred order. This uses UI
|
|
languages rather than the Region setting for dates and numbers; they can differ.
|
|
- **macOS:** `CFLocaleCopyPreferredLanguages`, in preferred order, without starting `defaults`
|
|
or depending on a particular `.plist` representation.
|
|
- **Linux/BSD:** the platform's standard locale environment, including `LANGUAGE` lists.
|
|
|
|
`PHOTOCRAFT_LOCALE` is an optional single-tag override for reproducible launches; an unsupported
|
|
override falls back to English. Empty overrides use the system. Unix locale variables do not
|
|
override Windows/macOS UI-language preferences. Tags are read once per process (at most 64,
|
|
128 bytes each) and matched against the supported language registry. Changes to the
|
|
OS language list itself take effect at the next launch. The web build keeps its existing
|
|
English Auto fallback until browser-locale detection is implemented.
|
|
|
|
API implementation and licensing: [sys-locale](https://github.com/1Password/sys-locale).
|
|
|
|
Agents use the existing `prefs.set` command through CLI, MCP or the desktop control channel:
|
|
|
|
```json
|
|
{"method":"engine.execute","params":{"command":"prefs.set","params":{"path":"interface.language","value":"ko"}}}
|
|
```
|
|
|
|
Control requests are processed before synchronising the drawing language, so a request
|
|
updates the labels in the same rendered frame. Drawing language is local to the UI thread;
|
|
a scoped preview restores the previous language even if drawing unwinds. Menu and dialog
|
|
identity continues to use command IDs, independent of translated labels.
|
|
|
|
This is hot switching among the bundled catalogs. Catalog files are embedded with
|
|
`include_str!`; editing a TSV file requires a rebuild. External catalog watching and
|
|
file-resource hot reload are not implemented.
|
|
|
|
## Fonts
|
|
|
|
The native lazy CJK font loader prioritises the selected Japanese, Korean or Chinese script.
|
|
Switching languages rebuilds the font definitions and resets the existing loader, so fonts
|
|
removed from the definitions can be registered again. Idle frames keep their font cache.
|
|
Other languages retain the system's CJK fallback preference for document names and text.
|
|
|
|
Font files are not added to this repository. Native rendering uses installed system fonts
|
|
and the optional craft-fonts build input; see [Fonts](development.md#fonts-craft-fonts).
|
|
The web build can select every catalog, but CJK glyph delivery and automatic browser-locale
|
|
detection remain separate outstanding work. Switching catalogs does not supply missing fonts.
|
|
|
|
## Add or maintain a catalog
|
|
|
|
1. Add `<code>.tsv` under `crates/ui-egui/src/i18n`, following the header in `ja.tsv`.
|
|
2. Register its code, native name and plural rule in `i18n::LANGUAGES`.
|
|
3. Translate the meaning of the English source keys. Preserve `{name}` placeholders, escaped
|
|
characters and the trailing `…` on dialog commands. Use `@id` to disambiguate a command
|
|
label and `@plural` for count-sensitive text. Keep product names such as PhotoCraft.
|
|
4. Set `complete_menus` when the catalog covers all enforced keys. Add source and license
|
|
attribution for translation assets, then run the catalog and shell tests.
|
|
|
|
```sh
|
|
cargo test -p photocraft-ui-egui --locked
|
|
cargo clippy -p photocraft-ui-egui --all-targets --locked -- -D warnings
|
|
cargo xtask i18n-coverage
|
|
cargo xtask layers
|
|
cargo xtask wasm
|
|
```
|
|
|
|
Render representative dialogs with the offscreen `snapshot` example, including a sequence
|
|
of language changes in one process. Inspect the PNGs for missing glyphs and truncated labels.
|
|
Translations are original work or reuse the open PhotoCraft contributions credited in
|
|
[ATTRIBUTION.md](../ATTRIBUTION.md); no proprietary localisation resources are used.
|