You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
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/main7087f99c:
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.
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.ts — t() at the resolveTranslations(locale) ?? mergedLocale(defaultLocale) line; no fallbackLocale.
packages/runtime/src/app-plugin.ts — loadTranslations, the setDefaultLocale / setSupportedLocales injection block.
packages/services/service-i18n/src/file-i18n-adapter.ts — the provider that does honour it, for contrast.
Observation
The core in-memory i18n fallback (
packages/core/src/fallbacks/memory-i18n.ts,createMemoryI18n) never receives the stack's declaredi18n.fallbackLocale, so on a kernel running that fallback the declaration is inert.Measured on
origin/main7087f99c:AppPlugin.loadTranslations(packages/runtime/src/app-plugin.ts:1790,:1830) injects the declareddefaultLocale(setDefaultLocale) andsupportedLocales(setSupportedLocales) into whicheveri18nservice is registered. It does not injectfallbackLocale, and the memory fallback has no setter or field for one.t()resolvesresolveTranslations(locale) ?? mergedLocale(defaultLocale)— its second locale is alwaysdefaultLocale.FileI18nAdapter.t()(service-i18n) consults the constructedfallbackLocaleinstead, whichos serveand the dev plugin pass asfallbackLocale || defaultLocale || 'en'.defaultLocale: 'zh-CN'withfallbackLocale: 'en'answers a missing zh-CN key fromenunderI18nServicePluginbut fromzh-CN(i.e. not at all) under the memory fallback. Two providers, one declaration, two answers.@objectstack/service-i18nis not registered (not installed, ortierEnabled('i18n')false) — the platform plugins still push their own bundles into it atkernel:ready.enbundle on a zh-CN workspace —localeChaindefaultsfallbackChainto ['en'] and ignoresi18n.fallbackLocale, so an authored Chinese label loses to a courtesy English bundle #14882 fix the REST metadata reads threadII18nService.getFallbackLocale()into the document translators' chain; the memory fallback does not implement the accessor (deliberately — deriving one fromdefaultLocalethere 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 (asetFallbackLocalethreaded byAppPluginthe waysetDefaultLocaleis) 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.ts—t()at theresolveTranslations(locale) ?? mergedLocale(defaultLocale)line; nofallbackLocale.packages/runtime/src/app-plugin.ts—loadTranslations, thesetDefaultLocale/setSupportedLocalesinjection block.packages/services/service-i18n/src/file-i18n-adapter.ts— the provider that does honour it, for contrast.Generated by Claude Code