import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import '../../../data/services/volcano_translation_service.dart'; import '../../../data/services/language_manager.dart'; import '../../../core/utils/logger.dart'; import '../../translation/views/dialogs/language_selection_dialog.dart'; /// 文本翻译控制器 class TextTranslationController extends GetxController { // 依赖服务 final VolcanoTranslationService _translationService = Get.find(); final LanguageManager _languageManager = Get.find(); final GetStorage _storage = GetStorage(); static const String _sourceLanguageKey = 'text_translation_source_language'; static const String _targetLanguageKey = 'text_translation_target_language'; static const String _sourceLanguageUserSetKey = 'text_translation_source_language_user_set'; static const String _targetLanguageUserSetKey = 'text_translation_target_language_user_set'; // 文本输入控制器 final TextEditingController textController = TextEditingController(); // 响应式状态 final sourceLanguageChineseName = 'autoDetect'.obs; final targetLanguageChineseName = '英语'.obs; final sourceLanguageCode = ''.obs; final targetLanguageCode = 'en-US'.obs; final translatedText = ''.obs; final isTranslating = false.obs; final inputText = ''.obs; // 支持的语言列表 List get supportedLanguages => _languageManager.getAllChineseNames(); @override void onInit() { super.onInit(); // 初始化翻译服务 _initializeTranslationService(); _loadSavedLanguages(); // 监听文本输入变化 textController.addListener(() { inputText.value = textController.text; }); } /// 初始化翻译服务 Future _initializeTranslationService() async { try { // 已初始化则跳过 if (_translationService.isInitialized) { Logger.info('翻译服务已初始化'); return; } // final initialized = final initialized = await _translationService.initialize(); if (!initialized) { Logger.error('翻译服务初始化失败'); Get.snackbar( 'error'.tr, '翻译服务初始化失败,请检查网络连接', snackPosition: SnackPosition.TOP, backgroundColor: Colors.red.withOpacity(0.9), colorText: Colors.white, ); } else { Logger.info('翻译服务初始化成功'); } } catch (e) { Logger.error('翻译服务初始化异常: $e'); } } @override void onClose() { textController.dispose(); super.onClose(); } /// 加载保存的语言设置 void _loadSavedLanguages() { try { final String? savedSourceLanguage = _storage.read(_sourceLanguageKey); String? savedTargetLanguage = _storage.read(_targetLanguageKey); final appDefaultTargetLanguage = _getLanguageByAppLocale(); final bool sourceUserSet = _storage.read(_sourceLanguageUserSetKey) ?? false; bool targetUserSet = _storage.read(_targetLanguageUserSetKey) ?? false; final bool targetUserSetKeyExists = _storage.hasData(_targetLanguageUserSetKey); if (!targetUserSetKeyExists) { if (savedTargetLanguage != null && appDefaultTargetLanguage != null && savedTargetLanguage == appDefaultTargetLanguage) { savedTargetLanguage = null; _storage.remove(_targetLanguageKey); targetUserSet = false; } else { targetUserSet = savedTargetLanguage != null; } _storage.write(_targetLanguageUserSetKey, targetUserSet); } if (sourceUserSet && savedSourceLanguage != null && (savedSourceLanguage == 'autoDetect' || supportedLanguages.contains(savedSourceLanguage))) { sourceLanguageChineseName.value = savedSourceLanguage; if (savedSourceLanguage == 'autoDetect') { sourceLanguageCode.value = ''; } else { final asrCode = _languageManager.getAsrCodeByChineseName(savedSourceLanguage); if (asrCode != null) sourceLanguageCode.value = asrCode; } } else { sourceLanguageChineseName.value = 'autoDetect'; sourceLanguageCode.value = ''; } if (targetUserSet && savedTargetLanguage != null && savedTargetLanguage != 'autoDetect' && supportedLanguages.contains(savedTargetLanguage)) { targetLanguageChineseName.value = savedTargetLanguage; final asrCode = _languageManager.getAsrCodeByChineseName(savedTargetLanguage); if (asrCode != null) targetLanguageCode.value = asrCode; } else if (appDefaultTargetLanguage != null && supportedLanguages.contains(appDefaultTargetLanguage)) { targetLanguageChineseName.value = appDefaultTargetLanguage; final asrCode = _languageManager.getAsrCodeByChineseName(appDefaultTargetLanguage); if (asrCode != null) targetLanguageCode.value = asrCode; } else { targetLanguageChineseName.value = '英语'; targetLanguageCode.value = 'en-US'; } } catch (e) { Logger.error('加载语言设置失败: $e'); } } void _saveLanguageSettings( {required bool saveSource, required bool saveTarget}) { try { if (saveSource) { _storage.write(_sourceLanguageKey, sourceLanguageChineseName.value); } if (saveTarget) { _storage.write(_targetLanguageKey, targetLanguageChineseName.value); } } catch (e) { Logger.error('保存语言设置失败: $e'); } } /// 设置源语言 void setSourceLanguage(String language) { if (language != sourceLanguageChineseName.value) { sourceLanguageChineseName.value = language; if (language == 'autoDetect') { sourceLanguageCode.value = ''; } else { final asrCode = _languageManager.getAsrCodeByChineseName(language); if (asrCode != null) { sourceLanguageCode.value = asrCode; } } _storage.write( _sourceLanguageUserSetKey, language != 'autoDetect', ); _saveLanguageSettings(saveSource: true, saveTarget: false); // 如果已有翻译结果,清空结果 if (translatedText.value.isNotEmpty) { translatedText.value = ''; } } } /// 设置目标语言 void setTargetLanguage(String language) { if (language != targetLanguageChineseName.value) { targetLanguageChineseName.value = language; // 同时更新语言代码 final asrCode = _languageManager.getAsrCodeByChineseName(language); if (asrCode != null) { targetLanguageCode.value = asrCode; } _storage.write(_targetLanguageUserSetKey, true); _saveLanguageSettings(saveSource: false, saveTarget: true); // 如果已有翻译结果,清空结果 if (translatedText.value.isNotEmpty) { translatedText.value = ''; } } } /// 交换源语言和目标语言 void swapLanguages() { if (sourceLanguageChineseName.value == 'autoDetect' || targetLanguageChineseName.value == 'autoDetect') { return; } final tempSource = sourceLanguageChineseName.value; final tempTarget = targetLanguageChineseName.value; final tempSourceCode = sourceLanguageCode.value; final tempTargetCode = targetLanguageCode.value; final tempInputText = textController.text; final tempTranslatedText = translatedText.value; sourceLanguageChineseName.value = tempTarget; targetLanguageChineseName.value = tempSource; sourceLanguageCode.value = tempTargetCode; targetLanguageCode.value = tempSourceCode; // 交换输入文本和翻译结果 textController.text = tempTranslatedText; translatedText.value = tempInputText; _storage.write(_sourceLanguageUserSetKey, true); _storage.write(_targetLanguageUserSetKey, true); _saveLanguageSettings(saveSource: true, saveTarget: true); } /// 执行翻译 Future translateText() async { final text = textController.text.trim(); // 验证输入 if (text.isEmpty) { // Get.snackbar( // 'error'.tr, // 'pleaseInputText'.tr, // snackPosition: SnackPosition.TOP, // backgroundColor: Colors.orange.withOpacity(0.9), // colorText: Colors.white, // ); return; } if (text.length > 5000) { // 5000 字符限制 Get.snackbar( 'error'.tr, 'textTooLong'.tr, snackPosition: SnackPosition.TOP, backgroundColor: Colors.orange.withOpacity(0.9), colorText: Colors.white, ); return; } // 检查源语言和目标语言是否相同 if (sourceLanguageChineseName.value == targetLanguageChineseName.value) { translatedText.value = text; return; } isTranslating.value = true; translatedText.value = ''; try { Logger.info('开始翻译: $text'); Logger.info( '源语言: ${sourceLanguageChineseName.value} -> ${sourceLanguageCode.value}'); Logger.info( '目标语言: ${targetLanguageChineseName.value} -> ${targetLanguageCode.value}'); // 确保翻译服务已初始化 Logger.info('确保翻译服务已初始化...'); bool initialized = _translationService.isInitialized; if (!initialized) { initialized = await _translationService.initialize(); } Logger.info('翻译服务初始化结果: $initialized'); if (!initialized) { throw Exception('翻译服务初始化失败'); } Logger.info('调用翻译服务...'); // 若选择了“自动检测”,先进行语种检测 if (sourceLanguageChineseName.value == 'autoDetect' || sourceLanguageCode.value.isEmpty) { Logger.info('源语言为自动检测,开始语种检测…'); final detectedAsrCode = await _translationService.detectTextLanguage(text: text); if (detectedAsrCode == null || detectedAsrCode.isEmpty) { Logger.error('语种检测失败'); Get.snackbar( 'error'.tr, // 错误 'languageDetectionFailed'.tr, // 语言检测失败 snackPosition: SnackPosition.TOP, backgroundColor: Colors.red.withOpacity(0.9), colorText: Colors.white, ); return; } sourceLanguageCode.value = detectedAsrCode; Logger.info('语种检测结果: $detectedAsrCode'); } if (sourceLanguageCode.value == targetLanguageCode.value) { translatedText.value = text; return; } // 调用翻译服务,使用检测或手动选择的源语言代码 final result = await _translationService.translateText( text: text, sourceLanguageCode: sourceLanguageCode.value, targetLanguageCode: targetLanguageCode.value, ); Logger.info('翻译服务返回结果: $result'); if (result != null && result.isNotEmpty) { translatedText.value = result; Logger.info('翻译成功: $result'); } else { Logger.error('翻译服务返回空结果'); throw Exception('翻译服务返回空结果'); } } catch (e) { Logger.error('翻译失败: $e'); Get.snackbar( 'error'.tr, // 错误 'translationFailed'.tr, // 翻译失败 snackPosition: SnackPosition.TOP, backgroundColor: Colors.red.withOpacity(0.9), colorText: Colors.white, ); } finally { isTranslating.value = false; } } /// 复制翻译结果 void copyResult() { if (translatedText.value.isNotEmpty) { Clipboard.setData(ClipboardData(text: translatedText.value)); Get.snackbar( 'success'.tr, 'copied'.tr, snackPosition: SnackPosition.TOP, backgroundColor: Colors.green.withOpacity(0.9), colorText: Colors.white, duration: const Duration(seconds: 1), ); } } /// 清空输入 void clearInput() { textController.clear(); translatedText.value = ''; } /// 显示语言选择对话框(统一与其它翻译模式的样式) void showLanguageSelector({required bool isSourceLanguage}) { final isDarkMode = Theme.of(Get.context!).brightness == Brightness.dark; // 复用统一语言选择弹窗组件 LanguageSelectionDialog.show( isSourceLanguage, isDarkMode, languages: supportedLanguages, currentLanguage: isSourceLanguage ? sourceLanguageChineseName.value : targetLanguageChineseName.value, includeAutoDetect: isSourceLanguage, translateLanguageNames: true, // 开启多语言显示,语言中文名作为翻译键 onSelected: (name) { if (isSourceLanguage) { setSourceLanguage(name); } else { setTargetLanguage(name); } }, ); } String? _getLanguageByAppLocale() { final Locale? locale = Get.locale ?? Get.deviceLocale; if (locale == null) return null; final languageCode = locale.languageCode.toLowerCase(); final countryCode = locale.countryCode?.toUpperCase(); final scriptCode = locale.scriptCode; if (languageCode == 'zh') { if (countryCode == 'HK' || countryCode == 'MO') { return _languageManager.getChineseNameByAsrCode('zh-HK'); } if (countryCode == 'TW') { return _languageManager.getChineseNameByAsrCode('zh-TW'); } if (scriptCode == 'Hant') { return _languageManager.getChineseNameByAsrCode('zh-TW'); } return _languageManager.getChineseNameByAsrCode('zh-CN'); } final normalizedShortCode = switch (languageCode) { 'nb' => 'no', _ => languageCode, }; return _languageManager.getChineseNameByShortCode(normalizedShortCode); } }