Files
RN_Template/RN_TEMPLATE/app/i18n/index.ts
2026-02-05 13:16:05 +08:00

88 lines
2.5 KiB
TypeScript

import { I18nManager } from "react-native"
import * as Localization from "expo-localization"
import i18n from "i18next"
import { initReactI18next } from "react-i18next"
import "intl-pluralrules"
// if English isn't your default language, move Translations to the appropriate language file.
import ar from "./ar"
import en, { Translations } from "./en"
import es from "./es"
import fr from "./fr"
import hi from "./hi"
import ja from "./ja"
import ko from "./ko"
import zh from "./zh"
const fallbackLocale = "en-US"
const systemLocales = Localization.getLocales()
const resources = { ar, en, ko, es, fr, ja, hi, zh }
const supportedTags = Object.keys(resources)
// Checks to see if the device locale matches any of the supported locales
// Device locale may be more specific and still match (e.g., en-US matches en)
const systemTagMatchesSupportedTags = (deviceTag: string) => {
const primaryTag = deviceTag.split("-")[0]
return supportedTags.includes(primaryTag)
}
const pickSupportedLocale: () => Localization.Locale | undefined = () => {
return systemLocales.find((locale) => systemTagMatchesSupportedTags(locale.languageTag))
}
const locale = pickSupportedLocale()
export let isRTL = false
// Need to set RTL ASAP to ensure the app is rendered correctly. Waiting for i18n to init is too late.
if (locale?.languageTag && locale?.textDirection === "rtl") {
I18nManager.allowRTL(true)
isRTL = true
} else {
I18nManager.allowRTL(false)
}
export const initI18n = async () => {
i18n.use(initReactI18next)
await i18n.init({
resources,
lng: locale?.languageTag ?? fallbackLocale,
fallbackLng: fallbackLocale,
interpolation: {
escapeValue: false,
},
})
return i18n
}
/**
* Builds up valid keypaths for translations.
*/
export type TxKeyPath = RecursiveKeyOf<Translations>
// via: https://stackoverflow.com/a/65333050
type RecursiveKeyOf<TObj extends object> = {
[TKey in keyof TObj & (string | number)]: RecursiveKeyOfHandleValue<TObj[TKey], `${TKey}`, true>
}[keyof TObj & (string | number)]
type RecursiveKeyOfInner<TObj extends object> = {
[TKey in keyof TObj & (string | number)]: RecursiveKeyOfHandleValue<TObj[TKey], `${TKey}`, false>
}[keyof TObj & (string | number)]
type RecursiveKeyOfHandleValue<
TValue,
Text extends string,
IsFirstLevel extends boolean,
> = TValue extends any[]
? Text
: TValue extends object
? IsFirstLevel extends true
? Text | `${Text}:${RecursiveKeyOfInner<TValue>}`
: Text | `${Text}.${RecursiveKeyOfInner<TValue>}`
: Text