diff --git a/frontend/src/core/components/tools/ocr/LanguagePicker.tsx b/frontend/src/core/components/tools/ocr/LanguagePicker.tsx index 428853b53..784d22da5 100644 --- a/frontend/src/core/components/tools/ocr/LanguagePicker.tsx +++ b/frontend/src/core/components/tools/ocr/LanguagePicker.tsx @@ -1,7 +1,8 @@ import React, { useState, useEffect } from 'react'; import { Text, Loader } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import { tempOcrLanguages, getAutoOcrLanguage } from '@app/utils/languageMapping'; +import { getAutoOcrLanguage, getBrowserLanguagesForOcr, getOcrDisplayName } from '@app/utils/languageMapping'; +import apiClient from '@app/services/apiClient'; import DropdownListWithFooter, { DropdownItem } from '@app/components/shared/DropdownListWithFooter'; export interface LanguageOption { @@ -37,32 +38,41 @@ const LanguagePicker: React.FC = ({ // Fetch available languages from backend const fetchLanguages = async () => { try { - const response = await fetch(languagesEndpoint); + const { data } = await apiClient.get<{ languages: string[] }>(languagesEndpoint); + const displayNames = typeof Intl.DisplayNames !== 'undefined' + ? new Intl.DisplayNames([i18n.language], { type: 'language' }) + : null; - if (response.ok) { - const data: { languages: string[] } = await response.json(); - const languages = data.languages; + const languageOptions = [...new Set(data.languages)] + .map((lang) => { + const displayName = getOcrDisplayName(lang); + const browserLanguageCodes = getBrowserLanguagesForOcr(lang); + const langKey = `lang.${lang}`; + const translatedFromKey = t(langKey); + const hasKeyTranslation = translatedFromKey !== langKey; - const languageOptions = languages.map(lang => { - // TODO: Use actual language translations when they become available - // For now, use temporary English translations - const translatedName = tempOcrLanguages.lang[lang as keyof typeof tempOcrLanguages.lang] || lang; - const displayName = translatedName; + const intlTranslatedName = displayNames + ? browserLanguageCodes + .map((code) => displayNames.of(code)) + .find((name): name is string => Boolean(name)) + : null; + + const translatedName = + (hasKeyTranslation ? translatedFromKey : null) + || intlTranslatedName + || t(`ocr.languages.${lang}`, displayName); return { value: lang, - name: displayName + name: translatedName, + label: translatedName }; - }); + }) + .sort((a, b) => a.name.localeCompare(b.name, i18n.language)); - setAvailableLanguages(languageOptions); - } else { - console.error('[LanguagePicker] Response not OK:', response.status, response.statusText); - const errorText = await response.text(); - console.error('[LanguagePicker] Error response body:', errorText); - } + setAvailableLanguages(languageOptions); } catch (error) { console.error('[LanguagePicker] Fetch failed with error:', error); console.error('[LanguagePicker] Error details:', { @@ -76,7 +86,7 @@ const LanguagePicker: React.FC = ({ }; fetchLanguages(); - }, [languagesEndpoint]); + }, [languagesEndpoint, i18n.language, t]); // Auto-fill OCR language based on browser language when languages are loaded useEffect(() => {