mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-06-14 22:55:12 +10:00
implement flutter_langdetect
This commit is contained in:
@@ -3,6 +3,7 @@ import 'dart:async';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:llamadart/llamadart.dart';
|
||||
import 'package:flutter_langdetect/flutter_langdetect.dart';
|
||||
|
||||
import '../models/app_settings.dart';
|
||||
import '../models/translation_support.dart';
|
||||
@@ -41,7 +42,10 @@ class TranslationService extends ChangeNotifier {
|
||||
TranslationService(
|
||||
this._appSettingsService, {
|
||||
TranslationFileStore? fileStore,
|
||||
}) : _fileStore = fileStore ?? TranslationFileStore();
|
||||
}) : _fileStore = fileStore ?? TranslationFileStore() {
|
||||
// Initialize langdetect once at service construction.
|
||||
_langDetectInit = initLangDetect();
|
||||
}
|
||||
|
||||
bool _isBusy = false;
|
||||
bool _isDownloading = false;
|
||||
@@ -51,6 +55,7 @@ class TranslationService extends ChangeNotifier {
|
||||
LlamaEngine? _engine;
|
||||
String? _loadedModelPath;
|
||||
String? _failedModelPath;
|
||||
Future<void>? _langDetectInit;
|
||||
int _downloadedBytes = 0;
|
||||
int? _downloadTotalBytes;
|
||||
String? _downloadFileName;
|
||||
@@ -436,7 +441,18 @@ class TranslationService extends ChangeNotifier {
|
||||
}
|
||||
|
||||
Future<String?> detectLanguage(String text) async {
|
||||
return _heuristicLanguageCode(text);
|
||||
try {
|
||||
// Ensure the detector is initialized (constructor starts init).
|
||||
await (_langDetectInit ??= initLangDetect());
|
||||
final code = detect(text);
|
||||
if (code.isEmpty) return null;
|
||||
return code;
|
||||
} catch (error) {
|
||||
_lastError = error.toString();
|
||||
appLogger.warn('Language detection failed: $error');
|
||||
notifyListeners();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> _translateText({
|
||||
@@ -518,72 +534,6 @@ class TranslationService extends ChangeNotifier {
|
||||
trimmed.startsWith('r:'));
|
||||
}
|
||||
|
||||
String? _heuristicLanguageCode(String text) {
|
||||
final trimmed = text.trim();
|
||||
if (trimmed.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (RegExp(r'[ぁ-んァ-ン]').hasMatch(text)) {
|
||||
return 'ja';
|
||||
}
|
||||
if (RegExp(r'[가-힣]').hasMatch(text)) {
|
||||
return 'ko';
|
||||
}
|
||||
if (RegExp(r'[\u4e00-\u9fff]').hasMatch(text)) {
|
||||
return 'zh';
|
||||
}
|
||||
|
||||
final lower = trimmed.toLowerCase();
|
||||
final patterns = <String, String>{
|
||||
'uk': r'\b(привіт|дякую|будь|ласка|як|де|не|так|це|є|най|ще|може|для)\b',
|
||||
'ru':
|
||||
r'\b(что|это|как|не|да|нет|он|она|они|быть|есть|для|сегодня|если|уже|может)\b',
|
||||
'bg': r'\b(ще|няма|благодаря|моля|това|какво|тук|ние|вие|не|със|за)\b',
|
||||
'de':
|
||||
r'\b(der|die|das|und|ist|nicht|ein|eine|ich|für|mit|auf|zu|auch|als|an|im|am|es|dem|den|sich|von)\b',
|
||||
'en':
|
||||
r'\b(the|and|is|you|for|with|from|not|that|this|have|be|are|was|were|but|can|will|your|what|when|how|they)\b',
|
||||
'es':
|
||||
r'\b(el|la|los|las|es|que|de|en|con|por|para|no|un|una|se|como|su|al|del|está)\b',
|
||||
'fr':
|
||||
r'\b(le|la|les|un|une|et|est|que|qui|pour|dans|pas|avec|sur|ne|vous|il|elle|des|ce|cette|je|tu|nous|vous)\b',
|
||||
'it':
|
||||
r'\b(il|la|lo|un|una|che|di|da|in|per|con|non|si|mi|ti|noi|voi|lui|lei)\b',
|
||||
'pt':
|
||||
r'\b(os|as|que|de|do|da|em|para|com|por|não|uma|um|se|você|também)\b',
|
||||
'nl':
|
||||
r'\b(de|het|een|en|is|niet|dat|wat|je|ik|op|aan|voor|met|als|nog|zijn)\b',
|
||||
'sv':
|
||||
r'\b(och|är|det|att|som|en|på|inte|har|var|men|du|jag|vi|ni|den|detta)\b',
|
||||
'pl':
|
||||
r'\b(na|się|nie|jest|to|że|do|od|dla|czy|tak|ale|ma|jak|on|ona|my)\b',
|
||||
'sk': r'\b(je|na|so|že|do|od|za|si|to|ten|tá|tí|ako|má|nie|som|sa)\b',
|
||||
'sl': r'\b(in|je|na|se|da|za|od|ne|to|ta|so|kako|bo|sem|si)\b',
|
||||
'hu':
|
||||
r'\b(az|és|nem|van|volt|hogy|mit|mire|ki|mi|ez|azért|is|de|ha|te|ő|mi|itt)\b',
|
||||
};
|
||||
|
||||
final scores = <String, int>{};
|
||||
for (final entry in patterns.entries) {
|
||||
scores[entry.key] = RegExp(
|
||||
entry.value,
|
||||
caseSensitive: false,
|
||||
).allMatches(lower).length;
|
||||
}
|
||||
|
||||
final sorted = scores.entries.toList()
|
||||
..sort((a, b) => b.value.compareTo(a.value));
|
||||
if (sorted.isEmpty || sorted.first.value == 0) {
|
||||
return null;
|
||||
}
|
||||
if (sorted.length > 1 && sorted.first.value == sorted[1].value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return sorted.first.key;
|
||||
}
|
||||
|
||||
String _languageLabel(String code) {
|
||||
for (final option in supportedTranslationLanguages) {
|
||||
if (option.code == code) {
|
||||
|
||||
@@ -72,6 +72,7 @@ dependencies:
|
||||
ml_algo: ^16.0.0
|
||||
ml_dataframe: ^1.0.0
|
||||
llamadart: '>=0.6.8 <0.7.0'
|
||||
flutter_langdetect: ^0.0.1
|
||||
|
||||
hooks:
|
||||
user_defines:
|
||||
|
||||
Reference in New Issue
Block a user