import { useState, useMemo } from 'react'; import { useT, useTranslation } from 'contexts/TranslationContext'; import { MdOutlineOpenInNew, MdComputer } from 'react-icons/md'; import { Radio, Checkbox, SearchInput } from 'components/Form/Settings'; import languages from '@/i18n/languages.json'; import translationPercentages from '@/i18n/translationPercentages.json'; const LanguageOptions = () => { const t = useT(); const { language: currentLanguage, changeLanguage } = useTranslation(); const languageTitle = t('modals.main.settings.sections.language.title'); const [searchQuery, setSearchQuery] = useState(''); // Create language options with both translated and native names const languageOptions = useMemo(() => { // Convert currentLanguage to ISO format (e.g., "de_DE" -> "de-DE") const currentLanguageISO = currentLanguage.replace('_', '-'); // Use Intl.DisplayNames to get language names in the current language const displayNames = new Intl.DisplayNames([currentLanguageISO], { type: 'language' }); const mappedLanguages = languages.map((lang) => { const nativeName = lang.name; // Convert language code to ISO format for Intl.DisplayNames // e.g., "en_GB" -> "en-GB", "zh_CN" -> "zh-CN" const isoCode = lang.value.replace('_', '-'); const percentage = translationPercentages[lang.value]?.percent || 0; let translatedName; try { translatedName = displayNames.of(isoCode); // Simplify by removing country suffixes: "German (Germany)" → "German" if (translatedName) { translatedName = translatedName.split(' (')[0]; } } catch { // Fallback if the code isn't recognized translatedName = nativeName; } // Show native name first, then translated name in brackets (greyed and smaller) const displayName = !translatedName || translatedName === nativeName ? ( <> {nativeName} ({percentage}%) ) : ( <> {nativeName}{' '} ({translatedName} • {percentage}%) ); return { name: displayName, value: lang.value, nativeName, percentage, searchText: `${nativeName} ${translatedName || ''}`.toLowerCase(), }; }); // Sort alphabetically by native name return mappedLanguages.sort((a, b) => a.nativeName.localeCompare(b.nativeName)); }, [currentLanguage]); // Filter languages based on search query const filteredLanguages = useMemo(() => { if (!searchQuery.trim()) return languageOptions; const query = searchQuery.toLowerCase(); return languageOptions.filter((lang) => lang.searchText.includes(query)); }, [languageOptions, searchQuery]); // Detect system language const systemLanguage = useMemo(() => { const browserLang = navigator.language.replace('-', '_'); // Check exact match first, then base language return ( languages.find((l) => l.value === browserLang) || languages.find((l) => l.value.startsWith(browserLang.split('_')[0])) ); }, []); // Find current language option for display const currentLangOption = languageOptions.find((l) => l.value === currentLanguage); return ( <>
{languageTitle}
Add translation
setSearchQuery(e.target.value)} /> {currentLangOption && (
{t('modals.main.settings.sections.language.current')}:{' '} {currentLangOption.nativeName}
)}
{systemLanguage && systemLanguage.value !== currentLanguage && ( )}
); }; export { LanguageOptions as default, LanguageOptions };