From 2ae25f3bbe2442e2d1b49ce3853ad05a99cc950e Mon Sep 17 00:00:00 2001 From: Huang Xin Date: Sat, 2 Aug 2025 23:09:09 +0800 Subject: [PATCH] translator: add more translator languages (#1738) --- .../components/annotator/TranslatorPopup.tsx | 16 +++++++--------- .../app/reader/components/settings/LangPanel.tsx | 11 +++++------ apps/readest-app/src/services/constants.ts | 16 ++++++++++++++++ apps/readest-app/src/utils/lang.ts | 12 ++++++++++++ 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/apps/readest-app/src/app/reader/components/annotator/TranslatorPopup.tsx b/apps/readest-app/src/app/reader/components/annotator/TranslatorPopup.tsx index 66f4edc8..a4b4b2ba 100644 --- a/apps/readest-app/src/app/reader/components/annotator/TranslatorPopup.tsx +++ b/apps/readest-app/src/app/reader/components/annotator/TranslatorPopup.tsx @@ -5,7 +5,7 @@ import { useAuth } from '@/context/AuthContext'; import { useSettingsStore } from '@/store/settingsStore'; import { useTranslation } from '@/hooks/useTranslation'; import { useTranslator } from '@/hooks/useTranslator'; -import { TRANSLATED_LANGS } from '@/services/constants'; +import { TRANSLATOR_LANGS } from '@/services/constants'; import { UseTranslatorOptions, getTranslators } from '@/services/translators'; import Select from '@/components/Select'; @@ -13,11 +13,11 @@ const notSupportedLangs = ['']; const generateTranslatorLangs = () => { return Object.fromEntries( - Object.entries(TRANSLATED_LANGS).filter(([code]) => !notSupportedLangs.includes(code)), + Object.entries(TRANSLATOR_LANGS).filter(([code]) => !notSupportedLangs.includes(code)), ); }; -const TRANSLATOR_LANGS = generateTranslatorLangs(); +const translatorLangs = generateTranslatorLangs(); interface TranslatorPopupProps { text: string; @@ -47,9 +47,7 @@ const TranslatorPopup: React.FC = ({ const [targetLang, setTargetLang] = useState(settings.globalReadSettings.translateTargetLang); const [provider, setProvider] = useState(settings.globalReadSettings.translationProvider); const [translation, setTranslation] = useState(null); - const [detectedSourceLang, setDetectedSourceLang] = useState< - keyof typeof TRANSLATOR_LANGS | null - >(null); + const [detectedSourceLang, setDetectedSourceLang] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); @@ -153,12 +151,12 @@ const TranslatorPopup: React.FC = ({ onChange={handleSourceLangChange} options={[ { value: 'AUTO', label: _('Auto Detect') }, - ...Object.entries(TRANSLATOR_LANGS) + ...Object.entries(translatorLangs) .sort((a, b) => a[1].localeCompare(b[1])) .map(([code, name]) => { const label = detectedSourceLang && sourceLang === 'AUTO' && code === 'AUTO' - ? `${TRANSLATOR_LANGS[detectedSourceLang] || detectedSourceLang} ` + + ? `${translatorLangs[detectedSourceLang] || detectedSourceLang} ` + _('(detected)') : name; return { value: code, label }; @@ -178,7 +176,7 @@ const TranslatorPopup: React.FC = ({ className='bg-gray-600 text-white/75' value={targetLang} onChange={handleTargetLangChange} - options={Object.entries(TRANSLATOR_LANGS) + options={Object.entries(translatorLangs) .sort((a, b) => a[1].localeCompare(b[1])) .map(([code, name]) => ({ value: code, label: name }))} /> diff --git a/apps/readest-app/src/app/reader/components/settings/LangPanel.tsx b/apps/readest-app/src/app/reader/components/settings/LangPanel.tsx index 8844f00c..465cf8c4 100644 --- a/apps/readest-app/src/app/reader/components/settings/LangPanel.tsx +++ b/apps/readest-app/src/app/reader/components/settings/LangPanel.tsx @@ -7,7 +7,7 @@ import { useReaderStore } from '@/store/readerStore'; import { useTranslation } from '@/hooks/useTranslation'; import { saveViewSettings } from '../../utils/viewSettingsHelper'; import { getTranslators } from '@/services/translators'; -import { TRANSLATED_LANGS } from '@/services/constants'; +import { TRANSLATED_LANGS, TRANSLATOR_LANGS } from '@/services/constants'; import { SettingsPanelPanelProp } from './SettingsDialog'; import { useResetViewSettings } from '../../hooks/useResetSettings'; import { saveAndReload } from '@/utils/reload'; @@ -54,8 +54,7 @@ const LangPanel: React.FC = ({ bookKey, onRegisterReset }; }; - const getLangOptions = () => { - const langs = TRANSLATED_LANGS as Record; + const getLangOptions = (langs: Record) => { const options = Object.entries(langs).map(([value, label]) => ({ value, label })); options.sort((a, b) => a.label.localeCompare(b.label)); options.unshift({ value: '', label: _('System Language') }); @@ -103,7 +102,7 @@ const LangPanel: React.FC = ({ bookKey, onRegisterReset const getCurrentTargetLangOption = () => { const value = translateTargetLang; - const availableOptions = getLangOptions(); + const availableOptions = getLangOptions(TRANSLATOR_LANGS); return availableOptions.find((o) => o.value === value) || availableOptions[0]!; }; @@ -153,7 +152,7 @@ const LangPanel: React.FC = ({ bookKey, onRegisterReset diff --git a/apps/readest-app/src/services/constants.ts b/apps/readest-app/src/services/constants.ts index 9c0d1788..7a2588d9 100644 --- a/apps/readest-app/src/services/constants.ts +++ b/apps/readest-app/src/services/constants.ts @@ -658,6 +658,22 @@ export const TRANSLATED_LANGS = { 'zh-TW': '正體中文', }; +export const TRANSLATOR_LANGS: Record = { + ...TRANSLATED_LANGS, + no: 'Norsk', + sv: 'Svenska', + fi: 'Suomi', + da: 'Dansk', + cs: 'Čeština', + hu: 'Magyar', + ro: 'Română', + bg: 'Български', + hr: 'Hrvatski', + lt: 'Lietuvių', + sl: 'Slovenščina', + sk: 'Slovenčina', +}; + export const SUPPORTED_LANGS: Record = { ...TRANSLATED_LANGS, zh: '中文' }; export const SUPPORTED_LANGNAMES: Record = Object.fromEntries( diff --git a/apps/readest-app/src/utils/lang.ts b/apps/readest-app/src/utils/lang.ts index 70ececc0..e0c05533 100644 --- a/apps/readest-app/src/utils/lang.ts +++ b/apps/readest-app/src/utils/lang.ts @@ -30,6 +30,18 @@ export const normalizeToFullLang = (langCode: string): string => { ru: 'ru-RU', uk: 'uk-UA', th: 'th-TH', + no: 'no-NO', + sv: 'sv-SE', + fi: 'fi-FI', + da: 'da-DK', + cs: 'cs-CZ', + hu: 'hu-HU', + ro: 'ro-RO', + bg: 'bg-BG', + hr: 'hr-HR', + lt: 'lt-LT', + sl: 'sl-SI', + sk: 'sk-SK', zh: 'zh-Hans', 'zh-cn': 'zh-Hans', 'zh-tw': 'zh-Hant',