import 'dart:convert'; import 'package:http/http.dart' as http; /// Erreur remontée par l'API de traduction IA, en conservant le message du backend /// (ex. "Quota IA mensuel dépassé") pour pouvoir l'afficher tel quel à l'utilisateur. class AiTranslateException implements Exception { final String message; final int statusCode; AiTranslateException(this.message, this.statusCode); /// true si l'échec est dû à un quota atteint (mensuel ou période d'essai) bool get isQuotaExceeded => statusCode == 429; @override String toString() => message; } class AiTranslateService { static Future> translate({ required String host, required String accessToken, required String instanceId, required String text, required String sourceLang, required List targetLangs, }) async { final uri = Uri.parse('$host/api/Ai/translate?instanceId=$instanceId'); final response = await http.post( uri, headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer $accessToken', }, body: jsonEncode({ 'text': text, 'sourceLang': sourceLang, 'targetLangs': targetLangs, }), ); if (response.statusCode != 200) { throw AiTranslateException(_extractMessage(response), response.statusCode); } final data = jsonDecode(utf8.decode(response.bodyBytes)); final translations = data['translations'] as Map; return translations.map((k, v) => MapEntry(k, v.toString())); } /// Le backend renvoie ses messages d'erreur en texte via StatusCode(429, "..."), /// ce qui donne une chaîne JSON. On décode en UTF-8 explicitement : le package http /// retombe sur latin1 quand le charset n'est pas précisé, ce qui casse les accents. static String _extractMessage(http.Response response) { final body = utf8.decode(response.bodyBytes, allowMalformed: true).trim(); if (body.isNotEmpty) { try { final decoded = jsonDecode(body); if (decoded is String && decoded.trim().isNotEmpty) return decoded.trim(); if (decoded is Map && decoded['title'] is String) return decoded['title'] as String; } catch (_) { return body; } } if (response.statusCode == 403) { return "L'assistant IA n'est pas activé pour cette instance"; } return 'Erreur lors de la traduction IA (${response.statusCode})'; } }