Files
simple-react-app-kit/packages/i18n/src/runtime/i18n-provider.tsx
T

123 lines
2.8 KiB
TypeScript
Raw Normal View History

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<LocaleDefinition>((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<typeof I18n>[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 (
<I18nRuntimeContext.Provider value={contextValue}>
<LinguiI18nProvider i18n={i18n} defaultComponent={defaultComponent}>
{children}
</LinguiI18nProvider>
</I18nRuntimeContext.Provider>
)
}