import i18next, { type i18n as I18nInstance, type Resource } from 'i18next'; import { initReactI18next } from 'react-i18next'; import { resources } from './resources'; import { DEFAULT_LOCALE, type SupportedLocale } from './types'; export * from './detect'; export * from './error-map'; export * from './types'; export interface InitI18nOptions { initialLocale: SupportedLocale; // Called whenever the active language changes. onLanguageChanged?: (locale: SupportedLocale) => void; } // Idempotent init — safe to call from multiple entry points. // Returns the configured i18next instance. export function initI18n(options: InitI18nOptions): I18nInstance { if (!i18next.isInitialized) { void i18next.use(initReactI18next).init({ resources: resources as unknown as Resource, lng: options.initialLocale, fallbackLng: DEFAULT_LOCALE, defaultNS: 'common', ns: ['common', 'auth', 'errors', 'app'], interpolation: { escapeValue: false }, returnNull: false, }); } else if (i18next.language !== options.initialLocale) { void i18next.changeLanguage(options.initialLocale); } if (options.onLanguageChanged) { i18next.off('languageChanged'); i18next.on('languageChanged', (lng: string) => { if (isSupportedLocale(lng)) { options.onLanguageChanged?.(lng); } }); } return i18next; } export function changeLocale(locale: SupportedLocale): Promise { return i18next.changeLanguage(locale); } export { i18next }; // Local type guard (detect.ts exports this too; re-declared here to keep this // file free of cyclic references). function isSupportedLocale(value: string): value is SupportedLocale { return value === 'en' || value === 'de'; }