import * as React from "react" import { setupI18n, type AllMessages, type I18n } from "@lingui/core" import { I18nProvider as LinguiI18nProvider, type I18nProviderProps as LinguiI18nProviderProps, } from "@lingui/react" import { I18nRuntimeContext } from "./context" import type { LocaleDefinition, LocaleDirection, LocaleInput } from "./types" const RTL_LANGUAGES = new Set([ "ar", "ckb", "dv", "fa", "he", "ku", "ps", "sd", "ug", "ur", "yi", ]) function inferLocaleDirection(locale: string): LocaleDirection { const language = locale.split("-")[0]?.toLowerCase() return language && RTL_LANGUAGES.has(language) ? "rtl" : "ltr" } function normalizeLocales( locale: string, locales: readonly LocaleInput[] | undefined, catalogs: AllMessages ): readonly LocaleDefinition[] { const inputs = locales && locales.length > 0 ? locales : Array.from(new Set([locale, ...Object.keys(catalogs)])) const definitions = inputs.map((input) => { const definition = typeof input === "string" ? { locale: input } : input return { ...definition, direction: definition.direction ?? inferLocaleDirection(definition.locale), label: definition.label ?? definition.locale, } }) if (!definitions.some((definition) => definition.locale === locale)) { return [ ...definitions, { direction: inferLocaleDirection(locale), label: locale, locale, }, ] } return definitions } export interface I18nProviderProps extends Pick< LinguiI18nProviderProps, "children" | "defaultComponent" > { catalogs?: AllMessages i18n?: I18n locale: string locales?: readonly LocaleInput[] missing?: ConstructorParameters[0]["missing"] } export function I18nProvider({ catalogs = {}, children, defaultComponent, i18n: providedI18n, locale, locales, missing, }: I18nProviderProps) { const i18n = React.useMemo(() => { const instance = providedI18n ?? setupI18n({ locale, messages: catalogs, missing, }) if (providedI18n) { providedI18n.load(catalogs) providedI18n.activate(locale) } return instance }, [catalogs, locale, missing, providedI18n]) const normalizedLocales = React.useMemo( () => normalizeLocales(locale, locales, catalogs), [catalogs, locale, locales] ) const contextValue = React.useMemo( () => ({ catalogs, locale, locales: normalizedLocales, }), [catalogs, locale, normalizedLocales] ) return ( {children} ) }