import React from 'react'; import { Check, Languages } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { Button } from '@/components/ui/button'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import i18n from '../i18n'; type SupportedLocale = 'de' | 'en'; const SUPPORTED_LANGUAGES: Array<{ code: SupportedLocale; labelKey: string }> = [ { code: 'de', labelKey: 'language.de' }, { code: 'en', labelKey: 'language.en' }, ]; function getCsrfToken(): string { return document.querySelector('meta[name=\"csrf-token\"]')?.content ?? ''; } async function persistLocale(locale: SupportedLocale): Promise { const response = await fetch('/set-locale', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': getCsrfToken(), Accept: 'application/json', 'X-Requested-With': 'XMLHttpRequest', }, body: JSON.stringify({ locale }), credentials: 'include', }); if (!response.ok) { throw new Error(`locale update failed with status ${response.status}`); } } export function LanguageSwitcher() { const { t } = useTranslation('common'); const [pendingLocale, setPendingLocale] = React.useState(null); const currentLocale = (i18n.language || document.documentElement.lang || 'de') as SupportedLocale; const changeLanguage = React.useCallback( async (locale: SupportedLocale) => { if (locale === currentLocale || pendingLocale) { return; } setPendingLocale(locale); try { await persistLocale(locale); await i18n.changeLanguage(locale); document.documentElement.setAttribute('lang', locale); } catch (error) { if (import.meta.env.DEV) { console.error('Failed to switch language', error); } } finally { setPendingLocale(null); } }, [currentLocale, pendingLocale] ); return ( {SUPPORTED_LANGUAGES.map(({ code, labelKey }) => { const isActive = currentLocale === code; const isPending = pendingLocale === code; return ( { event.preventDefault(); changeLanguage(code); }} className="flex items-center justify-between gap-3" disabled={isPending} > {t(labelKey)} {(isActive || isPending) && } ); })} ); }