diff --git a/lib/modules/picture_translation/views/picture_translation_view.dart b/lib/modules/picture_translation/views/picture_translation_view.dart index 453d8f9fa..56d93c4c0 100644 --- a/lib/modules/picture_translation/views/picture_translation_view.dart +++ b/lib/modules/picture_translation/views/picture_translation_view.dart @@ -242,6 +242,9 @@ class PictureTranslationView extends GetView { isDarkMode, languages: langs, currentLanguage: currentLanguage, + excludeLanguage: isSource + ? controller.targetLanguageChineseName.value + : controller.sourceLanguageChineseName.value, includeAutoDetect: isSource, translateLanguageNames: true, // 开启多语言显示,语言中文名作为翻译键 onSelected: (name) { diff --git a/lib/modules/text_translation/controllers/text_translation_controller.dart b/lib/modules/text_translation/controllers/text_translation_controller.dart index 76c0a0345..d1852614f 100644 --- a/lib/modules/text_translation/controllers/text_translation_controller.dart +++ b/lib/modules/text_translation/controllers/text_translation_controller.dart @@ -387,6 +387,9 @@ class TextTranslationController extends GetxController { currentLanguage: isSourceLanguage ? sourceLanguageChineseName.value : targetLanguageChineseName.value, + excludeLanguage: isSourceLanguage + ? targetLanguageChineseName.value + : sourceLanguageChineseName.value, includeAutoDetect: isSourceLanguage, translateLanguageNames: true, // 开启多语言显示,语言中文名作为翻译键 onSelected: (name) { diff --git a/lib/modules/translation/views/dialogs/language_selection_dialog.dart b/lib/modules/translation/views/dialogs/language_selection_dialog.dart index ccef8f120..b2a368672 100644 --- a/lib/modules/translation/views/dialogs/language_selection_dialog.dart +++ b/lib/modules/translation/views/dialogs/language_selection_dialog.dart @@ -12,12 +12,14 @@ class LanguageSelectionDialog { /// [currentLanguage] 当前选中的语言中文名称 /// [includeAutoDetect] 是否在源语言首项加入“自动检测”选项(仅文本翻译需要) /// [translateLanguageNames] 是否将语言名称作为翻译键进行翻译(语音翻译保持原逻辑) + /// [excludeLanguage] 需排除的语言中文名称(防止原语言与目标语言相同) /// [onSelected] 选中项回调,参数为中文名称 static void show( bool isSource, bool isDarkMode, { List? languages, String? currentLanguage, + String? excludeLanguage, bool includeAutoDetect = false, bool translateLanguageNames = true, ValueChanged? onSelected, @@ -31,6 +33,11 @@ class LanguageSelectionDialog { final displayLanguages = List.from(languages ?? fallbackLanguages); + // 过滤掉对侧已选语言,防止原语言与目标语言相同 + if (excludeLanguage != null && excludeLanguage.isNotEmpty) { + displayLanguages.remove(excludeLanguage); + } + // 源语言是否展示“自动检测”选项(仅列表显示,值为中文“自动检测”) final hasAutoDetect = includeAutoDetect && isSource; diff --git a/lib/modules/translation/views/translation_view.dart b/lib/modules/translation/views/translation_view.dart index e9ac3caf9..1c20717ed 100644 --- a/lib/modules/translation/views/translation_view.dart +++ b/lib/modules/translation/views/translation_view.dart @@ -316,9 +316,11 @@ class TranslationView extends GetView { sourceText: () => controller.sourceLanguage.value.split(' ')[0], targetText: () => controller.targetLanguage.value.split(' ')[0], onTapSource: () => - LanguageSelectionDialog.show(true, isDarkMode), + LanguageSelectionDialog.show(true, isDarkMode, + excludeLanguage: controller.targetLanguage.value), onTapTarget: () => - LanguageSelectionDialog.show(false, isDarkMode), + LanguageSelectionDialog.show(false, isDarkMode, + excludeLanguage: controller.sourceLanguage.value), onSwap: controller.swapLanguages, translateLanguageNames: true, // 是否翻译语言名称 fontSizeSp: 15, @@ -1022,8 +1024,10 @@ class TranslationView extends GetView { child: LanguageSelectorBar( sourceText: () => controller.sourceLanguage.value.split(' ')[0], targetText: () => controller.targetLanguage.value.split(' ')[0], - onTapSource: () => LanguageSelectionDialog.show(true, isDarkMode), - onTapTarget: () => LanguageSelectionDialog.show(false, isDarkMode), + onTapSource: () => LanguageSelectionDialog.show(true, isDarkMode, + excludeLanguage: controller.targetLanguage.value), + onTapTarget: () => LanguageSelectionDialog.show(false, isDarkMode, + excludeLanguage: controller.sourceLanguage.value), onSwap: controller.swapLanguages, translateLanguageNames: true, // 是否翻译语言名称 fontSizeSp: 15, diff --git a/lib/modules/translation/views/widgets/face_to_face_layout.dart b/lib/modules/translation/views/widgets/face_to_face_layout.dart index efc6140a3..8161c6ff2 100644 --- a/lib/modules/translation/views/widgets/face_to_face_layout.dart +++ b/lib/modules/translation/views/widgets/face_to_face_layout.dart @@ -258,6 +258,9 @@ class _FaceToFaceLayoutState extends State { /// 显示语言选择对话框 void _showLanguageSelectionDialog(bool isSource, bool isDarkMode) { - LanguageSelectionDialog.show(isSource, isDarkMode); + LanguageSelectionDialog.show(isSource, isDarkMode, + excludeLanguage: isSource + ? widget.controller.targetLanguage.value + : widget.controller.sourceLanguage.value); } } diff --git a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/DoubaoE2ETranslateHelper.kt b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/DoubaoE2ETranslateHelper.kt index 690e45dab..ea443b48e 100644 --- a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/DoubaoE2ETranslateHelper.kt +++ b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/DoubaoE2ETranslateHelper.kt @@ -231,7 +231,7 @@ class DoubaoE2ETranslateHelper( Type.SourceSubtitleResponse -> { Log.d(TAG, "onMessage: SourceSubtitleResponse text='${text}'") recvSourceText.add(text) - callback?.onPartialSourceText(sessionId, text) + callback?.onPartialSourceText(sessionId, recvSourceText.joinToString(" ")) } Type.SourceSubtitleEnd -> { Log.d(TAG, "onMessage: SourceSubtitleEnd") @@ -245,7 +245,7 @@ class DoubaoE2ETranslateHelper( Type.TranslationSubtitleResponse -> { Log.d(TAG, "onMessage: TranslationSubtitleResponse text='${text}'") recvText.add(text) - callback?.onPartialText(sessionId, text) + callback?.onPartialText(sessionId, recvText.joinToString(" ")) } Type.TranslationSubtitleEnd -> { Log.d(TAG, "onMessage: TranslationSubtitleEnd") diff --git a/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/DoubaoE2ETranslateHelper.swift b/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/DoubaoE2ETranslateHelper.swift index f0abee1a6..a3915d906 100644 --- a/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/DoubaoE2ETranslateHelper.swift +++ b/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/DoubaoE2ETranslateHelper.swift @@ -457,7 +457,7 @@ class DoubaoE2ETranslateHelper: NSObject, URLSessionWebSocketDelegate { case .sourceSubtitleResponse: // 高频事件,取消 info 日志 recvSourceText.append(text) - callback?.onPartialSourceText(sessionId: sessionId, text: text) + callback?.onPartialSourceText(sessionId: sessionId, text: recvSourceText.joined(separator: " ")) case .sourceSubtitleEnd: os_log("SourceSubtitleEnd, finalSrcLen=%{public}d", log: log, type: .info, recvSourceText.joined(separator: " ").count) @@ -467,7 +467,7 @@ class DoubaoE2ETranslateHelper: NSObject, URLSessionWebSocketDelegate { case .translationSubtitleResponse: // 高频事件,取消 info 日志 recvText.append(text) - callback?.onPartialText(sessionId: sessionId, text: text) + callback?.onPartialText(sessionId: sessionId, text: recvText.joined(separator: " ")) case .translationSubtitleEnd: os_log("TranslationSubtitleEnd, finalTgtLen=%{public}d", log: log, type: .info, recvText.joined(separator: " ").count) @@ -525,14 +525,14 @@ class DoubaoE2ETranslateHelper: NSObject, URLSessionWebSocketDelegate { recvSourceText.removeAll() case "SourceSubtitleResponse": recvSourceText.append(t) - callback?.onPartialSourceText(sessionId: sessionId, text: t) + callback?.onPartialSourceText(sessionId: sessionId, text: recvSourceText.joined(separator: " ")) case "SourceSubtitleEnd": callback?.onFinalSourceText(sessionId: sessionId, finalText: recvSourceText.joined(separator: " ")) case "TranslationSubtitleStart": recvText.removeAll() case "TranslationSubtitleResponse": recvText.append(t) - callback?.onPartialText(sessionId: sessionId, text: t) + callback?.onPartialText(sessionId: sessionId, text: recvText.joined(separator: " ")) case "TranslationSubtitleEnd": callback?.onFinalTranslatedText(sessionId: sessionId, finalText: recvText.joined(separator: " ")) startNewSubSession()