Skip to content

UI Localization Guide

Use this guide when adding or changing text that people see in an RIGOR Web application. It explains which translations are shared, which remain owned by a module, how a browser chooses a language, and how to validate locale parity.

ASCEND, Composer, PACE, LabBridge, LabFlow, and PRISM share one language-preference contract while keeping separate product dictionaries. English is the fallback language; Simplified Chinese and Spanish are the other supported locales.

Structure

text
packages/ui-i18n/src/common.js             shared actions, chat, and state labels
packages/ui-i18n/src/index.js              detection, persistence, and i18next setup
*/web/admin/*/locales.js                    English and Chinese product copy
*/web/admin/*/locales.es.js                 Spanish product copy where split out
labflow/web/admin/src/locale.js             native DOM localization adapter
prism/web/admin/src/locales.js              PRISM product copy
scripts/check-ui-locales.mjs               locale key parity check

Keep product-specific text in the owning application. Move a key to common.js only when its meaning and wording are genuinely shared.

The React applications use i18next directly. LabFlow keeps its existing native JavaScript architecture and applies the same dictionaries and preference contract through locale.js; this avoids coupling localization to a framework migration.

Language preference

The browser resolves a language in this order:

  1. ?lang=en, ?lang=zh-CN, or ?lang=es
  2. sdlx_locale cookie
  3. sdlx.locale local storage value
  4. browser language
  5. English

On *.sdl.digauto.org, the cookie is written with Domain=.sdl.digauto.org, Path=/, SameSite=Lax, and Secure, so the selection follows the user between RIGOR modules. Local development uses a host-only cookie and local storage.

The locale cookie is a UI preference, not an authentication or authorization mechanism.

Every module exposes the same segmented English, Simplified Chinese, and Spanish control. Do not replace it with a select menu: all supported choices should remain visible and the active language should be immediately apparent.

Translation boundary

Translate navigation, commands, labels, known status enums, validation headings, empty states, and help text. Do not translate experiment goals, agent messages, device identifiers, parameter keys or values, artifact content, backend errors, or durable audit records.

Unknown backend enum values fall back to a readable version of the original value. Add an explicit translation when the enum becomes part of a stable contract.

Adding copy

Add the same nested key to en, zh-CN, and es in the owning locale resources, then render it with tr("section.key"), tx("Visible label"), or useTranslation() inside reusable React components. LabFlow's native adapter translates exact known UI strings and attributes; keep YAML, identifiers, device data, and runtime output outside that boundary. Use interpolation for counts and dynamic labels rather than concatenating translated fragments.

Run the parity check directly:

bash
node scripts/check-ui-locales.mjs

All six application builds run their relevant locale check as part of npm run build.

RIGOR product, architecture, operations, and contributor documentation