import type { ReactNode } from "react"; import { I18nProvider } from "@lingui/react"; import { createContext, useContext, useEffect, useState } from "react"; import type { Locale } from "~/locales"; import { defaultLocale, locales } from "~/locales"; import { activateLocale, i18n, initializeI18n } from "~/utils/i18n"; interface LinguiContextType { locale: Locale; setLocale: (locale: Locale) => void; availableLocales: Locale[]; } const LinguiContext = createContext(undefined); export function useLinguiContext() { const context = useContext(LinguiContext); if (!context) { throw new Error("useLinguiContext must be used within a LinguiProvider"); } return context; } interface LinguiProviderProps { children: ReactNode; initialLocale?: Locale; } function detectBrowserLocale(availableLocales: readonly string[]): Locale { if (typeof navigator === "undefined") { return defaultLocale; } const browserLanguages = navigator.languages || [navigator.language]; for (const browserLang of browserLanguages) { const normalizedLocale = browserLang.toLowerCase(); const exactLocale = availableLocales.find( (availableLocale) => availableLocale.toLowerCase() === normalizedLocale, ); if (exactLocale) { return exactLocale as Locale; } const languageCode = normalizedLocale.split("-")[0]; if (languageCode === "zh" && availableLocales.includes("zh-CN")) { return "zh-CN"; } if (languageCode === "pt" && availableLocales.includes("ptbr")) { return "ptbr"; } const baseLocale = availableLocales.find( (availableLocale) => availableLocale.toLowerCase() === languageCode, ); if (baseLocale) { return baseLocale as Locale; } } return defaultLocale; } export function LinguiProviderWrapper({ children, initialLocale = defaultLocale, }: LinguiProviderProps) { const [locale, setLocale] = useState(initialLocale); const [isHydrated, setIsHydrated] = useState(false); initializeI18n(); useEffect(() => { const savedLocale = localStorage.getItem("locale") as Locale; if (savedLocale && locales.includes(savedLocale)) { setLocale(savedLocale); } else { const detectedLocale = detectBrowserLocale(locales); setLocale(detectedLocale); } setIsHydrated(true); }, [initialLocale]); useEffect(() => { if (isHydrated && locale !== defaultLocale) { activateLocale(locale).then(() => { localStorage.setItem("locale", locale); }); } else if (isHydrated) { localStorage.setItem("locale", locale); } }, [locale, isHydrated]); return ( {children} ); }