Skip to content

[P0 Localization Gap] Add versioned eight-locale translation resource ledger #308

Description

@seonghobae

Buyer-visible failure

Protected main@193a87ef54c3fe6dcda4755bce4d6bc81e3a0297 does not satisfy the LifeOS product locale contract.

Current Web localization is browser/static-catalog authority:

  • apps/web/app/localization.ts defines SupportedLocale = 'en' | 'ko' and imports only static en.json / ko.json catalogs;
  • apps/web/messages/ contains only those two locale files;
  • localization.test.ts proves structural parity only between Korean and English and falls unsupported fr / ja preferences back to English;
  • Today stores the selected locale only in browser localStorage under life-os.locale.v1 and derives fallback from navigator.languages.

This is useful bootstrap behavior, but it cannot provide durable cross-device locale preference, KO/EN/JA/ZH/VI/ES/DE/FR resource parity, reviewed resource versions, deterministic cache invalidation, or buyer-verifiable screen-key provenance.

Required outcome

LifeOS must support KO/EN/JA/ZH/VI/ES/DE/FR through a server-backed, versioned translation resource ledger and a bounded screen-key cache. A returning user on another device receives the durable locale preference and an exact resource version without the browser becoming the persistence owner.

The translation ledger is separate from the ontology-label ledger. It is not a requirement to preload a full browser catalog or build a monolithic translation SPA. Browser bundles/cache entries may remain screen-scoped and lazy as long as version/provenance and fallback semantics are explicit.

DDD ownership decision before production implementation

Do not place a new translation database behind Web merely because Web renders strings, and do not place arbitrary translation-resource truth in Identity merely because Identity can own user preference.

The first implementation PR must carry a Proposed ADR/Context Map choosing one canonical owner for translation resources. The preferred decomposition to evaluate is:

  • Identity / Account Settings owns only durable user locale preference and the authenticated preference mutation/read contract;
  • a Localization supporting bounded context owns translation resource versions, locale/screen/message-key values, review/publication state, resource digests and cache-version evidence;
  • Web consumes released/versioned localization contracts through its server boundary and keeps only bounded screen-key cache/materialized browser-safe resources;
  • ontology/concept labels remain outside this ledger and are consumed through their own semantic owner contract.

If an existing service is selected instead of a new Localization bounded context, the ADR must show why its ubiquitous language, aggregate ownership, persistence lifecycle and service credentials are actually compatible. Convenience co-location is not sufficient.

Minimum domain model

The canonical contract must make these concepts explicit and map them to API/DB/test artifacts:

  • LocaleCode — allowlisted canonical locale identity for ko, en, ja, zh, vi, es, de, fr;
  • ScreenKey and MessageKey — stable product/UI identities, not translated text and not ontology identifiers;
  • TranslationResourceVersion — immutable published version identity with creation/publication evidence;
  • TranslationEntry — locale + screen key + message key + value + review/publication state;
  • TranslationResourceDigest — deterministic digest over the exact published resource set;
  • explicit publication invariant: a version cannot be treated as complete for a declared screen until all required locale/key pairs are present and reviewed;
  • explicit fallback invariant: missing/invalid resources fail visibly or follow a documented deterministic fallback; they are never silently mistaken for complete localization.

Use service-owned PostgreSQL persistence/migrations/credentials, 3NF naming, bounded queries, deterministic ordering and idempotent publication. No cross-service SQL or source copy.

Locale-preference boundary

Durable locale preference is account/user evidence, not browser authority.

  • authenticated server authority determines the user/workspace context;
  • browser input may request one allowlisted locale but cannot nominate user/workspace identity;
  • persistence returns exact canonical locale evidence;
  • cross-device reads recover the same preference;
  • anonymous/local preference may remain local until explicit authenticated attachment/consent;
  • malformed/case/whitespace aliases must follow an explicit request-normalization contract and durable stored evidence must already be canonical;
  • locale preference and translation resource version are separate identities and may evolve independently.

Screen-key cache contract

The browser/server cache must be bounded by at least locale + screen + exact published resource version/digest. A stale cache from version N must not be treated as version N+1 after publication.

Required states include cold miss, warm hit, version rollover, missing key, resource unavailable, permission/error path and recovery. Do not hide resource failures by shipping an untracked hard-coded English string on a screen declared complete.

RED acceptance

Start with realistic regression evidence against protected behavior, not production implementation. At minimum prove that current protected source cannot satisfy:

  1. ja, zh, vi, es, de, fr as first-class supported locale contracts;
  2. durable cross-device locale preference without relying on localStorage;
  3. exact resource-version binding for a screen cache;
  4. eight-locale screen-key completeness/publication;
  5. deterministic stale-cache invalidation after a new resource version;
  6. translation-ledger / ontology-label separation.

Do not make the first RED a synthetic in-memory-only replacement for required persistence behavior. Unit fixtures may be synthetic, but PostgreSQL and buyer-path evidence must use the real migrations/adapters once production persistence exists.

GREEN acceptance

  • KO/EN/JA/ZH/VI/ES/DE/FR are valid canonical product locales with published resource evidence.
  • Account locale preference is durable, authenticated and recoverable across devices.
  • Translation resources are DB-versioned and immutable once published; supersession creates a new version rather than mutating historical evidence.
  • Every declared complete screen has locale/key parity for the exact published version.
  • Web fetch/cache is screen-scoped and exact-version-bound; stale versions cannot masquerade as current.
  • Missing/unavailable resources are explicit states, never silent success.
  • CJK font fallback, text expansion, truncation/overflow, keyboard/focus/accessibility labels and responsive layouts are exercised per material screen.
  • Storybook/E2E covers normal/loading/empty/error/permission/offline/cache-rollover states where applicable and references the relevant Figma node/token authority.
  • Owned production statement/branch/function/line coverage, edge cases and production docstrings remain at repository-enforced targets.
  • If a buyer-path API is introduced, current-head async/k6 evidence measures the intended p95 ≤ 20 ms contract without warm-cache/sample exclusions.
  • PRD/TRD/ARCHITECTURE/ADR/ERD/UML/UX/TEST_STRATEGY/OPERABILITY/CHANGELOG and canonical docs: establish LifeOS product and technical gap baseline #211 product-gap ledger are code-current before promotion.

Migration compatibility

Existing KO/EN static catalogs are source data to migrate/reconcile, not an excuse to maintain two mutable translation authorities indefinitely. The migration plan must define bootstrap/import, digest comparison, rollback, version history and when static fallback ceases to be canonical. A temporary compatibility adapter must have an ADR removal condition.

Non-goals

  • translating ontology/concept labels inside the UI translation ledger;
  • browser-owned durable locale/resource truth;
  • a full-catalog SPA download as a prerequisite for every route;
  • machine-generated translations being auto-published without explicit publication/review evidence;
  • hard-coded English fallback being counted as eight-locale completion;
  • moving unrelated user/profile persistence into a localization service.

Integration order

Keep #209 as the buyer-journey umbrella and #211 as the only docs/product-technical-gap-baseline.md writer. This issue owns the localization gap and owner-boundary decision. The first code PR should be regression/ADR-first from fresh protected main and remain Draft until its owner contract is explicit; material workspace PRs may continue independently but must not claim localization completion from KO/EN static catalogs.

Refs #209 #211.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions