nerdware/apps/web/src/i18n/language-toggle.tsx
AyoubBenziza 1e5ef2be90 feat(web): i18n (FR/EN) — homemade typed dictionary
- lightweight, dependency-free i18n: typed fr/en dictionaries (fr is the source
  of truth, en must match its shape → compile error on drift), I18nProvider +
  useI18n hook, browser detection + localStorage persistence
- FR/EN language switcher (home + room header)
- translated the whole player-facing flow: home, join, pseudo, room shell,
  lobby (incl. settings, categories, bots, track submission, history),
  quiz, blindtest, player-cards, round transitions, end screen (podium, awards,
  tracks, rounds recap), and server-error messages (mapped by code)
- history dates localized to the active language

Content (questions/categories) intentionally left as-is. Back-office (admin)
not translated yet — internal, token-gated tool.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 19:03:28 +02:00

25 lines
700 B
TypeScript

import { useI18n, type Lang } from "./context"
const LANGS: Lang[] = ["fr", "en"]
/** Petit sélecteur FR / EN. */
export function LanguageToggle({ className = "" }: { className?: string }) {
const { lang, setLang } = useI18n()
return (
<div className={`flex gap-1 ${className}`}>
{LANGS.map((l) => (
<button
key={l}
onClick={() => setLang(l)}
className={`rounded-md px-2 py-1 text-xs font-semibold uppercase transition-colors ${
lang === l
? "bg-primary/10 text-foreground"
: "text-muted-foreground hover:text-foreground"
}`}
>
{l}
</button>
))}
</div>
)
}