import { createContext, useContext, useState, useCallback, type ReactNode } from 'react';
import { translations, type Lang } from './translations';
const STORE_KEY = 'sz_lang';
// Default to the stored choice, else the browser's UI language (ru/en), else en.
function detectLang(): Lang {
try {
const stored = localStorage.getItem(STORE_KEY);
if (stored === 'en' || stored === 'ru') return stored;
} catch { /* ignore */ }
const nav = (navigator.language || 'en').toLowerCase();
return nav.startsWith('ru') ? 'ru' : 'en';
}
type TParams = Record<string, string | number>;
interface LangCtx {
lang: Lang;
setLang: (l: Lang) => void;
t: (key: string, params?: TParams) => string;
}
const LanguageContext = createContext<LangCtx | null>(null);
export function LanguageProvider({ children }: { children: ReactNode }) {
const [lang, setLangState] = useState<Lang>(detectLang);
const setLang = useCallback((l: Lang) => {
setLangState(l);
try { localStorage.setItem(STORE_KEY, l); } catch { /* ignore */ }
try { document.documentElement.lang = l; } catch { /* ignore */ }
}, []);
const t = useCallback(
(key: string, params?: TParams) => {
const tpl = translations[lang][key] ?? translations.en[key] ?? key;
return params
? tpl.replace(/\{(\w+)\}/g, (_, k) => String(params[k] ?? `{${k}}`))
: tpl;
},
[lang]
);
return (
<LanguageContext.Provider value={{ lang, setLang, t }}>
{children}
</LanguageContext.Provider>
);
}
// eslint-disable-next-line react-refresh/only-export-components
export function useT(): LangCtx {
const ctx = useContext(LanguageContext);
if (!ctx) throw new Error('useT must be used within LanguageProvider');
return ctx;
}
📜 Git History
6c47fa4chore: local Polikopi project home + Phase 1 redesign artifacts12 days ago
Show last diff
Loading...