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/:
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
localStoragevalue 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-LanguageHTTP 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:
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 aschfor Chinese orbrfor Brazilian Portuguese). The file mirrors the structure of the existing translation files; the simplest start is to copyen.jsonand translate each value.Register the locale in the bootstrap module at
odd-platform-ui/src/locales/i18n.ts— add the import and add the entry to theresourcesmap (and, to keep it consistent with the others, add the code to thefallbackLngarray). Theresourcesmap is what populates the picker, so this step is what makes the locale selectable.Add the new code to both maps in
odd-platform-ui/src/lib/constants.ts—LANGUAGES_MAP(code → display name, shown in the picker) andLANG_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 fromLANGUAGES_MAPwill break the picker. TheLangtype is derived fromLANGUAGES_MAP, so adding the key here is also what makes the rest of the code recognise the new locale.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