| 1 | import { LANGS, type Lang, type Prefs } from '../game/prefs'; |
| 2 | import { useT } from './lang'; |
| 3 | |
| 4 | interface Props { |
| 5 | prefs: Prefs; |
| 6 | onPrefs: (p: Prefs) => void; |
| 7 | /** Icon only, for the cramped row of controls in the middle of the table. */ |
| 8 | compact?: boolean; |
| 9 | } |
| 10 | |
| 11 | /** Glyph, and what the button says it is currently showing. Each language is |
| 12 | * named in itself, the way a language picker should be; only 'both' is a word |
| 13 | * in whatever is being read. */ |
| 14 | const MODES: Record<Lang, { icon: string; label: [string, string] }> = { |
| 15 | bi: { icon: '雙', label: ['雙語', 'Bilingual'] }, |
| 16 | zh: { icon: '中', label: ['繁體中文', '繁體中文'] }, |
| 17 | en: { icon: 'A', label: ['English', 'English'] }, |
| 18 | }; |
| 19 | |
| 20 | /** |
| 21 | * Bilingual · 繁體中文 · English. Three states rather than two, so it steps |
| 22 | * round on each tap instead of flipping — and names the mode it is in now, |
| 23 | * not the one the tap would take you to. |
| 24 | * |
| 25 | * It sits on the lobby beside 設定 rather than only inside it: the player who |
| 26 | * needs it most is the one who cannot read the button that opens Settings. |
| 27 | */ |
| 28 | export function LanguageToggle({ prefs, onPrefs, compact }: Props) { |
| 29 | const t = useT(); |
| 30 | const mode = MODES[prefs.lang]; |
| 31 | const label = t(...mode.label); |
| 32 | const next = LANGS[(LANGS.indexOf(prefs.lang) + 1) % LANGS.length]; |
| 33 | return ( |
| 34 | <button |
| 35 | className={`btn ghost pill lang-toggle ${compact ? 'compact' : ''}`} |
| 36 | aria-label={`${t('語言', 'Language')}: ${label}`} |
| 37 | onClick={() => onPrefs({ ...prefs, lang: next })} |
| 38 | > |
| 39 | <span className="lang-icon" aria-hidden> |
| 40 | {mode.icon} |
| 41 | </span> |
| 42 | {!compact && <span>{label}</span>} |
| 43 | </button> |
| 44 | ); |
| 45 | } |