From cb7f045b0b31d6c725868d1c1386ec7bcaa877a1 Mon Sep 17 00:00:00 2001 From: Thomas Fransolet Date: Thu, 13 Aug 2026 16:29:36 +0200 Subject: [PATCH] =?UTF-8?q?J4=20=E2=80=94=20mention=20d'information=20aux?= =?UTF-8?q?=20visiteurs=20dans=20l'assistant?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit §8.3 des CGU : la mention doit être accessible depuis l'assistant lui-même, là où la collecte a lieu. Panneau dépliable dans l'en-tête, borné en hauteur et défilant pour ne pas chasser le fil de conversation hors de l'écran. Texte repris mot pour mot de DOCS/mention-information-visiteurs.md, comme la version Dart de mymuseum-visitapp : les trois doivent rester alignés, et une correction se fait dans le document d'abord. FR/NL/EN avec repli sur l'anglais, alors que le reste de cette interface parle six langues : traduire une mention de protection des données sans relecture humaine serait pire que la servir en anglais. npm run build vert. Co-Authored-By: Claude Opus 5 --- src/components/assistant/AssistantBubble.tsx | 83 ++++++++++++++++++++ src/components/assistant/assistant.css | 24 ++++++ 2 files changed, 107 insertions(+) diff --git a/src/components/assistant/AssistantBubble.tsx b/src/components/assistant/AssistantBubble.tsx index f082719..5cf2851 100644 --- a/src/components/assistant/AssistantBubble.tsx +++ b/src/components/assistant/AssistantBubble.tsx @@ -53,10 +53,65 @@ const UI: Record> = { ES: 'La guía descansa por hoy. Vuelva mañana.', IT: 'La guida riposa per oggi. Torna domani.', }, + privacy: { + FR: 'Vos questions au guide', + NL: 'Uw vragen aan de gids', + EN: 'Your questions to the guide', + DE: 'Ihre Fragen an den Guide', + ES: 'Sus preguntas a la guía', + IT: 'Le tue domande alla guida', + }, } const label = (key: keyof typeof UI, lang: string) => UI[key][lang] ?? UI[key].FR +/// Mention d'information aux visiteurs (§8.3 des CGU) — miroir de +/// `mymuseum-visitapp/lib/Components/VisitorPrivacyNotice.dart`, lui-même repris mot pour +/// mot de `DOCS/mention-information-visiteurs.md`. **Les trois doivent rester alignés.** +/// +/// ⚠️ **Trois langues, repli sur l'anglais — c'est un choix, pas un oubli.** Le reste de +/// cette interface parle six langues, mais traduire une mention de protection des données +/// sans relecture humaine serait pire que la servir en anglais : une nuance perdue sur +/// « nous n'enregistrons pas votre adresse IP » n'est pas une coquille d'interface. Les +/// autres langues attendent une traduction relue, à demander avec la relecture juridique. +const PRIVACY_NOTICE: Record = { + FR: + "Lorsque vous posez une question à notre guide, votre question et la réponse qui vous est " + + "donnée sont enregistrées. Cela nous sert à repérer ce que nos visiteurs cherchent sans le " + + "trouver, et à compléter nos contenus en conséquence.\n\n" + + "Nous n'enregistrons ni votre nom, ni votre compte, ni votre adresse IP. Un identifiant de " + + "session tiré au hasard permet seulement de relier entre elles les questions d'une même " + + "conversation ; il disparaît avec elle.\n\n" + + "Votre question est transmise à notre fournisseur d'intelligence artificielle (Google) pour " + + "produire la réponse. Le texte de vos questions est supprimé au bout de 90 jours ; seuls des " + + "regroupements par sujet, sans le texte de vos questions, sont conservés au-delà.\n\n" + + "Le champ de question est libre : nous vous invitons à ne pas y saisir d'informations " + + "personnelles.", + NL: + "Wanneer u onze gids een vraag stelt, worden uw vraag en het gegeven antwoord opgeslagen. Zo " + + "zien we wat onze bezoekers zoeken zonder het te vinden, en vullen we onze inhoud aan.\n\n" + + "Wij registreren noch uw naam, noch een account, noch uw IP-adres. Een willekeurig " + + "gegenereerde sessie-identificatie dient enkel om de vragen van eenzelfde gesprek aan elkaar " + + "te koppelen; ze verdwijnt samen met dat gesprek.\n\n" + + "Uw vraag wordt doorgestuurd naar onze aanbieder van kunstmatige intelligentie (Google) om " + + "het antwoord op te stellen. De tekst van uw vragen wordt na 90 dagen verwijderd; daarna " + + "blijven enkel groeperingen per onderwerp bewaard, zonder de tekst van uw vragen.\n\n" + + "Het vraagveld is vrij in te vullen: wij raden u aan er geen persoonsgegevens in te typen.", + EN: + "When you ask our guide a question, your question and the answer you are given are recorded. " + + "This helps us see what our visitors look for without finding it, and improve our content " + + "accordingly.\n\n" + + "We record neither your name, nor an account, nor your IP address. A randomly generated " + + "session identifier only links together the questions of a single conversation; it " + + "disappears with it.\n\n" + + "Your question is sent to our artificial intelligence provider (Google) to produce the " + + "answer. The text of your questions is deleted after 90 days; beyond that, only groupings by " + + "topic are kept, without the text of your questions.\n\n" + + "The question field is free text: we invite you not to enter personal information in it.", +} + +const privacyNotice = (lang: string) => PRIVACY_NOTICE[lang] ?? PRIVACY_NOTICE.EN + /// L'API de reconnaissance vocale n'est pas standardisée partout : on ne montre le /// micro que si le navigateur la propose réellement. function getSpeechRecognition(): any { @@ -77,6 +132,7 @@ export default function AssistantBubble({ const [pending, setPending] = useState(false) const [listening, setListening] = useState(false) const [speechReady, setSpeechReady] = useState(false) + const [noticeOpen, setNoticeOpen] = useState(false) const threadRef = useRef(null) const inputRef = useRef(null) @@ -233,6 +289,18 @@ export default function AssistantBubble({ {label('title', language)} {venueName && {venueName}} + {/* §8.3 des CGU : la mention doit être accessible depuis l'assistant lui-même, + c'est-à-dire là où la collecte a lieu. */} +