// Copyright (c) Meta Platforms, Inc. and affiliates. 'use client'; /** * @file InternationalizationProvider.tsx * @input React, InternationalizationContext, i18n types * @output Exports InternationalizationProvider component and props type * @position Provider component for astryx i18n locale + messages * * Wraps a subtree with a locale and (optional) additional message catalogs + * overrides. Astryx components inside the subtree resolve their strings via * this context. If a consumer never renders a provider, astryx components * still work — they use the shipped en catalog directly. * * SYNC: When modified, update these files to stay in sync: * - /packages/core/src/i18n/InternationalizationContext.ts * - /packages/core/src/i18n/index.ts * - /packages/core/src/i18n/InternationalizationProvider.doc.mjs */ import { useMemo, type ReactNode } from 'react'; import { InternationalizationContext } from "./InternationalizationContext.js"; import { getLocaleDirection } from "./getLocaleDirection.js"; import type { Locale, MessagesByLocale, Overrides } from "./types.js"; import { getResolve } from "./resolve.js"; export interface InternationalizationProviderProps { /** * BCP 47 language tag. Examples: `'en'`, `'pt'`, `'pt-BR'`, `'zh-Hans'`. * * Regional tags are respected — resolving a message walks the tag from * most-specific to least-specific (`pt-BR` → `pt`), then falls back to * the shipped `en` catalog. */ locale: Locale; /** * Additional shipped catalogs to make available for the selected locale. * `en` is bundled with astryx and never needs to be listed here. * * @example * ``` * import {fr} from '@astryxdesign/core/locales/fr.json'; * * ``` */ messages?: MessagesByLocale; /** * Sparse per-locale overrides applied on top of shipped defaults. * Only the keys you want to override need to be listed. * * @example * ``` * * ``` */ overrides?: Overrides; /** * Optional explicit text direction override. When omitted, direction is derived * from `locale` via `Intl.Locale.getTextInfo()`. Provide this to force a * direction (e.g. RTL layout testing under an English catalog) or to skip the * derivation when you already know the direction. * * This sets the direction astryx reads via context; it does NOT set the DOM * `dir` attribute. You must set `dir` on `` (or a wrapping element) * yourself — astryx components mirror layout and directional icons from the * DOM `dir`, so an RTL locale won't visually mirror without it. Keep the two * in sync (e.g. `dir={getLocaleDirection(locale)}` on both). */ dir?: 'ltr' | 'rtl'; children: ReactNode; } /** * Provides locale + additional messages + overrides to all astryx * components in the subtree. */ export function InternationalizationProvider({ locale, messages, overrides, dir, children }: InternationalizationProviderProps) { const direction = dir ?? getLocaleDirection(locale); const value = useMemo(() => ({ locale, direction, messages: messages ?? {}, overrides, translate: getResolve(locale, messages ?? {}, overrides) }), [locale, direction, messages, overrides]); return {children} ; } InternationalizationProvider.displayName = 'InternationalizationProvider';