← Back
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...