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

@@ -259,7 +259,7 @@ class _ProgramsPageState extends ConsumerState<ProgramsPage> {
SizedBox(
width: 80,
child: Text(
'状态',
l10n?.status ?? '状态',
style: TextStyle(
fontWeight: FontWeight.w600,
color: AppTheme.textPrimary,
@@ -358,7 +358,7 @@ class _ProgramsPageState extends ConsumerState<ProgramsPage> {
borderRadius: BorderRadius.circular(4),
),
child: Text(
program.status == 1 ? '启用' : '停用',
program.status == 1 ? (l10n?.enabled ?? '启用') : (l10n?.disabled ?? '停用'),
style: TextStyle(
color: program.status == 1
? AppTheme.successColor
@@ -413,6 +413,7 @@ class _ProgramsPageState extends ConsumerState<ProgramsPage> {
/// 导入程序
Future<void> _importPrograms(BuildContext context, WidgetRef ref) async {
final l10n = AppLocalizations.of(context);
try {
// 选择文件
final result = await FilePicker.platform.pickFiles(
@@ -428,7 +429,7 @@ class _ProgramsPageState extends ConsumerState<ProgramsPage> {
final file = result.files.first;
if (file.path == null) {
if (!context.mounted) return;
ToastService.showError(context, '无法读取文件');
ToastService.showError(context, l10n?.cannotReadFile ?? '无法读取文件');
return;
}
@@ -441,25 +442,26 @@ class _ProgramsPageState extends ConsumerState<ProgramsPage> {
if (!context.mounted) return;
if (importedCount > 0) {
ToastService.showSuccess(context, '成功处理 $importedCount 个程序');
ToastService.showSuccess(context, l10n?.processedPrograms(importedCount) ?? '成功处理 $importedCount 个程序');
} else {
ToastService.showWarning(context, 'Excel 中无有效程序数据');
ToastService.showWarning(context, l10n?.noValidProgramData ?? 'Excel 中无有效程序数据');
}
} catch (e) {
if (!context.mounted) return;
ToastService.showError(context, '导入失败: ${e.toString()}');
ToastService.showError(context, '${l10n?.importFailed ?? '导入失败'}: ${e.toString()}');
}
}
/// 下载 Excel 模板
Future<void> _downloadTemplate(BuildContext context) async {
final l10n = AppLocalizations.of(context);
try {
final path = await ExcelTemplateService.instance.generateTemplate();
if (!context.mounted) return;
ToastService.showSuccess(context, '模板已保存: $path');
ToastService.showSuccess(context, '${l10n?.templateSaved ?? '模板已保存'}: $path');
} catch (e) {
if (!context.mounted) return;
ToastService.showError(context, '生成模板失败: ${e.toString()}');
ToastService.showError(context, '${l10n?.generateTemplateFailed ?? '生成模板失败'}: ${e.toString()}');
}
}
@@ -484,8 +486,8 @@ class _ProgramsPageState extends ConsumerState<ProgramsPage> {
title: Text(l10n?.confirm ?? '确认'),
content: Text(
ids.length == 1
? '确定要删除此程序吗?'
: '确定要删除选中的 ${ids.length} 个程序吗?',
? (l10n?.deleteConfirmSingle ?? '确定要删除此程序吗?')
: (l10n?.deleteConfirmMultiple(ids.length) ?? '确定要删除选中的 ${ids.length} 个程序吗?'),
),
actions: [
TextButton(