From 4fd00af27301f240404992b7e73bdb8aa0b40f17 Mon Sep 17 00:00:00 2001 From: Phantom <59059173+EurFelux@users.noreply.github.com> Date: Tue, 12 Aug 2025 11:20:18 +0800 Subject: [PATCH] feat: support swap auto detected language in translate page (#9072) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(translate): 支持自动检测语言时交换语言并添加异常处理 * fix(i18n): 更新翻译错误信息并添加缺失的翻译项 * docs(translate): 添加与自动检测相关的交换条件检查注释 * fix(translate): 为翻译结果添加类型声明 --- src/renderer/src/i18n/locales/en-us.json | 2 ++ src/renderer/src/i18n/locales/ja-jp.json | 2 ++ src/renderer/src/i18n/locales/ru-ru.json | 2 ++ src/renderer/src/i18n/locales/zh-cn.json | 2 ++ src/renderer/src/i18n/locales/zh-tw.json | 2 ++ src/renderer/src/i18n/translate/el-gr.json | 2 ++ src/renderer/src/i18n/translate/es-es.json | 2 ++ src/renderer/src/i18n/translate/fr-fr.json | 2 ++ src/renderer/src/i18n/translate/pt-pt.json | 2 ++ .../src/pages/translate/TranslatePage.tsx | 26 +++++++++++++++---- 10 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 21c3baa1fc..861af88c93 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -3612,8 +3612,10 @@ }, "empty": "Translation content is empty", "error": { + "detected_unknown": "Unknown language cannot be exchanged", "empty": "The translation result is empty content", "failed": "Translation failed", + "invalid_source": "Invalid source language", "not_configured": "Translation model is not configured", "not_supported": "Unsupported language {{language}}", "unknown": "An unknown error occurred during translation" diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index fe29a51b4a..a0a08924cd 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -3612,8 +3612,10 @@ }, "empty": "翻訳内容が空です", "error": { + "detected_unknown": "未知の言語は交換できません", "empty": "翻訳結果が空の内容です", "failed": "翻訳に失敗しました", + "invalid_source": "無効なソース言語", "not_configured": "翻訳モデルが設定されていません", "not_supported": "サポートされていない言語 {{language}}", "unknown": "翻訳中に不明なエラーが発生しました" diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index cd6ffdfd70..28547d5ad6 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -3612,8 +3612,10 @@ }, "empty": "Содержимое перевода пусто", "error": { + "detected_unknown": "Неизвестный язык не подлежит обмену", "empty": "Результат перевода пуст", "failed": "Перевод не удалось", + "invalid_source": "Недопустимый исходный язык", "not_configured": "Модель перевода не настроена", "not_supported": "Язык не поддерживается {{language}}", "unknown": "Во время перевода возникла неизвестная ошибка" diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 1d794015e2..dd46809b78 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -3612,8 +3612,10 @@ }, "empty": "翻译内容为空", "error": { + "detected_unknown": "未知语言不可交换", "empty": "翻译结果为空内容", "failed": "翻译失败", + "invalid_source": "无效的源语言", "not_configured": "翻译模型未配置", "not_supported": "不支持的语言 {{language}}", "unknown": "翻译过程中遇到未知错误" diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 893f85e459..c5e3be5888 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -3612,8 +3612,10 @@ }, "empty": "翻譯內容為空", "error": { + "detected_unknown": "未知語言不可交換", "empty": "翻译结果为空内容", "failed": "翻譯失敗", + "invalid_source": "無效的源語言", "not_configured": "翻譯模型未設定", "not_supported": "不支援的語言 {{language}}", "unknown": "翻譯過程中遇到未知錯誤" diff --git a/src/renderer/src/i18n/translate/el-gr.json b/src/renderer/src/i18n/translate/el-gr.json index 093f6ace02..d3e74849f9 100644 --- a/src/renderer/src/i18n/translate/el-gr.json +++ b/src/renderer/src/i18n/translate/el-gr.json @@ -3612,8 +3612,10 @@ }, "empty": "Το μεταφρασμένο κείμενο είναι κενό", "error": { + "detected_unknown": "Άγνωστη γλώσσα μη ανταλλάξιμη", "empty": "το αποτέλεσμα της μετάφρασης είναι κενό περιεχόμενο", "failed": "Η μετάφραση απέτυχε", + "invalid_source": "Ακύρωση γλώσσας πηγής", "not_configured": "Το μοντέλο μετάφρασης δεν είναι ρυθμισμένο", "not_supported": "Μη υποστηριζόμενη γλώσσα {{language}}", "unknown": "κατά τη μετάφραση παρουσιάστηκε άγνωστο σφάλμα" diff --git a/src/renderer/src/i18n/translate/es-es.json b/src/renderer/src/i18n/translate/es-es.json index fb7bca8fe5..9352f4635d 100644 --- a/src/renderer/src/i18n/translate/es-es.json +++ b/src/renderer/src/i18n/translate/es-es.json @@ -3612,8 +3612,10 @@ }, "empty": "El contenido de traducción está vacío", "error": { + "detected_unknown": "Idioma desconocido no intercambiable", "empty": "El resultado de la traducción está vacío", "failed": "Fallo en la traducción", + "invalid_source": "Invalid source language", "not_configured": "El modelo de traducción no está configurado", "not_supported": "Idioma no compatible {{language}}", "unknown": "Se produjo un error desconocido durante la traducción" diff --git a/src/renderer/src/i18n/translate/fr-fr.json b/src/renderer/src/i18n/translate/fr-fr.json index e25c633ffd..b0c4beee9b 100644 --- a/src/renderer/src/i18n/translate/fr-fr.json +++ b/src/renderer/src/i18n/translate/fr-fr.json @@ -3612,8 +3612,10 @@ }, "empty": "Le contenu à traduire est vide", "error": { + "detected_unknown": "Langue inconnue non échangeable", "empty": "Le résultat de la traduction est un contenu vide", "failed": "échec de la traduction", + "invalid_source": "Langue source invalide", "not_configured": "le modèle de traduction n'est pas configuré", "not_supported": "Langue non prise en charge {{language}}", "unknown": "Une erreur inconnue s'est produite lors de la traduction" diff --git a/src/renderer/src/i18n/translate/pt-pt.json b/src/renderer/src/i18n/translate/pt-pt.json index 18eb0c12cb..72f2dd5998 100644 --- a/src/renderer/src/i18n/translate/pt-pt.json +++ b/src/renderer/src/i18n/translate/pt-pt.json @@ -3612,8 +3612,10 @@ }, "empty": "O conteúdo de tradução está vazio", "error": { + "detected_unknown": "Idioma desconhecido não pode ser trocado", "empty": "Resultado da tradução está vazio", "failed": "Tradução falhou", + "invalid_source": "Idioma de origem inválido", "not_configured": "Modelo de tradução não configurado", "not_supported": "Idioma não suportado {{language}}", "unknown": "Ocorreu um erro desconhecido durante a tradução" diff --git a/src/renderer/src/pages/translate/TranslatePage.tsx b/src/renderer/src/pages/translate/TranslatePage.tsx index 7fb7ad08ee..7ba579ebfb 100644 --- a/src/renderer/src/pages/translate/TranslatePage.tsx +++ b/src/renderer/src/pages/translate/TranslatePage.tsx @@ -116,7 +116,7 @@ const TranslatePage: FC = () => { setTranslating(true) - let translated + let translated: string try { translated = await translateText(text, actualTargetLanguage, throttle(setTranslatedContent, 100)) } catch (e) { @@ -224,17 +224,33 @@ const TranslatePage: FC = () => { } // 控制语言切换按钮 - const couldExchange = useMemo(() => sourceLanguage !== 'auto' && !isBidirectional, [isBidirectional, sourceLanguage]) + /** 与自动检测相关的交换条件检查 */ + const couldExchangeAuto = useMemo( + () => + (sourceLanguage === 'auto' && detectedLanguage && detectedLanguage.langCode !== UNKNOWN.langCode) || + sourceLanguage !== 'auto', + [detectedLanguage, sourceLanguage] + ) + + const couldExchange = useMemo(() => couldExchangeAuto && !isBidirectional, [couldExchangeAuto, isBidirectional]) const handleExchange = useCallback(() => { - if (sourceLanguage === 'auto') { + if (sourceLanguage === 'auto' && !couldExchangeAuto) { + return + } + const source = sourceLanguage === 'auto' ? detectedLanguage : sourceLanguage + if (!source) { + window.message.error(t('translate.error.invalid_source')) + return + } + if (source.langCode === UNKNOWN.langCode) { + window.message.error(t('translate.error.detected_unknown')) return } - const source = sourceLanguage const target = targetLanguage setSourceLanguage(target) setTargetLanguage(source) - }, [sourceLanguage, targetLanguage]) + }, [couldExchangeAuto, detectedLanguage, sourceLanguage, t, targetLanguage]) useEffect(() => { isEmpty(text) && setTranslatedContent('')