|
|
|
|
| import { createContext, useContext, useEffect, ReactNode } from 'react'; |
| import { useTranslation } from 'react-i18next'; |
| import { type Locale, defaultLocale, supportedLocales } from '@/lib/i18n'; |
| import '@/lib/i18n/config'; |
|
|
| const LOCALE_STORAGE_KEY = 'locale'; |
|
|
| |
| function resolveLocale(lang: string): Locale { |
| |
| const exact = supportedLocales.find((l) => l.code === lang); |
| if (exact) return exact.code; |
| |
| const prefix = lang.split('-')[0].toLowerCase(); |
| const match = supportedLocales.find((l) => l.code.toLowerCase().startsWith(prefix)); |
| return match?.code ?? defaultLocale; |
| } |
|
|
| type I18nContextType = { |
| locale: Locale; |
| setLocale: (locale: Locale) => void; |
| t: (key: string, options?: Record<string, unknown>) => string; |
| }; |
|
|
| const I18nContext = createContext<I18nContextType | undefined>(undefined); |
|
|
| export function I18nProvider({ children }: { children: ReactNode }) { |
| const { t, i18n } = useTranslation(); |
|
|
| const locale = (i18n.language || defaultLocale) as Locale; |
|
|
| |
| |
| |
| useEffect(() => { |
| try { |
| const stored = localStorage.getItem(LOCALE_STORAGE_KEY); |
| const raw = stored || navigator.language || defaultLocale; |
| const target = resolveLocale(raw); |
| if (target !== i18n.language) i18n.changeLanguage(target); |
| } catch { |
| |
| } |
| }, []); |
|
|
| const setLocale = (newLocale: Locale) => { |
| i18n.changeLanguage(newLocale); |
| try { |
| localStorage.setItem(LOCALE_STORAGE_KEY, newLocale); |
| } catch { |
| |
| } |
| }; |
|
|
| return <I18nContext.Provider value={{ locale, setLocale, t }}>{children}</I18nContext.Provider>; |
| } |
|
|
| export function useI18n() { |
| const context = useContext(I18nContext); |
| if (!context) { |
| throw new Error('useI18n must be used within I18nProvider'); |
| } |
| return context; |
| } |
|
|