Skip to content

i18n: the core in-memory i18n fallback never receives the declared i18n.fallbackLocale — its t() falls back to defaultLocale only, so one declaration answers differently under the memory fallback and under service-i18n #15694

Description

@claude

Observation

The core in-memory i18n fallback (packages/core/src/fallbacks/memory-i18n.ts, createMemoryI18n) never receives the stack's declared i18n.fallbackLocale, so on a kernel running that fallback the declaration is inert.

Measured on origin/main 7087f99c:

  • AppPlugin.loadTranslations (packages/runtime/src/app-plugin.ts:1790, :1830) injects the declared defaultLocale (setDefaultLocale) and supportedLocales (setSupportedLocales) into whichever i18n service is registered. It does not inject fallbackLocale, and the memory fallback has no setter or field for one.
  • The memory fallback's t() resolves resolveTranslations(locale) ?? mergedLocale(defaultLocale) — its second locale is always defaultLocale. FileI18nAdapter.t() (service-i18n) consults the constructed fallbackLocale instead, which os serve and the dev plugin pass as fallbackLocale || defaultLocale || 'en'.
  • Consequence: a stack declaring defaultLocale: 'zh-CN' with fallbackLocale: 'en' answers a missing zh-CN key from en under I18nServicePlugin but from zh-CN (i.e. not at all) under the memory fallback. Two providers, one declaration, two answers.
  • Reach: the memory fallback carries an app bundle only when the stack declares translations and @objectstack/service-i18n is not registered (not installed, or tierEnabled('i18n') false) — the platform plugins still push their own bundles into it at kernel:ready.
  • After the i18n: metadata label lookup falls through to the en bundle on a zh-CN workspace — localeChain defaults fallbackChain to ['en'] and ignores i18n.fallbackLocale, so an authored Chinese label loses to a courtesy English bundle #14882 fix the REST metadata reads thread II18nService.getFallbackLocale() into the document translators' chain; the memory fallback does not implement the accessor (deliberately — deriving one from defaultLocale there would decide the default-locale contract question that card leaves open), so those reads keep the resolvers' own ['en'] default on that path.

Filed as an observation, not a defect claim: the fallback self-declares degraded (__serviceInfo), and whether it should learn the declared fallback (a setFallbackLocale threaded by AppPlugin the way setDefaultLocale is) or the divergence is acceptable for a degraded provider is a triage call. Related: #14882 (the REST/document-translator half), and the gate-vs-runtime default-locale contract question the PM is splitting from that card.

Where

  • packages/core/src/fallbacks/memory-i18n.tst() at the resolveTranslations(locale) ?? mergedLocale(defaultLocale) line; no fallbackLocale.
  • packages/runtime/src/app-plugin.tsloadTranslations, the setDefaultLocale / setSupportedLocales injection block.
  • packages/services/service-i18n/src/file-i18n-adapter.ts — the provider that does honour it, for contrast.

Generated by Claude Code

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