Skip to main content

UI Strings and Translations

Source of truth: en.json

All user-facing UI strings live in a single English resource file in the frontend repository:

src/translations/en.json

It is a nested JSON object (roughly 8,200 strings) whose top-level sections are panel, state, state_badge, groups, config_entry, ui, and landing-page. String keys are addressed by their flattened dot path, for example:

{
"ui": {
"common": {
"cancel": "Cancel"
}
}
}

is referenced as ui.common.cancel.

The localize function

Components never hardcode user-facing text; they resolve keys through the localize function, which is available on the application state object:

this.apex.localize("ui.common.cancel");

Its signature:

type LocalizeFunc = (
key: LocalizeKeys,
values?: Record<string, string | number | HTMLTemplateResult | null | undefined>
) => string;
  • Keys are type-checked. LocalizeKeys is generated by flattening the shape of the translation dictionary, so a typo in a key is a TypeScript error in most categories.
  • Messages use ICU MessageFormat. Strings are compiled with intl-messageformat, so they support placeholders, plurals, and selects. The values argument fills the placeholders:
this.apex.localize("ui.panel.my_feature.greeting", { name: user.name });
// with "greeting": "Hello, {name}!"

Compiled messages are cached per key/locale, and missing or malformed messages degrade gracefully (an empty string, plus a translation-error event for reporting) rather than crashing the UI.

If a string is missing from the active locale, the frontend falls back to English.

Adding strings as a contributor

  1. Add the English string to src/translations/en.json in the same pull request as the feature that uses it, following the existing nesting for its category (ui.panel.<panel>.…, ui.components.…, ui.dialogs.…, etc.).
  2. Reference it in code via localize("your.new.key").
  3. Do not edit any other locale. English is the only language maintained in the repository; the other locales (64 languages are listed in the frontend's translation metadata) are produced through the project's translation pipeline and flow back into builds automatically.

During a build, the gulp build-translations step turns the resource files into the per-locale fragments the app loads at runtime. For development against up-to-date community translations, script/setup_translations configures fetching the latest translation snapshots.