import { router, usePage } from '@inertiajs/react'; import { Check, Globe2, Languages } from 'lucide-react'; import { useState } from 'react'; import { Button } from '@/components/ui/button'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { applyDocumentLocalization } from '@/lib/localization'; import { useTranslation } from '@/lib/translations'; import { cn } from '@/lib/utils'; import { update as updateLanguage } from '@/routes/language'; import type { Localization, LocaleOption } from '@/types'; type LanguageSwitcherProps = { align?: 'center' | 'end' | 'start'; className?: string; variant?: 'compact' | 'settings' | 'sidebar'; }; export function LanguageSwitcher({ align = 'end', className, variant = 'compact', }: LanguageSwitcherProps) { const { localization } = usePage().props; const { t } = useTranslation(); const [pendingLocale, setPendingLocale] = useState(null); const currentLocale = localization.locales.find( (locale) => locale.code === localization.locale, ) ?? localization.locales[0]; if (!currentLocale) { return null; } const updateLocale = (locale: string): void => { if (locale === localization.locale || pendingLocale) { return; } const nextLocale = localization.locales.find( (option) => option.code === locale, ); if (!nextLocale) { return; } setPendingLocale(locale); applyDocumentLocalization({ direction: nextLocale.direction, locale: nextLocale.code, }); router .optimistic((props) => ({ locale: nextLocale.code, localization: { ...(props as { localization: Localization }).localization, direction: nextLocale.direction, isRtl: nextLocale.direction === 'rtl', locale: nextLocale.code, }, })) .post( updateLanguage.url(), { locale }, { preserveScroll: true, preserveState: false, onCancel: () => applyDocumentLocalization(localization), onError: () => applyDocumentLocalization(localization), onFinish: () => setPendingLocale(null), onNetworkError: () => applyDocumentLocalization(localization), onSuccess: (page) => applyDocumentLocalization( page.props.localization as Localization | undefined, ), }, ); }; if (variant === 'settings') { return (

{t('Interface language')}

{t('Choose the language used across Nyone.')}

{localization.locales.map((locale) => ( ))}
); } return ( {t('Language')} {localization.locales.map((locale) => ( updateLocale(locale.code)} > {locale.nativeName} {t(locale.name)} {locale.code === localization.locale && ( )} ))} ); } type LanguageOptionButtonProps = { isActive: boolean; isPending: boolean; locale: LocaleOption; onSelect: (locale: string) => void; }; function LanguageOptionButton({ isActive, isPending, locale, onSelect, }: LanguageOptionButtonProps) { const { t } = useTranslation(); return ( ); } function LocaleBadge({ locale }: { locale: LocaleOption }) { return ( {locale.code} ); }