| 1 | import type { FlatNamespace, KeyPrefix, Namespace } from 'i18next' |
| 2 | import type { FallbackNs } from 'react-i18next' |
| 3 | import { createInstance } from 'i18next' |
| 4 | import resourcesToBackend from 'i18next-resources-to-backend' |
| 5 | import { initReactI18next } from 'react-i18next/initReactI18next' |
| 6 | import { getOptions } from './settings' |
| 7 | |
| 8 | async function initI18next(lng: string, ns: string | string[]) { |
| 9 | // on server side we create a new instance for each render, because during compilation everything seems to be executed in parallel |
| 10 | const i18nInstance = createInstance() |
| 11 | await i18nInstance |
| 12 | .use(initReactI18next) |
| 13 | .use( |
| 14 | resourcesToBackend( |
| 15 | (language: string, namespace: string) => import(`./locales/${language}/${namespace}.json`), |
| 16 | ), |
| 17 | ) |
| 18 | .init(getOptions(lng, ns)) |
| 19 | return i18nInstance |
| 20 | } |
| 21 | |
| 22 | type $Tuple<T> = readonly [T?, ...T[]] |
| 23 | type $FirstNamespace<Ns extends Namespace> = Ns extends readonly any[] ? Ns[0] : Ns |
| 24 | |
| 25 | export async function useTranslation< |
| 26 | Ns extends FlatNamespace | $Tuple<FlatNamespace>, |
| 27 | KPrefix extends KeyPrefix< |
| 28 | FallbackNs<Ns extends FlatNamespace ? FlatNamespace : $FirstNamespace<FlatNamespace>> |
| 29 | > = undefined, |
| 30 | >(lng: string, ns?: Ns, options: { keyPrefix?: KPrefix } = {}) { |
| 31 | // @ts-ignore |
| 32 | ns = ns || 'translation' |
| 33 | const i18nextInstance = await initI18next( |
| 34 | lng, |
| 35 | Array.isArray(ns) ? (ns as string[]) : (ns as string), |
| 36 | ) |
| 37 | return { |
| 38 | t: Array.isArray(ns) |
| 39 | ? i18nextInstance.getFixedT(lng, ns[0], options.keyPrefix) |
| 40 | : i18nextInstance.getFixedT(lng, ns as FlatNamespace, options.keyPrefix), |
| 41 | i18n: i18nextInstance, |
| 42 | } |
| 43 | } |
| 44 |