Files
fotospiel-app/resources/js/admin/components/LanguageSwitcher.tsx

78 lines
2.3 KiB
TypeScript

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 { SUPPORTED_LANGUAGES, getCurrentLocale, switchLocale, type SupportedLocale } from '../lib/locale';
export function LanguageSwitcher() {
const { t } = useTranslation('common');
const [pendingLocale, setPendingLocale] = React.useState<SupportedLocale | null>(null);
const currentLocale = getCurrentLocale();
const changeLanguage = React.useCallback(
async (locale: SupportedLocale) => {
if (locale === currentLocale || pendingLocale) {
return;
}
setPendingLocale(locale);
try {
await switchLocale(locale);
} catch (error) {
if (import.meta.env.DEV) {
console.error('Failed to switch language', error);
}
} finally {
setPendingLocale(null);
}
},
[currentLocale, pendingLocale]
);
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="outline"
size="sm"
className="border-brand-rose-soft text-brand-rose hover:bg-brand-rose-soft/40"
aria-label={t('app.languageSwitch')}
>
<Languages className="mr-2 h-4 w-4" />
<span className="hidden sm:inline">{t('app.languageSwitch')}</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{SUPPORTED_LANGUAGES.map(({ code, labelKey }) => {
const isActive = currentLocale === code;
const isPending = pendingLocale === code;
return (
<DropdownMenuItem
key={code}
onSelect={(event) => {
event.preventDefault();
changeLanguage(code);
}}
className="flex items-center justify-between gap-3"
disabled={isPending}
>
<span>{t(labelKey)}</span>
{(isActive || isPending) && <Check className="h-4 w-4 text-brand-rose" />}
</DropdownMenuItem>
);
})}
</DropdownMenuContent>
</DropdownMenu>
);
}