For the complete documentation index, see llms.txt. This page is also available as Markdown.

Multilingual UI

Seven locale translations for the ODD Platform UI shell — loaded at SPA bootstrap, switched via the toolbar, persisted per browser in localStorage. Operator-authored content stays verbatim.

The ODD Platform UI ships with seven locale translations loaded at SPA bootstrap. Users switch the active locale from the user-account menu in the top-right of the toolbar; the choice persists per browser device in localStorage. The platform's API surface remains English-only — the localisation applies to the UI shell (toolbar labels, page titles, button captions, form field labels, error messages); operator-authored content (entity descriptions, glossary terms, custom-metadata field names, namespaces, tag names) is rendered verbatim regardless of the active locale.

Supported locales

The platform's translation table currently includes seven entries, sourced from odd-platform-ui/src/locales/translations/:

Code
Language

en

English (default)

es

Spanish

ch

Chinese

fr

French

ua

Ukrainian

hy

Armenian

br

Brazilian Portuguese

The default is en — a fresh browser session with no prior locale selection lands on English. The br locale (Brazilian Portuguese) ships from platform release 0.28.0 — a community contribution (odd-platform#1564); deployments on earlier releases offer the original six.

How users switch

The active locale is changed from the user-account menu in the top-right of the toolbar — the area showing your username next to a dropdown arrow. Click it to open the account dropdown (the same menu that holds Logout), then click the Select language entry — it shows the current language and a chevron. That opens a Select language dialog with one searchable entry per supported locale. Picking a locale takes effect immediately on the current page; subsequent SPA navigation continues in the chosen locale.

Persistence model — per-device, not per-user-account

The chosen locale is stored in the browser's localStorage under the key i18nextLng. The implications operators should know:

  • Per browser device. The locale preference is bound to the browser profile, not to the user's catalog account — signing in from a different browser, a different machine, or an incognito session starts from the default (en) until the user picks again.

  • Survives logout and re-login. The localStorage value is not cleared by sign-out; the next sign-in from the same browser resumes the prior locale choice.

  • No server-side propagation. The platform does not record the user's locale preference on the server, does not honour an Accept-Language HTTP header, and does not push the choice to other devices the same user is signed in on.

If the deployment serves a user population that uses multiple devices and expects a single, account-bound locale choice — for example a company-managed account propagating across the user's laptop and phone — this is a known absence; the per-device localStorage model is the only persistence path today.

Known caveat — how missing translations behave (and the 0.28.0 catch-up)

Each locale's translation table uses the English text itself as the lookup key (for example "Activity": "Activity"). When a key a component asks for is missing from the active locale, i18next falls back to English (the fallbackLng: 'en' setting) — the English label renders with no warning and no visible marker. A locale can therefore look fully translated and still show English wherever its table trails the code.

As of 0.28.0 every shipped locale table is complete. Earlier releases carried a real gap: a June 2026 sweep found code-referenced keys (about 70, growing to 84 as more UI surfaces landed) absent from every non-English catalog — confirmation dialogs, the Data Quality dashboard headlines, lookup-table and query-example labels, the activity-feed actor tooltips — so a non-English locale showed English in those spots. odd-platform#1748 fixed the first slice (the three top-level navigation tabs — Data Quality, Data Modelling, Master Data — which had been absent from every bundle); odd-platform#1751 completed the rest, translating the remaining 84 keys into all six non-English catalogs (es, ch, fr, ua, hy) and the seventh, br — which had separately trailed by eight keys, including the Master Data tab. All seven catalogs (en, es, ch, fr, ua, hy, br) now carry the same key set. A separate gap was also closed in 0.28.0: a number of UI strings were hardcoded in the source with no translation lookup at all (so they showed English under every locale, independent of the catalogs) — these were wrapped so they pass through the translation layer and were translated across all seven locales. Three automated build checks now keep this from regressing: a key-parity check (every locale must carry the English key set), a no-untranslated-string check (a new user-facing label that skips the translation layer fails the build — covering both JSX text and component attributes such as placeholders and labels), and — added in 0.29.0 — a symbolic-key value check. So the gap should not silently reopen as new screens are built.

The third check guards a subtler defect than a missing key. Because the keys are the English text, a translator working from the key list alone can mistranslate the one symbolic key — main search placeholder, whose English value is the home-page search hint (Search data tables, feature group, jobs and ML models via keywords) rather than the key itself. All six non-English catalogs had rendered it as a literal gloss of the key ("main search space" / "main search pointer" / the i18n word "placeholder" in Chinese), so a non-English operator saw meaningless text on the first surface they meet — the home-page catalog search box. The 0.29.0 fix translated the hint into every locale, and the new check now requires every non-English value of a symbolic key to be a translated hint, not a literal gloss of the key (odd-platform#1776).

These bulk catch-up translations were contributed in one pass; native-speaker refinements to any string are welcome — correcting an existing translation is the same workflow as adding a new locale (see How to contribute a new locale below), applied to the value already in the JSON.

The fallback mechanism remains by design: a future code change that introduces a new t('...') string renders the English label under any locale whose table has not yet caught up. For completeness audits, treat the translation-table JSON files as the source of truth, not the running UI — because a missing key shows the English text, an English-locale UI always looks complete. On releases that predate 0.28.0, the gaps described above are present.

How to contribute a new locale

Adding an eighth locale (or any subsequent locale) is a contributor-facing workflow on the UI repository (odd-platform). The shape:

  1. Create a new translation file at odd-platform-ui/src/locales/translations/{code}.json (where {code} is the locale code — typically the 2-letter ISO 639-1 code, or the project's own short code such as ch for Chinese or br for Brazilian Portuguese). The file mirrors the structure of the existing translation files; the simplest start is to copy en.json and translate each value.

  2. Register the locale in the bootstrap module at odd-platform-ui/src/locales/i18n.ts — add the import and add the entry to the resources map (and, to keep it consistent with the others, add the code to the fallbackLng array). The resources map is what populates the picker, so this step is what makes the locale selectable.

  3. Add the new code to both maps in odd-platform-ui/src/lib/constants.ts — LANGUAGES_MAP (code → display name, shown in the picker) and LANG_TO_COUNTRY_CODE_MAP (code → flag country code). These are required: the Select language dialog renders each row by looking the code up in these maps, and a code that is missing from LANGUAGES_MAP will break the picker. The Lang type is derived from LANGUAGES_MAP, so adding the key here is also what makes the rest of the code recognise the new locale.

  4. Open a pull request against the UI repository. The contribution does not require platform-API changes, and the Select language dialog needs no edits — it builds its list from the registered locales automatically. odd-platform#1564, which added Brazilian Portuguese, is a complete worked example of exactly this shape — three files, no other changes.

The build-and-run workflow for the platform (including the frontend UI) is documented at Build and run ODD Platform.

Where to next

  • Management — the operator surface inside the platform UI; the localisation applies to the Management section's tab labels and form controls.

  • Main Concepts → Terms & Aliases — the alias registry where "Multilingual UI", "i18n", "internationalisation", and "locale switching" point at this page.

Last updated