Flutter 框架跨平台鸿蒙开发 - 中英互译助手 - 完整开发教程

Flutter中英互译助手 - 完整开发教程

项目简介

这是一个使用Flutter开发的中英互译助手应用,提供实时翻译、历史记录、常用短语和收藏管理等功能。应用采用本地词典的方式实现翻译,无需网络连接,适合学习Flutter文本处理和数据管理。

运行效果图




核心特性

  • 🔄 中英互译:支持中英文双向翻译
  • 📝 实时翻译:输入即时翻译
  • 📚 历史记录:自动保存翻译历史
  • ⭐ 收藏管理:收藏常用翻译
  • 📖 常用短语:分类常用短语库
  • 🔊 语音朗读:文本朗读功能(预留)
  • 📋 快速复制:一键复制翻译结果
  • 💾 数据持久化:使用SharedPreferences

技术栈

  • Flutter 3.6+
  • Dart 3.0+
  • shared_preferences: 数据持久化
  • Material Design 3

项目架构

中英互译助手
翻译页面
历史记录
常用短语
收藏管理
语言切换
翻译引擎
结果展示
记录列表
收藏操作
分类浏览
音标显示

数据模型设计

TranslationRecord - 翻译记录模型

dart 复制代码
class TranslationRecord {
  final String id;                  // 唯一标识
  final String sourceText;          // 原文
  final String translatedText;      // 译文
  final String sourceLanguage;      // 源语言
  final String targetLanguage;      // 目标语言
  final DateTime timestamp;         // 时间戳
  bool isFavorite;                  // 是否收藏
  
  TranslationRecord({
    required this.id,
    required this.sourceText,
    required this.translatedText,
    required this.sourceLanguage,
    required this.targetLanguage,
    required this.timestamp,
    this.isFavorite = false,
  });
  
  // JSON序列化
  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'sourceText': sourceText,
      'translatedText': translatedText,
      'sourceLanguage': sourceLanguage,
      'targetLanguage': targetLanguage,
      'timestamp': timestamp.toIso8601String(),
      'isFavorite': isFavorite,
    };
  }
  
  // JSON反序列化
  factory TranslationRecord.fromJson(Map<String, dynamic> json) {
    return TranslationRecord(
      id: json['id'],
      sourceText: json['sourceText'],
      translatedText: json['translatedText'],
      sourceLanguage: json['sourceLanguage'],
      targetLanguage: json['targetLanguage'],
      timestamp: DateTime.parse(json['timestamp']),
      isFavorite: json['isFavorite'] ?? false,
    );
  }
}

CommonPhrase - 常用短语模型

dart 复制代码
class CommonPhrase {
  final String chinese;         // 中文
  final String english;         // 英文
  final String category;        // 分类
  final String pronunciation;   // 音标
  
  CommonPhrase({
    required this.chinese,
    required this.english,
    required this.category,
    required this.pronunciation,
  });
}

核心功能实现

1. 语言切换功能

实现中英文双向切换:

dart 复制代码
bool _isChineseToEnglish = true;

void _swapLanguages() {
  setState(() {
    _isChineseToEnglish = !_isChineseToEnglish;
    // 交换输入和输出
    final temp = _inputController.text;
    _inputController.text = _translatedText;
    _translatedText = temp;
  });
}

// UI展示
Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    Text(
      _isChineseToEnglish ? '中文' : '英文',
      style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
    ),
    SizedBox(width: 16),
    IconButton(
      icon: Icon(Icons.swap_horiz, size: 32),
      onPressed: _swapLanguages,
      color: Colors.blue,
    ),
    SizedBox(width: 16),
    Text(
      _isChineseToEnglish ? '英文' : '中文',
      style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
    ),
  ],
)

切换特点

  • 一键切换方向
  • 自动交换内容
  • 视觉反馈清晰

2. 翻译引擎实现

使用本地词典实现翻译:

dart 复制代码
// 翻译词典
final Map<String, String> _chineseToEnglish = {
  '你好': 'Hello',
  '谢谢': 'Thank you',
  '再见': 'Goodbye',
  // ... 更多词汇
};

// 中译英
String _translateChineseToEnglish(String text) {
  for (var entry in _chineseToEnglish.entries) {
    if (text.contains(entry.key)) {
      return text.replaceAll(entry.key, entry.value);
    }
  }
  // 找不到时的处理
  return 'Translation: ${text.split('').join(' ')}';
}

// 英译中
String _translateEnglishToChinese(String text) {
  final lowerText = text.toLowerCase();
  for (var entry in _chineseToEnglish.entries) {
    if (lowerText.contains(entry.value.toLowerCase())) {
      return text.replaceAll(
        RegExp(entry.value, caseSensitive: false),
        entry.key,
      );
    }
  }
  return '翻译:${text.split(' ').join('·')}';
}

// 执行翻译
Future<void> _translate() async {
  if (_inputController.text.trim().isEmpty) return;
  
  setState(() {
    _isTranslating = true;
  });
  
  // 模拟翻译延迟
  await Future.delayed(const Duration(milliseconds: 500));
  
  String result;
  if (_isChineseToEnglish) {
    result = _translateChineseToEnglish(_inputController.text);
  } else {
    result = _translateEnglishToChinese(_inputController.text);
  }
  
  setState(() {
    _translatedText = result;
    _isTranslating = false;
  });
  
  // 添加到历史记录
  _addToHistory(result);
}

翻译特点

  • 本地词典查找
  • 支持部分匹配
  • 异步处理
  • 加载状态提示

3. 输入区域设计

创建美观的输入框:

dart 复制代码
Container(
  margin: const EdgeInsets.all(16),
  decoration: BoxDecoration(
    color: Colors.white,
    borderRadius: BorderRadius.circular(12),
    boxShadow: [
      BoxShadow(
        color: Colors.grey.withValues(alpha: 0.2),
        blurRadius: 8,
        offset: const Offset(0, 2),
      ),
    ],
  ),
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      // 标题栏
      Padding(
        padding: const EdgeInsets.all(12),
        child: Row(
          children: [
            Icon(Icons.edit, size: 20, color: Colors.grey.shade600),
            SizedBox(width: 8),
            Text(
              '输入文本',
              style: TextStyle(fontSize: 14, color: Colors.grey.shade600),
            ),
          ],
        ),
      ),
      // 输入框
      TextField(
        controller: _inputController,
        maxLines: 6,
        decoration: InputDecoration(
          hintText: '请输入要翻译的内容...',
          border: InputBorder.none,
          contentPadding: EdgeInsets.all(16),
        ),
        style: TextStyle(fontSize: 16),
      ),
      // 字符统计
      Padding(
        padding: const EdgeInsets.all(12),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            if (_inputController.text.isNotEmpty)
              Text(
                '${_inputController.text.length} 字符',
                style: TextStyle(fontSize: 12, color: Colors.grey.shade600),
              ),
          ],
        ),
      ),
    ],
  ),
)

输入框特点

  • 卡片式设计
  • 阴影效果
  • 字符计数
  • 多行输入

4. 翻译结果展示

美观的结果展示区域:

dart 复制代码
if (_translatedText.isNotEmpty)
  Container(
    margin: const EdgeInsets.all(16),
    decoration: BoxDecoration(
      color: Colors.green.shade50,
      borderRadius: BorderRadius.circular(12),
      border: Border.all(color: Colors.green.shade200),
    ),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // 标题栏
        Padding(
          padding: const EdgeInsets.all(12),
          child: Row(
            children: [
              Icon(Icons.check_circle, size: 20, color: Colors.green.shade700),
              SizedBox(width: 8),
              Text(
                '翻译结果',
                style: TextStyle(
                  fontSize: 14,
                  color: Colors.green.shade700,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ],
          ),
        ),
        // 翻译文本
        Padding(
          padding: const EdgeInsets.all(16),
          child: SelectableText(
            _translatedText,
            style: TextStyle(fontSize: 16, height: 1.5),
          ),
        ),
        // 操作按钮
        Padding(
          padding: const EdgeInsets.all(12),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: [
              TextButton.icon(
                icon: Icon(Icons.copy, size: 18),
                label: Text('复制'),
                onPressed: () => _copyToClipboard(_translatedText),
              ),
              SizedBox(width: 8),
              TextButton.icon(
                icon: Icon(Icons.volume_up, size: 18),
                label: Text('朗读'),
                onPressed: _speakText,
              ),
            ],
          ),
        ),
      ],
    ),
  )

结果展示特点

  • 绿色主题
  • 可选择文本
  • 快捷操作
  • 清晰布局

5. 历史记录管理

实现翻译历史的保存和展示:

dart 复制代码
List<TranslationRecord> historyRecords = [];

// 添加记录
void _addRecord(TranslationRecord record) {
  setState(() {
    historyRecords.insert(0, record);
    // 限制历史记录数量
    if (historyRecords.length > 100) {
      historyRecords.removeLast();
    }
  });
  _saveData();
}

// 保存数据
Future<void> _saveData() async {
  final prefs = await SharedPreferences.getInstance();
  final historyData = historyRecords.map((r) => jsonEncode(r.toJson())).toList();
  await prefs.setStringList('translation_history', historyData);
}

// 加载数据
Future<void> _loadData() async {
  final prefs = await SharedPreferences.getInstance();
  final historyData = prefs.getStringList('translation_history') ?? [];
  setState(() {
    historyRecords = historyData
        .map((json) => TranslationRecord.fromJson(jsonDecode(json)))
        .toList();
  });
}

// 清空历史
void _clearHistory() {
  setState(() {
    historyRecords.clear();
  });
  _saveData();
}

历史记录特点

  • 自动保存
  • 限制数量
  • 持久化存储
  • 批量清空

6. 历史记录卡片

展示历史记录的卡片设计:

dart 复制代码
Widget _buildHistoryCard(BuildContext context, TranslationRecord record) {
  return Card(
    margin: const EdgeInsets.only(bottom: 12),
    child: Padding(
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // 语言标签和时间
          Row(
            children: [
              Container(
                padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
                decoration: BoxDecoration(
                  color: Colors.blue.withValues(alpha: 0.1),
                  borderRadius: BorderRadius.circular(12),
                ),
                child: Text(
                  '${record.sourceLanguage} → ${record.targetLanguage}',
                  style: TextStyle(fontSize: 12, color: Colors.blue),
                ),
              ),
              Spacer(),
              Text(
                _formatTime(record.timestamp),
                style: TextStyle(fontSize: 12, color: Colors.grey.shade600),
              ),
            ],
          ),
          SizedBox(height: 12),
          // 原文
          Text(
            record.sourceText,
            style: TextStyle(fontSize: 15, fontWeight: FontWeight.w500),
          ),
          SizedBox(height: 8),
          // 译文
          Container(
            padding: EdgeInsets.all(12),
            decoration: BoxDecoration(
              color: Colors.grey.shade100,
              borderRadius: BorderRadius.circular(8),
            ),
            child: Text(
              record.translatedText,
              style: TextStyle(fontSize: 14, color: Colors.grey.shade800),
            ),
          ),
          SizedBox(height: 8),
          // 操作按钮
          Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: [
              IconButton(
                icon: Icon(
                  record.isFavorite ? Icons.star : Icons.star_border,
                  color: record.isFavorite ? Colors.amber : Colors.grey,
                ),
                onPressed: () => onToggleFavorite(record),
              ),
              IconButton(
                icon: Icon(Icons.copy, size: 20),
                onPressed: () => _copyText(record.translatedText),
              ),
              IconButton(
                icon: Icon(Icons.delete, size: 20),
                onPressed: () => onDelete(record),
              ),
            ],
          ),
        ],
      ),
    ),
  );
}

// 时间格式化
String _formatTime(DateTime time) {
  final now = DateTime.now();
  final diff = now.difference(time);
  
  if (diff.inMinutes < 1) return '刚刚';
  if (diff.inHours < 1) return '${diff.inMinutes}分钟前';
  if (diff.inDays < 1) return '${diff.inHours}小时前';
  if (diff.inDays < 7) return '${diff.inDays}天前';
  return '${time.month}-${time.day}';
}

卡片特点

  • 语言方向标签
  • 相对时间显示
  • 快捷操作按钮
  • 收藏状态显示

7. 常用短语功能

分类展示常用短语:

dart 复制代码
class _CommonPhrasesPageState extends State<CommonPhrasesPage> {
  String _selectedCategory = '问候';
  
  final Map<String, List<CommonPhrase>> _phrases = {
    '问候': [
      CommonPhrase(
        chinese: '你好',
        english: 'Hello',
        category: '问候',
        pronunciation: 'həˈləʊ',
      ),
      // ... 更多短语
    ],
    '感谢': [
      CommonPhrase(
        chinese: '谢谢',
        english: 'Thank you',
        category: '感谢',
        pronunciation: 'θæŋk juː',
      ),
      // ... 更多短语
    ],
    // ... 更多分类
  };
  
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        // 左侧分类列表
        Container(
          width: 100,
          color: Colors.grey.shade100,
          child: ListView.builder(
            itemCount: categories.length,
            itemBuilder: (context, index) {
              final category = categories[index];
              final isSelected = category == _selectedCategory;
              return InkWell(
                onTap: () {
                  setState(() {
                    _selectedCategory = category;
                  });
                },
                child: Container(
                  padding: EdgeInsets.symmetric(vertical: 16),
                  decoration: BoxDecoration(
                    color: isSelected ? Colors.white : Colors.transparent,
                    border: Border(
                      left: BorderSide(
                        color: isSelected ? Colors.blue : Colors.transparent,
                        width: 3,
                      ),
                    ),
                  ),
                  child: Center(
                    child: Text(
                      category,
                      style: TextStyle(
                        fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
                        color: isSelected ? Colors.blue : Colors.black87,
                      ),
                    ),
                  ),
                ),
              );
            },
          ),
        ),
        // 右侧短语列表
        Expanded(
          child: ListView.builder(
            padding: EdgeInsets.all(16),
            itemCount: currentPhrases.length,
            itemBuilder: (context, index) {
              return _buildPhraseCard(currentPhrases[index]);
            },
          ),
        ),
      ],
    );
  }
}

常用短语特点

  • 分类浏览
  • 左右布局
  • 音标显示
  • 朗读功能

8. 短语卡片设计

展示短语的详细信息:

dart 复制代码
Widget _buildPhraseCard(CommonPhrase phrase) {
  return Card(
    margin: const EdgeInsets.only(bottom: 12),
    child: Padding(
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    // 中文
                    Text(
                      phrase.chinese,
                      style: TextStyle(
                        fontSize: 18,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    SizedBox(height: 4),
                    // 英文
                    Text(
                      phrase.english,
                      style: TextStyle(
                        fontSize: 16,
                        color: Colors.grey.shade700,
                      ),
                    ),
                  ],
                ),
              ),
              // 朗读按钮
              IconButton(
                icon: Icon(Icons.volume_up),
                onPressed: () => _speakPhrase(phrase),
              ),
            ],
          ),
          SizedBox(height: 8),
          // 音标
          Container(
            padding: EdgeInsets.symmetric(horizontal: 12, vertical: 6),
            decoration: BoxDecoration(
              color: Colors.blue.withValues(alpha: 0.1),
              borderRadius: BorderRadius.circular(16),
            ),
            child: Text(
              '/${phrase.pronunciation}/',
              style: TextStyle(
                fontSize: 12,
                color: Colors.blue,
                fontStyle: FontStyle.italic,
              ),
            ),
          ),
        ],
      ),
    ),
  );
}

短语卡片特点

  • 中英对照
  • 音标展示
  • 朗读按钮
  • 清晰布局

9. 收藏功能

管理收藏的翻译:

dart 复制代码
List<TranslationRecord> favoriteRecords = [];

void _toggleFavorite(TranslationRecord record) {
  setState(() {
    record.isFavorite = !record.isFavorite;
    if (record.isFavorite) {
      if (!favoriteRecords.any((r) => r.id == record.id)) {
        favoriteRecords.insert(0, record);
      }
    } else {
      favoriteRecords.removeWhere((r) => r.id == record.id);
    }
  });
  _saveData();
}

// 收藏页面
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: Text('我的收藏')),
    body: favoriteRecords.isEmpty
        ? Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Icon(Icons.star_outline, size: 80, color: Colors.grey.shade400),
                SizedBox(height: 16),
                Text('还没有收藏的翻译'),
              ],
            ),
          )
        : ListView.builder(
            itemCount: favoriteRecords.length,
            itemBuilder: (context, index) {
              return _buildFavoriteCard(favoriteRecords[index]);
            },
          ),
  );
}

收藏特点

  • 一键收藏
  • 独立列表
  • 快速访问
  • 持久化保存

UI组件设计

1. 翻译按钮

大号翻译按钮设计:

dart 复制代码
SizedBox(
  width: double.infinity,
  height: 50,
  child: ElevatedButton(
    onPressed: _isTranslating ? null : _translate,
    style: ElevatedButton.styleFrom(
      backgroundColor: Colors.blue,
      foregroundColor: Colors.white,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(25),
      ),
    ),
    child: _isTranslating
        ? SizedBox(
            width: 24,
            height: 24,
            child: CircularProgressIndicator(
              strokeWidth: 2,
              valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
            ),
          )
        : Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Icon(Icons.translate),
              SizedBox(width: 8),
              Text('翻译', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
            ],
          ),
  ),
)

2. 语言标签

小型语言标签:

dart 复制代码
Container(
  padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
  decoration: BoxDecoration(
    color: Colors.blue.withValues(alpha: 0.1),
    borderRadius: BorderRadius.circular(12),
  ),
  child: Text(
    '中文 → 英文',
    style: TextStyle(fontSize: 12, color: Colors.blue),
  ),
)

3. 操作按钮组

快捷操作按钮:

dart 复制代码
Row(
  mainAxisAlignment: MainAxisAlignment.end,
  children: [
    TextButton.icon(
      icon: Icon(Icons.copy, size: 18),
      label: Text('复制'),
      onPressed: _copyText,
    ),
    SizedBox(width: 8),
    TextButton.icon(
      icon: Icon(Icons.volume_up, size: 18),
      label: Text('朗读'),
      onPressed: _speakText,
    ),
  ],
)

4. 底部导航栏

Material 3风格导航:

dart 复制代码
NavigationBar(
  selectedIndex: _selectedIndex,
  onDestinationSelected: (index) {
    setState(() {
      _selectedIndex = index;
    });
  },
  destinations: const [
    NavigationDestination(
      icon: Icon(Icons.translate_outlined),
      selectedIcon: Icon(Icons.translate),
      label: '翻译',
    ),
    NavigationDestination(
      icon: Icon(Icons.history_outlined),
      selectedIcon: Icon(Icons.history),
      label: '历史',
    ),
    NavigationDestination(
      icon: Icon(Icons.book_outlined),
      selectedIcon: Icon(Icons.book),
      label: '常用语',
    ),
    NavigationDestination(
      icon: Icon(Icons.star_outline),
      selectedIcon: Icon(Icons.star),
      label: '收藏',
    ),
  ],
)

功能扩展建议

1. 在线翻译API集成

接入真实翻译API:

dart 复制代码
import 'package:http/http.dart' as http;

class TranslationApiService {
  static const String apiKey = 'YOUR_API_KEY';
  static const String baseUrl = 'https://translation.googleapis.com/language/translate/v2';
  
  Future<String> translate(String text, String sourceLang, String targetLang) async {
    final response = await http.post(
      Uri.parse(baseUrl),
      headers: {
        'Content-Type': 'application/json',
      },
      body: jsonEncode({
        'q': text,
        'source': sourceLang,
        'target': targetLang,
        'format': 'text',
        'key': apiKey,
      }),
    );
    
    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      return data['data']['translations'][0]['translatedText'];
    }
    throw Exception('Translation failed');
  }
}

2. 语音朗读功能

使用flutter_tts实现语音朗读:

dart 复制代码
import 'package:flutter_tts/flutter_tts.dart';

class TextToSpeechService {
  final FlutterTts _tts = FlutterTts();
  
  Future<void> init() async {
    await _tts.setLanguage('en-US');
    await _tts.setSpeechRate(0.5);
    await _tts.setVolume(1.0);
    await _tts.setPitch(1.0);
  }
  
  Future<void> speak(String text, String language) async {
    await _tts.setLanguage(language == '中文' ? 'zh-CN' : 'en-US');
    await _tts.speak(text);
  }
  
  Future<void> stop() async {
    await _tts.stop();
  }
}

// 使用
IconButton(
  icon: Icon(Icons.volume_up),
  onPressed: () async {
    final tts = TextToSpeechService();
    await tts.init();
    await tts.speak(_translatedText, '英文');
  },
)

3. 语音输入功能

使用speech_to_text实现语音输入:

dart 复制代码
import 'package:speech_to_text/speech_to_text.dart';

class SpeechToTextService {
  final SpeechToText _speech = SpeechToText();
  bool _isListening = false;
  
  Future<void> init() async {
    await _speech.initialize();
  }
  
  Future<void> startListening(Function(String) onResult) async {
    if (!_isListening) {
      _isListening = true;
      await _speech.listen(
        onResult: (result) {
          onResult(result.recognizedWords);
        },
      );
    }
  }
  
  Future<void> stopListening() async {
    if (_isListening) {
      _isListening = false;
      await _speech.stop();
    }
  }
}

// 添加语音输入按钮
IconButton(
  icon: Icon(_isListening ? Icons.mic : Icons.mic_none),
  onPressed: () async {
    if (_isListening) {
      await _speechService.stopListening();
    } else {
      await _speechService.startListening((text) {
        setState(() {
          _inputController.text = text;
        });
      });
    }
  },
)

4. 拍照翻译功能

使用相机识别文字并翻译:

dart 复制代码
import 'package:image_picker/image_picker.dart';
import 'package:google_ml_kit/google_ml_kit.dart';

class OCRTranslationService {
  final ImagePicker _picker = ImagePicker();
  final TextRecognizer _textRecognizer = GoogleMlKit.vision.textRecognizer();
  
  Future<String> recognizeTextFromCamera() async {
    final XFile? photo = await _picker.pickImage(source: ImageSource.camera);
    if (photo == null) return '';
    
    final inputImage = InputImage.fromFilePath(photo.path);
    final RecognizedText recognizedText = await _textRecognizer.processImage(inputImage);
    
    return recognizedText.text;
  }
  
  Future<String> recognizeTextFromGallery() async {
    final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
    if (image == null) return '';
    
    final inputImage = InputImage.fromFilePath(image.path);
    final RecognizedText recognizedText = await _textRecognizer.processImage(inputImage);
    
    return recognizedText.text;
  }
}

// 添加拍照按钮
Row(
  children: [
    IconButton(
      icon: Icon(Icons.camera_alt),
      onPressed: () async {
        final text = await _ocrService.recognizeTextFromCamera();
        setState(() {
          _inputController.text = text;
        });
      },
      tooltip: '拍照翻译',
    ),
    IconButton(
      icon: Icon(Icons.photo_library),
      onPressed: () async {
        final text = await _ocrService.recognizeTextFromGallery();
        setState(() {
          _inputController.text = text;
        });
      },
      tooltip: '相册翻译',
    ),
  ],
)

5. 离线词典

实现完整的离线词典:

dart 复制代码
import 'package:sqflite/sqflite.dart';

class OfflineDictionary {
  static Database? _database;
  
  Future<Database> get database async {
    if (_database != null) return _database!;
    _database = await _initDatabase();
    return _database!;
  }
  
  Future<Database> _initDatabase() async {
    String path = join(await getDatabasesPath(), 'dictionary.db');
    return await openDatabase(
      path,
      version: 1,
      onCreate: (db, version) async {
        await db.execute('''
          CREATE TABLE words(
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            english TEXT,
            chinese TEXT,
            pronunciation TEXT,
            category TEXT,
            example TEXT
          )
        ''');
      },
    );
  }
  
  Future<String?> translate(String word) async {
    final db = await database;
    final List<Map<String, dynamic>> maps = await db.query(
      'words',
      where: 'english = ? OR chinese = ?',
      whereArgs: [word, word],
    );
    
    if (maps.isNotEmpty) {
      return maps[0]['english'] == word 
          ? maps[0]['chinese'] 
          : maps[0]['english'];
    }
    return null;
  }
  
  Future<void> importDictionary(List<Map<String, String>> words) async {
    final db = await database;
    final batch = db.batch();
    for (var word in words) {
      batch.insert('words', word);
    }
    await batch.commit();
  }
}

6. 翻译历史统计

统计翻译使用情况:

dart 复制代码
class TranslationStatistics {
  final List<TranslationRecord> records;
  
  TranslationStatistics(this.records);
  
  // 总翻译次数
  int get totalTranslations => records.length;
  
  // 今日翻译次数
  int get todayTranslations {
    final today = DateTime.now();
    return records.where((r) {
      return r.timestamp.year == today.year &&
          r.timestamp.month == today.month &&
          r.timestamp.day == today.day;
    }).length;
  }
  
  // 最常用的翻译方向
  String get mostUsedDirection {
    final directions = <String, int>{};
    for (var record in records) {
      final key = '${record.sourceLanguage} → ${record.targetLanguage}';
      directions[key] = (directions[key] ?? 0) + 1;
    }
    return directions.entries
        .reduce((a, b) => a.value > b.value ? a : b)
        .key;
  }
  
  // 最常翻译的词汇
  List<String> get topWords {
    final wordCount = <String, int>{};
    for (var record in records) {
      wordCount[record.sourceText] = (wordCount[record.sourceText] ?? 0) + 1;
    }
    final sorted = wordCount.entries.toList()
      ..sort((a, b) => b.value.compareTo(a.value));
    return sorted.take(10).map((e) => e.key).toList();
  }
  
  Widget buildStatisticsCard() {
    return Card(
      child: Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('翻译统计', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            _buildStatItem('总翻译次数', '$totalTranslations 次'),
            _buildStatItem('今日翻译', '$todayTranslations 次'),
            _buildStatItem('常用方向', mostUsedDirection),
          ],
        ),
      ),
    );
  }
}

7. 多语言支持

扩展支持更多语言:

dart 复制代码
enum Language {
  chinese('中文', 'zh'),
  english('英文', 'en'),
  japanese('日文', 'ja'),
  korean('韩文', 'ko'),
  french('法文', 'fr'),
  german('德文', 'de'),
  spanish('西班牙文', 'es');
  
  final String label;
  final String code;
  const Language(this.label, this.code);
}

class MultiLanguageTranslator extends StatefulWidget {
  @override
  State<MultiLanguageTranslator> createState() => _MultiLanguageTranslatorState();
}

class _MultiLanguageTranslatorState extends State<MultiLanguageTranslator> {
  Language _sourceLanguage = Language.chinese;
  Language _targetLanguage = Language.english;
  
  Widget _buildLanguageSelector() {
    return Row(
      children: [
        Expanded(
          child: DropdownButton<Language>(
            value: _sourceLanguage,
            isExpanded: true,
            items: Language.values.map((lang) {
              return DropdownMenuItem(
                value: lang,
                child: Text(lang.label),
              );
            }).toList(),
            onChanged: (value) {
              setState(() {
                _sourceLanguage = value!;
              });
            },
          ),
        ),
        IconButton(
          icon: Icon(Icons.swap_horiz),
          onPressed: () {
            setState(() {
              final temp = _sourceLanguage;
              _sourceLanguage = _targetLanguage;
              _targetLanguage = temp;
            });
          },
        ),
        Expanded(
          child: DropdownButton<Language>(
            value: _targetLanguage,
            isExpanded: true,
            items: Language.values.map((lang) {
              return DropdownMenuItem(
                value: lang,
                child: Text(lang.label),
              );
            }).toList(),
            onChanged: (value) {
              setState(() {
                _targetLanguage = value!;
              });
            },
          ),
        ),
      ],
    );
  }
}

8. 单词本功能

创建个人单词本:

dart 复制代码
class Vocabulary {
  final String word;
  final String translation;
  final String pronunciation;
  final String example;
  final DateTime addedDate;
  int reviewCount;
  DateTime? lastReviewDate;
  
  Vocabulary({
    required this.word,
    required this.translation,
    required this.pronunciation,
    required this.example,
    required this.addedDate,
    this.reviewCount = 0,
    this.lastReviewDate,
  });
}

class VocabularyBook extends StatefulWidget {
  @override
  State<VocabularyBook> createState() => _VocabularyBookState();
}

class _VocabularyBookState extends State<VocabularyBook> {
  List<Vocabulary> _vocabularies = [];
  
  void _addToVocabulary(String word, String translation) {
    setState(() {
      _vocabularies.add(Vocabulary(
        word: word,
        translation: translation,
        pronunciation: '',
        example: '',
        addedDate: DateTime.now(),
      ));
    });
    _saveVocabularies();
  }
  
  Widget _buildVocabularyCard(Vocabulary vocab) {
    return Card(
      child: ListTile(
        title: Text(vocab.word),
        subtitle: Text(vocab.translation),
        trailing: Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text('复习${vocab.reviewCount}次'),
            IconButton(
              icon: Icon(Icons.check),
              onPressed: () => _markAsReviewed(vocab),
            ),
          ],
        ),
      ),
    );
  }
  
  void _markAsReviewed(Vocabulary vocab) {
    setState(() {
      vocab.reviewCount++;
      vocab.lastReviewDate = DateTime.now();
    });
    _saveVocabularies();
  }
}

9. 翻译分享功能

分享翻译结果:

dart 复制代码
import 'package:share_plus/share_plus.dart';

class TranslationShareService {
  Future<void> shareTranslation(TranslationRecord record) async {
    final text = '''
【翻译】
原文:${record.sourceText}
译文:${record.translatedText}
${record.sourceLanguage} → ${record.targetLanguage}

来自中英互译助手
    ''';
    
    await Share.share(text);
  }
  
  Future<void> shareAsImage(TranslationRecord record) async {
    // 生成翻译卡片图片
    final image = await _generateTranslationCard(record);
    await Share.shareXFiles([XFile(image.path)]);
  }
}

// 添加分享按钮
IconButton(
  icon: Icon(Icons.share),
  onPressed: () async {
    await TranslationShareService().shareTranslation(record);
  },
  tooltip: '分享',
)

10. 翻译质量评分

评估翻译质量:

dart 复制代码
class TranslationQuality {
  // 简单的质量评分算法
  static double calculateScore(String source, String translation) {
    double score = 100.0;
    
    // 长度检查
    if (translation.isEmpty) return 0;
    
    // 长度比例检查
    final lengthRatio = translation.length / source.length;
    if (lengthRatio < 0.5 || lengthRatio > 2.0) {
      score -= 20;
    }
    
    // 特殊字符检查
    if (translation.contains('?') || translation.contains('Unknown')) {
      score -= 30;
    }
    
    return score.clamp(0, 100);
  }
  
  static String getQualityLabel(double score) {
    if (score >= 80) return '优秀';
    if (score >= 60) return '良好';
    if (score >= 40) return '一般';
    return '较差';
  }
  
  Widget buildQualityIndicator(double score) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 12, vertical: 6),
      decoration: BoxDecoration(
        color: _getQualityColor(score).withValues(alpha: 0.2),
        borderRadius: BorderRadius.circular(16),
      ),
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(
            _getQualityIcon(score),
            size: 16,
            color: _getQualityColor(score),
          ),
          SizedBox(width: 4),
          Text(
            getQualityLabel(score),
            style: TextStyle(
              fontSize: 12,
              color: _getQualityColor(score),
            ),
          ),
        ],
      ),
    );
  }
  
  Color _getQualityColor(double score) {
    if (score >= 80) return Colors.green;
    if (score >= 60) return Colors.blue;
    if (score >= 40) return Colors.orange;
    return Colors.red;
  }
  
  IconData _getQualityIcon(double score) {
    if (score >= 80) return Icons.check_circle;
    if (score >= 60) return Icons.thumb_up;
    if (score >= 40) return Icons.warning;
    return Icons.error;
  }
}

性能优化建议

1. 翻译缓存

缓存翻译结果避免重复翻译:

dart 复制代码
class TranslationCache {
  static final Map<String, String> _cache = {};
  
  static String? get(String text, String direction) {
    final key = '$text|$direction';
    return _cache[key];
  }
  
  static void set(String text, String direction, String translation) {
    final key = '$text|$direction';
    _cache[key] = translation;
    
    // 限制缓存大小
    if (_cache.length > 1000) {
      _cache.remove(_cache.keys.first);
    }
  }
  
  static void clear() {
    _cache.clear();
  }
}

// 使用缓存
Future<String> _translateWithCache(String text) async {
  final direction = _isChineseToEnglish ? 'zh-en' : 'en-zh';
  
  // 检查缓存
  final cached = TranslationCache.get(text, direction);
  if (cached != null) {
    return cached;
  }
  
  // 执行翻译
  final result = await _translate(text);
  
  // 保存到缓存
  TranslationCache.set(text, direction, result);
  
  return result;
}

2. 防抖处理

避免频繁触发翻译:

dart 复制代码
import 'dart:async';

class Debouncer {
  final Duration delay;
  Timer? _timer;
  
  Debouncer({this.delay = const Duration(milliseconds: 500)});
  
  void run(VoidCallback action) {
    _timer?.cancel();
    _timer = Timer(delay, action);
  }
  
  void dispose() {
    _timer?.cancel();
  }
}

// 使用防抖
final _debouncer = Debouncer();

TextField(
  onChanged: (value) {
    _debouncer.run(() {
      _translate();
    });
  },
)

3. 历史记录分页

分页加载历史记录:

dart 复制代码
class PaginatedHistory extends StatefulWidget {
  @override
  State<PaginatedHistory> createState() => _PaginatedHistoryState();
}

class _PaginatedHistoryState extends State<PaginatedHistory> {
  final ScrollController _scrollController = ScrollController();
  List<TranslationRecord> _displayedRecords = [];
  int _currentPage = 0;
  final int _pageSize = 20;
  bool _isLoading = false;
  
  @override
  void initState() {
    super.initState();
    _loadMore();
    _scrollController.addListener(_onScroll);
  }
  
  void _onScroll() {
    if (_scrollController.position.pixels >= 
        _scrollController.position.maxScrollExtent * 0.8) {
      _loadMore();
    }
  }
  
  Future<void> _loadMore() async {
    if (_isLoading) return;
    
    setState(() {
      _isLoading = true;
    });
    
    final start = _currentPage * _pageSize;
    final end = min(start + _pageSize, allRecords.length);
    
    setState(() {
      _displayedRecords.addAll(allRecords.sublist(start, end));
      _currentPage++;
      _isLoading = false;
    });
  }
}

测试建议

1. 单元测试

测试翻译逻辑:

dart 复制代码
import 'package:flutter_test/flutter_test.dart';

void main() {
  group('Translation Tests', () {
    test('Chinese to English translation', () {
      final translator = Translator();
      final result = translator.translate('你好', 'zh', 'en');
      expect(result, 'Hello');
    });
    
    test('Translation cache', () {
      TranslationCache.set('你好', 'zh-en', 'Hello');
      final cached = TranslationCache.get('你好', 'zh-en');
      expect(cached, 'Hello');
    });
  });
}

2. Widget测试

测试UI组件:

dart 复制代码
void main() {
  testWidgets('Translation button works', (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(home: TranslatePage()));
    
    // 输入文本
    await tester.enterText(find.byType(TextField), '你好');
    
    // 点击翻译按钮
    await tester.tap(find.text('翻译'));
    await tester.pumpAndSettle();
    
    // 验证结果
    expect(find.text('Hello'), findsOneWidget);
  });
}

部署发布

1. Android打包

bash 复制代码
flutter build apk --release
flutter build appbundle --release

2. iOS打包

bash 复制代码
flutter build ipa --release

3. 应用图标

yaml 复制代码
dev_dependencies:
  flutter_launcher_icons: ^0.13.1

flutter_launcher_icons:
  android: true
  ios: true
  image_path: "assets/icon/app_icon.png"

项目总结

技术亮点

  1. 双向翻译:支持中英文互译
  2. 本地词典:无需网络即可翻译
  3. 历史管理:自动保存翻译记录
  4. 常用短语:分类短语库
  5. 收藏功能:快速访问常用翻译
  6. 精美UI:卡片式设计、清晰布局
  7. 数据持久化:SharedPreferences保存数据

学习收获

通过本项目,你将掌握:

  • Flutter文本处理
  • 数据模型设计
  • SharedPreferences使用
  • 列表展示和管理
  • 时间格式化
  • 剪贴板操作
  • 状态管理
  • UI组件设计

应用场景

本应用适用于:

  • 日常翻译需求
  • 语言学习辅助
  • 旅游出行翻译
  • 商务沟通

后续优化方向

  1. 接入在线翻译API
  2. 添加语音朗读功能
  3. 实现语音输入
  4. 支持拍照翻译
  5. 完善离线词典
  6. 添加翻译统计
  7. 支持多语言
  8. 创建单词本
  9. 实现分享功能
  10. 翻译质量评分

这个中英互译助手应用展示了Flutter在工具类应用开发中的实用性。通过简洁的界面和完善的功能,为用户提供了便捷的翻译体验。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

相关推荐
No Silver Bullet3 小时前
HarmonyOS NEXT开发进阶(二十一):compatibleSdkVersion 和 targetSdkVersion配置项详解
华为·harmonyos
一个小废渣4 小时前
Flutter Web端网络请求跨域错误解决方法
前端·flutter
鸣弦artha4 小时前
Flutter框架跨平台鸿蒙开发——Extension扩展方法
android·javascript·flutter
小白阿龙4 小时前
鸿蒙+flutter 跨平台开发——图像编解码与水印嵌入技术实战
flutter·华为·harmonyos·鸿蒙
哈哈你是真的厉害4 小时前
基础入门 React Native 鸿蒙跨平台开发:ActionSheet 动作面板
react native·react.js·harmonyos
夜雨声烦丿4 小时前
Flutter 框架跨平台鸿蒙开发 - 成语词典 - 完整开发教程
flutter·华为·harmonyos
奔跑的露西ly5 小时前
【HarmonyOS NEXT】踩坑记录:00306046 Specification Limit Violation
华为·harmonyos
[H*]5 小时前
Flutter框架跨平台鸿蒙开发——MethodChannel方法通道
flutter
kirk_wang5 小时前
Flutter艺术探索-Flutter网络请求基础:http包使用指南
flutter·移动开发·flutter教程·移动开发教程