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 _baseUrl() async { final url = await _settings.getServerUrl(); if (url == null || url.isEmpty) { throw TranslateException('Sunucu adresi ayarlanmamış. Ayarlar\'dan ekleyin.'); } return url; } Map _withApiKey(Map 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> 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 data = jsonDecode(utf8.decode(res.bodyBytes)); return data.map((e) => Language.fromJson(e as Map)).toList(); } Future 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 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 data = jsonDecode(utf8.decode(res.bodyBytes)); if (data.isEmpty) return null; final best = data.first as Map; return DetectResult( language: best['language'] as String, confidence: ((best['confidence'] ?? 0) as num).round(), ); } }