libretranslatr

This commit is contained in:
y1lm0z
2026-07-14 17:37:17 +03:00
parent 1b8149a4cf
commit 8a562e5bf6
46 changed files with 2040 additions and 106 deletions
+125
View File
@@ -0,0 +1,125 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../models/language.dart';
import 'settings_service.dart';
class TranslateException implements Exception {
final String message;
TranslateException(this.message);
@override
String toString() => message;
}
class DetectResult {
final String language;
final int confidence;
DetectResult({required this.language, required this.confidence});
}
/// Kullanıcının kendi sunucusundaki LibreTranslate API'sine istek atar.
class TranslateService {
final SettingsService _settings;
TranslateService(this._settings);
Future<String> _baseUrl() async {
final url = await _settings.getServerUrl();
if (url == null || url.isEmpty) {
throw TranslateException('Sunucu adresi ayarlanmamış. Ayarlar\'dan ekleyin.');
}
return url;
}
Map<String, dynamic> _withApiKey(Map<String, dynamic> body, String? apiKey) {
if (apiKey != null && apiKey.isNotEmpty) {
body['api_key'] = apiKey;
}
return body;
}
String _errorFromBody(String body, int statusCode) {
try {
final decoded = jsonDecode(body);
if (decoded is Map && decoded['error'] != null) {
return decoded['error'].toString();
}
} catch (_) {
// JSON değilse aşağıda genel mesaj kullanılır.
}
return 'Sunucu hatası (HTTP $statusCode)';
}
/// Sunucuya bağlanıp desteklenen dilleri getirir.
/// Hem "bağlantı testi" hem de dil listesini doldurmak için kullanılır.
Future<List<Language>> fetchLanguages() async {
final base = await _baseUrl();
final apiKey = await _settings.getApiKey();
final uri = Uri.parse('$base/languages').replace(
queryParameters: apiKey != null ? {'api_key': apiKey} : null,
);
final res = await http.get(uri).timeout(const Duration(seconds: 10));
if (res.statusCode != 200) {
throw TranslateException(_errorFromBody(res.body, res.statusCode));
}
final List<dynamic> data = jsonDecode(utf8.decode(res.bodyBytes));
return data.map((e) => Language.fromJson(e as Map<String, dynamic>)).toList();
}
Future<String> translate({
required String text,
required String sourceLang,
required String targetLang,
}) async {
if (text.trim().isEmpty) return '';
final base = await _baseUrl();
final apiKey = await _settings.getApiKey();
final body = _withApiKey({
'q': text,
'source': sourceLang,
'target': targetLang,
'format': 'text',
}, apiKey);
final res = await http
.post(
Uri.parse('$base/translate'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode(body),
)
.timeout(const Duration(seconds: 15));
if (res.statusCode != 200) {
throw TranslateException(_errorFromBody(res.body, res.statusCode));
}
final decoded = jsonDecode(utf8.decode(res.bodyBytes));
return decoded['translatedText'] as String;
}
Future<DetectResult?> detect(String text) async {
if (text.trim().isEmpty) return null;
final base = await _baseUrl();
final apiKey = await _settings.getApiKey();
final body = _withApiKey({'q': text}, apiKey);
final res = await http
.post(
Uri.parse('$base/detect'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode(body),
)
.timeout(const Duration(seconds: 10));
if (res.statusCode != 200) {
throw TranslateException(_errorFromBody(res.body, res.statusCode));
}
final List<dynamic> data = jsonDecode(utf8.decode(res.bodyBytes));
if (data.isEmpty) return null;
final best = data.first as Map<String, dynamic>;
return DetectResult(
language: best['language'] as String,
confidence: ((best['confidence'] ?? 0) as num).round(),
);
}
}