Browse Source

feat(i18n): 补全蓝牙/Agent/OTA/翻译等模块的中文国际化键值对

为蓝牙扫描、AI助手导航、消息气泡、OTA固件升级、翻译模块中的硬编码中文文本
添加国际化支持,在zh_cn.dart中新增约70个翻译键,并将各模块源码中的硬编码
文本替换为.tr/.trParams()调用。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
weicu
lxm 7 months ago
parent
commit
b4b37b16f9
  1. 101
      lib/core/translations/language/zh_cn.dart
  2. 52
      lib/modules/agent/controllers/agent_controller.dart
  3. 14
      lib/modules/agent/views/message_bubble.dart
  4. 52
      lib/modules/ble/controllers/ble_controller.dart
  5. 56
      lib/modules/ota_upgrade/controllers/ota_core_contropller.dart
  6. 32
      lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart
  7. 18
      lib/modules/ota_upgrade/views/ota_upgrade_popup_view.dart
  8. 4
      lib/modules/translation/controllers/translation_controller.dart
  9. 10
      lib/modules/translation/views/translation_view.dart

101
lib/core/translations/language/zh_cn.dart

@ -160,6 +160,26 @@ const Map<String, String> zhCN = {
'right': '右', 'right': '右',
'checkConnectionStatusFailed': '检查连接状态失败', 'checkConnectionStatusFailed': '检查连接状态失败',
// 蓝牙扫描模块
'bleInitFailedWithError': '蓝牙初始化失败: @error',
'needBluetoothAndLocationPermission': '需要蓝牙和位置权限才能扫描设备',
'permissionRequestFailedWithError': '权限请求失败: @error',
'needPermission': '需要权限',
'blePermissionDialogContent': '应用需要蓝牙和位置权限才能扫描设备。请在设置中手动开启权限。',
'needEnableBluetooth': '需要开启蓝牙',
'enableBluetoothDialogContent': '请开启蓝牙以扫描和连接设备。',
'bleScanFailedWithError': '扫描失败: @error',
'bleConnectionSuccess': '连接成功',
'bleConnectedToDevice': '已连接到 @device',
'bleConnectionFailedWithError': '连接失败: @error',
'bleDisconnected': '已断开连接',
'bleDeviceDisconnected': '设备已断开连接',
'bleDisconnectFailedWithError': '断开连接失败: @error',
'signalStrong': '信号强',
'signalMedium': '信号中等',
'signalWeak': '信号弱',
'signalVeryWeak': '信号很弱',
// 发现页 // 发现页
"searchAi": "搜索AI功能...", "searchAi": "搜索AI功能...",
"exploreSlogan": "智能耳机,无限可能", "exploreSlogan": "智能耳机,无限可能",
@ -828,6 +848,13 @@ const Map<String, String> zhCN = {
'reportDescriptionHint': '我们想知道你举报的原因,你可以描述你遇到的问题。', 'reportDescriptionHint': '我们想知道你举报的原因,你可以描述你遇到的问题。',
'generatedByAi': '由AI生成', 'generatedByAi': '由AI生成',
// Agent模块 - 工具调用
'toolCall': '工具调用',
'noResult': '无结果',
'noToolCallContentToCopy': '没有工具调用内容可以拷贝',
'toolCallDetails': '工具调用详情:',
'toolCallContentCopied': '工具调用内容已复制到剪贴板',
// Agent模块 - 音乐卡片 // Agent模块 - 音乐卡片
'recommendedMusic': '以下是一些推荐的音乐:', 'recommendedMusic': '以下是一些推荐的音乐:',
'playList': '播放列表', 'playList': '播放列表',
@ -848,6 +875,28 @@ const Map<String, String> zhCN = {
"bicycling": "骑行", "bicycling": "骑行",
"tsransit": "公交", "tsransit": "公交",
// Agent模块 - 导航选择
'selectNavigationApp': '选择导航软件',
'amapMap': '高德地图',
'useAmapNavigation': '使用高德地图导航',
'baiduMap': '百度地图',
'useBaiduNavigation': '使用百度地图导航',
'googleMap': '谷歌地图',
'useGoogleNavigation': '使用谷歌地图导航',
'appleMap': '苹果地图',
'useAppleNavigation': '使用苹果地图导航',
'builtInNavigation': '内置导航',
'useBuiltInNavigation': '使用内置地图导航',
'navigationStartFailed': '启动导航失败',
'cannotPlayMusicListRetryLater': '无法播放音乐列表,请稍后重试',
'cannotPlaySong': '无法播放歌曲',
'openMapError': '打开地图时发生错误',
'pleaseInstallAmapApp': '请先安装高德地图应用',
'pleaseInstallBaiduMapApp': '请先安装百度地图应用',
'appleMapStartFailed': '苹果地图启动失败',
'appleMapUnavailable': '苹果地图不可用',
'openAppleMapError': '打开苹果地图时发生错误',
// Agent模块 - 天气卡片 // Agent模块 - 天气卡片
'weatherQuery': '查询天气情况:', 'weatherQuery': '查询天气情况:',
'highest': '最高', 'highest': '最高',
@ -908,9 +957,18 @@ const Map<String, String> zhCN = {
"bluetoothCallStateError": "请确保蓝牙耳机已连接到手机并处于通话状态", "bluetoothCallStateError": "请确保蓝牙耳机已连接到手机并处于通话状态",
"autoDetect": "自动检测", // 自动检测 "autoDetect": "自动检测", // 自动检测
// 翻译模块 - 悬浮窗与权限
'disableFloatingWindow': '禁用悬浮窗',
'enableFloatingWindow': '启用悬浮窗',
'permissionTip': '权限提示',
'micPermissionRequiredForRecording': '需要麦克风权限才能使用录音功能',
'deleteTranslationRecordError': '删除翻译记录时发生错误: @error',
// 翻译模块 - 文本翻译 // 翻译模块 - 文本翻译
"languageDetectionFailed": "语言检测失败", "languageDetectionFailed": "语言检测失败",
"translationFailed": "翻译失败", "translationFailed": "翻译失败",
"translating": "正在翻译",
"translate": "翻译",
"pleaseInputText": "请输入文本", "pleaseInputText": "请输入文本",
"textTooLong": "文本过长,最多5000字符", "textTooLong": "文本过长,最多5000字符",
@ -1258,6 +1316,49 @@ const Map<String, String> zhCN = {
"updateContent": "更新内容", "updateContent": "更新内容",
"removeEarbudsEnsureBattery": "取出双耳机,并保证电量均为20%以上的状态", "removeEarbudsEnsureBattery": "取出双耳机,并保证电量均为20%以上的状态",
// OTA升级模块 - 弹窗与对话框
'otaNewVersionFoundWithVersion': '发现新版本 @version',
'otaConfirmUpdateNow': '是否立即更新?',
'otaUpdate': '更新',
'otaUpgradeSuccess': '升级成功',
'otaUpgradeCompleteRepair': '固件升级已完成!\n\n设备需要重新配对才能正常使用,现在跳转到配对页面吗?',
'otaPairLater': '稍后配对',
'otaPairNow': '立即配对',
'okConfirm': '确定',
// OTA升级模块 - 设备检查
'otaBleCheckErrorWithError': '检查BLE连接状态时发生错误:@error',
'otaBleNotConnected': 'BLE设备未连接',
'otaBleNeedConnection': '固件升级需要连接BLE设备\n请确保设备已正确连接后再试',
'otaDeviceInfoUnavailableTitle': '设备信息不可用',
'otaCannotGetDeviceInfo': '无法获取设备信息\n请重新连接设备或稍后再试',
'otaBleCheckFailed': 'BLE连接检查失败',
'otaCannotGetDeviceInfoCheckConnection': '无法获取设备信息,请检查设备连接',
'otaCannotGetProductInfoWithName': '无法获取产品信息,设备名称: @deviceName',
'otaCannotGetBatteryInfo': '无法获取有效的电量信息',
'otaLowBattery': '电量不足',
'otaSingleBatteryLow': '设备电量不足,无法进行固件升级\n升级要求:设备电量需大于20%\n当前电量:@ear @battery%\n请充电后再试',
'otaDoubleBatteryLow': '设备电量不足,无法进行固件升级\n升级要求:左右耳电量均需大于20%\n当前电量:左耳 @left%,右耳 @right%\n请充电后再试',
'otaBatteryCheckFailed': '电量检查失败',
// OTA升级模块 - 升级状态
'otaDefaultUpdateDesc': '本次更新包含性能优化和错误修复。',
'otaGetLatestVersionFailed': '获取最新版本信息失败',
'otaGetVersionInfoFailed': '获取版本信息失败',
'otaCheckingDeviceStatus': '正在检查设备状态...',
'otaDownloadFailedCheckNetwork': '下载失败,请检查网络连接',
'otaDownloadFailed': '下载失败',
'otaPreparingConnection': '准备设备连接...',
'otaConnectingDevice': '正在连接设备...',
'otaUpgradeStarted': 'OTA升级已开始...',
'otaUpgradeProgressWithPercent': '升级进度: @percent%',
'otaUpgradeSuccessComplete': '升级成功完成',
'otaUpgradeFailedWithCode': '升级失败,错误码:@code',
'otaUpgradeFailedTitle': '升级失败',
'otaUpgradeFailedDesc': '请检查设备连接或升级包,错误码:@code',
'otaDeviceDisconnected': '设备连接断开',
'otaDeviceConnected': '设备连接成功',
// 音乐模块 // 音乐模块
"noMusic": "暂无音乐", // 暂无音乐 "noMusic": "暂无音乐", // 暂无音乐
"noPlayingMusic": "暂无播放音乐", // 暂无播放音乐 "noPlayingMusic": "暂无播放音乐", // 暂无播放音乐

52
lib/modules/agent/controllers/agent_controller.dart

@ -2156,10 +2156,10 @@ class AgentController extends GetxController with WidgetsBindingObserver {
), ),
), ),
// 标题 // 标题
const Padding( Padding(
padding: EdgeInsets.all(20), padding: const EdgeInsets.all(20),
child: Text( child: Text(
'选择导航软件', 'selectNavigationApp'.tr,
style: TextStyle( style: TextStyle(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -2176,8 +2176,8 @@ class AgentController extends GetxController with WidgetsBindingObserver {
), ),
child: const Icon(Icons.map, color: Colors.blue), child: const Icon(Icons.map, color: Colors.blue),
), ),
title: const Text('高德地图'), title: Text('amapMap'.tr),
subtitle: const Text('使用高德地图导航'), subtitle: Text('useAmapNavigation'.tr),
onTap: () { onTap: () {
Get.back(); Get.back();
openGaodeMap(destination, endlatitude, endlongitude, mode); openGaodeMap(destination, endlatitude, endlongitude, mode);
@ -2192,8 +2192,8 @@ class AgentController extends GetxController with WidgetsBindingObserver {
), ),
child: const Icon(Icons.map, color: Colors.green), child: const Icon(Icons.map, color: Colors.green),
), ),
title: const Text('百度地图'), title: Text('baiduMap'.tr),
subtitle: const Text('使用百度地图导航'), subtitle: Text('useBaiduNavigation'.tr),
onTap: () { onTap: () {
Get.back(); Get.back();
openBaiduMap(destination, endlatitude, endlongitude, mode); openBaiduMap(destination, endlatitude, endlongitude, mode);
@ -2208,8 +2208,8 @@ class AgentController extends GetxController with WidgetsBindingObserver {
), ),
child: const Icon(Icons.map, color: Colors.red), child: const Icon(Icons.map, color: Colors.red),
), ),
title: const Text('谷歌地图'), title: Text('googleMap'.tr),
subtitle: const Text('使用谷歌地图导航'), subtitle: Text('useGoogleNavigation'.tr),
onTap: () { onTap: () {
Get.back(); Get.back();
openGoogleMap(destination, mode); openGoogleMap(destination, mode);
@ -2226,8 +2226,8 @@ class AgentController extends GetxController with WidgetsBindingObserver {
), ),
child: const Icon(Icons.map, color: Colors.orange), child: const Icon(Icons.map, color: Colors.orange),
), ),
title: const Text('苹果地图'), title: Text('appleMap'.tr),
subtitle: const Text('使用苹果地图导航'), subtitle: Text('useAppleNavigation'.tr),
onTap: () { onTap: () {
Get.back(); Get.back();
openAppleMap(destination, mode); openAppleMap(destination, mode);
@ -2242,8 +2242,8 @@ class AgentController extends GetxController with WidgetsBindingObserver {
), ),
child: const Icon(Icons.navigation, color: Colors.grey), child: const Icon(Icons.navigation, color: Colors.grey),
), ),
title: const Text('内置导航'), title: Text('builtInNavigation'.tr),
subtitle: const Text('使用内置地图导航'), subtitle: Text('useBuiltInNavigation'.tr),
onTap: () { onTap: () {
Get.back(); Get.back();
openInternalGaodeMap( openInternalGaodeMap(
@ -2361,7 +2361,7 @@ class AgentController extends GetxController with WidgetsBindingObserver {
// Get.snackbar('提示', '未找到可用的导航应用,请安装$availableApps'); // Get.snackbar('提示', '未找到可用的导航应用,请安装$availableApps');
} catch (e) { } catch (e) {
print('自动选择导航失败: $e'); print('自动选择导航失败: $e');
Get.snackbar('错误', '启动导航失败'); Get.snackbar('error'.tr, 'navigationStartFailed'.tr);
} }
} }
@ -2472,8 +2472,8 @@ class AgentController extends GetxController with WidgetsBindingObserver {
// 显示错误提示 // 显示错误提示
Get.snackbar( Get.snackbar(
'播放失败', 'playFailed'.tr,
'无法播放音乐列表,请稍后重试', 'cannotPlayMusicListRetryLater'.tr,
snackPosition: SnackPosition.BOTTOM, snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red[400], backgroundColor: Colors.red[400],
colorText: Colors.white, colorText: Colors.white,
@ -2643,7 +2643,7 @@ class AgentController extends GetxController with WidgetsBindingObserver {
// Get.snackbar('开始播放', song.name); // Get.snackbar('开始播放', song.name);
_qqmusicManager.syncCurrentPlayInfo(); _qqmusicManager.syncCurrentPlayInfo();
} else { } else {
Get.snackbar('播放失败', result['error'] ?? '无法播放歌曲'); Get.snackbar('playFailed'.tr, result['error'] ?? 'cannotPlaySong'.tr);
} }
return; return;
} }
@ -2665,7 +2665,7 @@ class AgentController extends GetxController with WidgetsBindingObserver {
// Get.snackbar('开始播放', song.name); // Get.snackbar('开始播放', song.name);
_qqmusicManager.syncCurrentPlayInfo(); _qqmusicManager.syncCurrentPlayInfo();
} else { } else {
Get.snackbar('播放失败', result['error'] ?? '无法播放歌曲'); Get.snackbar('playFailed'.tr, result['error'] ?? 'cannotPlaySong'.tr);
} }
} }
} }
@ -2688,7 +2688,7 @@ class AgentController extends GetxController with WidgetsBindingObserver {
return true; return true;
} catch (e) { } catch (e) {
print('打开内置高德地图失败: $e'); print('打开内置高德地图失败: $e');
Get.snackbar('错误', '打开地图时发生错误'); Get.snackbar('error'.tr, 'openMapError'.tr);
return false; return false;
} }
} }
@ -2797,12 +2797,12 @@ class AgentController extends GetxController with WidgetsBindingObserver {
return launched; return launched;
} else { } else {
print('高德地图未安装'); print('高德地图未安装');
Get.snackbar('提示', '请先安装高德地图应用'); Get.snackbar('tip'.tr, 'pleaseInstallAmapApp'.tr);
return false; return false;
} }
} catch (e) { } catch (e) {
print('打开高德地图失败: $e'); print('打开高德地图失败: $e');
Get.snackbar('错误', '打开地图时发生错误'); Get.snackbar('error'.tr, 'openMapError'.tr);
return false; return false;
} }
} }
@ -2860,12 +2860,12 @@ class AgentController extends GetxController with WidgetsBindingObserver {
return launched; return launched;
} else { } else {
print('百度地图未安装'); print('百度地图未安装');
Get.snackbar('提示', '请先安装百度地图应用'); Get.snackbar('tip'.tr, 'pleaseInstallBaiduMapApp'.tr);
return false; return false;
} }
} catch (e) { } catch (e) {
print('打开百度地图失败: $e'); print('打开百度地图失败: $e');
Get.snackbar('错误', '打开地图时发生错误'); Get.snackbar('error'.tr, 'openMapError'.tr);
return false; return false;
} }
} }
@ -2892,15 +2892,15 @@ class AgentController extends GetxController with WidgetsBindingObserver {
); );
if (!launched) { if (!launched) {
print('苹果地图启动失败'); print('苹果地图启动失败');
Get.snackbar('提示', '苹果地图启动失败'); Get.snackbar('tip'.tr, 'appleMapStartFailed'.tr);
} }
} else { } else {
print('苹果地图不可用'); print('苹果地图不可用');
Get.snackbar('提示', '苹果地图不可用'); Get.snackbar('tip'.tr, 'appleMapUnavailable'.tr);
} }
} catch (e) { } catch (e) {
print('打开苹果地图失败: $e'); print('打开苹果地图失败: $e');
Get.snackbar('错误', '打开苹果地图时发生错误'); Get.snackbar('error'.tr, 'openAppleMapError'.tr);
} }
} }

14
lib/modules/agent/views/message_bubble.dart

@ -691,7 +691,7 @@ class MessageBubble extends GetView<AgentController> {
child: Text( child: Text(
functionCalls != null && functionCalls!.isNotEmpty functionCalls != null && functionCalls!.isNotEmpty
? functionCalls!.keys.last ? functionCalls!.keys.last
: '工具调用', : 'toolCall'.tr,
style: TextStyle( style: TextStyle(
fontSize: 16, // 适当增大字体 fontSize: 16, // 适当增大字体
color: color:
@ -812,7 +812,7 @@ class MessageBubble extends GetView<AgentController> {
// 工具结果 - 剩余空间 // 工具结果 - 剩余空间
Expanded( Expanded(
child: Text( child: Text(
toolResult?.toString() ?? '无结果', toolResult?.toString() ?? 'noResult'.tr,
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 12,
color: Theme.of(context).brightness == color: Theme.of(context).brightness ==
@ -839,8 +839,8 @@ class MessageBubble extends GetView<AgentController> {
void _copyFunctionCallsToClipboard() { void _copyFunctionCallsToClipboard() {
if (functionCalls == null || functionCalls!.isEmpty) { if (functionCalls == null || functionCalls!.isEmpty) {
Get.snackbar( Get.snackbar(
'提示', 'tip'.tr,
'没有工具调用内容可以拷贝', 'noToolCallContentToCopy'.tr,
snackPosition: SnackPosition.BOTTOM, snackPosition: SnackPosition.BOTTOM,
duration: const Duration(seconds: 2), duration: const Duration(seconds: 2),
); );
@ -848,7 +848,7 @@ class MessageBubble extends GetView<AgentController> {
} }
StringBuffer buffer = StringBuffer(); StringBuffer buffer = StringBuffer();
buffer.writeln('工具调用详情:'); buffer.writeln('toolCallDetails'.tr);
buffer.writeln('=' * 30); buffer.writeln('=' * 30);
functionCalls!.forEach((toolName, toolData) { functionCalls!.forEach((toolName, toolData) {
@ -866,8 +866,8 @@ class MessageBubble extends GetView<AgentController> {
Clipboard.setData(ClipboardData(text: buffer.toString())); Clipboard.setData(ClipboardData(text: buffer.toString()));
Get.snackbar( Get.snackbar(
'成功', 'success'.tr,
'工具调用内容已复制到剪贴板', 'toolCallContentCopied'.tr,
snackPosition: SnackPosition.BOTTOM, snackPosition: SnackPosition.BOTTOM,
duration: const Duration(seconds: 2), duration: const Duration(seconds: 2),
); );

52
lib/modules/ble/controllers/ble_controller.dart

@ -44,7 +44,7 @@ class BleController extends GetxController {
if (state == fbp.BluetoothAdapterState.on) { if (state == fbp.BluetoothAdapterState.on) {
errorMessage.value = ''; errorMessage.value = '';
} else { } else {
errorMessage.value = '请开启蓝牙'; errorMessage.value = 'pleaseEnableBluetooth'.tr;
stopScan(); stopScan();
} }
}); });
@ -59,7 +59,7 @@ class BleController extends GetxController {
isScanning.value = scanning; isScanning.value = scanning;
}); });
} catch (e) { } catch (e) {
errorMessage.value = '蓝牙初始化失败: $e'; errorMessage.value = 'bleInitFailedWithError'.trParams({'error': e.toString()});
} }
} }
@ -76,7 +76,7 @@ class BleController extends GetxController {
statuses.values.every((status) => status == PermissionStatus.granted); statuses.values.every((status) => status == PermissionStatus.granted);
if (!hasPermissions.value) { if (!hasPermissions.value) {
errorMessage.value = '需要蓝牙和位置权限才能扫描设备'; errorMessage.value = 'needBluetoothAndLocationPermission'.tr;
} }
} catch (e) { } catch (e) {
print('检查权限失败: $e'); print('检查权限失败: $e');
@ -105,14 +105,14 @@ class BleController extends GetxController {
if (hasPermanentlyDenied) { if (hasPermanentlyDenied) {
_showPermissionDialog(); _showPermissionDialog();
} else { } else {
errorMessage.value = '需要蓝牙和位置权限才能扫描设备'; errorMessage.value = 'needBluetoothAndLocationPermission'.tr;
} }
} }
return allGranted; return allGranted;
} catch (e) { } catch (e) {
print('请求权限失败: $e'); print('请求权限失败: $e');
errorMessage.value = '权限请求失败: $e'; errorMessage.value = 'permissionRequestFailedWithError'.trParams({'error': e.toString()});
return false; return false;
} }
} }
@ -121,19 +121,19 @@ class BleController extends GetxController {
void _showPermissionDialog() { void _showPermissionDialog() {
Get.dialog( Get.dialog(
AlertDialog( AlertDialog(
title: Text('需要权限'), title: Text('needPermission'.tr),
content: Text('应用需要蓝牙和位置权限才能扫描设备。请在设置中手动开启权限。'), content: Text('blePermissionDialogContent'.tr),
actions: [ actions: [
TextButton( TextButton(
onPressed: () => Get.back(), onPressed: () => Get.back(),
child: Text('取消'), child: Text('cancel'.tr),
), ),
TextButton( TextButton(
onPressed: () { onPressed: () {
Get.back(); Get.back();
AppSettings.openAppSettings(); AppSettings.openAppSettings();
}, },
child: Text('去设置'), child: Text('goToSettings'.tr),
), ),
], ],
), ),
@ -144,12 +144,12 @@ class BleController extends GetxController {
void _showBluetoothDialog() { void _showBluetoothDialog() {
Get.dialog( Get.dialog(
AlertDialog( AlertDialog(
title: Text('需要开启蓝牙'), title: Text('needEnableBluetooth'.tr),
content: Text('请开启蓝牙以扫描和连接设备。'), content: Text('enableBluetoothDialogContent'.tr),
actions: [ actions: [
TextButton( TextButton(
onPressed: () => Get.back(), onPressed: () => Get.back(),
child: Text('取消'), child: Text('cancel'.tr),
), ),
TextButton( TextButton(
onPressed: () { onPressed: () {
@ -157,7 +157,7 @@ class BleController extends GetxController {
// 尝试开启蓝牙 // 尝试开启蓝牙
fbp.FlutterBluePlus.turnOn(); fbp.FlutterBluePlus.turnOn();
}, },
child: Text('开启蓝牙'), child: Text('enableBluetooth'.tr),
), ),
], ],
), ),
@ -191,7 +191,7 @@ class BleController extends GetxController {
androidUsesFineLocation: true, androidUsesFineLocation: true,
); );
} catch (e) { } catch (e) {
errorMessage.value = '扫描失败: $e'; errorMessage.value = 'bleScanFailedWithError'.trParams({'error': e.toString()});
} }
} }
@ -217,15 +217,15 @@ class BleController extends GetxController {
connectedDevice.value = device; connectedDevice.value = device;
Get.snackbar( Get.snackbar(
'连接成功', 'bleConnectionSuccess'.tr,
'已连接到 ${device.platformName.isNotEmpty ? device.platformName : '未知设备'}', 'bleConnectedToDevice'.trParams({'device': device.platformName.isNotEmpty ? device.platformName : 'unknownEquipment'.tr}),
backgroundColor: Colors.green, backgroundColor: Colors.green,
colorText: Colors.white, colorText: Colors.white,
); );
} catch (e) { } catch (e) {
errorMessage.value = '连接失败: $e'; errorMessage.value = 'bleConnectionFailedWithError'.trParams({'error': e.toString()});
Get.snackbar( Get.snackbar(
'连接失败', 'connectionFailed'.tr,
e.toString(), e.toString(),
backgroundColor: Colors.red, backgroundColor: Colors.red,
colorText: Colors.white, colorText: Colors.white,
@ -241,14 +241,14 @@ class BleController extends GetxController {
connectedDevice.value = null; connectedDevice.value = null;
Get.snackbar( Get.snackbar(
'已断开连接', 'bleDisconnected'.tr,
'设备已断开连接', 'bleDeviceDisconnected'.tr,
backgroundColor: Colors.orange, backgroundColor: Colors.orange,
colorText: Colors.white, colorText: Colors.white,
); );
} }
} catch (e) { } catch (e) {
errorMessage.value = '断开连接失败: $e'; errorMessage.value = 'bleDisconnectFailedWithError'.trParams({'error': e.toString()});
} }
} }
@ -260,15 +260,15 @@ class BleController extends GetxController {
if (result.advertisementData.localName.isNotEmpty) { if (result.advertisementData.localName.isNotEmpty) {
return result.advertisementData.localName; return result.advertisementData.localName;
} }
return '未知设备'; return 'unknownEquipment'.tr;
} }
// 获取信号强度描述 // 获取信号强度描述
String getSignalStrengthText(int rssi) { String getSignalStrengthText(int rssi) {
if (rssi >= -50) return '信号强'; if (rssi >= -50) return 'signalStrong'.tr;
if (rssi >= -70) return '信号中等'; if (rssi >= -70) return 'signalMedium'.tr;
if (rssi >= -90) return '信号弱'; if (rssi >= -90) return 'signalWeak'.tr;
return '信号很弱'; return 'signalVeryWeak'.tr;
} }
// 获取信号强度图标 // 获取信号强度图标

56
lib/modules/ota_upgrade/controllers/ota_core_contropller.dart

@ -97,7 +97,7 @@ class OtaCoreService {
return true; return true;
} catch (e) { } catch (e) {
_showBleCheckFailedSnackbar('检查BLE连接状态时发生错误:$e'); _showBleCheckFailedSnackbar('otaBleCheckErrorWithError'.trParams({'error': e.toString()}));
return false; return false;
} }
} }
@ -107,14 +107,14 @@ class OtaCoreService {
Get.dialog( Get.dialog(
AlertDialog( AlertDialog(
title: Text( title: Text(
'BLE设备未连接', 'otaBleNotConnected'.tr,
style: TextStyle( style: TextStyle(
color: Colors.red[700], color: Colors.red[700],
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),
content: Text( content: Text(
'固件升级需要连接BLE设备\n请确保设备已正确连接后再试', 'otaBleNeedConnection'.tr,
style: TextStyle( style: TextStyle(
color: Colors.red[600], color: Colors.red[600],
), ),
@ -125,7 +125,7 @@ class OtaCoreService {
style: TextButton.styleFrom( style: TextButton.styleFrom(
foregroundColor: Colors.red[700], foregroundColor: Colors.red[700],
), ),
child: const Text('确定'), child: Text('okConfirm'.tr),
), ),
], ],
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
@ -145,14 +145,14 @@ class OtaCoreService {
Get.dialog( Get.dialog(
AlertDialog( AlertDialog(
title: Text( title: Text(
'设备信息不可用', 'otaDeviceInfoUnavailableTitle'.tr,
style: TextStyle( style: TextStyle(
color: Colors.orange[700], color: Colors.orange[700],
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),
content: Text( content: Text(
'无法获取设备信息\n请重新连接设备或稍后再试', 'otaCannotGetDeviceInfo'.tr,
style: TextStyle( style: TextStyle(
color: Colors.orange[600], color: Colors.orange[600],
), ),
@ -163,7 +163,7 @@ class OtaCoreService {
style: TextButton.styleFrom( style: TextButton.styleFrom(
foregroundColor: Colors.orange[700], foregroundColor: Colors.orange[700],
), ),
child: const Text('确定'), child: Text('okConfirm'.tr),
), ),
], ],
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
@ -182,7 +182,7 @@ class OtaCoreService {
/// [message] 错误信息 /// [message] 错误信息
void _showBleCheckFailedSnackbar(String message) { void _showBleCheckFailedSnackbar(String message) {
Get.snackbar( Get.snackbar(
'BLE连接检查失败', 'otaBleCheckFailed'.tr,
message, message,
snackPosition: SnackPosition.BOTTOM, snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red[600], backgroundColor: Colors.red[600],
@ -202,7 +202,7 @@ class OtaCoreService {
final deviceInfo = _bleManager.deviceInfo.value; final deviceInfo = _bleManager.deviceInfo.value;
if (deviceInfo == null) { if (deviceInfo == null) {
_showBatteryCheckFailedSnackbar('无法获取设备信息,请检查设备连接'); _showBatteryCheckFailedSnackbar('otaCannotGetDeviceInfoCheckConnection'.tr);
return false; return false;
} }
@ -213,7 +213,7 @@ class OtaCoreService {
// 如果根据设备名称找不到产品,尝试使用默认产品名称 // 如果根据设备名称找不到产品,尝试使用默认产品名称
product = AppConfig.getproduct("DeapSound"); product = AppConfig.getproduct("DeapSound");
if (product == null) { if (product == null) {
_showBatteryCheckFailedSnackbar('无法获取产品信息,设备名称: $deviceName'); _showBatteryCheckFailedSnackbar('otaCannotGetProductInfoWithName'.trParams({'deviceName': deviceName}));
return false; return false;
} }
} }
@ -236,7 +236,7 @@ class OtaCoreService {
return _checkDoubleHeadsetBattery(leftBattery, rightBattery); return _checkDoubleHeadsetBattery(leftBattery, rightBattery);
} }
} catch (e) { } catch (e) {
_showBatteryCheckFailedSnackbar('检查设备电量时发生错误:$e'); _showBatteryCheckFailedSnackbar('otaBleCheckErrorWithError'.trParams({'error': e.toString()}));
return false; return false;
} }
} }
@ -253,14 +253,14 @@ class OtaCoreService {
if (leftBattery > 0 && leftBattery != 127) { if (leftBattery > 0 && leftBattery != 127) {
// 左耳有效,使用左耳电量 // 左耳有效,使用左耳电量
activeBattery = leftBattery; activeBattery = leftBattery;
activeEar = '左耳'; activeEar = 'leftEar'.tr;
} else if (rightBattery > 0 && rightBattery != 127) { } else if (rightBattery > 0 && rightBattery != 127) {
// 左耳无效,使用右耳电量 // 左耳无效,使用右耳电量
activeBattery = rightBattery; activeBattery = rightBattery;
activeEar = '右耳'; activeEar = 'rightEar'.tr;
} else { } else {
// 两边都无效 // 两边都无效
_showBatteryCheckFailedSnackbar('无法获取有效的电量信息'); _showBatteryCheckFailedSnackbar('otaCannotGetBatteryInfo'.tr);
return false; return false;
} }
@ -285,7 +285,7 @@ class OtaCoreService {
bool rightValid = rightBattery > 0 && rightBattery != 127; bool rightValid = rightBattery > 0 && rightBattery != 127;
if (!leftValid || !rightValid) { if (!leftValid || !rightValid) {
_showBatteryCheckFailedSnackbar('无法获取有效的电量信息'); _showBatteryCheckFailedSnackbar('otaCannotGetBatteryInfo'.tr);
return false; return false;
} }
@ -314,15 +314,15 @@ class OtaCoreService {
/// [earSide] 耳机端(左耳/右耳) /// [earSide] 耳机端(左耳/右耳)
/// [batteryLevel] 电量百分比 /// [batteryLevel] 电量百分比
void _showSingleHeadsetLowBatteryDialog(String earSide, int batteryLevel) { void _showSingleHeadsetLowBatteryDialog(String earSide, int batteryLevel) {
String message = '设备电量不足,无法进行固件升级\n'; String message = 'otaSingleBatteryLow'.trParams({
message += '升级要求:设备电量需大于20%\n'; 'ear': earSide,
message += '当前电量:$earSide ${batteryLevel}%\n'; 'battery': batteryLevel.toString(),
message += '请充电后再试'; });
Get.dialog( Get.dialog(
AlertDialog( AlertDialog(
title: Text( title: Text(
'电量不足', 'otaLowBattery'.tr,
style: TextStyle( style: TextStyle(
color: Colors.orange[700], color: Colors.orange[700],
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@ -340,7 +340,7 @@ class OtaCoreService {
style: TextButton.styleFrom( style: TextButton.styleFrom(
foregroundColor: Colors.orange[700], foregroundColor: Colors.orange[700],
), ),
child: const Text('确定'), child: Text('okConfirm'.tr),
), ),
], ],
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
@ -359,15 +359,15 @@ class OtaCoreService {
/// [leftBattery] 左耳电量 /// [leftBattery] 左耳电量
/// [rightBattery] 右耳电量 /// [rightBattery] 右耳电量
void _showLowBatteryDialog(int leftBattery, int rightBattery) { void _showLowBatteryDialog(int leftBattery, int rightBattery) {
String message = '设备电量不足,无法进行固件升级\n'; String message = 'otaDoubleBatteryLow'.trParams({
message += '升级要求:左右耳电量均需大于20%\n'; 'left': leftBattery.toString(),
message += '当前电量:左耳 ${leftBattery}%,右耳 ${rightBattery}%\n'; 'right': rightBattery.toString(),
message += '请充电后再试'; });
Get.dialog( Get.dialog(
AlertDialog( AlertDialog(
title: Text( title: Text(
'电量不足', 'otaLowBattery'.tr,
style: TextStyle( style: TextStyle(
color: Colors.orange[700], color: Colors.orange[700],
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@ -385,7 +385,7 @@ class OtaCoreService {
style: TextButton.styleFrom( style: TextButton.styleFrom(
foregroundColor: Colors.orange[700], foregroundColor: Colors.orange[700],
), ),
child: const Text('确定'), child: Text('okConfirm'.tr),
), ),
], ],
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
@ -404,7 +404,7 @@ class OtaCoreService {
/// [message] 错误信息 /// [message] 错误信息
void _showBatteryCheckFailedSnackbar(String message) { void _showBatteryCheckFailedSnackbar(String message) {
Get.snackbar( Get.snackbar(
'电量检查失败', 'otaBatteryCheckFailed'.tr,
message, message,
snackPosition: SnackPosition.BOTTOM, snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.orange[600], backgroundColor: Colors.orange[600],

32
lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart

@ -104,7 +104,7 @@ class OtaUpgradeController extends GetxController {
// 设置更新描述信息 // 设置更新描述信息
updatedescription.value = updatedescription.value =
latestInfo['updateDescription'] ?? '本次更新包含性能优化和错误修复。'; latestInfo['updateDescription'] ?? 'otaDefaultUpdateDesc'.tr;
// 检查是否有更新 // 检查是否有更新
isUpdateAvailable.value = _coreService.isNewVersionAvailable( isUpdateAvailable.value = _coreService.isNewVersionAvailable(
@ -125,11 +125,11 @@ class OtaUpgradeController extends GetxController {
if (latestVersion.value.isNotEmpty) { if (latestVersion.value.isNotEmpty) {
_uiService.showUpdateDialog(latestVersion.value, _startUpdateProcess); _uiService.showUpdateDialog(latestVersion.value, _startUpdateProcess);
} else { } else {
_uiService.showErrorSnackbar('错误', '获取最新版本信息失败', _uiService.showErrorSnackbar('error'.tr, 'otaGetLatestVersionFailed'.tr,
backgroundColor: Colors.orange[800]); backgroundColor: Colors.orange[800]);
} }
} catch (e) { } catch (e) {
_uiService.showErrorSnackbar('错误', '获取版本信息失败', _uiService.showErrorSnackbar('error'.tr, 'otaGetVersionInfoFailed'.tr,
backgroundColor: Colors.orange[800]); backgroundColor: Colors.orange[800]);
} }
} }
@ -139,7 +139,7 @@ class OtaUpgradeController extends GetxController {
Future<void> startUpdate() async { Future<void> startUpdate() async {
//立即给用户状态反馈 //立即给用户状态反馈
showDetailedStatus.value = true; showDetailedStatus.value = true;
detailedStatus.value = '正在检查设备状态...'; detailedStatus.value = 'otaCheckingDeviceStatus'.tr;
await _startUpdateProcess(); await _startUpdateProcess();
} }
@ -180,9 +180,9 @@ class OtaUpgradeController extends GetxController {
await _startUpgrading(filePath); await _startUpgrading(filePath);
} catch (e) { } catch (e) {
isDownloading.value = false; isDownloading.value = false;
detailedStatus.value = '下载失败,请检查网络连接'; detailedStatus.value = 'otaDownloadFailedCheckNetwork'.tr;
showDetailedStatus.value = false; showDetailedStatus.value = false;
_handleError('下载失败', e.toString()); _handleError('otaDownloadFailed'.tr, e.toString());
Logger.d('OtaUpgradeController', '下载失败: $e'); Logger.d('OtaUpgradeController', '下载失败: $e');
} }
} }
@ -191,9 +191,9 @@ class OtaUpgradeController extends GetxController {
/// [filePath] 固件文件路径 /// [filePath] 固件文件路径
/// 启动OTA升级过程 /// 启动OTA升级过程
Future<void> _startUpgrading(String filePath) async { Future<void> _startUpgrading(String filePath) async {
detailedStatus.value = '准备设备连接...'; detailedStatus.value = 'otaPreparingConnection'.tr;
await Future.delayed(const Duration(milliseconds: 500)); await Future.delayed(const Duration(milliseconds: 500));
detailedStatus.value = '正在连接设备...'; detailedStatus.value = 'otaConnectingDevice'.tr;
_jlota.startUpgrading(address: _address, filePath: filePath); _jlota.startUpgrading(address: _address, filePath: filePath);
} }
@ -236,13 +236,13 @@ class OtaUpgradeController extends GetxController {
type.value = event.type!; type.value = event.type!;
isUpgrade.value = true; isUpgrade.value = true;
detailedStatus.value = detailedStatus.value =
'升级进度: ${(event.progress! * 100).toStringAsFixed(1)}%'; 'otaUpgradeProgressWithPercent'.trParams({'percent': (event.progress! * 100).toStringAsFixed(1)});
} }
break; break;
case 'onStartOTA': case 'onStartOTA':
type.value = OtaCoreService.START_UPGRADING; type.value = OtaCoreService.START_UPGRADING;
isUpgrade.value = true; isUpgrade.value = true;
detailedStatus.value = 'OTA升级已开始...'; detailedStatus.value = 'otaUpgradeStarted'.tr;
break; break;
case 'onStopOTA': case 'onStopOTA':
_handleUpgradeSuccess(); _handleUpgradeSuccess();
@ -264,7 +264,7 @@ class OtaUpgradeController extends GetxController {
void _handleUpgradeSuccess() { void _handleUpgradeSuccess() {
type.value = OtaCoreService.UPGRADE_SUCCESS; type.value = OtaCoreService.UPGRADE_SUCCESS;
isUpgrade.value = false; isUpgrade.value = false;
detailedStatus.value = '升级成功完成'; detailedStatus.value = 'otaUpgradeSuccessComplete'.tr;
showDetailedStatus.value = false; showDetailedStatus.value = false;
// 更新版本信息 // 更新版本信息
@ -281,11 +281,11 @@ class OtaUpgradeController extends GetxController {
void _handleUpgradeError(dynamic errorCode) { void _handleUpgradeError(dynamic errorCode) {
type.value = OtaCoreService.UPGRADE_FAILED; type.value = OtaCoreService.UPGRADE_FAILED;
isUpgrade.value = false; isUpgrade.value = false;
detailedStatus.value = '升级失败,错误码:$errorCode'; detailedStatus.value = 'otaUpgradeFailedWithCode'.trParams({'code': errorCode.toString()});
showDetailedStatus.value = false; showDetailedStatus.value = false;
_uiService.showErrorSnackbar( _uiService.showErrorSnackbar(
'升级失败', 'otaUpgradeFailedTitle'.tr,
'请检查设备连接或升级包,错误码:$errorCode', 'otaUpgradeFailedDesc'.trParams({'code': errorCode.toString()}),
); );
} }
@ -294,7 +294,7 @@ class OtaUpgradeController extends GetxController {
void _handleConnectionLost() { void _handleConnectionLost() {
type.value = OtaCoreService.CONNECTION_DISCONNECTION; type.value = OtaCoreService.CONNECTION_DISCONNECTION;
isUpgrade.value = false; isUpgrade.value = false;
detailedStatus.value = '设备连接断开'; detailedStatus.value = 'otaDeviceDisconnected'.tr;
showDetailedStatus.value = false; showDetailedStatus.value = false;
} }
@ -303,7 +303,7 @@ class OtaUpgradeController extends GetxController {
void _handleConnectionSuccess() { void _handleConnectionSuccess() {
type.value = OtaCoreService.CONNECTION_SUCCESS; type.value = OtaCoreService.CONNECTION_SUCCESS;
isUpgrade.value = true; isUpgrade.value = true;
detailedStatus.value = '设备连接成功'; detailedStatus.value = 'otaDeviceConnected'.tr;
} }
/// 统一错误处理 /// 统一错误处理

18
lib/modules/ota_upgrade/views/ota_upgrade_popup_view.dart

@ -14,15 +14,15 @@ class OtaUpgradePopUp {
Logger().d('显示更新对话框'); Logger().d('显示更新对话框');
Get.dialog( Get.dialog(
AlertDialog( AlertDialog(
title: Text('发现新版本 $latestVersion'), title: Text('otaNewVersionFoundWithVersion'.trParams({'version': latestVersion})),
content: const Text('是否立即更新?'), content: Text('otaConfirmUpdateNow'.tr),
actions: [ actions: [
TextButton( TextButton(
onPressed: () { onPressed: () {
Logger().d('取消按钮被点击'); Logger().d('取消按钮被点击');
Get.back(); Get.back();
}, },
child: const Text('取消'), child: Text('cancel'.tr),
), ),
TextButton( TextButton(
onPressed: () { onPressed: () {
@ -31,7 +31,7 @@ class OtaUpgradePopUp {
Future.delayed(const Duration(milliseconds: 300)); Future.delayed(const Duration(milliseconds: 300));
onConfirm(); onConfirm();
}, },
child: const Text('更新'), child: Text('otaUpdate'.tr),
), ),
], ],
), ),
@ -52,7 +52,7 @@ class OtaUpgradePopUp {
), ),
SizedBox(width: 12.w), SizedBox(width: 12.w),
Text( Text(
'升级成功', 'otaUpgradeSuccess'.tr,
style: TextStyle( style: TextStyle(
color: Colors.green[700], color: Colors.green[700],
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@ -60,8 +60,8 @@ class OtaUpgradePopUp {
), ),
], ],
), ),
content: const Text( content: Text(
'固件升级已完成!\n\n设备需要重新配对才能正常使用,现在跳转到配对页面吗?', 'otaUpgradeCompleteRepair'.tr,
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
height: 1.4, height: 1.4,
@ -73,7 +73,7 @@ class OtaUpgradePopUp {
Get.back(); Get.back();
}, },
child: Text( child: Text(
'稍后配对', 'otaPairLater'.tr,
style: TextStyle(color: Colors.grey[600]), style: TextStyle(color: Colors.grey[600]),
), ),
), ),
@ -86,7 +86,7 @@ class OtaUpgradePopUp {
backgroundColor: Colors.green[600], backgroundColor: Colors.green[600],
foregroundColor: Colors.white, foregroundColor: Colors.white,
), ),
child: const Text('立即配对'), child: Text('otaPairNow'.tr),
), ),
], ],
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(

4
lib/modules/translation/controllers/translation_controller.dart

@ -110,8 +110,8 @@ class TranslationController extends GetxController with WidgetsBindingObserver {
final floatingButtonPosition = Rx<Offset>(Offset(2.0, 100.0)); // 默认位置 final floatingButtonPosition = Rx<Offset>(Offset(2.0, 100.0)); // 默认位置
// ==================== 语言相关 ==================== // ==================== 语言相关 ====================
final sourceLanguage = '中文(简体)'.obs; final sourceLanguage = '中文(简体)'.tr.obs;
final targetLanguage = '英语'.obs; final targetLanguage = '英语'.tr.obs;
final sourceLanguageCode = 'zh-CN'.obs; final sourceLanguageCode = 'zh-CN'.obs;
final targetLanguageCode = 'en-US'.obs; final targetLanguageCode = 'en-US'.obs;
var detectedLanguageCode = ''; var detectedLanguageCode = '';

10
lib/modules/translation/views/translation_view.dart

@ -256,8 +256,8 @@ class TranslationView extends GetView<TranslationController> {
), ),
onPressed: controller.toggleFloatingWindow, onPressed: controller.toggleFloatingWindow,
tooltip: controller.isFloatingWindowEnabled.value tooltip: controller.isFloatingWindowEnabled.value
? '禁用悬浮窗' ? 'disableFloatingWindow'.tr
: '启用悬浮窗', : 'enableFloatingWindow'.tr,
); );
} }
return const SizedBox.shrink(); return const SizedBox.shrink();
@ -607,7 +607,7 @@ class TranslationView extends GetView<TranslationController> {
onPointerDown: (_) async { onPointerDown: (_) async {
// 检查权限 // 检查权限
if (!controller.hasRecordPermission.value) { if (!controller.hasRecordPermission.value) {
Get.snackbar('权限提示', '需要麦克风权限才能使用录音功能'); Get.snackbar('permissionTip'.tr, 'micPermissionRequiredForRecording'.tr);
return; return;
} }
@ -933,8 +933,8 @@ class TranslationView extends GetView<TranslationController> {
} catch (e) { } catch (e) {
// 显示删除失败提示 // 显示删除失败提示
Get.snackbar( Get.snackbar(
'error'.tr, // deleteFailed 'error'.tr,
'删除翻译记录时发生错误: ${e.toString()}', // deleteTranslationError 'deleteTranslationRecordError'.trParams({'error': e.toString()}),
snackPosition: SnackPosition.BOTTOM, snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red[400], backgroundColor: Colors.red[400],
colorText: Colors.white, colorText: Colors.white,

Loading…
Cancel
Save