import { useEffect } from 'react'; import type { ReactNode } from 'react'; import type { TranslationMap } from 'i18n'; import { I18nProvider, localeDirection } from 'i18n'; import { setNameRevision } from 'workspaces/react'; import { panelCatalogs } from 'officerdev'; import { uiCatalogs } from '@/components/locales'; import { useSettings } from 'state/useSettings'; import { FALLBACK_LOCALE, SHIPPED_LOCALES } from './locales'; import appEnGB from '../locales/en-GB.json'; import appPtPT from '../locales/pt-PT.json'; const appCatalogs: TranslationMap = { 'en-GB': appEnGB, 'pt-PT': appPtPT }; /** * Deep-merges the three per-workspace catalogs (D6) into one map per shipped locale — `app.*` from * officer-web, `panel.*` from officerdev's panel apps, `ui.*` from shared components. */ const translations: TranslationMap = Object.fromEntries( SHIPPED_LOCALES.map(({ code }) => [ code, { app: appCatalogs[code] ?? {}, panel: panelCatalogs[code] ?? {}, ui: uiCatalogs[code] ?? {}, }, ]), ); type I18nBridgeProps = { children: ReactNode; }; export const I18nBridge = ({ children }: I18nBridgeProps) => { const { settings } = useSettings(); const locale = settings.languages.default; // Prepared for RTL (D3) — every shipped locale is `ltr` today, but the wiring exists so a future // RTL catalog needs no second pass over the tree. useEffect(() => { document.documentElement.dir = localeDirection(locale); }, [locale]); /* Panel names are thunks resolved during the framework's own render (AppRegistryEntry.name), and the framework is not subscribed to this provider — it has no i18n dependency at all, deliberately. So tell it that the words changed. It treats the value as opaque; that it happens to be a locale is this file's business, not the framework's. Set during render rather than in an effect: an effect would leave the first paint after a locale switch showing the previous language's titles. */ setNameRevision(locale); return ( {children} ); };