diff --git a/lib/Components/AssistantChatSheet.dart b/lib/Components/AssistantChatSheet.dart index 79d14dd..3da9fcd 100644 --- a/lib/Components/AssistantChatSheet.dart +++ b/lib/Components/AssistantChatSheet.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:mymuseum_visitapp/Components/VisitorPrivacyNotice.dart'; import 'package:mymuseum_visitapp/Helpers/assistantSuggestions.dart'; +import 'package:mymuseum_visitapp/Helpers/voiceLanguage.dart'; import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; import 'package:mymuseum_visitapp/Models/AssistantResponse.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; @@ -152,15 +153,8 @@ class _AssistantChatSheetState extends State { } } - String _toLangCode(String lang) { - switch (lang.toUpperCase()) { - case 'FR': return 'fr-FR'; - case 'NL': return 'nl-NL'; - case 'EN': return 'en-US'; - case 'DE': return 'de-DE'; - default: return 'fr-FR'; - } - } + /// Voir `Helpers/voiceLanguage.dart` : limite assumée à FR/NL/EN/DE, pas un oubli. + String _toLangCode(String lang) => toVoiceLangCode(lang); void _scrollToBottom() { WidgetsBinding.instance.addPostFrameCallback((_) { diff --git a/lib/Helpers/voiceLanguage.dart b/lib/Helpers/voiceLanguage.dart new file mode 100644 index 0000000..d935e4a --- /dev/null +++ b/lib/Helpers/voiceLanguage.dart @@ -0,0 +1,24 @@ +/// Code de langue passé au moteur de synthèse vocale. +/// +/// ⛔ **L'assistant vocal est limité à FR/NL/EN/DE — décidé le 2026-08-13**, cf. +/// `DOCS/voice-latency-plan.md` §1.6. Les six autres langues déclarées dans +/// `constants.dart` retombent sur `fr-FR` : un visiteur italien se fait répondre en +/// français, sans erreur ni trace. En ajouter une coûte peu — les traductions `voice.*` +/// existent déjà pour les 10 langues, Whisper est multilingue et le wake word est +/// phonétique — mais il faut aussi compléter les quatre listes de commandes de +/// `VoiceOrchestrator`, sinon la langue n'est supportée qu'à moitié. +/// +/// ⚠️ **Ce fichier existe parce que la fonction était copiée trois fois** : dans +/// `VoiceOrchestrator`, dans `AssistantChatSheet` et dans `GeoBeaconTriggerService` — et +/// la décision ci-dessus n'était écrite que dans la première. Les deux autres ressemblaient +/// à un oubli qu'on aurait envie de « corriger » en ajoutant des langues, ce qui aurait +/// produit un support partiel silencieux. Une seule copie, une seule décision. +String toVoiceLangCode(String? language) { + switch ((language ?? 'FR').toUpperCase()) { + case 'FR': return 'fr-FR'; + case 'NL': return 'nl-NL'; + case 'EN': return 'en-US'; + case 'DE': return 'de-DE'; + default: return 'fr-FR'; + } +} diff --git a/lib/Services/Glasses/voice_orchestrator.dart b/lib/Services/Glasses/voice_orchestrator.dart index a970b34..c4a5dab 100644 --- a/lib/Services/Glasses/voice_orchestrator.dart +++ b/lib/Services/Glasses/voice_orchestrator.dart @@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart'; import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; import 'package:just_audio/just_audio.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; +import 'package:mymuseum_visitapp/Helpers/voiceLanguage.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:mymuseum_visitapp/Services/Glasses/engines/llm_client.dart'; import 'package:mymuseum_visitapp/Services/Glasses/engines/stt_engine.dart'; @@ -459,19 +460,8 @@ class VoiceOrchestrator { bool _isRepeatCommand(String text) => _matchesAny(text, _repeatPhrases); - /// ⛔ L'assistant vocal est limité à FR/NL/EN/DE — décidé le 2026-08-13, cf. - /// `DOCS/voice-latency-plan.md` §1.6. Les six autres langues déclarées dans - /// `constants.dart` retombent ici sur `fr-FR` : un visiteur italien se fait répondre - /// en français, sans erreur ni trace. En ajouter une coûte peu — les traductions - /// `voice.*` existent déjà pour les 10 langues — mais il faut aussi compléter les - /// quatre listes de commandes ci-dessous, sinon la langue est à moitié supportée. - String _toLangCode(String lang) { - switch (lang.toUpperCase()) { - case 'FR': return 'fr-FR'; - case 'NL': return 'nl-NL'; - case 'EN': return 'en-US'; - case 'DE': return 'de-DE'; - default: return 'fr-FR'; - } - } + /// Déléguée à `toVoiceLangCode` — la fonction était copiée ici, dans `AssistantChatSheet` + /// et dans `GeoBeaconTriggerService`, et la décision « FR/NL/EN/DE seulement » n'était + /// écrite que dans cette copie-ci. Voir `Helpers/voiceLanguage.dart`. + String _toLangCode(String lang) => toVoiceLangCode(lang); } diff --git a/lib/Services/geo_beacon_trigger_service.dart b/lib/Services/geo_beacon_trigger_service.dart index c1d5dd4..9ff1763 100644 --- a/lib/Services/geo_beacon_trigger_service.dart +++ b/lib/Services/geo_beacon_trigger_service.dart @@ -4,6 +4,7 @@ import 'package:beacon_scanner/beacon_scanner.dart'; import 'package:manager_api_new/api.dart'; import 'package:flutter/foundation.dart'; import 'package:geolocator/geolocator.dart'; +import 'package:mymuseum_visitapp/Helpers/voiceLanguage.dart'; import 'package:mymuseum_visitapp/Models/beaconSection.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:mymuseum_visitapp/Services/assistantService.dart'; @@ -292,15 +293,11 @@ class GeoBeaconTriggerService { } } - String _toLangCode(String lang) { - switch (lang.toUpperCase()) { - case 'FR': return 'fr-FR'; - case 'NL': return 'nl-NL'; - case 'EN': return 'en-US'; - case 'DE': return 'de-DE'; - default: return 'fr-FR'; - } - } + /// Voir `Helpers/voiceLanguage.dart` : le vocal ne couvre que FR/NL/EN/DE, et un + /// visiteur italien se fait donc accueillir en français à l'approche d'une œuvre. + /// C'est une limite assumée, pas un oubli — elle était invisible ici tant que la + /// fonction était recopiée. + String _toLangCode(String lang) => toVoiceLangCode(lang); void dispose() { stop();