Skip to content
Xila
Demonstration

Internationalization

Understand Xila's build-time locale selection and external embedded-i18n integration.

Last updatedEdit page

Xila uses the external embedded-i18n dependency for build-time localization. Core re-exports it as xila::internationalization; there is no separate internationalization crate under the new libraries/ tree.

Core’s .cargo/config.toml selects locale and fallback using EMBEDDED_I18N_LOCALE and EMBEDDED_I18N_FALLBACK. English is the fallback. Executables use embedded_i18n::translate! for ordinary and C-string literals and keep translations in their locales/ directories.

Core and Applications maintain compiled catalogs for English (en), French (fr), Spanish (es), German (de), Brazilian Portuguese (pt-BR), Italian (it), Polish (pl) and Simplified Chinese (zh-CN). The seven Latin-script locales are included in the deployment demonstrations; Chinese can be built and validated but has not completed native-speaker/embedded-device review and is not enabled in deployment bundles. Languages require separately built, matching host, guest and seed-image artifacts; no runtime language selector is implemented.

The selected translations are embedded in the build. This avoids carrying a dynamic catalog lookup in each runtime call; language choice belongs to the build configuration rather than a live session-language service. Quantity-dependent text uses CLDR plural variants where needed (for example, stopwatch laps, DNS record counts and ping byte counts); Polish requires one, few, many and other.

The Graphics crate’s Rust build helpers generate and cache deduplicated font-range variants in Cargo OUT_DIR. Every font C object has a unique symbol; subsystems/graphics/src/fonts.rs selects the six active locale/fallback symbols at compile time so unselected archive members do not add font data to the linked executable (Core #508). For zh-CN, Source Han Sans SC provides only the Chinese characters and punctuation found in selected translation values, rather than the full CJK range (Core #456). Arbitrary user-supplied Chinese is not guaranteed covered. The standalone fonts_generator task remains removed. Node is used to run lv_font_conv, not for Rust catalog discovery.

Core #517 migrated the Rust macro calls and JSON catalogs from English-message keys to stable semantic IDs, formatted as lowercase snake_case segments separated by dots (feature.component.purpose). Wording-only edits retain the ID; meaning or placeholder-contract changes require a new ID and translator review. Separate contexts should not share a key solely because their English text matches. CLDR plural suffixes (for example .one, .few, .many, .other) remain locale-specific. The migration retained translation values but did not migrate remote Tolgee history or keys; avoid destructive synchronization without an explicit migration plan.

Tolgee extraction uses tolgee.config.ts and a token-aware Rust macro scanner in tolgee.extractor.mjs. Per-namespace old-to-new mappings and validation are in tools/localization/mappings and tools/localization/check.mjs. See tools/localization/README.md for conventions and the development command reference for current mise commands.

All 160 non-empty catalogs across 20 localized namespaces and eight locales now use nested JSON objects instead of flat keys. Rust macro calls and Tolgee still use the same stable dotted semantic identifiers; translated values and locale-specific CLDR plurals were preserved.

{
"alarm": {
"controls": {
"delete": "Delete"
}
}
}

This is accessed as translate!("alarm.controls.delete"). The shared tools/localization/catalog.mjs flattener rejects duplicate paths and parent/leaf collisions rather than silently overwriting keys. tolgee.config.ts retains JSON_C and sets pull.delimiter: "." to export nested JSON; push.removeOtherKeys remains false. A real remote Tolgee push/pull was not validated in #528: inspect the first synchronization carefully and avoid tolgee pull --empty-dir during migration.

Test the new catalog behavior with node --test tools/localization/catalog.test.mjs, mise run localization:lint and the usual strict per-locale builds. See tools/localization/README.md.

Xila does not currently maintain a separate internationalization crate in libraries/. Instead, its entrypoint re-exports the external embedded-i18n crate and the project provides locale catalogs and build tooling. This page describes that cross-cutting build integration, not a runtime manager.

Use the build-time locale and fallback consistently across host binaries, WebAssembly guests, generated fonts and reference seed images. Locale strings are compiled into the binaries, so changing the preferred language requires rebuilding compatible artifacts; there is no persistent per-user runtime language selector.

embedded_i18n::track_locales!() declares the translation integration for crates with catalogs, while translate! selects the appropriate compiled key. Pluralized strings need the CLDR categories supported by each locale: missing few or many variants are especially noticeable in Polish.

  1. Add a stable dotted semantic ID to an executable/library translate! call, keeping user-facing English text in its en.json catalog. Do not use the English message itself as the key.
  2. Add translations under that crate’s locales/<locale>.json, preserving the intended namespace and plural categories.
  3. Run mise run localization:lint and node --test tolgee.extractor.test.mjs; check tools/localization/mappings/ for historical key mapping and use strict per-locale compilation (EMBEDDED_I18N_LOCALE=fr EMBEDDED_I18N_STRICT=1 mise run localization:check) for affected locales. Do not remove unused Tolgee keys automatically.
  4. Build host, guests and seeded disk content for the same locale. Cargo regenerates and compiles the locale-dependent graphics font archive as needed; install the Core workspace’s Node dependencies with npm ci before building graphics.
  5. Check text truncation, symbol availability and UI layout in Graphics.

The Graphics font inputs live in subsystems/graphics/fonts/ and generation is handled by subsystems/graphics/build.rs, rather than by a separate executable. These build artifacts are not a runtime localization subsystem.

English fallback prevents missing-key failures but does not guarantee appropriate terminology or glyph coverage. Language completeness needs review on the actual display and guest programs.