feat(i18n): 完成全量 UI 文本国际化,替换所有硬编码中文为 AppLocalizations 调用

- core/localization: 新增约 60 个翻译键(含参数化方法),中英双语覆盖
- shared/widgets: CommonDialog 默认参数国际化
- features/home: 完成页操作步骤指引、状态栏串口连接状态、程序列表状态标签
- features/programs: 表头状态列、表单验证提示、导入/模板操作反馈、删除确认(参数化)
- features/program_detail: 步骤列表/表单标题、删除确认、速度档位显示(参数化)
- features/device: run_state_provider 错误消息改为错误码
- features/settings: 升级页、密码面板、语言面板、U盘导入面板、串口配置面板全部替换

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Developer
2026-06-12 15:09:47 +08:00
parent 5d65744618
commit 3d849bd468
23 changed files with 688 additions and 127 deletions

View File

@@ -130,6 +130,127 @@ class AppLocalizations {
String get updateAvailable => _localizedValues[locale.languageCode]?['updateAvailable'] ?? '有新版本可用';
String get checkUpdate => _localizedValues[locale.languageCode]?['checkUpdate'] ?? '检查更新';
// ---- 状态 ----
String get status => _localizedValues[locale.languageCode]?['status'] ?? '状态';
String get operation => _localizedValues[locale.languageCode]?['operation'] ?? '操作';
String get serialConnected => _localizedValues[locale.languageCode]?['serialConnected'] ?? '已连接';
String get serialConnecting => _localizedValues[locale.languageCode]?['serialConnecting'] ?? '连接中';
String get serialDisconnected => _localizedValues[locale.languageCode]?['serialDisconnected'] ?? '未连接';
String get serialError => _localizedValues[locale.languageCode]?['serialError'] ?? '错误';
// ---- 完成页 ----
String get programRunComplete => _localizedValues[locale.languageCode]?['programRunComplete'] ?? '程序运行完成';
String get extractSample => _localizedValues[locale.languageCode]?['extractSample'] ?? '取出样本';
String get dropToTestCard => _localizedValues[locale.languageCode]?['dropToTestCard'] ?? '滴入检测卡';
String get waitForReaction => _localizedValues[locale.languageCode]?['waitForReaction'] ?? '等待反应';
String get viewResults => _localizedValues[locale.languageCode]?['viewResults'] ?? '查看结果';
// ---- 表单 ----
String get codeLabel => _localizedValues[locale.languageCode]?['codeLabel'] ?? '编号';
String get nameLabel => _localizedValues[locale.languageCode]?['nameLabel'] ?? '名称';
String get enterCode => _localizedValues[locale.languageCode]?['enterCode'] ?? '请输入编号';
String get enterName => _localizedValues[locale.languageCode]?['enterName'] ?? '请输入名称';
String get enterStepName => _localizedValues[locale.languageCode]?['enterStepName'] ?? '请输入步骤名称';
String get hintCode => _localizedValues[locale.languageCode]?['hintCode'] ?? '例如: P001';
String get hintProgramName => _localizedValues[locale.languageCode]?['hintProgramName'] ?? '请输入程序名称';
String get hintStepName => _localizedValues[locale.languageCode]?['hintStepName'] ?? '例如: 混合、吸磁、吹气';
String get saveFailed => _localizedValues[locale.languageCode]?['saveFailed'] ?? '保存失败,请检查编号是否重复';
String get saved => _localizedValues[locale.languageCode]?['saved'] ?? '已保存';
String get stepUpdated => _localizedValues[locale.languageCode]?['stepUpdated'] ?? '步骤已更新';
String get add => _localizedValues[locale.languageCode]?['add'] ?? '添加';
String get reset => _localizedValues[locale.languageCode]?['reset'] ?? '重置';
String get confirmNewPassword => _localizedValues[locale.languageCode]?['confirmNewPassword'] ?? '确认新密码';
String get enterNewPassword => _localizedValues[locale.languageCode]?['enterNewPassword'] ?? '再次输入新密码';
String get enterCurrentPassword => _localizedValues[locale.languageCode]?['enterCurrentPassword'] ?? '请输入当前密码';
String get newPwdMinLength => _localizedValues[locale.languageCode]?['newPwdMinLength'] ?? '新密码至少6位字符';
String get defaultPassword => _localizedValues[locale.languageCode]?['defaultPassword'] ?? '默认密码为 123456';
// ---- 删除确认 ----
String get deleteConfirmSingle => _localizedValues[locale.languageCode]?['deleteConfirmSingle'] ?? '确定要删除此程序吗?';
String deleteConfirmMultiple(int count) =>
locale.languageCode == 'en'
? 'Are you sure to delete $count selected programs?'
: '确定要删除选中的 $count 个程序吗?';
String get deleteStepConfirmSingle => _localizedValues[locale.languageCode]?['deleteStepConfirmSingle'] ?? '确定要删除此步骤吗?';
String deleteStepConfirmMultiple(int count) =>
locale.languageCode == 'en'
? 'Are you sure to delete $count selected steps?'
: '确定要删除选中的 $count 个步骤吗?';
// ---- 导入 ----
String get cannotReadFile => _localizedValues[locale.languageCode]?['cannotReadFile'] ?? '无法读取文件';
String processedPrograms(int count) =>
locale.languageCode == 'en'
? 'Successfully processed $count programs'
: '成功处理 $count 个程序';
String get noValidProgramData => _localizedValues[locale.languageCode]?['noValidProgramData'] ?? 'Excel 中无有效程序数据';
String get templateSaved => _localizedValues[locale.languageCode]?['templateSaved'] ?? '模板已保存';
String get generateTemplateFailed => _localizedValues[locale.languageCode]?['generateTemplateFailed'] ?? '生成模板失败';
String get importingPrograms => _localizedValues[locale.languageCode]?['importingPrograms'] ?? '正在导入程序...';
// ---- 语言设置 ----
String get languageSettings => _localizedValues[locale.languageCode]?['languageSettings'] ?? '语言设置';
String get switchLanguageEffect => _localizedValues[locale.languageCode]?['switchLanguageEffect'] ?? '切换语言后立即生效';
// ---- 串口配置 ----
String get serialStatus => _localizedValues[locale.languageCode]?['serialStatus'] ?? '串口状态';
String get availableSerialDevices => _localizedValues[locale.languageCode]?['availableSerialDevices'] ?? '可用串口设备';
String get refresh => _localizedValues[locale.languageCode]?['refresh'] ?? '刷新';
String get noSerialDevice => _localizedValues[locale.languageCode]?['noSerialDevice'] ?? '未检测到 USB 串口设备';
String get serialDeviceHint => _localizedValues[locale.languageCode]?['serialDeviceHint'] ?? '请确认下位机已上电并通过 USB 接入设备';
String get scanFailed => _localizedValues[locale.languageCode]?['scanFailed'] ?? '扫描设备失败';
String get selectSerialFirst => _localizedValues[locale.languageCode]?['selectSerialFirst'] ?? '请先选择串口设备';
String get connectSuccess => _localizedValues[locale.languageCode]?['connectSuccess'] ?? '连接成功';
String get connectFailed => _localizedValues[locale.languageCode]?['connectFailed'] ?? '连接失败';
String get disconnected => _localizedValues[locale.languageCode]?['disconnected'] ?? '已断开串口';
String get connectFirst => _localizedValues[locale.languageCode]?['connectFirst'] ?? '请先连接串口';
String get sendTestFrame => _localizedValues[locale.languageCode]?['sendTestFrame'] ?? '发送测试帧';
String get serialParams => _localizedValues[locale.languageCode]?['serialParams'] ?? '串口参数';
String get baudRate => _localizedValues[locale.languageCode]?['baudRate'] ?? '波特率';
String get dataBits => _localizedValues[locale.languageCode]?['dataBits'] ?? '数据位';
String get stopBits => _localizedValues[locale.languageCode]?['stopBits'] ?? '停止位';
String get parity => _localizedValues[locale.languageCode]?['parity'] ?? '校验位';
String get parityNone => _localizedValues[locale.languageCode]?['parityNone'] ?? '';
String get parityOdd => _localizedValues[locale.languageCode]?['parityOdd'] ?? '';
String get parityEven => _localizedValues[locale.languageCode]?['parityEven'] ?? '';
String get parityMark => _localizedValues[locale.languageCode]?['parityMark'] ?? '标记';
String get paritySpace => _localizedValues[locale.languageCode]?['paritySpace'] ?? '';
String get flowControl => _localizedValues[locale.languageCode]?['flowControl'] ?? '流控';
String get autoSaveParams => _localizedValues[locale.languageCode]?['autoSaveParams'] ?? '参数修改后自动保存';
String get connect => _localizedValues[locale.languageCode]?['connect'] ?? '连接';
String get disconnect => _localizedValues[locale.languageCode]?['disconnect'] ?? '断开';
String get unknownError => _localizedValues[locale.languageCode]?['unknownError'] ?? '未知错误';
// ---- USB 导入 ----
String get usbConnected => _localizedValues[locale.languageCode]?['usbConnected'] ?? 'U盘已连接';
String get mountPath => _localizedValues[locale.languageCode]?['mountPath'] ?? '挂载路径';
String get reDetect => _localizedValues[locale.languageCode]?['reDetect'] ?? '重新检测';
String get usageInstructions => _localizedValues[locale.languageCode]?['usageInstructions'] ?? '使用说明';
String get usbUsageStep1 => _localizedValues[locale.languageCode]?['usbUsageStep1'] ?? '将程序文件 (.json) 放入 U盘根目录的 programs 文件夹';
String get usbUsageStep2 => _localizedValues[locale.languageCode]?['usbUsageStep2'] ?? '插入 U盘后点击"重新检测"';
String get usbUsageStep3 => _localizedValues[locale.languageCode]?['usbUsageStep3'] ?? '检测成功后点击"导入程序"加载程序列表';
String get usbPathInvalid => _localizedValues[locale.languageCode]?['usbPathInvalid'] ?? 'U盘路径无效';
// ---- 通用 ----
String get back => _localizedValues[locale.languageCode]?['back'] ?? '返回';
String get totalProgress => _localizedValues[locale.languageCode]?['totalProgress'] ?? '总进度';
String get appTitle => _localizedValues[locale.languageCode]?['appTitle'] ?? '污水毒品快检一体机';
// ---- 参数化方法 ----
String get stepUnit => _localizedValues[locale.languageCode]?['stepUnit'] ?? '';
String speedLevelValue(int speed) =>
locale.languageCode == 'en'
? '$speed level'
: '$speed';
String stepLabel(int stepNo) =>
locale.languageCode == 'en'
? 'Step $stepNo'
: '步骤 $stepNo';
String stepsCountLabel(int count) =>
locale.languageCode == 'en'
? '$count steps'
: '$count';
static final Map<String, Map<String, String>> _localizedValues = {
'zh': {
'deviceName': '污水毒品前处理一体机',
@@ -233,6 +354,83 @@ class AppLocalizations {
'latestVersion': '已是最新版本',
'updateAvailable': '有新版本可用',
'checkUpdate': '检查更新',
'status': '状态',
'operation': '操作',
'serialConnected': '已连接',
'serialConnecting': '连接中',
'serialDisconnected': '未连接',
'serialError': '错误',
'programRunComplete': '程序运行完成',
'extractSample': '取出样本',
'dropToTestCard': '滴入检测卡',
'waitForReaction': '等待反应',
'viewResults': '查看结果',
'codeLabel': '编号',
'nameLabel': '名称',
'enterCode': '请输入编号',
'enterName': '请输入名称',
'enterStepName': '请输入步骤名称',
'hintCode': '例如: P001',
'hintProgramName': '请输入程序名称',
'hintStepName': '例如: 混合、吸磁、吹气',
'saveFailed': '保存失败,请检查编号是否重复',
'saved': '已保存',
'stepUpdated': '步骤已更新',
'add': '添加',
'reset': '重置',
'confirmNewPassword': '确认新密码',
'enterNewPassword': '再次输入新密码',
'enterCurrentPassword': '请输入当前密码',
'newPwdMinLength': '新密码至少6位字符',
'defaultPassword': '默认密码为 123456',
'deleteConfirmSingle': '确定要删除此程序吗?',
'deleteStepConfirmSingle': '确定要删除此步骤吗?',
'cannotReadFile': '无法读取文件',
'noValidProgramData': 'Excel 中无有效程序数据',
'templateSaved': '模板已保存',
'generateTemplateFailed': '生成模板失败',
'importingPrograms': '正在导入程序...',
'languageSettings': '语言设置',
'switchLanguageEffect': '切换语言后立即生效',
'serialStatus': '串口状态',
'availableSerialDevices': '可用串口设备',
'refresh': '刷新',
'noSerialDevice': '未检测到 USB 串口设备',
'serialDeviceHint': '请确认下位机已上电并通过 USB 接入设备',
'scanFailed': '扫描设备失败',
'selectSerialFirst': '请先选择串口设备',
'connectSuccess': '连接成功',
'connectFailed': '连接失败',
'disconnected': '已断开串口',
'connectFirst': '请先连接串口',
'sendTestFrame': '发送测试帧',
'serialParams': '串口参数',
'baudRate': '波特率',
'dataBits': '数据位',
'stopBits': '停止位',
'parity': '校验位',
'parityNone': '',
'parityOdd': '',
'parityEven': '',
'parityMark': '标记',
'paritySpace': '',
'flowControl': '流控',
'autoSaveParams': '参数修改后自动保存',
'connect': '连接',
'disconnect': '断开',
'unknownError': '未知错误',
'usbConnected': 'U盘已连接',
'mountPath': '挂载路径',
'reDetect': '重新检测',
'usageInstructions': '使用说明',
'usbUsageStep1': '将程序文件 (.json) 放入 U盘根目录的 programs 文件夹',
'usbUsageStep2': '插入 U盘后点击"重新检测"',
'usbUsageStep3': '检测成功后点击"导入程序"加载程序列表',
'usbPathInvalid': 'U盘路径无效',
'back': '返回',
'totalProgress': '总进度',
'appTitle': '污水毒品快检一体机',
'stepUnit': '',
},
'en': {
'deviceName': 'Wastewater Drug Pretreatment System',
@@ -336,6 +534,83 @@ class AppLocalizations {
'latestVersion': 'Already latest version',
'updateAvailable': 'Update available',
'checkUpdate': 'Check Update',
'status': 'Status',
'operation': 'Actions',
'serialConnected': 'Connected',
'serialConnecting': 'Connecting',
'serialDisconnected': 'Disconnected',
'serialError': 'Error',
'programRunComplete': 'Program Run Complete',
'extractSample': 'Extract Sample',
'dropToTestCard': 'Drop to Test Card',
'waitForReaction': 'Wait for Reaction',
'viewResults': 'View Results',
'codeLabel': 'Code',
'nameLabel': 'Name',
'enterCode': 'Please enter code',
'enterName': 'Please enter name',
'enterStepName': 'Please enter step name',
'hintCode': 'e.g. P001',
'hintProgramName': 'Enter program name',
'hintStepName': 'e.g. Mix, Magnet, Blow',
'saveFailed': 'Save failed, please check if code is duplicate',
'saved': 'Saved',
'stepUpdated': 'Step updated',
'add': 'Add',
'reset': 'Reset',
'confirmNewPassword': 'Confirm New Password',
'enterNewPassword': 'Re-enter new password',
'enterCurrentPassword': 'Enter current password',
'newPwdMinLength': 'New password at least 6 characters',
'defaultPassword': 'Default password is 123456',
'deleteConfirmSingle': 'Are you sure to delete this program?',
'deleteStepConfirmSingle': 'Are you sure to delete this step?',
'cannotReadFile': 'Cannot read file',
'noValidProgramData': 'No valid program data in Excel',
'templateSaved': 'Template saved',
'generateTemplateFailed': 'Failed to generate template',
'importingPrograms': 'Importing programs...',
'languageSettings': 'Language Settings',
'switchLanguageEffect': 'Language change takes effect immediately',
'serialStatus': 'Serial Status',
'availableSerialDevices': 'Available Serial Devices',
'refresh': 'Refresh',
'noSerialDevice': 'No USB serial device detected',
'serialDeviceHint': 'Please ensure the device is powered on and connected via USB',
'scanFailed': 'Device scan failed',
'selectSerialFirst': 'Please select a serial device first',
'connectSuccess': 'Connected successfully',
'connectFailed': 'Connection failed',
'disconnected': 'Serial disconnected',
'connectFirst': 'Please connect serial first',
'sendTestFrame': 'Send Test Frame',
'serialParams': 'Serial Parameters',
'baudRate': 'Baud Rate',
'dataBits': 'Data Bits',
'stopBits': 'Stop Bits',
'parity': 'Parity',
'parityNone': 'None',
'parityOdd': 'Odd',
'parityEven': 'Even',
'parityMark': 'Mark',
'paritySpace': 'Space',
'flowControl': 'Flow Control',
'autoSaveParams': 'Parameters auto-saved after change',
'connect': 'Connect',
'disconnect': 'Disconnect',
'unknownError': 'Unknown error',
'usbConnected': 'USB Connected',
'mountPath': 'Mount Path',
'reDetect': 'Re-detect',
'usageInstructions': 'Usage Instructions',
'usbUsageStep1': 'Place program files (.json) in the programs folder on USB root',
'usbUsageStep2': 'Insert USB then click "Re-detect"',
'usbUsageStep3': 'After detection, click "Import Programs" to load',
'usbPathInvalid': 'USB path invalid',
'back': 'Back',
'totalProgress': 'Total Progress',
'appTitle': 'Wastewater Drug Detection System',
'stepUnit': 'steps',
},
};
}