import { createContext, memo, useContext, useEffect, useMemo, useState } from "react" import texts from "./texts.yml" type Keys = keyof typeof texts const ALLOWED = new Set(["en", "fr"]) const LOCALSTORAGE_KEY = "preferred-locale" function getLocaleFromStorage() { try { const key = localStorage.getItem(LOCALSTORAGE_KEY) if (key && ALLOWED.has(key)) { return key } } catch {} } function getNavigatorLocale() { if (typeof navigator !== "undefined") { for (const lang of navigator.languages) { if (ALLOWED.has(lang)) { return lang } } } } function getEnvLocale() { return getLocaleFromStorage() ?? getNavigatorLocale() ?? "en" } const LocaleContext = createContext<{ locale: string setLocale(locale: string): void }>(undefined!) export const useLocaleContext = () => useContext(LocaleContext) export function useTranslate() { const { locale } = useContext(LocaleContext) const t = useMemo( () => new Proxy( {}, { get(_, p: string) { if ( process.env.NODE_ENV === "development" && !Object.prototype.hasOwnProperty.call(texts, p) ) { throw new Error(`t.${p} does not exist.`) } return (texts as any)[p][locale] }, } ) as { [key in Keys]: string }, [locale] ) return t } export const LocaleContextProvider = memo(({ children }) => { const [locale, setLocale] = useState(getEnvLocale) useEffect(() => { try { localStorage.setItem(LOCALSTORAGE_KEY, locale) } catch {} }, [locale]) const value = useMemo(() => ({ locale, setLocale }), [locale]) return {children} })