Disciplines · Launch

Oshun V1 Translation Workflow

Shared shell strings — anything that appears in the customer shell chrome or in the assistant compliance/disclosure copy — live in the canonical catalog at

9sections5 minread

On this page

Companion to docs/launch/locale-coverage.md. Defines the workflow, glossary ownership, language fallback, RTL handling, and text-expansion QA that govern customer-facing strings in libs/oshun/i18n/ and domain-owned catalogs.

Catalog ownership#

Surface or domain Source-of-truth catalog Owner
Shared shell strings libs/oshun/i18n/src/index.ts (CUSTOMER_MESSAGES) Platform UI + localization
Assistant disclosures libs/oshun/i18n/src/index.ts T&S + assistant product
Privacy disclosures libs/oshun/i18n/src/index.ts Privacy + legal
Tara content libs/oshun/i18n/ shared keys + Tara seed/content records Tara editorial
Veritas content libs/oshun/i18n/ shared keys + Veritas seed/content records Veritas editorial
Nyx event copy libs/oshun/i18n/ shared keys + Nyx seed/content records Nyx editorial
Arete prompts libs/oshun/i18n/ shared keys + Arete seed/content records Arete product
Nisaba metadata libs/oshun/i18n/ shared keys + canonical passage metadata Nisaba editorial
Metis course frames libs/oshun/i18n/ shared keys + Metis course seed records Metis product
Persona disclosures persona records inside libs/oshun/persona-policy-lilith/ T&S persona ops
Operator (admin) strings apps/oshun/admin/src/i18n/ Admin product

Shared shell strings — anything that appears in the customer shell chrome or in the assistant compliance/disclosure copy — live in the canonical catalog at libs/oshun/i18n/. Domain-owned content records may carry source text, but their customer-visible shared labels, disclosures, status copy, formatting rules, fallback rules, and launch-locale metadata depend on this package and may not redefine its keys.

Glossary#

A single glossary, owned by the localization lead, governs proper nouns, persona names, domain names (Tara, Veritas, Nyx, Arete, Nisaba, Metis), and trust-and-safety terminology that must read identically across surfaces.

  • Glossary location: libs/oshun/i18n/glossary/. Each glossary entry is JSON: source term, allowed translations per locale, do-not- translate flag, gender/animacy hints, disclosure context.
  • Glossary review: localization lead + T&S lead sign-off for terms that touch persona identity or refusal copy.
  • Glossary lint: a glossary-coverage check runs against every PR that adds or modifies a translation: terms in the glossary must translate to the allowed values per locale; do-not-translate terms must remain in source language. Failures block merge.

Fallback chain#

The runtime fallback for a missing key is:

  1. Requested locale (e.g., es-US).
  2. Language-only locale (e.g., es).
  3. en-US.

The chain is implemented in resolveFallbackChain and translate in libs/oshun/i18n/src/index.ts. The same package also exposes the mapping from legacy customer language preferences (en, es, etc.) to launch locales (en-US, es-US, etc.) so web and mobile selectors cannot advertise languages outside the V1 launch coverage list. A fallback hit emits an analytics event so that gaps surface in the launch dashboards.

A fallback gap discovered on a critical surface (disclosure, privacy, crisis) is a sev2 — it does not block GA, but it blocks the locale from being marked launch-quality for that surface.

RTL handling#

ar and he are RTL launch locales. Every shell, domain, and admin surface must:

  1. Mirror the layout: the primary visual flow runs right-to-left.
  2. Mirror icons that imply direction (back/forward, next/previous, chevrons, sliders).
  3. Preserve bidi safety: customer-controlled strings appear inside bidi-isolated runs.
  4. Number and digit policy: western numerals by default; Arabic-Indic digits opt-in per content piece for ar.
  5. Punctuation: locale-correct quotation marks, dashes, ellipsis.

The cross-cutting RTL test suite lives at tests/locale/rtl-smoke.spec.ts and runs against every locale-tagged view in Playwright.

Text-expansion QA#

Every shell layout is verified against the LOCALE_EXPANSION_BUDGET table in the i18n library:

  • en-US: 1.0 baseline.
  • es-US: 1.25.
  • fr-FR: 1.3.
  • de-DE: 1.4.
  • ar: 1.2 (script width plus mirroring).
  • he: 1.15.
  • ja-JP: 0.7 (denser script).
  • pt-BR: 1.3.

The customer preference aliases exposed in profile settings and the language switcher are launch-scoped: en, es, fr, de, ar, he, ja, and pt. Unsupported prelaunch aliases such as zh, ko, and hi are not surfaced to customers until they receive a launch-locale coverage row and full catalog coverage.

QA generates synthetic strings at each locale's budget against every catalog key, drops them into the shell, and verifies no truncation, no unintended wrap, no overflow into the next region. Failures are filed against the shell owner; layout fixes are required before the locale can be marked launch-quality.

Translation workflow#

  1. Author the source string in en-US in the matching catalog. PRs must include a one-sentence translator note when the meaning is non-obvious (e.g., "disclosure copy — must read calmly, not alarming").
  2. Run the catalog-lint check locally; this verifies the key is declared in the type union and the placeholder convention is correct.
  3. Trigger the localization pipeline: the localization lead routes the new key to the contracted translators with context (surface, character budget, tone, glossary references).
  4. Review the returned translations: locale leads + glossary lint + visual review against the actual surface (Storybook or staging) at the expansion-budget length.
  5. Land the translations: PR merges only when every launch locale has a translation (the every customer message key has a translation in every launch locale test enforces this).
  6. Run the runtime smoke: in staging, render the surface in every locale; verify no fallback hits, no truncation, no RTL break.

Audit and provenance#

  • Every change to CUSTOMER_MESSAGES lands with the i18n maintainer + matching domain maintainer review.
  • Trust-and-safety disclosure copy changes require T&S sign-off.
  • Privacy disclosure copy changes require privacy + legal sign-off.
  • The translation pipeline records translator identity (team or contractor), timestamp, and source-language hash so customer-facing disclosures have a clean provenance audit trail.

Adding a new launch locale#

Adding a locale is a launch-class change:

  1. Add the locale to OSHUN_LAUNCH_LOCALES.
  2. Add a row to LOCALE_EXPANSION_BUDGET, LOCALE_CALENDAR, and RTL_LOCALES if applicable.
  3. Translate every key in CUSTOMER_MESSAGES.
  4. Run the RTL smoke and the expansion-budget QA across every shell.
  5. Update docs/launch/locale-coverage.md to reflect the locale's coverage tier.
  6. Run the locale-coverage gate at the next release-readiness review.

Until every catalog entry passes the test suite, the locale stays in the staging-only tier and is not surfaced to customers.

Owner#

Localization lead owns this workflow. Platform UI lead, T&S lead, privacy lead, and legal counsel co-review changes that affect disclosure or trust-touching copy. Updates require sign-off from localization plus any affected co-owner.