diff --git a/lib/core/translations/language/en_us.dart b/lib/core/translations/language/en_us.dart index 15c5c1829..3868f975a 100644 --- a/lib/core/translations/language/en_us.dart +++ b/lib/core/translations/language/en_us.dart @@ -186,6 +186,52 @@ const Map enUS = { "usageStatsInfo": "View Your Usage Statistics", "scene": "Scenarios", + /// 用量统计模块 + "aiChat": "AI Chat", + "translationStats": "Translation Statistics", + "meetingStats": "Meeting Statistics", + "today": "Today", + "thisWeek": "This Week", + "thisMonth": "This Month", + "history": "History", + "currentSessionStats": "Current Session Stats", + "translationCount": "Translation Count", + "sessionDuration": "Session Duration", + "characters": "Characters", + "recordingDuration": "Recording Duration", + "totalApiCalls": "Total API Calls", + "sessionCount": "Session Count", + "totalCharacters": "Total Characters", + "apiCallStats": "API Call Stats", + "translationApi": "Translation API", + "asr": "ASR", + "tts": "TTS", + // "aiSummary": "AI Summary", + "dataVolumeStats": "Data Volume Stats", + "sourceTextCharacters": "Source Text Characters", + "ttsTextCharacters": "TTS Text Characters", + "effectiveAudioDuration": "Effective Audio Duration", + "totalSessionDuration": "Total Session Duration", + "costStats": "Cost Stats", + "estimatedCost": "Estimated Cost", + "dailyCostThreshold": "Daily Cost Threshold", + "monthlyCostThreshold": "Monthly Cost Threshold", + "usageBehaviorStats": "Usage Behavior Stats", + "mostUsedLanguagePair": "Most-used language pair", + "mostUsedMode": "Most-used mode", + "asrApiCalls": "ASR Calls", + "totalAudioDuration": "Total Audio Duration", + "audioFileSize": "Audio File Size", + "transcriptBytes": "Transcript Bytes", + //通知文案 + "loadFailed": "Load Failed", + "statsLoadFailedTryLater": + "Statistics failed to load. Please try again later.", + "cleanupComplete": "Cleanup Complete", + "cleanedOldData": "Cleaned data older than 90 days", + "exportFeature": "Export Feature", + "exportInDevelopment": "Data export is under development", + // 商品页面(AI/翻译/会议) 'availablePackages': 'Available Packages', 'remainingQuota': 'Remaining Quota', @@ -1150,6 +1196,7 @@ const Map enUS = { // 翻译主页 (translation_view.dart) "translationHistory": "Translation History", + "historyRecords": "History Records", "enableRecording": "Enable Recording", "viewAudioFiles": "View Audio Files", "headsetUser": "Headset User", @@ -1162,9 +1209,15 @@ const Map enUS = { // 通用对话按钮与选项(用于统一语言选择弹窗等) // 翻译键代表的中文文本内容:取消/确认/自动检测 "autoDetect": "Auto Detect", + // Text translation & language detection + "languageDetectionFailed": "Language detection failed", + "translationFailed": "Translation failed", + "pleaseInputText": "Please input text", + "textTooLong": "Text too long, max 5000 characters", // 翻译历史页 "noTranslationHistory": "No translation history", + "clearResults": "Clear Results", "clearHistory": "Clear History", "clearHistoryConfirm": "Are you sure you want to clear all translation history? This action cannot be undone.", @@ -1173,6 +1226,57 @@ const Map enUS = { "deleteSessionConfirm": "Are you sure you want to delete all translation records for this session? This action cannot be undone.", + // Picture Translation module + "selectImageSource": "Select Image Source", + "imagePreview": "Image Preview", + "translationResult": "Translation Result", + "recognitionResult": "Recognition Result", + "translatedImagePreview": "Translated Image Preview", + "translatedImageLoadFailed": "Failed to load translated image", + "pleaseSelectImage": "Please select an image", + "imageLoadFailed": "Image load failed", + "imageQuality": "Image Quality", + "maxSize": "Max Size", + "close": "Close", + "setImageQuality": "Set Image Quality", + "currentQuality": "Current quality: @value%", + "setMaxSize": "Set Max Size", + "currentMaxSize": "Current: @pxpx", + "waitingForAction": "Waiting for action", + "pleaseSelectImageToStart": "Please select an image to start", + "chooseImage": "Choose Image", + "openingCamera": "Opening camera...", + "openingPhotoAlbum": "Opening photo album...", + "cancelled": "Cancelled", + "userCancelledSelection": "User cancelled selection", + "translatingImage": "Translating Image", + "callingImageTranslateService": "Calling image translation service...", + "savingRecord": "Saving Record", + "savingTranslationResult": "Saving translation result...", + "translationCompleted": "Translation Completed", + "allStepsCompleted": "All steps completed", + "processingFailed": "Processing Failed", + "imageProcessingOrTranslationFailed": + "Image processing or translation failed. Please retry.\nError: {error}", + "imageTooLarge": "Image size exceeds 4MB limit", + "imageTooLargeHint": + "Image size exceeds 4MB. Reduce quality or dimensions and retry", + "emptyTranslationResult": "Image translation API returned empty result", + "imageTranslationFailedTryLater": + "Image translation failed. Network issue or rate limit. Please try later", + "imageTranslationApiException": + "Image translation API exception. Check network and retry", + "permissionRequired": "Permission Required", + "cameraPermissionRequired": "Camera permission required to take photos", + "photoAlbumPermissionRequired": + "Photo album permission required to pick images", + "translationDetails": "Translation Details", + "originalImage": "Original Image", + "sourceLanguage": "Source Language", + "targetLanguage": "Target Language", + "translationTime": "Translation Time", + "shareInDevelopment": "Sharing feature under development", + // 翻译录音文件列表页 "translateAudioFiles": "Translate Audio Files", "noAudioFiles": "No audio files", @@ -1382,6 +1486,9 @@ const Map enUS = { "justNow": "Just now", "minutesAgo": "@minutes minutes ago", "yesterday": "Yesterday", + // Time extensions (used by picture translation) + "daysAgo": "@days days ago", + "hoursAgo": "@hours hours ago", //补充 "insufficientIntegral": "Insufficient integral", @@ -1390,4 +1497,7 @@ const Map enUS = { "insufficientBalanceDesc": 'Insufficient balance, please go to the corresponding recharge page to recharge.', "recharge": 'Go to Recharge', + // 会员到期提示(中文注释) + "aiMemberExpiredDesc": + 'AI membership expired, please go to the membership recharge page to renew.', }; diff --git a/lib/core/translations/language/zh_cn.dart b/lib/core/translations/language/zh_cn.dart index 2b5504527..64db2449d 100644 --- a/lib/core/translations/language/zh_cn.dart +++ b/lib/core/translations/language/zh_cn.dart @@ -179,6 +179,50 @@ const Map zhCN = { "usageStats": "用量统计", "usageStatsInfo": "查看您的使用统计数据", "scene": "场景", + // 用量统计模块 + "aiChat": "AI聊天", + "translationStats": "翻译统计", + "meetingStats": "会议统计", + "today": "今日", + "thisWeek": "本周", + "thisMonth": "本月", + "history": "历史", + "currentSessionStats": "当前会话统计", + "translationCount": "翻译次数", + "sessionDuration": "会话时长", + "characters": "字符数", + "recordingDuration": "录音时长", + "totalApiCalls": "总调用次数", + "sessionCount": "会话数量", + "totalCharacters": "总字符数", + "apiCallStats": "API调用统计", + "translationApi": "翻译API", + "asr": "语音识别", + "tts": "语音合成", + //"aiSummary": "AI摘要", + "dataVolumeStats": "数据量统计", + "sourceTextCharacters": "源文本字符", + "ttsTextCharacters": "TTS文本字符", + "effectiveAudioDuration": "有效音频时长", + "totalSessionDuration": "总会话时长", + "costStats": "成本统计", + "estimatedCost": "预估成本", + "dailyCostThreshold": "日成本预警阈值", + "monthlyCostThreshold": "月成本预警阈值", + "usageBehaviorStats": "使用行为统计", + "mostUsedLanguagePair": "最常用语言对", + "mostUsedMode": "最常用模式", + "asrApiCalls": "ASR调用次数", + "totalAudioDuration": "音频总时长", + "audioFileSize": "音频文件大小", + "transcriptBytes": "转写字节", + // 通知文案 + "loadFailed": "加载失败", + "statsLoadFailedTryLater": "统计数据加载失败,请稍后重试", + "cleanupComplete": "清理完成", + "cleanedOldData": "已清理90天前的过期数据", + "exportFeature": "导出功能", + "exportInDevelopment": "数据导出功能正在开发中", // 商品页面(AI/翻译/会议) 'availablePackages': '可购买套餐', @@ -1067,15 +1111,68 @@ const Map zhCN = { // 通用对话按钮与选项(用于统一语言选择弹窗等) // 以下翻译键的中文文本内容如注释所示 "autoDetect": "自动检测", // 自动检测 + // 文本翻译与语种检测 + "languageDetectionFailed": "语言检测失败", + "translationFailed": "翻译失败", + "pleaseInputText": "请输入文本", + "textTooLong": "文本过长,最多5000字符", // 翻译历史页 "noTranslationHistory": "暂无历史记录", + "historyRecords": "历史记录", + "clearResults": "清空结果", "clearHistory": "清除历史记录", "clearHistoryConfirm": "确定要清除所有翻译历史记录吗?此操作无法撤销。", "unknownLanguage": "未知语言", "deleteSessionRecord": "删除会话记录", "deleteSessionConfirm": "确定要删除该会话的所有翻译记录吗?此操作无法撤销。", + // 图片翻译模块(Picture Translation) + "selectImageSource": "选择图片来源", + "imagePreview": "图片预览", + "translationResult": "翻译结果", + "recognitionResult": "识别结果", + "translatedImagePreview": "翻译后的图片预览", + "translatedImageLoadFailed": "翻译图片加载失败", + "pleaseSelectImage": "请选择图片", + "imageLoadFailed": "图片加载失败", + "imageQuality": "图片质量", + "maxSize": "最大尺寸", + "close": "关闭", + "setImageQuality": "设置图片质量", + "currentQuality": "当前质量: @value%", + "setMaxSize": "设置最大尺寸", + "currentMaxSize": "当前: @pxpx", + "waitingForAction": "等待操作", + "pleaseSelectImageToStart": "请选择图片开始翻译", + "chooseImage": "选择图片", + "openingCamera": "正在打开相机...", + "openingPhotoAlbum": "正在打开相册...", + "cancelled": "已取消", + "userCancelledSelection": "用户取消了选择", + "translatingImage": "翻译图片", + "callingImageTranslateService": "正在调用图片翻译服务...", + "savingRecord": "保存记录", + "savingTranslationResult": "正在保存翻译结果...", + "translationCompleted": "翻译完成", + "allStepsCompleted": "所有步骤已完成", + "processingFailed": "处理失败", + "imageProcessingOrTranslationFailed": "图片处理或翻译失败,请重试。\n错误信息: {error}", + "imageTooLarge": "图片大小超过4MB限制", + "imageTooLargeHint": "图片大小超过4MB限制,请降低质量或尺寸后重试", + "emptyTranslationResult": "图片翻译接口返回空结果", + "imageTranslationFailedTryLater": "图片翻译失败,可能的原因:网络异常或接口限流,请稍后重试", + "imageTranslationApiException": "图片翻译接口调用异常,请检查网络后重试", + "permissionRequired": "权限需求", + "cameraPermissionRequired": "需要相机权限才能拍照", + "photoAlbumPermissionRequired": "需要相册权限才能选择图片", + "translationDetails": "翻译详情", + "originalImage": "原图片", + "sourceLanguage": "源语言", + "targetLanguage": "目标语言", + "translationTime": "翻译时间", + "shareInDevelopment": "分享功能开发中", + // 翻译录音文件列表页 "translateAudioFiles": "翻译录音文件", "noAudioFiles": "暂无音频文件", @@ -1266,6 +1363,9 @@ const Map zhCN = { "justNow": "刚刚", "minutesAgo": "@minutes分钟前", "yesterday": "昨天", + // 时间扩展(图片翻译模块使用) + "daysAgo": "@days天前", + "hoursAgo": "@hours小时前", //补充 "insufficientIntegral": "积分不足", @@ -1273,4 +1373,6 @@ const Map zhCN = { //余额不足弹窗 "insufficientBalanceDesc": "余额不足,请前往对应充值界面进行充值", "recharge": "前往充值", + // 会员到期提示 + "aiMemberExpiredDesc": "AI会员已到期,请前往会员充值续费", }; diff --git a/lib/data/models/translation_usage_stats.dart b/lib/data/models/translation_usage_stats.dart index 6d73b1958..db420c771 100644 --- a/lib/data/models/translation_usage_stats.dart +++ b/lib/data/models/translation_usage_stats.dart @@ -1,5 +1,3 @@ - - /// 翻译模式统计数据 class TranslationModeStats { final int apiCalls; // API调用次数 @@ -46,7 +44,8 @@ class TranslationModeStats { return TranslationModeStats( apiCalls: apiCalls ?? this.apiCalls, sourceCharacters: sourceCharacters ?? this.sourceCharacters, - effectiveAudioDuration: effectiveAudioDuration ?? this.effectiveAudioDuration, + effectiveAudioDuration: + effectiveAudioDuration ?? this.effectiveAudioDuration, ttsCharacters: ttsCharacters ?? this.ttsCharacters, cost: cost ?? this.cost, ); @@ -158,7 +157,7 @@ class TranslationUsageStats { final double estimatedCost; // 预估成本 final String currency; // 货币单位 final Map costBreakdown; // 成本分解(ASR/TTS/Translation) - + TranslationUsageStats({ required this.id, required this.date, @@ -196,7 +195,8 @@ class TranslationUsageStats { final languagePairStatsMap = {}; if (json['languagePairStats'] != null) { - final languagePairStatsJson = json['languagePairStats'] as Map; + final languagePairStatsJson = + json['languagePairStats'] as Map; languagePairStatsJson.forEach((key, value) { languagePairStatsMap[key] = LanguagePairStats.fromJson(value); }); @@ -219,9 +219,15 @@ class TranslationUsageStats { asrApiCalls: json['asrApiCalls'] ?? 0, ttsApiCalls: json['ttsApiCalls'] ?? 0, aiSummaryApiCalls: json['aiSummaryApiCalls'] ?? 0, - sourceTextCharacters: json['sourceTextCharacters'] ?? json['sourceCharacterCount'] ?? 0, // 兼容旧字段 - effectiveAudioDuration: json['effectiveAudioDuration'] ?? json['audioRecordingDuration'] ?? 0, // 兼容旧字段 - ttsTextCharacters: json['ttsTextCharacters'] ?? json['targetCharacterCount'] ?? 0, // 兼容旧字段 + sourceTextCharacters: json['sourceTextCharacters'] ?? + json['sourceCharacterCount'] ?? + 0, // 兼容旧字段 + effectiveAudioDuration: json['effectiveAudioDuration'] ?? + json['audioRecordingDuration'] ?? + 0, // 兼容旧字段 + ttsTextCharacters: json['ttsTextCharacters'] ?? + json['targetCharacterCount'] ?? + 0, // 兼容旧字段 totalSessionDuration: json['totalSessionDuration'] ?? 0, asrNetworkBytes: json['asrNetworkBytes'] ?? 0, ttsNetworkBytes: json['ttsNetworkBytes'] ?? 0, @@ -328,12 +334,14 @@ class TranslationUsageStats { ttsApiCalls: ttsApiCalls ?? this.ttsApiCalls, aiSummaryApiCalls: aiSummaryApiCalls ?? this.aiSummaryApiCalls, sourceTextCharacters: sourceTextCharacters ?? this.sourceTextCharacters, - effectiveAudioDuration: effectiveAudioDuration ?? this.effectiveAudioDuration, + effectiveAudioDuration: + effectiveAudioDuration ?? this.effectiveAudioDuration, ttsTextCharacters: ttsTextCharacters ?? this.ttsTextCharacters, totalSessionDuration: totalSessionDuration ?? this.totalSessionDuration, asrNetworkBytes: asrNetworkBytes ?? this.asrNetworkBytes, ttsNetworkBytes: ttsNetworkBytes ?? this.ttsNetworkBytes, - translationNetworkBytes: translationNetworkBytes ?? this.translationNetworkBytes, + translationNetworkBytes: + translationNetworkBytes ?? this.translationNetworkBytes, sessionCount: sessionCount ?? this.sessionCount, modeStats: modeStats ?? this.modeStats, languagePairStats: languagePairStats ?? this.languagePairStats, @@ -345,7 +353,8 @@ class TranslationUsageStats { } /// 获取总API调用次数 - int get totalApiCalls => translationApiCalls + asrApiCalls + ttsApiCalls + aiSummaryApiCalls; + int get totalApiCalls => + translationApiCalls + asrApiCalls + ttsApiCalls + aiSummaryApiCalls; /// 获取总字符数(精确计费基础) int get totalCharacterCount => sourceTextCharacters + ttsTextCharacters; @@ -354,19 +363,21 @@ class TranslationUsageStats { int get totalAudioDuration => effectiveAudioDuration + totalSessionDuration; /// 获取总网络流量 - int get totalNetworkBytes => asrNetworkBytes + ttsNetworkBytes + translationNetworkBytes; + int get totalNetworkBytes => + asrNetworkBytes + ttsNetworkBytes + translationNetworkBytes; /// 获取最常用的语言对 String get mostUsedLanguagePair { - if (languagePairStats.isEmpty) return '无数据'; + if (languagePairStats.isEmpty) return 'null'; return languagePairStats.entries - .reduce((a, b) => a.value.translationCount > b.value.translationCount ? a : b) + .reduce((a, b) => + a.value.translationCount > b.value.translationCount ? a : b) .key; } /// 获取最常用的翻译模式 String get mostUsedMode { - if (modeStats.isEmpty) return '无数据'; + if (modeStats.isEmpty) return 'null'; return modeStats.entries .reduce((a, b) => a.value.apiCalls > b.value.apiCalls ? a : b) .key; diff --git a/lib/modules/common/widgets/language_selector_bar.dart b/lib/modules/common/widgets/language_selector_bar.dart index 495a01a00..4b7878287 100644 --- a/lib/modules/common/widgets/language_selector_bar.dart +++ b/lib/modules/common/widgets/language_selector_bar.dart @@ -58,7 +58,7 @@ class LanguageSelectorBar extends StatelessWidget { isDarkMode ? AppColors.primary.withOpacity(0.2) : Colors.blue[50]; final swapIconColor = isDarkMode ? AppColors.primary : Colors.blue; - // 规范化特殊项的翻译键,例如:自动检测 -> autoDetect(翻译键代表的中文文本内容) + // 规范化特殊项的翻译键,例如:自动检测 -> autoDetect(对应中文:自动检测) String _normalizeKey(String text) { switch (text) { case '自动检测': diff --git a/lib/modules/common/widgets/recharge_dialog.dart b/lib/modules/common/widgets/recharge_dialog.dart index 1dd6562b4..b3f6d15b8 100644 --- a/lib/modules/common/widgets/recharge_dialog.dart +++ b/lib/modules/common/widgets/recharge_dialog.dart @@ -2,6 +2,9 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../routes/app_routes.dart'; +/// 显示充值弹窗 +/// [type] 充值类型,可选值为 'agent'、'translation'、'meeting' +/// 分别跳转对应ai充值、翻译充值、会议充值界面 void showRechargeDialog(String type) { Get.dialog( Dialog( @@ -24,7 +27,10 @@ void showRechargeDialog(String type) { ), const SizedBox(height: 12), Text( - 'insufficientBalanceDesc'.tr, //'余额不足,请前往对应充值界面进行充值', + (type == 'agent' + ? 'aiMemberExpiredDesc' + : 'insufficientBalanceDesc') + .tr, // 会员过期描述 / 余额不足描述 textAlign: TextAlign.center, ), const SizedBox(height: 20), diff --git a/lib/modules/meeting/controllers/meeting_home_controller.dart b/lib/modules/meeting/controllers/meeting_home_controller.dart index fcea611a4..7eaab1b26 100644 --- a/lib/modules/meeting/controllers/meeting_home_controller.dart +++ b/lib/modules/meeting/controllers/meeting_home_controller.dart @@ -410,7 +410,8 @@ class MeetingHomeController extends GetxController { Logger.error('importFailed' .tr .replaceAll('{filePath}', filePath) - .replaceAll('{error}', e.toString())); // 翻译键代表的中文文本内容 + .replaceAll('{error}', + e.toString())); // 对应中文:导入文件失败: {filePath}, error: {error} } } else { effectivePath = filePath; diff --git a/lib/modules/picture_translation/controllers/picture_translation_controller.dart b/lib/modules/picture_translation/controllers/picture_translation_controller.dart index 9f25c0350..abd55af47 100644 --- a/lib/modules/picture_translation/controllers/picture_translation_controller.dart +++ b/lib/modules/picture_translation/controllers/picture_translation_controller.dart @@ -34,8 +34,8 @@ class PictureTranslationController extends GetxController { final isProcessing = false.obs; final pickedImageFile = Rx(null); final currentStep = ProcessingStep( - title: '等待操作', - description: '请选择图片开始翻译', + title: 'waitingForAction'.tr, // 等待操作 + description: 'pleaseSelectImageToStart'.tr, // 请选择图片开始翻译 status: ProcessingStatus.idle, ).obs; @@ -152,13 +152,17 @@ class PictureTranslationController extends GetxController { if (source == ImageSource.camera) { final status = await Permission.camera.request(); if (!status.isGranted) { - Get.snackbar('权限需求', '需要相机权限才能拍照'); + Get.snackbar( + 'permissionRequired'.tr, // 权限需求 + 'cameraPermissionRequired'.tr); // 需要相机权限才能拍照 return false; } } else { final status = await Permission.photos.request(); if (!status.isGranted) { - Get.snackbar('权限需求', '需要相册权限才能选择图片'); + Get.snackbar( + 'permissionRequired'.tr, // 权限需求 + 'photoAlbumPermissionRequired'.tr); // 需要相册权限才能选择图片 return false; } } @@ -194,8 +198,10 @@ class PictureTranslationController extends GetxController { try { isProcessing.value = true; _updateStep( - '选择图片', - '正在打开${source == ImageSource.camera ? '相机' : '相册'}...', + 'chooseImage'.tr, // 选择图片 + (source == ImageSource.camera + ? 'openingCamera'.tr // 正在打开相机... + : 'openingPhotoAlbum'.tr), // 正在打开相册... ProcessingStatus.picking); final XFile? image = await _imagePicker.pickImage( @@ -206,7 +212,10 @@ class PictureTranslationController extends GetxController { ); if (image == null) { - _updateStep('已取消', '用户取消了选择', ProcessingStatus.idle); + _updateStep( + 'cancelled'.tr, // 已取消 + 'userCancelledSelection'.tr, // 用户取消了选择 + ProcessingStatus.idle); return; } @@ -217,23 +226,39 @@ class PictureTranslationController extends GetxController { pickedImageFile.value = file; // 直接调用图片翻译API(包含识别+回贴) - _updateStep('翻译图片', '正在调用图片翻译服务...', ProcessingStatus.translating, + _updateStep( + 'translatingImage'.tr, // 翻译图片 + 'callingImageTranslateService'.tr, // 正在调用图片翻译服务... + ProcessingStatus.translating, progress: 0.6); await _performImageTranslation(file); // 保存历史记录 if (sourceText.value.isNotEmpty && translatedText.value.isNotEmpty) { - _updateStep('保存记录', '正在保存翻译结果...', ProcessingStatus.saving, + _updateStep( + 'savingRecord'.tr, // 保存记录 + 'savingTranslationResult'.tr, // 正在保存翻译结果... + ProcessingStatus.saving, progress: 0.9); await _saveTranslationResult(file); } - _updateStep('翻译完成', '所有步骤已完成', ProcessingStatus.idle, progress: 1.0); + _updateStep( + 'translationCompleted'.tr, // 翻译完成 + 'allStepsCompleted'.tr, // 所有步骤已完成 + ProcessingStatus.idle, + progress: 1.0); } catch (e) { Logger.error('PictureTranslation', '处理失败: $e'); - _updateStep('处理失败', e.toString(), ProcessingStatus.error); - _showErrorDialog('处理失败', '图片处理或翻译失败,请重试。\n错误信息: $e'); + _updateStep( + 'processingFailed'.tr, // 处理失败 + e.toString(), + ProcessingStatus.error); + _showErrorDialog( + 'processingFailed'.tr, // 处理失败 + 'imageProcessingOrTranslationFailed'.tr.replaceAll( + '{error}', e.toString())); // 图片处理或翻译失败,请重试。错误信息: {error} } finally { isProcessing.value = false; } @@ -286,8 +311,13 @@ class PictureTranslationController extends GetxController { // 图片大小限制:4MB(文档要求) const int maxSize = 4 * 1024 * 1024; if (bytes.lengthInBytes > maxSize) { - _updateStep('处理失败', '图片大小超过4MB限制', ProcessingStatus.error); - _showErrorDialog('处理失败', '图片大小超过4MB限制,请降低质量或尺寸后重试'); + _updateStep( + 'processingFailed'.tr, // 处理失败 + 'imageTooLarge'.tr, // 图片大小超过4MB限制 + ProcessingStatus.error); + _showErrorDialog( + 'processingFailed'.tr, // 处理失败 + 'imageTooLargeHint'.tr); // 图片大小超过4MB限制,请降低质量或尺寸后重试 return; } @@ -301,8 +331,13 @@ class PictureTranslationController extends GetxController { ); if (result == null) { - _updateStep('处理失败', '图片翻译接口返回空结果', ProcessingStatus.error); - _showErrorDialog('处理失败', '图片翻译失败,可能的原因:网络异常或接口限流,请稍后重试'); + _updateStep( + 'processingFailed'.tr, // 处理失败 + 'emptyTranslationResult'.tr, // 图片翻译接口返回空结果 + ProcessingStatus.error); + _showErrorDialog( + 'processingFailed'.tr, // 处理失败 + 'imageTranslationFailedTryLater'.tr); // 失败原因提示 return; } @@ -322,8 +357,13 @@ class PictureTranslationController extends GetxController { } } catch (e) { Logger.error('PictureTranslation', '图片翻译调用失败: $e'); - _updateStep('处理失败', e.toString(), ProcessingStatus.error); - _showErrorDialog('处理失败', '图片翻译接口调用异常,请检查网络后重试'); + _updateStep( + 'processingFailed'.tr, // 处理失败 + e.toString(), + ProcessingStatus.error); + _showErrorDialog( + 'processingFailed'.tr, // 处理失败 + 'imageTranslationApiException'.tr); // 接口调用异常 } } @@ -362,7 +402,7 @@ class PictureTranslationController extends GetxController { actions: [ TextButton( onPressed: () => Get.back(), - child: const Text('确定'), + child: Text('confirm'.tr), // 确认 ), ], ), @@ -403,7 +443,9 @@ class PictureTranslationController extends GetxController { void copyText(String text) { if (text.isNotEmpty) { // 这里可以添加复制到剪切板的逻辑 - Get.snackbar('成功', '文本已复制到剪切板'); + Get.snackbar( + 'success'.tr, // 成功 + 'copied'.tr); // 已复制 } } @@ -413,6 +455,9 @@ class PictureTranslationController extends GetxController { translatedText.value = ''; translatedImageBytes.value = null; pickedImageFile.value = null; - _updateStep('等待操作', '请选择图片开始翻译', ProcessingStatus.idle); + _updateStep( + 'waitingForAction'.tr, // 等待操作 + 'pleaseSelectImageToStart'.tr, // 请选择图片开始翻译 + ProcessingStatus.idle); } } diff --git a/lib/modules/picture_translation/views/picture_translation_history_detail_view.dart b/lib/modules/picture_translation/views/picture_translation_history_detail_view.dart index b2fb50c8a..bf664acbc 100644 --- a/lib/modules/picture_translation/views/picture_translation_history_detail_view.dart +++ b/lib/modules/picture_translation/views/picture_translation_history_detail_view.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; +import 'package:intl/intl.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import '../../../core/theme/app_colors.dart'; @@ -20,8 +21,7 @@ class PictureTranslationHistoryDetailView extends StatelessWidget { Widget build(BuildContext context) { final isDarkMode = Theme.of(context).brightness == Brightness.dark; return Scaffold( - backgroundColor: - isDarkMode ? AppColors.darkBackground : Colors.grey[50], + backgroundColor: isDarkMode ? AppColors.darkBackground : Colors.grey[50], appBar: AppBar( leading: IconButton( icon: Icon( @@ -32,7 +32,7 @@ class PictureTranslationHistoryDetailView extends StatelessWidget { onPressed: () => Get.back(), ), centerTitle: true, - title: Text('翻译详情', + title: Text('translationDetails'.tr, // 翻译详情 style: TextStyle( color: isDarkMode ? AppColors.textPrimary : Colors.black87)), backgroundColor: isDarkMode ? AppColors.cardBackground : Colors.white, @@ -56,9 +56,15 @@ class PictureTranslationHistoryDetailView extends StatelessWidget { SizedBox(height: 16.h), _buildLanguageInfo(), SizedBox(height: 16.h), - _buildTextSection('识别结果', item.sourceText, Colors.blue), + _buildTextSection( + 'recognitionResult'.tr, // 识别结果 + item.sourceText, + Colors.blue), SizedBox(height: 16.h), - _buildTextSection('翻译结果', item.translatedText, Colors.green), + _buildTextSection( + 'translationResult'.tr, // 翻译结果 + item.translatedText, + Colors.green), SizedBox(height: 16.h), _buildTimeInfo(), ], @@ -89,12 +95,11 @@ class PictureTranslationHistoryDetailView extends StatelessWidget { Padding( padding: EdgeInsets.all(16.w), child: Text( - '原图片', + 'originalImage'.tr, // 原图片 style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, - color: - Get.isDarkMode ? AppColors.textPrimary : Colors.black87, + color: Get.isDarkMode ? AppColors.textPrimary : Colors.black87, ), ), ), @@ -122,7 +127,7 @@ class PictureTranslationHistoryDetailView extends StatelessWidget { size: 48.sp, color: AppColors.error), SizedBox(height: 8.h), Text( - '图片加载失败', + 'imageLoadFailed'.tr, // 图片加载失败 style: TextStyle( fontSize: 14.sp, color: AppColors.error), ), @@ -161,7 +166,7 @@ class PictureTranslationHistoryDetailView extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - '源语言', + 'sourceLanguage'.tr, // 源语言 style: TextStyle( fontSize: 12.sp, color: Get.isDarkMode @@ -170,7 +175,7 @@ class PictureTranslationHistoryDetailView extends StatelessWidget { ), SizedBox(height: 4.h), Text( - item.sourceLanguageName, + item.sourceLanguageName.tr, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, @@ -187,7 +192,7 @@ class PictureTranslationHistoryDetailView extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( - '目标语言', + 'targetLanguage'.tr, // 目标语言 style: TextStyle( fontSize: 12.sp, color: Get.isDarkMode @@ -196,7 +201,7 @@ class PictureTranslationHistoryDetailView extends StatelessWidget { ), SizedBox(height: 4.h), Text( - item.targetLanguageName, + item.targetLanguageName.tr, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, @@ -245,11 +250,13 @@ class PictureTranslationHistoryDetailView extends StatelessWidget { icon: Icon(Icons.copy, size: 20.sp, color: color), onPressed: () { Clipboard.setData(ClipboardData(text: content)); - Get.snackbar('成功', '已复制到剪切板'); + Get.snackbar( + 'success'.tr, // 成功 + 'copied'.tr); // 已复制 }, padding: EdgeInsets.zero, constraints: const BoxConstraints(), - tooltip: '复制', + tooltip: 'copy'.tr, // 复制 ), ], ), @@ -287,12 +294,11 @@ class PictureTranslationHistoryDetailView extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - '翻译时间', + 'translationTime'.tr, // 翻译时间 style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, - color: - Get.isDarkMode ? AppColors.textPrimary : Colors.black87, + color: Get.isDarkMode ? AppColors.textPrimary : Colors.black87, ), ), SizedBox(height: 8.h), @@ -300,7 +306,8 @@ class PictureTranslationHistoryDetailView extends StatelessWidget { _formatDateTime(item.timestamp), style: TextStyle( fontSize: 14.sp, - color: Get.isDarkMode ? AppColors.textSecondary : Colors.grey[600], + color: + Get.isDarkMode ? AppColors.textSecondary : Colors.grey[600], ), ), ], @@ -309,17 +316,18 @@ class PictureTranslationHistoryDetailView extends StatelessWidget { } String _formatDateTime(DateTime dateTime) { - return '${dateTime.year}年${dateTime.month}月${dateTime.day}日 ' - '${dateTime.hour.toString().padLeft(2, '0')}:' - '${dateTime.minute.toString().padLeft(2, '0')}'; + return DateFormat('yyyy-MM-dd HH:mm').format(dateTime); } void _shareTranslation() { - final shareText = '原文:${item.sourceText}\n\n' - '译文:${item.translatedText}\n\n' - '翻译方向:${item.sourceLanguageName} → ${item.targetLanguageName}'; + final shareText = '${'originalText'.tr}:${item.sourceText}\n\n' // 原文 + '${'translatedText'.tr}:${item.translatedText}\n\n' // 译文 + '${'sourceLanguage'.tr}:${item.sourceLanguageName.tr} → ' // 源语言 + '${'targetLanguage'.tr}:${item.targetLanguageName.tr}'; // 目标语言 // 这里可以调用分享插件 - Get.snackbar('提示', '分享功能开发中'); + Get.snackbar( + 'tip'.tr, // 提示 + 'shareInDevelopment'.tr); // 分享功能开发中 } } diff --git a/lib/modules/picture_translation/views/picture_translation_view.dart b/lib/modules/picture_translation/views/picture_translation_view.dart index 491204cc0..b53acb156 100644 --- a/lib/modules/picture_translation/views/picture_translation_view.dart +++ b/lib/modules/picture_translation/views/picture_translation_view.dart @@ -21,8 +21,7 @@ class PictureTranslationView extends GetView { Widget build(BuildContext context) { final isDarkMode = Theme.of(context).brightness == Brightness.dark; return Scaffold( - backgroundColor: - isDarkMode ? AppColors.darkBackground : Colors.grey[50], + backgroundColor: isDarkMode ? AppColors.darkBackground : Colors.grey[50], appBar: _buildAppBar(isDarkMode), body: SafeArea( child: Obx(() { @@ -85,7 +84,7 @@ class PictureTranslationView extends GetView { IconButton( icon: const Icon(Icons.history), onPressed: _showHistoryBottomSheet, - tooltip: 'historyRecords'.tr, //历史记录 + tooltip: 'historyRecords'.tr, // 历史记录 ), PopupMenuButton( onSelected: _handleMenuAction, @@ -157,12 +156,11 @@ class PictureTranslationView extends GetView { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - '选择图片来源'.tr, //选择图片来源 + 'selectImageSource'.tr, // 选择图片来源 style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, - color: - Get.isDarkMode ? AppColors.textPrimary : Colors.black87, + color: Get.isDarkMode ? AppColors.textPrimary : Colors.black87, ), ), SizedBox(height: 12.h), @@ -277,12 +275,11 @@ class PictureTranslationView extends GetView { Padding( padding: EdgeInsets.all(16.w), child: Text( - '图片预览', + 'imagePreview'.tr, // 图片预览 style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, - color: - Get.isDarkMode ? AppColors.textPrimary : Colors.black87, + color: Get.isDarkMode ? AppColors.textPrimary : Colors.black87, ), ), ), @@ -377,8 +374,7 @@ class PictureTranslationView extends GetView { ), ); case ProcessingStatus.error: - return Icon(Icons.error_outline, - color: AppColors.error, size: 20.sp); + return Icon(Icons.error_outline, color: AppColors.error, size: 20.sp); case ProcessingStatus.idle: return Icon(Icons.check_circle_outline, color: AppColors.success, size: 20.sp); @@ -423,25 +419,24 @@ class PictureTranslationView extends GetView { Padding( padding: EdgeInsets.all(16.w), child: Text( - '翻译结果', + 'translationResult'.tr, // 翻译结果 style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, - color: - Get.isDarkMode ? AppColors.textPrimary : Colors.black87, + color: Get.isDarkMode ? AppColors.textPrimary : Colors.black87, ), ), ), if (controller.sourceText.value.isNotEmpty) _buildTextCard( - '识别结果', + 'recognitionResult'.tr, // 识别结果 controller.sourceText.value, controller.sourceLanguageChineseName.value, Colors.blue, ), if (controller.translatedText.value.isNotEmpty) _buildTextCard( - '翻译结果', + 'translationResult'.tr, // 翻译结果 controller.translatedText.value, controller.targetLanguageChineseName.value, Colors.green, @@ -449,22 +444,22 @@ class PictureTranslationView extends GetView { if (controller.translatedImageBytes.value != null) ...[ Padding( padding: EdgeInsets.symmetric(horizontal: 16.w), - child: Text( - '翻译后的图片预览', - style: TextStyle( - fontSize: 14.sp, - fontWeight: FontWeight.w600, - color: - Get.isDarkMode ? AppColors.textPrimary : Colors.black87, + child: Text( + 'translatedImagePreview'.tr, // 翻译后的图片预览 + style: TextStyle( + fontSize: 14.sp, + fontWeight: FontWeight.w600, + color: + Get.isDarkMode ? AppColors.textPrimary : Colors.black87, + ), ), ), - ), - SizedBox(height: 8.h), - Container( - height: 200.h, - margin: - EdgeInsets.symmetric(horizontal: 16.w).copyWith(bottom: 16.h), - decoration: BoxDecoration( + SizedBox(height: 8.h), + Container( + height: 200.h, + margin: + EdgeInsets.symmetric(horizontal: 16.w).copyWith(bottom: 16.h), + decoration: BoxDecoration( color: Get.isDarkMode ? AppColors.cardBackground : Colors.grey[100], @@ -491,7 +486,7 @@ class PictureTranslationView extends GetView { size: 48.sp, color: Colors.red[400]), SizedBox(height: 8.h), Text( - '翻译图片加载失败', + 'translatedImageLoadFailed'.tr, // 翻译图片加载失败 style: TextStyle( fontSize: 14.sp, color: Colors.red[600]), ), @@ -517,8 +512,8 @@ class PictureTranslationView extends GetView { decoration: BoxDecoration( color: color.withOpacity(Get.isDarkMode ? 0.15 : 0.05), borderRadius: BorderRadius.circular(8.r), - border: Border.all( - color: color.withOpacity(Get.isDarkMode ? 0.3 : 0.2)), + border: + Border.all(color: color.withOpacity(Get.isDarkMode ? 0.3 : 0.2)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -538,11 +533,11 @@ class PictureTranslationView extends GetView { icon: Icon(Icons.copy, size: 18.sp, color: color), onPressed: () { Clipboard.setData(ClipboardData(text: content)); - Get.snackbar('success'.tr, 'copied'.tr); // 翻译键代表的中文文本内容 + Get.snackbar('success'.tr, 'copied'.tr); // 对应中文:复制成功 }, padding: EdgeInsets.zero, constraints: const BoxConstraints(), - tooltip: 'copy'.tr, // 翻译键代表的中文文本内容 + tooltip: 'copy'.tr, // 复制 ), ], ), @@ -551,8 +546,7 @@ class PictureTranslationView extends GetView { content, style: TextStyle( fontSize: 15.sp, - color: - Get.isDarkMode ? Colors.white70 : Colors.black87, + color: Get.isDarkMode ? Colors.white70 : Colors.black87, height: 1.4), ), ], @@ -584,7 +578,7 @@ class PictureTranslationView extends GetView { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - 'translationHistory'.tr, // 翻译键代表的中文文本内容 + 'translationHistory'.tr, // 翻译历史 style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, @@ -594,7 +588,7 @@ class PictureTranslationView extends GetView { ), TextButton( onPressed: _showHistoryBottomSheet, - child: Text('viewAll'.tr), // 翻译键代表的中文文本内容 + child: Text('viewAll'.tr), // 查看全部 ), ], ), @@ -604,7 +598,7 @@ class PictureTranslationView extends GetView { padding: EdgeInsets.symmetric(horizontal: 16.w).copyWith(bottom: 16.h), child: Text( - 'noTranslationHistory'.tr, // 翻译键代表的中文文本内容 + 'noTranslationHistory'.tr, // 暂无历史记录 style: TextStyle( fontSize: 14.sp, color: Get.isDarkMode @@ -629,8 +623,9 @@ class PictureTranslationView extends GetView { child: Container( width: 40.w, height: 40.w, - color: - Get.isDarkMode ? Colors.white.withOpacity(0.05) : Colors.grey[200], + color: Get.isDarkMode + ? Colors.white.withOpacity(0.05) + : Colors.grey[200], child: Icon(Icons.image, color: Get.isDarkMode ? Colors.white70 : Colors.grey[400]), ), @@ -642,18 +637,16 @@ class PictureTranslationView extends GetView { style: TextStyle(fontSize: 14.sp), ), subtitle: Text( - '${item.sourceLanguageName} → ${item.targetLanguageName}', + '${item.sourceLanguageName.tr} → ${item.targetLanguageName.tr}', // 源语言名/目标语言名 style: TextStyle( fontSize: 12.sp, - color: - Get.isDarkMode ? AppColors.textSecondary : Colors.grey[600]), + color: Get.isDarkMode ? AppColors.textSecondary : Colors.grey[600]), ), trailing: Text( _formatTime(item.timestamp), style: TextStyle( fontSize: 12.sp, - color: - Get.isDarkMode ? Colors.white54 : Colors.grey[500]), + color: Get.isDarkMode ? Colors.white54 : Colors.grey[500]), ), onTap: () => _showHistoryDetail(item), ); @@ -675,19 +668,16 @@ class PictureTranslationView extends GetView { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - 'translationHistory'.tr, // 翻译键代表的中文文本内容 + 'translationHistory'.tr, // 翻译历史 style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.bold, - color: Get.isDarkMode - ? AppColors.textPrimary - : null), + color: Get.isDarkMode ? AppColors.textPrimary : null), ), IconButton( onPressed: () => Get.back(), icon: Icon(Icons.close, - color: - Get.isDarkMode ? AppColors.textPrimary : null), + color: Get.isDarkMode ? AppColors.textPrimary : null), ), ], ), @@ -698,7 +688,7 @@ class PictureTranslationView extends GetView { if (controller.historyList.isEmpty) { return Center( child: Text( - 'noTranslationHistory'.tr, // 翻译键代表的中文文本内容 + 'noTranslationHistory'.tr, // 暂无历史记录 style: TextStyle( fontSize: 16.sp, color: Get.isDarkMode @@ -745,13 +735,18 @@ class PictureTranslationView extends GetView { final difference = now.difference(timestamp); if (difference.inDays > 0) { - return '${difference.inDays}天前'; + return 'daysAgo' + .tr + .replaceAll('@days', difference.inDays.toString()); // @days天前 } else if (difference.inHours > 0) { - return '${difference.inHours}小时前'; + return 'hoursAgo' + .tr + .replaceAll('@hours', difference.inHours.toString()); // @hours小时前 } else if (difference.inMinutes > 0) { - return '${difference.inMinutes}分钟前'; + return 'minutesAgo'.tr.replaceAll( + '@minutes', difference.inMinutes.toString()); // @minutes分钟前 } else { - return '刚刚'; + return 'justNow'.tr; // 刚刚 } } @@ -759,7 +754,7 @@ class PictureTranslationView extends GetView { Get.dialog( AlertDialog( backgroundColor: Get.isDarkMode ? Colors.grey[900] : Colors.white, - title: Text('设置', + title: Text('settings'.tr, // 设置 style: TextStyle( color: Get.isDarkMode ? Colors.white : Colors.black87)), content: Column( @@ -768,16 +763,17 @@ class PictureTranslationView extends GetView { ListTile( leading: Icon(Icons.photo_size_select_actual, color: Get.isDarkMode ? Colors.white : null), - title: Text('图片质量', + title: Text('imageQuality'.tr, // 图片质量 + style: TextStyle( + color: Get.isDarkMode ? Colors.white : Colors.black87)), + subtitle: Obx(() => Text( + 'currentQuality'.tr.replaceAll( + '@value', + controller.imageQuality.value + .toString()), // 当前质量: @value% style: TextStyle( color: - Get.isDarkMode ? Colors.white : Colors.black87)), - subtitle: - Obx(() => Text('当前: ${controller.imageQuality.value}%', - style: TextStyle( - color: Get.isDarkMode - ? Colors.white70 - : Colors.black54))), + Get.isDarkMode ? Colors.white70 : Colors.black54))), onTap: () { Get.back(); _showImageQualityDialog(); @@ -786,16 +782,15 @@ class PictureTranslationView extends GetView { ListTile( leading: Icon(Icons.photo_size_select_large, color: Get.isDarkMode ? Colors.white : null), - title: Text('最大尺寸', + title: Text('maxSize'.tr, // 最大尺寸 + style: TextStyle( + color: Get.isDarkMode ? Colors.white : Colors.black87)), + subtitle: Obx(() => Text( + 'currentMaxSize'.tr.replaceAll('@px', + controller.maxImageSize.value.toString()), // 当前: @pxpx style: TextStyle( color: - Get.isDarkMode ? Colors.white : Colors.black87)), - subtitle: - Obx(() => Text('当前: ${controller.maxImageSize.value}px', - style: TextStyle( - color: Get.isDarkMode - ? Colors.white70 - : Colors.black54))), + Get.isDarkMode ? Colors.white70 : Colors.black54))), onTap: () { Get.back(); _showImageSizeDialog(); @@ -806,7 +801,7 @@ class PictureTranslationView extends GetView { actions: [ TextButton( onPressed: () => Get.back(), - child: Text('关闭', + child: Text('close'.tr, // 关闭 style: TextStyle( color: Get.isDarkMode ? Colors.white70 : Colors.black54)), ), @@ -819,13 +814,17 @@ class PictureTranslationView extends GetView { Get.dialog( AlertDialog( backgroundColor: Get.isDarkMode ? Colors.grey[900] : Colors.white, - title: Text('设置图片质量', + title: Text('setImageQuality'.tr, // 设置图片质量 style: TextStyle( color: Get.isDarkMode ? Colors.white : Colors.black87)), content: Obx(() => Column( mainAxisSize: MainAxisSize.min, children: [ - Text('当前质量: ${controller.imageQuality.value}%', + Text( + 'currentQuality'.tr.replaceAll( + '@value', + controller.imageQuality.value + .toString()), // 当前质量: @value% style: TextStyle( color: Get.isDarkMode ? Colors.white70 : Colors.black54)), @@ -843,7 +842,7 @@ class PictureTranslationView extends GetView { actions: [ TextButton( onPressed: () => Get.back(), - child: Text('确定', + child: Text('confirm'.tr, // 确认 style: TextStyle( color: Get.isDarkMode ? Colors.white70 : Colors.black54)), ), @@ -857,7 +856,7 @@ class PictureTranslationView extends GetView { Get.dialog( AlertDialog( backgroundColor: Get.isDarkMode ? Colors.grey[900] : Colors.white, - title: Text('设置最大尺寸', + title: Text('setMaxSize'.tr, // 设置最大尺寸 style: TextStyle( color: Get.isDarkMode ? Colors.white : Colors.black87)), content: Column( @@ -879,7 +878,7 @@ class PictureTranslationView extends GetView { actions: [ TextButton( onPressed: () => Get.back(), - child: Text('取消', + child: Text('cancel'.tr, // 取消 style: TextStyle( color: Get.isDarkMode ? Colors.white70 : Colors.black54)), ), @@ -892,16 +891,16 @@ class PictureTranslationView extends GetView { Get.dialog( AlertDialog( backgroundColor: Get.isDarkMode ? Colors.grey[900] : Colors.white, - title: Text('清空历史', + title: Text('clearHistory'.tr, // 清除历史记录 style: TextStyle( color: Get.isDarkMode ? Colors.white : Colors.black87)), - content: Text('确定要清空所有翻译历史吗?此操作不可撤销。', + content: Text('clearHistoryConfirm'.tr, // 确定要清除所有翻译历史记录吗?此操作无法撤销。 style: TextStyle( color: Get.isDarkMode ? Colors.white70 : Colors.black54)), actions: [ TextButton( onPressed: () => Get.back(), - child: Text('取消', + child: Text('cancel'.tr, // 取消 style: TextStyle( color: Get.isDarkMode ? Colors.white70 : Colors.black54)), ), @@ -910,7 +909,8 @@ class PictureTranslationView extends GetView { controller.clearHistory(); Get.back(); }, - child: Text('确定', style: TextStyle(color: AppColors.error)), + child: Text('confirm'.tr, // 确认 + style: TextStyle(color: AppColors.error)), ), ], ), @@ -923,11 +923,10 @@ class PictureTranslationView extends GetView { height: 200.h, margin: EdgeInsets.symmetric(horizontal: 16.w).copyWith(bottom: 16.h), decoration: BoxDecoration( - color: - Get.isDarkMode ? AppColors.cardBackground : Colors.grey[100], + color: Get.isDarkMode ? AppColors.cardBackground : Colors.grey[100], borderRadius: BorderRadius.circular(8.r), - border: - Border.all(color: Get.isDarkMode ? Colors.white12 : Colors.grey[300]!), + border: Border.all( + color: Get.isDarkMode ? Colors.white12 : Colors.grey[300]!), ), child: file == null ? Center( @@ -936,10 +935,11 @@ class PictureTranslationView extends GetView { children: [ Icon(Icons.image_outlined, size: 48.sp, - color: Get.isDarkMode ? Colors.white54 : Colors.grey[400]), + color: + Get.isDarkMode ? Colors.white54 : Colors.grey[400]), SizedBox(height: 8.h), Text( - '请选择图片', + 'pleaseSelectImage'.tr, // 请选择图片 style: TextStyle( fontSize: 14.sp, color: Get.isDarkMode @@ -967,7 +967,7 @@ class PictureTranslationView extends GetView { size: 48.sp, color: Colors.red[400]), SizedBox(height: 8.h), Text( - '图片加载失败', + 'imageLoadFailed'.tr, // 图片加载失败 style: TextStyle( fontSize: 14.sp, color: Get.isDarkMode @@ -985,11 +985,15 @@ class PictureTranslationView extends GetView { } Widget _buildSourceTextBox() { - return _buildTextBox('识别结果', controller.sourceText.value); + return _buildTextBox( + 'recognitionResult'.tr, // 识别结果 + controller.sourceText.value); } Widget _buildTranslatedTextBox() { - return _buildTextBox('翻译结果', controller.translatedText.value); + return _buildTextBox( + 'translationResult'.tr, // 翻译结果 + controller.translatedText.value); } Widget _buildTextBox(String title, String content) { diff --git a/lib/modules/text_translation/controllers/text_translation_controller.dart b/lib/modules/text_translation/controllers/text_translation_controller.dart index 8b4b1ed5e..131a560f1 100644 --- a/lib/modules/text_translation/controllers/text_translation_controller.dart +++ b/lib/modules/text_translation/controllers/text_translation_controller.dart @@ -257,8 +257,8 @@ class TextTranslationController extends GetxController { if (detectedAsrCode == null || detectedAsrCode.isEmpty) { Logger.error('语种检测失败'); Get.snackbar( - 'error'.tr, // 翻译键代表的中文文本内容 - 'languageDetectionFailed'.tr, // 翻译键代表的中文文本内容 + 'error'.tr, // 错误 + 'languageDetectionFailed'.tr, // 语言检测失败 snackPosition: SnackPosition.TOP, backgroundColor: Colors.red.withOpacity(0.9), colorText: Colors.white, @@ -288,8 +288,8 @@ class TextTranslationController extends GetxController { } catch (e) { Logger.error('翻译失败: $e'); Get.snackbar( - 'error'.tr, - 'translationFailed'.tr, + 'error'.tr, // 错误 + 'translationFailed'.tr, // 翻译失败 snackPosition: SnackPosition.TOP, backgroundColor: Colors.red.withOpacity(0.9), colorText: Colors.white, diff --git a/lib/modules/text_translation/views/text_translation_view.dart b/lib/modules/text_translation/views/text_translation_view.dart index 723e3cd48..0c7dc317a 100644 --- a/lib/modules/text_translation/views/text_translation_view.dart +++ b/lib/modules/text_translation/views/text_translation_view.dart @@ -99,10 +99,12 @@ class TextTranslationView extends GetView { return LanguageSelectorBar( sourceText: () => controller.sourceLanguageChineseName.value, targetText: () => controller.targetLanguageChineseName.value, - onTapSource: () => controller.showLanguageSelector(isSourceLanguage: true), - onTapTarget: () => controller.showLanguageSelector(isSourceLanguage: false), + onTapSource: () => + controller.showLanguageSelector(isSourceLanguage: true), + onTapTarget: () => + controller.showLanguageSelector(isSourceLanguage: false), onSwap: controller.swapLanguages, - translateLanguageNames: true, // 翻译键代表的中文文本内容 + translateLanguageNames: true, // 是否翻译语言名称 fontSizeSp: 15, ); } diff --git a/lib/modules/translation/middleware/controllers/translation_middleware_controller.dart b/lib/modules/translation/middleware/controllers/translation_middleware_controller.dart index bf4202e54..ff336f4b7 100644 --- a/lib/modules/translation/middleware/controllers/translation_middleware_controller.dart +++ b/lib/modules/translation/middleware/controllers/translation_middleware_controller.dart @@ -91,7 +91,7 @@ class TranslationMiddlewareController extends GetxController { void navigateToTranslationFeature(TranslationOption option) { // 不可用则提示用户连接设备 if (!isOptionEnabled(option)) { - // 翻译键代表的中文文本内容 + // 连接设备 / 请连接 Voitrans 设备 Get.snackbar('connectDevice'.tr, 'pleaseConnectDeepSoundDevice'.tr, // 连接设备 / 请连接 Voitrans 设备 snackPosition: SnackPosition.TOP, diff --git a/lib/modules/translation/views/dialogs/language_selection_dialog.dart b/lib/modules/translation/views/dialogs/language_selection_dialog.dart index 6bd5be25d..ccef8f120 100644 --- a/lib/modules/translation/views/dialogs/language_selection_dialog.dart +++ b/lib/modules/translation/views/dialogs/language_selection_dialog.dart @@ -65,8 +65,8 @@ class LanguageSelectionDialog { padding: EdgeInsets.symmetric(horizontal: 8.w), child: Text( isSource - ? 'selectSourceLanguage'.tr // 翻译键代表的中文文本内容 - : 'selectTargetLanguage'.tr, // 翻译键代表的中文文本内容 + ? 'selectSourceLanguage'.tr // 选择源语言 + : 'selectTargetLanguage'.tr, // 选择目标语言 style: TextStyle( fontSize: 18.sp, // 调整字号 fontWeight: FontWeight.w600, // 使用数字字重 @@ -94,7 +94,7 @@ class LanguageSelectionDialog { : displayLanguages[ hasAutoDetect ? index - 1 : index]; final displayText = isAutoDetectItem - ? 'autoDetect'.tr // 翻译键代表的中文文本内容 + ? 'autoDetect'.tr // 自动检测 : (translateLanguageNames ? valueText.tr : valueText); @@ -196,7 +196,7 @@ class LanguageSelectionDialog { child: TextButton( onPressed: () => Get.back(), child: Text( - 'cancel'.tr, // 翻译键代表的中文文本内容 + 'cancel'.tr, // 取消 style: TextStyle( color: isDarkMode ? const Color(0xFF6200EE) : Colors.blue, ), diff --git a/lib/modules/translation/views/translation_view.dart b/lib/modules/translation/views/translation_view.dart index 595126454..75df6b81b 100644 --- a/lib/modules/translation/views/translation_view.dart +++ b/lib/modules/translation/views/translation_view.dart @@ -314,7 +314,7 @@ class TranslationView extends GetView { onTapTarget: () => LanguageSelectionDialog.show(false, isDarkMode), onSwap: controller.swapLanguages, - translateLanguageNames: true, // 翻译键代表的中文文本内容 + translateLanguageNames: true, // 是否翻译语言名称 fontSizeSp: 15, targetSuffix: controller.currentMode.value == 'call' ? Icon( @@ -1019,7 +1019,7 @@ class TranslationView extends GetView { onTapSource: () => LanguageSelectionDialog.show(true, isDarkMode), onTapTarget: () => LanguageSelectionDialog.show(false, isDarkMode), onSwap: controller.swapLanguages, - translateLanguageNames: true, // 翻译键代表的中文文本内容 + translateLanguageNames: true, // 是否翻译语言名称 fontSizeSp: 15, ), ); diff --git a/lib/modules/translation/views/widgets/translation_item_widget.dart b/lib/modules/translation/views/widgets/translation_item_widget.dart index 56ae1b264..38840b00c 100644 --- a/lib/modules/translation/views/widgets/translation_item_widget.dart +++ b/lib/modules/translation/views/widgets/translation_item_widget.dart @@ -140,7 +140,7 @@ class TranslationItemWidget extends GetView { child: Container( padding: EdgeInsets.all(4.w), child: Tooltip( - message: 'copy'.tr, // 翻译键代表的中文文本内容 + message: 'copy'.tr, // 复制 child: Icon( Icons.copy, size: 20.sp, @@ -169,7 +169,7 @@ class TranslationItemWidget extends GetView { child: Container( padding: EdgeInsets.all(4.w), child: Tooltip( - message: 'delete'.tr, // 翻译键代表的中文文本内容 + message: 'delete'.tr, // 删除 child: Icon( Icons.delete_outline, size: 20.sp, diff --git a/lib/modules/usage/controllers/meeting_stats_controller.dart b/lib/modules/usage/controllers/meeting_stats_controller.dart index bbcb7f9f6..147c709c7 100644 --- a/lib/modules/usage/controllers/meeting_stats_controller.dart +++ b/lib/modules/usage/controllers/meeting_stats_controller.dart @@ -8,34 +8,32 @@ class MeetingStatsController extends GetxController { final isLoading = false.obs; final selectedTabIndex = 0.obs; - final selectedTimeRange = '今日'.obs; - - final Rx todayStats = - MeetingAsrHistoryStats( - userId: '', - allAsrCalls: 0, - allAudioSeconds: 0, - allAudioFileBytes: 0, - allTranscriptBytes: 0, - ).obs; - final Rx weekStats = - MeetingAsrHistoryStats( - userId: '', - allAsrCalls: 0, - allAudioSeconds: 0, - allAudioFileBytes: 0, - allTranscriptBytes: 0, - ).obs; - final Rx monthStats = - MeetingAsrHistoryStats( - userId: '', - allAsrCalls: 0, - allAudioSeconds: 0, - allAudioFileBytes: 0, - allTranscriptBytes: 0, - ).obs; - - final RxList historyDaily = [].obs; + final selectedTimeRange = 'today'.tr.obs; // 今日 + + final Rx todayStats = MeetingAsrHistoryStats( + userId: '', + allAsrCalls: 0, + allAudioSeconds: 0, + allAudioFileBytes: 0, + allTranscriptBytes: 0, + ).obs; + final Rx weekStats = MeetingAsrHistoryStats( + userId: '', + allAsrCalls: 0, + allAudioSeconds: 0, + allAudioFileBytes: 0, + allTranscriptBytes: 0, + ).obs; + final Rx monthStats = MeetingAsrHistoryStats( + userId: '', + allAsrCalls: 0, + allAudioSeconds: 0, + allAudioFileBytes: 0, + allTranscriptBytes: 0, + ).obs; + + final RxList historyDaily = + [].obs; @override void onInit() { @@ -72,7 +70,8 @@ class MeetingStatsController extends GetxController { final historyStart = now.subtract(const Duration(days: 7)); historyDaily.value = await _usageService.getMeetingHistoryStats( - startDate: DateTime(historyStart.year, historyStart.month, historyStart.day), + startDate: + DateTime(historyStart.year, historyStart.month, historyStart.day), endDate: DateTime(now.year, now.month, now.day), ); @@ -88,16 +87,16 @@ class MeetingStatsController extends GetxController { selectedTabIndex.value = index; switch (index) { case 0: - selectedTimeRange.value = '今日'; + selectedTimeRange.value = 'today'.tr; // 今日 break; case 1: - selectedTimeRange.value = '本周'; + selectedTimeRange.value = 'thisWeek'.tr; // 本周 break; case 2: - selectedTimeRange.value = '本月'; + selectedTimeRange.value = 'thisMonth'.tr; // 本月 break; case 3: - selectedTimeRange.value = '历史'; + selectedTimeRange.value = 'history'.tr; // 历史 break; } } @@ -117,15 +116,15 @@ class MeetingStatsController extends GetxController { String formatDuration(int seconds) { if (seconds < 60) { - return '$seconds秒'; + return '$seconds${'seconds'.tr}'; // 秒 } else if (seconds < 3600) { final minutes = seconds ~/ 60; final remainingSeconds = seconds % 60; - return '$minutes分$remainingSeconds秒'; + return '$minutes${'minutes'.tr}$remainingSeconds${'seconds'.tr}'; // 分钟秒 } else { final hours = seconds ~/ 3600; final minutes = (seconds % 3600) ~/ 60; - return '$hours小时$minutes分'; + return '$hours${'hours'.tr}$minutes${'minutes'.tr}'; // 小时分钟 } } @@ -149,4 +148,3 @@ class MeetingStatsController extends GetxController { await loadAllStats(); } } - diff --git a/lib/modules/usage/controllers/translation_stats_controller.dart b/lib/modules/usage/controllers/translation_stats_controller.dart index 099138941..7a3266136 100644 --- a/lib/modules/usage/controllers/translation_stats_controller.dart +++ b/lib/modules/usage/controllers/translation_stats_controller.dart @@ -9,7 +9,7 @@ class TranslationStatsController extends GetxController { final isLoading = false.obs; final selectedTabIndex = 0.obs; - final selectedTimeRange = '今日'.obs; + final selectedTimeRange = 'today'.tr.obs; // 今日 final Rx todayStats = TranslationUsageStats.empty('').obs; @@ -62,8 +62,8 @@ class TranslationStatsController extends GetxController { } catch (e) { Logger.error('加载统计数据失败: $e'); Get.snackbar( - '加载失败', - '统计数据加载失败,请稍后重试', + 'loadFailed'.tr, // 加载失败 + 'statsLoadFailedTryLater'.tr, // 统计数据加载失败,请稍后重试 snackPosition: SnackPosition.TOP, backgroundColor: Get.theme.colorScheme.error.withValues(alpha: 0.1), colorText: Get.theme.colorScheme.error, @@ -180,7 +180,7 @@ class TranslationStatsController extends GetxController { switch (selectedTabIndex.value) { case 0: data.add({ - 'label': '今日', + 'label': 'today'.tr, // 今日 'apiCalls': todayStats.value.totalApiCalls, 'cost': 0.0, 'characters': todayStats.value.totalCharacterCount, @@ -188,7 +188,7 @@ class TranslationStatsController extends GetxController { break; case 1: data.add({ - 'label': '本周', + 'label': 'thisWeek'.tr, // 本周 'apiCalls': weekStats.value.totalApiCalls, 'cost': 0.0, 'characters': weekStats.value.totalCharacterCount, @@ -196,7 +196,7 @@ class TranslationStatsController extends GetxController { break; case 2: data.add({ - 'label': '本月', + 'label': 'thisMonth'.tr, // 本月 'apiCalls': monthStats.value.totalApiCalls, 'cost': 0.0, 'characters': monthStats.value.totalCharacterCount, @@ -222,16 +222,16 @@ class TranslationStatsController extends GetxController { switch (index) { case 0: - selectedTimeRange.value = '今日'; + selectedTimeRange.value = 'today'.tr; // 今日 break; case 1: - selectedTimeRange.value = '本周'; + selectedTimeRange.value = 'thisWeek'.tr; // 本周 break; case 2: - selectedTimeRange.value = '本月'; + selectedTimeRange.value = 'thisMonth'.tr; // 本月 break; case 3: - selectedTimeRange.value = '历史'; + selectedTimeRange.value = 'history'.tr; // 历史 break; } @@ -258,8 +258,8 @@ class TranslationStatsController extends GetxController { void cleanupOldData() { _usageService.cleanupOldData(); Get.snackbar( - '清理完成', - '已清理90天前的过期数据', + 'cleanupComplete'.tr, // 清理完成 + 'cleanedOldData'.tr, // 已清理90天前的过期数据 snackPosition: SnackPosition.TOP, backgroundColor: Get.theme.colorScheme.primary.withValues(alpha: 0.1), colorText: Get.theme.colorScheme.primary, @@ -269,8 +269,8 @@ class TranslationStatsController extends GetxController { Future exportStats() async { try { Get.snackbar( - '导出功能', - '数据导出功能正在开发中', + 'exportFeature'.tr, // 导出功能 + 'exportInDevelopment'.tr, // 数据导出功能正在开发中 snackPosition: SnackPosition.TOP, backgroundColor: Get.theme.colorScheme.primary.withValues(alpha: 0.1), colorText: Get.theme.colorScheme.primary, @@ -282,15 +282,15 @@ class TranslationStatsController extends GetxController { String formatDuration(int seconds) { if (seconds < 60) { - return '$seconds秒'; + return '$seconds${'seconds'.tr}'; // 秒 } else if (seconds < 3600) { final minutes = seconds ~/ 60; final remainingSeconds = seconds % 60; - return '$minutes分$remainingSeconds秒'; + return '$minutes${'minutes'.tr}$remainingSeconds${'seconds'.tr}'; // 分钟秒 } else { final hours = seconds ~/ 3600; final minutes = (seconds % 3600) ~/ 60; - return '$hours小时$minutes分'; + return '$hours${'hours'.tr}$minutes${'minutes'.tr}'; // 小时分钟 } } diff --git a/lib/modules/usage/views/aichat_stats_view.dart b/lib/modules/usage/views/aichat_stats_view.dart index a04fe6c44..728bc180f 100644 --- a/lib/modules/usage/views/aichat_stats_view.dart +++ b/lib/modules/usage/views/aichat_stats_view.dart @@ -29,7 +29,7 @@ class AiChatStatsView extends GetView { backgroundColor: isDarkMode ? AppColors.darkBackground : Colors.white, elevation: 0.5, title: Text( - 'AI chat', + 'aiChat'.tr, // AI聊天 style: TextStyle( fontSize: 17.sp, fontWeight: FontWeight.w600, @@ -70,7 +70,7 @@ class AiChatStatsView extends GetView { SizedBox(width: 8.w), Expanded( child: Text( - 'AI聊天积分', + 'remainingQuota'.tr, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, diff --git a/lib/modules/usage/views/meeting_stats_view.dart b/lib/modules/usage/views/meeting_stats_view.dart index 63ea4897a..140a40447 100644 --- a/lib/modules/usage/views/meeting_stats_view.dart +++ b/lib/modules/usage/views/meeting_stats_view.dart @@ -31,7 +31,7 @@ class MeetingStatsView extends GetView { backgroundColor: isDarkMode ? AppColors.darkBackground : Colors.white, elevation: 0.5, title: Text( - '会议统计', + 'meetingStats'.tr, // 会议统计 style: TextStyle( fontSize: 17.sp, fontWeight: FontWeight.w600, @@ -91,7 +91,7 @@ class MeetingStatsView extends GetView { SizedBox(width: 8.w), Expanded( child: Text( - '会议积分', + 'remainingQuota'.tr, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, @@ -127,10 +127,10 @@ class MeetingStatsView extends GetView { ), child: Obx(() => Row( children: [ - _buildTimeRangeTab('今日', 0, isDarkMode), - _buildTimeRangeTab('本周', 1, isDarkMode), - _buildTimeRangeTab('本月', 2, isDarkMode), - _buildTimeRangeTab('历史', 3, isDarkMode), + _buildTimeRangeTab('today'.tr, 0, isDarkMode), // 今日 + _buildTimeRangeTab('thisWeek'.tr, 1, isDarkMode), // 本周 + _buildTimeRangeTab('thisMonth'.tr, 2, isDarkMode), // 本月 + _buildTimeRangeTab('history'.tr, 3, isDarkMode), // 历史 ], )), ); @@ -186,7 +186,7 @@ class MeetingStatsView extends GetView { Icon(Icons.dashboard, color: AppColors.primary, size: 20.sp), SizedBox(width: 8.w), Obx(() => Text( - '${controller.selectedTimeRange.value}概览', + '${controller.selectedTimeRange.value}${'overview'.tr}', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, @@ -199,13 +199,13 @@ class MeetingStatsView extends GetView { children: [ Expanded( child: _buildStatItem( - 'ASR调用次数', + 'asrApiCalls'.tr, // ASR调用次数 controller.formatNumber(stats.allAsrCalls), Icons.api, isDarkMode)), Expanded( child: _buildStatItem( - '音频总时长', + 'totalAudioDuration'.tr, // 音频总时长 controller.formatDuration(stats.allAudioSeconds), Icons.mic, isDarkMode)), @@ -216,13 +216,13 @@ class MeetingStatsView extends GetView { children: [ Expanded( child: _buildStatItem( - '音频文件大小', + 'audioFileSize'.tr, // 音频文件大小 controller.formatBytes(stats.allAudioFileBytes), Icons.folder, isDarkMode)), Expanded( child: _buildStatItem( - '转写字节', + 'transcriptBytes'.tr, // 转写字节 controller.formatNumber(stats.allTranscriptBytes), Icons.text_snippet, isDarkMode)), diff --git a/lib/modules/usage/views/translation_stats_view.dart b/lib/modules/usage/views/translation_stats_view.dart index 6fc3c706c..3600000b0 100644 --- a/lib/modules/usage/views/translation_stats_view.dart +++ b/lib/modules/usage/views/translation_stats_view.dart @@ -36,7 +36,7 @@ class TranslationStatsView extends GetView { title: GestureDetector( onTap: controller.onTitleTap, child: Text( - '翻译统计', + 'translationStats'.tr, // style: TextStyle( fontSize: 17.sp, fontWeight: FontWeight.w600, @@ -143,7 +143,7 @@ class TranslationStatsView extends GetView { SizedBox(width: 8.w), Expanded( child: Text( - '翻译积分', + 'remainingQuota'.tr, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, @@ -180,10 +180,10 @@ class TranslationStatsView extends GetView { ), child: Obx(() => Row( children: [ - _buildTimeRangeTab('今日', 0, isDarkMode), - _buildTimeRangeTab('本周', 1, isDarkMode), - _buildTimeRangeTab('本月', 2, isDarkMode), - _buildTimeRangeTab('历史', 3, isDarkMode), + _buildTimeRangeTab('today'.tr, 0, isDarkMode), // 今日 + _buildTimeRangeTab('thisWeek'.tr, 1, isDarkMode), // 本周 + _buildTimeRangeTab('thisMonth'.tr, 2, isDarkMode), // 本月 + _buildTimeRangeTab('history'.tr, 3, isDarkMode), // 历史 ], )), ); @@ -245,7 +245,7 @@ class TranslationStatsView extends GetView { ), SizedBox(width: 8.w), Text( - '当前会话统计', + 'currentSessionStats'.tr, // 当前会话统计 style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, @@ -259,7 +259,7 @@ class TranslationStatsView extends GetView { children: [ Expanded( child: _buildStatItem( - '翻译次数', + 'translationCount'.tr, // 翻译次数 controller.realtimeStats.translationCount.toString(), Icons.translate, isDarkMode, @@ -267,8 +267,8 @@ class TranslationStatsView extends GetView { ), Expanded( child: _buildStatItem( - '会话时长', - '${controller.realtimeStats.sessionDurationMinutes}分钟', + 'sessionDuration'.tr, // 会话时长 + '${controller.realtimeStats.sessionDurationMinutes}${'minutes'.tr}', Icons.timer, isDarkMode, ), @@ -280,7 +280,7 @@ class TranslationStatsView extends GetView { children: [ Expanded( child: _buildStatItem( - '字符数', + 'characters'.tr, // 字符数 controller.formatNumber( controller.realtimeStats.sourceCharacters + controller.realtimeStats.targetCharacters, @@ -291,7 +291,7 @@ class TranslationStatsView extends GetView { ), Expanded( child: _buildStatItem( - '录音时长', + 'recordingDuration'.tr, // 录音时长 controller.formatDuration( controller.realtimeStats.recordingDuration), Icons.mic, @@ -331,7 +331,7 @@ class TranslationStatsView extends GetView { ), SizedBox(width: 8.w), Obx(() => Text( - '${controller.selectedTimeRange.value}概览', + '${controller.selectedTimeRange.value}${'overview'.tr}', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, @@ -345,7 +345,7 @@ class TranslationStatsView extends GetView { children: [ Expanded( child: _buildStatItem( - '总调用次数', + 'totalApiCalls'.tr, // 总调用次数 controller .formatNumber(controller.currentStats.totalApiCalls), Icons.api, @@ -359,7 +359,7 @@ class TranslationStatsView extends GetView { children: [ Expanded( child: _buildStatItem( - '会话数量', + 'sessionCount'.tr, // 会话数量 controller.currentStats.sessionCount.toString(), Icons.chat, isDarkMode, @@ -367,7 +367,7 @@ class TranslationStatsView extends GetView { ), Expanded( child: _buildStatItem( - '总字符数', + 'totalCharacters'.tr, // 总字符数 controller.formatNumber( controller.currentStats.totalCharacterCount), Icons.text_snippet, @@ -437,7 +437,7 @@ class TranslationStatsView extends GetView { ), SizedBox(width: 8.w), Text( - 'API调用统计', + 'apiCallStats'.tr, // API调用统计 style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, @@ -450,19 +450,25 @@ class TranslationStatsView extends GetView { Obx(() => Column( children: [ _buildApiCallRow( - '翻译API', + 'translationApi'.tr, // 翻译API controller.currentStats.translationApiCalls, Icons.translate, isDarkMode), SizedBox(height: 12.h), - _buildApiCallRow('语音识别', controller.currentStats.asrApiCalls, - Icons.mic, isDarkMode), + _buildApiCallRow( + 'asr'.tr, + controller.currentStats.asrApiCalls, + Icons.mic, + isDarkMode), SizedBox(height: 12.h), - _buildApiCallRow('语音合成', controller.currentStats.ttsApiCalls, - Icons.volume_up, isDarkMode), + _buildApiCallRow( + 'tts'.tr, + controller.currentStats.ttsApiCalls, + Icons.volume_up, + isDarkMode), SizedBox(height: 12.h), _buildApiCallRow( - 'AI摘要', + 'aiSummary'.tr, // AI总结 controller.currentStats.aiSummaryApiCalls, Icons.summarize, isDarkMode), @@ -530,7 +536,7 @@ class TranslationStatsView extends GetView { ), SizedBox(width: 8.w), Text( - '数据量统计', + 'dataVolumeStats'.tr, // 数据量统计 style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, @@ -546,7 +552,7 @@ class TranslationStatsView extends GetView { children: [ Expanded( child: _buildStatItem( - '源文本字符', + 'sourceTextCharacters'.tr, // 源文本字符 controller.formatNumber( controller.currentStats.sourceTextCharacters), Icons.text_fields, @@ -555,7 +561,7 @@ class TranslationStatsView extends GetView { ), Expanded( child: _buildStatItem( - 'TTS文本字符', + 'ttsTextCharacters'.tr, // TTS文本字符 controller.formatNumber( controller.currentStats.ttsTextCharacters), Icons.translate, @@ -569,7 +575,7 @@ class TranslationStatsView extends GetView { children: [ Expanded( child: _buildStatItem( - '有效音频时长', + 'effectiveAudioDuration'.tr, // 有效音频时长 controller.formatDuration( controller.currentStats.effectiveAudioDuration), Icons.mic, @@ -578,7 +584,7 @@ class TranslationStatsView extends GetView { ), Expanded( child: _buildStatItem( - '总会话时长', + 'totalSessionDuration'.tr, // 总会话时长 controller.formatDuration( controller.currentStats.totalSessionDuration), Icons.volume_up, @@ -620,7 +626,7 @@ class TranslationStatsView extends GetView { ), SizedBox(width: 8.w), Text( - '成本统计', + 'costStats'.tr, // 成本统计 style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, @@ -642,7 +648,7 @@ class TranslationStatsView extends GetView { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - '${controller.selectedTimeRange.value}预估成本', + '${controller.selectedTimeRange.value}${'estimatedCost'.tr}', style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w500, @@ -666,7 +672,7 @@ class TranslationStatsView extends GetView { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - '日成本预警阈值', + 'dailyCostThreshold'.tr, // 日成本预警阈值 style: TextStyle( fontSize: 12.sp, color: isDarkMode ? Colors.white70 : Colors.black54, @@ -687,7 +693,7 @@ class TranslationStatsView extends GetView { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - '月成本预警阈值', + 'monthlyCostThreshold'.tr, // 月成本预警阈值 style: TextStyle( fontSize: 12.sp, color: isDarkMode ? Colors.white70 : Colors.black54, @@ -736,7 +742,7 @@ class TranslationStatsView extends GetView { ), SizedBox(width: 8.w), Text( - '使用行为统计', + 'usageBehaviorStats'.tr, // 使用行为统计 style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, @@ -749,14 +755,14 @@ class TranslationStatsView extends GetView { Obx(() => Column( children: [ _buildUsageBehaviorRow( - '最常用语言对', + 'mostUsedLanguagePair'.tr, // 最常用语言对 controller.currentStats.mostUsedLanguagePair, Icons.language, isDarkMode, ), SizedBox(height: 12.h), _buildUsageBehaviorRow( - '最常用模式', + 'mostUsedMode'.tr, // 最常用模式 controller.currentStats.mostUsedMode, Icons.settings, isDarkMode, diff --git a/lib/modules/usage/views/usage_view.dart b/lib/modules/usage/views/usage_view.dart index 814b64ad3..7bf1c8ead 100644 --- a/lib/modules/usage/views/usage_view.dart +++ b/lib/modules/usage/views/usage_view.dart @@ -43,7 +43,7 @@ class UsageView extends GetView { // 4. 使用生成的导航项 items: (controller.showAiChat.value ? const [ - _NavItem(Icons.chat_bubble_outline, 'AI chat'), + _NavItem(Icons.chat_bubble_outline, 'aiChat'), _NavItem(Icons.translate, 'interpretation'), _NavItem(Icons.people, 'meeting'), ]