// i18n.jsx — la langue et le vocabulaire du domaine. // // Deux choses distinctes, et les confondre est ce qui rendait l'interface // « subventions » : // // 1. **La LANGUE** (fr/en) : du chrome d'interface. Il vit ici, en code, parce // que c'est notre produit qui parle — pas le domaine du client. // 2. **Le VOCABULAIRE du domaine** (« demande de subvention » / « grant // application » / « déclaration ») : c'est une DONNÉE, elle vient de // `FormDomain.lexicon` (migration 011). Un revendeur qui vend le moteur // pour des formulaires fiscaux change une ligne de base, pas du React. // // Conséquence pratique : on n'écrit jamais « subvention » dans un écran. On // écrit `t("Vos {demandes}")`, et le mot arrive du domaine actif. // // Le dictionnaire est indexé par la CHAÎNE FRANÇAISE elle-même (façon gettext). // C'est délibéré : pas de clés à inventer, et une traduction manquante affiche // le français — visible et corrigeable — au lieu d'un trou. const I18N = (() => { const KEY = "grant4me.lang"; // Repli si le domaine n'expose pas encore de lexique : des mots génériques // qui ne mentent sur aucun métier. const LEXIQUE_DEFAUT = { fr: { demande: "demande", demandes: "demandes", demandeM: "la demande", programme: "programme", organisme: "organisme", formulaire: "formulaire", formulaires: "formulaires", programmes: "programmes", piece: "pièce jointe", pieces: "pièces jointes" }, en: { demande: "request", demandes: "requests", demandeM: "the request", programme: "program", organisme: "organization", formulaire: "form", formulaires: "forms", programmes: "programs", piece: "attachment", pieces: "attachments" }, }; const EN = { // — Chrome, navigation, actions — "Texte normal": "Normal text", "Texte plus grand": "Larger text", "Texte très grand": "Largest text", "Aide": "Help", "Retour": "Back", "Continuer": "Continue", "Terminer": "Finish", "Enregistrer et continuer": "Save and continue", "Enregistrement…": "Saving…", "Envoi…": "Sending…", "Fermer": "Close", "Annuler": "Cancel", "Français": "French", "Anglais": "English", "Langue": "Language", // — Tableau de bord — "Vos {demandes}": "Your {demandes}", "Reprenez là où vous étiez, ou lancez une nouvelle {demande}.": "Pick up where you left off, or start a new {demande}.", "Nouvelle {demande}": "New {demande}", "Commencer une nouvelle {demande}": "Start a new {demande}", "Téléversez un {formulaire}. On s'occupe du reste.": "Upload the {formulaire}. We'll handle the rest.", "Reprendre": "Resume", "Mis à jour": "Updated", "complété": "complete", "Aucune {demande} pour l'instant": "No {demandes} yet", "Votre première {demande} commence par le {formulaire} à remplir. Téléversez-le : on lit les champs, on remplit ce qu'on peut, et on ne vous demande que le reste.": "Your first {demande} starts with the {formulaire} you need to fill. Upload it: we read the fields, fill what we can, and ask you only for the rest.", "{demande} sans titre": "Untitled {demande}", "données réelles": "live data", "mode démonstration": "demo mode", // — Statuts — "brouillon": "draft", "en cours": "in progress", "à confirmer": "needs review", "Soumis": "Submitted", "Échec": "Failed", "Prêt": "Ready", // — Étapes de l'assistant — "VOTRE {demande}": "YOUR {demande}", "Votre entreprise": "Your company", "Confirmez votre profil": "Confirm your profile", "Votre projet": "Your project", "Décrivez votre projet": "Describe your project", "Le {formulaire}": "The {formulaire}", "Téléversez le document à remplir": "Upload the document to fill", "Remplissage auto": "Auto-fill", "L'assistant remplit le {formulaire}": "The assistant fills the {formulaire}", "À confirmer": "To confirm", "Validez quelques champs": "Confirm a few fields", "Prêt à soumettre": "Ready to submit", "Téléchargez et déposez": "Download and submit", "Étape {n} sur 6": "Step {n} of 6", // — Étape 1 : profil — "Votre profil d'entreprise": "Your company profile", "Ces informations serviront à remplir ": "This information will fill ", "tous vos {formulaires}": "all your {formulaires}", " : ce que vous saisissez ici, on ne vous le redemandera plus. ": ": what you enter here, we won't ask again. ", "On a pré-rempli ce qu'on a trouvé au Registraire des entreprises. Vérifiez, complétez ce qui manque. ": "We pre-filled what we found at the enterprise registrar. Check it, complete what's missing. ", "Vous ne savez pas où trouver une information ?": "Not sure where to find something?", "Cliquez le « ? » à côté du champ.": "Click the “?” next to the field.", "Ce profil ne se remplit ": "This profile is filled ", "qu'une fois": "only once", ". Il sert à toutes vos {demandes} : plus vous le complétez, mieux on cible les bons {programmes} et plus le remplissage est précis.": ". It serves all your {demandes}: the more complete it is, the better we match {programmes} and the more accurate the filling.", "IDENTITÉ DE L'ENTREPRISE": "COMPANY IDENTITY", "Raison sociale": "Legal name", "NEQ (Québec)": "Business number (Québec)", "Statut juridique": "Legal form", "Numéro d'entreprise fédéral (NE / ARC)": "Federal business number (BN / CRA)", "Année de constitution": "Year of incorporation", "Nombre d'employés": "Number of employees", "Secteur d'activité": "Industry", "Revenus bruts annuels": "Annual gross revenue", "Revenus nets annuels": "Annual net revenue", "Bénéfice": "Profit", "Tel qu'enregistré à votre dossier. Corrigez-le au besoin.": "As recorded in your file. Correct it if needed.", "Vérifié au Registre des entreprises": "Verified at the enterprise registry", "CODES D'ACTIVITÉ": "ACTIVITY CODES", "ADRESSES": "ADDRESSES", "PERSONNES-RESSOURCES": "CONTACTS", "BESOINS DE FINANCEMENT": "FINANCING NEEDS", "Ajouter un code": "Add a code", "Ajouter une adresse": "Add an address", "Adresse du siège": "Head office address", "Adresse supplémentaire": "Additional address", "Principal": "Primary", "Supprimer": "Remove", "On vous accompagne": "We're with you", "Bloqué sur une information ? Chaque champ a un « ? » qui vous dit ": "Stuck on something? Every field has a “?” that tells you ", "où aller la chercher": "where to find it", ", en mots simples.": ", in plain language.", "Rechercher un code d'activité": "Search an activity code", "Tapez un mot : « ébénisterie », « restaurant », « logiciel »": "Type a word: “cabinetmaking”, “restaurant”, “software”", // — Étape 2 : fiche projet — "Parlez-nous de votre projet": "Tell us about your project", "Répondez à quelques questions simples. L'assistant en fera une fiche de référence qui servira à remplir tous vos {formulaires}.": "Answer a few simple questions. The assistant turns them into a reference sheet used to fill all your {formulaires}.", "Pourquoi cette étape ?": "Why this step?", " Plutôt que de vous faire affronter un {formulaire} de 14 pages, on part de vos réponses en langage courant. Pas de jargon, pas de bonne ou mauvaise réponse.": " Instead of throwing a 14-page {formulaire} at you, we start from your answers in plain language. No jargon, no right or wrong answer.", "Générer ma fiche projet": "Generate my project sheet", "Votre fiche projet": "Your project sheet", "Relisez et ajustez. C'est ce texte que l'assistant utilisera pour remplir vos {formulaires}.": "Read it over and adjust. This is the text the assistant will use to fill your {formulaires}.", "Approuver cette fiche": "Approve this sheet", "Modifier": "Edit", "Enregistré": "Saved", "L'assistant rédige votre fiche…": "The assistant is writing your sheet…", "Documents utiles (facultatif)": "Useful documents (optional)", // — Étape 3 : téléversement — "Téléversez le {formulaire} à remplir": "Upload the {formulaire} to fill", "Glissez votre fichier ici": "Drop your file here", "ou cliquez pour le choisir": "or click to choose it", "Choisir un fichier": "Choose a file", "Seuls les PDF à champs remplissables fonctionnent": "Only PDFs with fillable fields work", " Un PDF scanné ou une image ne peut pas encore être rempli automatiquement : l'assistant a besoin de champs de saisie déjà présents dans le document.": " A scanned PDF or an image cannot be auto-filled yet: the assistant needs input fields already present in the document.", "Lancer le remplissage": "Start filling", "On ouvre": "Opening", // — Étape 4 : remplissage — "L'assistant remplit votre {formulaire}": "The assistant is filling your {formulaire}", "champs détectés": "fields detected", "remplis automatiquement": "filled automatically", "à confirmer": "to confirm", "Lecture du document…": "Reading the document…", "Analyse des champs…": "Analyzing fields…", "Remplissage…": "Filling…", "Terminé": "Done", "Confirmer les {n} derniers champs": "Confirm the last {n} fields", "Voir le résultat": "See the result", // — Étape 5 : confirmation / révision — "Confirmez les derniers détails": "Confirm the last details", "Relisez avant de générer": "Read it over before generating", "L'assistant a ": "The assistant has ", "déjà proposé une réponse": "already proposed an answer", " pour chacun de ces {n} champs, à partir de votre fiche projet et de vos documents. Vérifiez simplement que c'est juste et corrigez au besoin.": " for each of these {n} fields, from your project sheet and your documents. Just check it's right and correct as needed.", "Le moteur a rempli ": "The engine filled ", "{n} champs": "{n} fields", " sans avoir besoin de vous poser de question. Relisez-les : ce {formulaire} sera déposé en votre nom, et c'est ": " without needing to ask you anything. Read them over: this {formulaire} will be submitted in your name, and ", "votre confirmation qui l'engage": "your confirmation is what commits you", ". Corrigez ce que vous voulez.": ". Correct whatever you want.", "confirmé": "confirmed", "confirmés": "confirmed", "Proposé par l'assistant": "Proposed by the assistant", "Repris de votre profil d'entreprise.": "Taken from your company profile.", "Réponse que vous aviez déjà validée sur un autre {formulaire}.": "An answer you already confirmed on another {formulaire}.", "Déjà validé par vous.": "Already confirmed by you.", "Rédigé par l'IA à partir de votre dossier. À relire.": "Written by the AI from your file. Please review.", "À vérifier avant l'envoi de votre {demande}.": "To check before sending your {demande}.", "Cette information ne figure ni dans votre profil ni dans votre dossier.": "This information is in neither your profile nor your file.", "L'assistant a une proposition, mais préfère votre confirmation.": "The assistant has a suggestion, but would rather you confirm.", "Cette réponse demande votre jugement et vous engage.": "This answer needs your judgment and commits you.", "Terminer ma {demande}": "Finish my {demande}", "Confirmez les {n} champs restants": "Confirm the {n} remaining fields", "OK": "OK", "Envoi impossible :": "Could not send:", // — Étape 6 : résultat — "Votre {demande} est prête à déposer": "Your {demande} is ready to submit", "{formulaire} rempli": "{formulaire} filled", "Télécharger le PDF": "Download the PDF", "{pieces} à joindre": "{pieces} to attach", "Obligatoire": "Required", "Facultatif": "Optional", "Rempli automatiquement": "Filled automatically", "Validé par vous": "Confirmed by you", "Ce que vous devez faire maintenant": "What you need to do now", "Téléchargez le PDF, joignez les {pieces} ci-dessus, et déposez le tout auprès de l'{organisme}.": "Download the PDF, attach the {pieces} above, and submit everything to the {organisme}.", // — Connexion — "Vos {demandes}, remplies pour vous.": "Your {demandes}, filled for you.", "Grant4me lit le {formulaire} officiel, retrouve vos informations et le remplit. Vous n'avez qu'à confirmer le reste.": "Grant4me reads the official {formulaire}, finds your information and fills it in. You only confirm the rest.", "On repère chaque champ du {formulaire}, même les PDF complexes.": "We locate every field of the {formulaire}, even in complex PDFs.", "On remplit automatiquement à partir de votre profil et vos documents.": "We fill automatically from your profile and your documents.", "Vos données restent au Québec. Conforme à la Loi 25.": "Your data stays in Québec. Compliant with Law 25.", "Un service pensé pour les PME": "A service built for SMBs", "Connexion sécurisée": "Secure sign-in", "Bienvenue": "Welcome", "Connectez-vous pour reprendre vos {demandes} ou en commencer une nouvelle.": "Sign in to resume your {demandes} or start a new one.", "Courriel": "Email", "Connexion…": "Signing in…", "Se connecter": "Sign in", "Compte inconnu ou backend injoignable :": "Unknown account or backend unreachable:", "Authentification gérée par votre identifiant unique (OIDC)": "Authentication handled by your single sign-on (OIDC)", "Hébergement et traitement au Québec": "Hosted and processed in Québec", "Taille du texte": "Text size", "Texte": "Text", "Étapes de votre {demande}": "Steps of your {demande}", // — Pastilles de statut — "Rempli pour vous": "Filled for you", "Fourni": "Provided", "À fournir": "To provide", "À compléter": "To complete", "Brouillon": "Draft", "Officielle": "Official", // — Profil : sections et gestes — "Identité de l'entreprise": "Company identity", "Adresses": "Addresses", "Codes d'activité": "Activity codes", "Personnes-ressources": "Contacts", "Adresse officielle de l'entreprise": "Company's official address", "Ajouter une adresse (atelier, lieu de réalisation…)": "Add an address (workshop, project site…)", "Seule l'adresse officielle est enregistrée à votre dossier pour l'instant.": "Only the official address is saved to your file for now.", "Une entreprise peut en avoir plusieurs. Tapez votre activité dans le libellé : on cherche dans le référentiel officiel et le code se remplit seul. Indiquez le principal.": "A company can have several. Type your activity in the label: we search the official reference list and the code fills itself. Mark the main one.", "Ajouter un code d'activité": "Add an activity code", "Rechercher une activité (ex. « ébénisterie », « génie »)…": "Search an activity (e.g. “cabinetmaking”, “engineering”)…", "Référentiel officiel · 50 résultats max": "Official reference list · 50 results max", "Principal": "Main", "Supprimer ce code": "Remove this code", "Supprimer l'adresse": "Remove the address", "Nom": "Name", "Fonction": "Role", "Téléphone": "Phone", "Signataire principal de la {demande}": "Main signatory of the {demande}", "Profil détaillé": "Detailed profile", "Facultatif · améliore le ciblage": "Optional · improves targeting", "Pour quels besoins cherchez-vous du financement ?": "What needs are you seeking financing for?", "Produits et services offerts": "Products and services offered", "Objectifs de croissance": "Growth objectives", "Date de constitution (AAAA-MM-JJ)": "Date of incorporation (YYYY-MM-DD)", "Revenus bruts (chiffre d'affaires)": "Gross revenue (turnover)", "Enregistrement impossible :": "Could not save:", "Aucun résultat pour « {q} »": "No results for “{q}”", "Aide : ": "Help: ", "où trouver cette information": "where to find this information", // — Fourchettes (la valeur canonique reste en base ; ceci est l'AFFICHAGE) — "Moins de 250 k$": "Under $250K", "250 k$ – 500 k$": "$250K – $500K", "500 k$ – 1 M$": "$500K – $1M", "1 M$ – 5 M$": "$1M – $5M", "5 M$ – 10 M$": "$5M – $10M", "10 M$ – 50 M$": "$10M – $50M", "Plus de 50 M$": "Over $50M", // — Besoins de financement — "Automatisation": "Automation", "Achat d'équipements": "Equipment purchase", "Innovation / R&D": "Innovation / R&D", "Amélioration opérationnelle": "Operational improvement", "Virage numérique": "Digital transformation", "Exportation": "Exporting", "Croissance": "Growth", "Embauche": "Hiring", "Formation": "Training", "Nouveaux produits / services": "New products / services", // — Fiche projet : questions — "En une phrase, qu'est-ce que votre projet va accomplir ?": "In one sentence, what will your project accomplish?", "Pas besoin de jargon. Dites-le comme à un ami.": "No jargon needed. Say it like you would to a friend.", "Quel problème est-ce que ça règle ?": "What problem does it solve?", "Ce qui ne va pas aujourd'hui, et pourquoi ça vaut la peine d'agir.": "What's wrong today, and why it's worth acting.", "Qu'est-ce que vous voulez avoir accompli à la fin ?": "What do you want to have accomplished by the end?", "Vos objectifs, en résultats concrets.": "Your objectives, as concrete results.", "Comment allez-vous vous y prendre ?": "How will you go about it?", "Les grandes étapes, dans l'ordre. Trois ou quatre suffisent.": "The main steps, in order. Three or four are enough.", "Combien ça coûte, et qu'est-ce que vous demandez ?": "How much does it cost, and what are you asking for?", "Une estimation suffit à ce stade.": "An estimate is enough at this stage.", // — Fiche projet : écran — "Lecture de vos réponses…": "Reading your answers…", "Rédaction de la fiche : cadre, objectifs, moyens…": "Writing the sheet: framing, objectives, means…", "Structuration du budget et des résultats attendus…": "Structuring the budget and expected results…", "On rédige votre fiche projet…": "Writing your project sheet…", "Ça prend quelques secondes. On combine vos réponses en une fiche claire et réutilisable.": "It takes a few seconds. We combine your answers into a clear, reusable sheet.", "Voici votre fiche projet": "Here is your project sheet", "L'assistant a transformé vos réponses en une fiche structurée. ": "The assistant turned your answers into a structured sheet. ", "Relisez-la, ajustez ce que vous voulez": "Read it over, adjust anything you want", ", puis approuvez-la. Elle deviendra la référence de toutes vos {demandes}.": ", then approve it. It becomes the reference for all your {demandes}.", "Brouillon à approuver": "Draft to approve", "Cadre du projet": "Project framing", "Problématique": "Problem statement", "Objectifs": "Objectives", "Moyens / méthodologie": "Means / methodology", "Résultats attendus": "Expected results", "Une fois approuvée, cette fiche est ": "Once approved, this sheet is ", "gelée et réutilisée": "frozen and reused", " pour remplir vos {formulaires}. Vous pourrez en créer une nouvelle version quand votre projet évolue.": " to fill your {formulaires}. You can create a new version as your project evolves.", "Modifier mes réponses": "Edit my answers", "Approuver ma fiche": "Approve my sheet", "Étape 2 sur 6 · Votre fiche projet": "Step 2 of 6 · Your project sheet", "À remplir : cette section est vide pour l'instant.": "To fill in: this section is empty for now.", // — Téléversement — "Glissez le {formulaire} (PDF) que vous voulez déposer. On le lit immédiatement et on repère tous les champs à remplir.": "Drop the {formulaire} (PDF) you want to submit. We read it immediately and locate every field to fill.", "Formulaires pris en charge : les PDF avec des cases à remplir intégrées.": "Supported forms: PDFs with built-in fillable fields.", " Pour vérifier en 5 secondes : ouvrez le PDF et cliquez dans une case : si vous pouvez taper, c'est bon. Un scan ou un document à imprimer sera refusé immédiatement, sans frais d'analyse.": " To check in 5 seconds: open the PDF and click a field: if you can type, it works. A scan or a print-only document is refused immediately, at no analysis cost.", "Choisissez votre {formulaire}": "Choose your {formulaire}", "PDF · jusqu'à 25 Mo · vos fichiers restent privés": "PDF · up to 25 MB · your files stay private", "Langue des questions :": "Language of the questions:", "Automatique": "Automatic", "Choisir un {formulaire} PDF": "Choose a PDF {formulaire}", "Lecture du document…": "Reading the document…", "On ouvre {f}": "Opening {f}", "Remplissage démarré. Suivez le travail à l'étape suivante.": "Filling started. Follow the work at the next step.", "Lu avec succès": "Read successfully", "Aucun dossier ouvert. Connectez-vous d'abord.": "No file open. Sign in first.", // — Run — "L'assistant remplit votre {formulaire}…": "The assistant is filling your {formulaire}…", "Le remplissage s'est arrêté": "The filling stopped", "Le formulaire est rempli": "The form is filled", "Une étape a échoué. Vos réponses sont conservées.": "A step failed. Your answers are kept.", "On a complété tout ce qu'on savait. Quelques champs ont besoin de votre confirmation.": "We completed everything we knew. A few fields need your confirmation.", "Le moteur travaille. Suivez l'avancement en direct ci-dessous.": "The engine is working. Follow the progress live below.", "Recherche de vos infos": "Finding your information", "Lecture du {formulaire}": "Reading the {formulaire}", "Remplissage": "Filling", "Vérification": "Review", "On repère tous les champs à remplir": "We locate every field to fill", "On puise dans votre profil et vos documents": "We draw on your profile and documents", "On inscrit ce qu'on sait déjà": "We write in what we already know", "On vous montre ce qui reste à confirmer": "We show you what's left to confirm", "champs détectés dans le {formulaire}": "fields detected in the {formulaire}", "remplis automatiquement pour vous": "filled automatically for you", "à confirmer ensemble": "to confirm together", "Ce que fait l'assistant": "What the assistant is doing", "J'ouvre votre document…": "Opening your document…", "{n} champs à remplir détectés.": "{n} fields to fill detected.", "Je puise dans votre profil d'entreprise et votre fiche projet.": "I'm drawing on your company profile and your project sheet.", "J'inscris ce que je sais déjà, sans rien inventer.": "I'm writing in what I already know, without inventing anything.", "{n} champs ont besoin de vous.": "{n} fields need you.", "Tout est rempli. À vous de relire et de confirmer.": "Everything is filled. Now you read it over and confirm.", "{formulaire} rempli et prêt.": "{formulaire} filled and ready.", "Aperçu du {formulaire}": "Preview of the {formulaire}", "votre {formulaire}": "your {formulaire}", "Tous les champs connus sont remplis": "All known fields are filled", "Remplissage en cours…": "Filling in progress…", "Relire et confirmer les {n} champs": "Review and confirm the {n} fields", "Aucun remplissage en cours": "No filling in progress", "Téléversez d'abord un {formulaire} à l'étape précédente : c'est lui qui lance le travail.": "First upload your {formulaire} at the previous step: that's what starts the work.", // — Confirmation : variantes — "Proposé par l'assistant": "Proposed by the assistant", "C'est exact": "That's right", "Confirmé": "Confirmed", "Question {i} sur {n}": "Question {i} of {n}", "Assistant Grant4me": "Grant4me assistant", "Ma proposition": "My suggestion", "Oui, c'est exact": "Yes, that's right", "Ajuster": "Adjust", "Suivant": "Next", "Carte {i} sur {n}": "Card {i} of {n}", "Précédent": "Previous", "C'est exact, terminer": "That's right, finish", "C'est exact, carte suivante": "That's right, next card", "Toutes confirmées": "All confirmed", "Carte suivante": "Next card", "Rien à confirmer ici": "Nothing to confirm here", "Le moteur n'a laissé aucune question en suspens pour ce {formulaire}.": "The engine left no open questions for this {formulaire}.", // — Résultat — "Votre {formulaire} rempli": "Your filled {formulaire}", "{formulaire} rempli ({n} champs)": "{formulaire} filled ({n} fields)", "Remplissage automatique : ": "Automatic filling: ", " · validé par vous : ": " · confirmed by you: ", ". Il vous reste à joindre quelques pièces.": ". You still need to attach a few documents.", "PDF rempli, prêt à signer et à transmettre. Vous pourrez le rouvrir et le modifier à tout moment.": "Filled PDF, ready to sign and send. You can reopen and edit it anytime.", "Télécharger le PDF rempli": "Download the filled PDF", "Comment soumettre": "How to submit", "Rassemblez les {pieces}": "Gather the {pieces}", " listées à droite.": " listed on the right.", "Faites signer le {formulaire}": "Have the {formulaire} signed", " par la personne autorisée de votre entreprise.": " by your company's authorized person.", "Déposez le tout": "Submit everything", " auprès de l'{organisme} avant l'échéance.": " to the {organisme} before the deadline.", "{n} à rassembler": "{n} to gather", "aperçu (page 1)": "preview (page 1)", "Revenir au tableau de bord": "Back to dashboard", "Le PDF n'est pas encore prêt.": "The PDF isn't ready yet.", // — Aide et tutoriel — "Aide et questions fréquentes": "Help and frequently asked questions", "Revoir le tutoriel": "Replay the tutorial", "Deux minutes, pas à pas, avec un exemple, sans toucher à vos dossiers.": "Two minutes, step by step, on an example, without touching your files.", "Un doute sur un champ précis ? Chaque champ du profil a un « ? » qui dit où trouver l'information.": "Unsure about a specific field? Every profile field has a “?” that says where to find the information.", "Tutoriel": "Tutorial", "Tutoriel (exemple)": "Tutorial (example)", "Passer le tutoriel": "Skip the tutorial", "Commencer pour vrai": "Start for real", "Signataire": "Signatory", "Quoi ?": "What?", "champs détectés": "fields detected", "remplis pour vous": "filled for you", "Salaire horaire proposé": "Proposed hourly wage", "Voilà le geste : votre confirmation engage, et cette réponse resservira sur vos prochains formulaires.": "That's the gesture: your confirmation commits you, and this answer will serve again on your next forms.", "PDF rempli": "Filled PDF", "pièces à joindre": "documents to attach", // — Plateforme (metering, admin) — "Plateforme · consommation par entreprise": "Platform · usage by company", "Entreprise": "Company", "Mois": "Month", "Runs": "Runs", "Unités SaaS": "SaaS units", "Questions": "Questions", "Mémoire (0 jeton)": "Memory (0 tokens)", "Jetons LLM": "LLM tokens", "Durée moy.": "Avg. duration", "Fichier trop volumineux : la limite est de 25 Mo.": "File too large: the limit is 25 MB.", "Mot de passe": "Password", "courriel ou mot de passe refusé": "email or password refused", }; const state = { lang: localStorage.getItem(KEY) || ((navigator.language || "fr").toLowerCase().startsWith("en") ? "en" : "fr"), lexique: null, // posé par LangProvider depuis activeDomain listeners: new Set(), }; function interpole(s, vars) { const lex = (state.lexique && state.lexique[state.lang]) || LEXIQUE_DEFAUT[state.lang] || LEXIQUE_DEFAUT.fr; return String(s).replace(/\{(\w+)\}/g, (m, k) => { if (vars && vars[k] != null) return vars[k]; if (lex[k] != null) return lex[k]; const def = LEXIQUE_DEFAUT[state.lang] || LEXIQUE_DEFAUT.fr; return def[k] != null ? def[k] : m; }); } return { get lang() { return state.lang; }, set(lang) { if (lang === state.lang) return; state.lang = lang; try { localStorage.setItem(KEY, lang); } catch (e) {} // Le titre d'onglet suit la langue comme le reste de la page. try { document.title = "Grant4me — " + this.t("Vos {demandes}"); } catch (e) {} state.listeners.forEach((fn) => fn(lang)); }, setLexique(lex) { state.lexique = lex || null; state.listeners.forEach((fn) => fn(state.lang)); }, subscribe(fn) { state.listeners.add(fn); return () => state.listeners.delete(fn); }, /** t("Vos {demandes}") — traduit puis interpole le lexique du domaine. */ t(fr, vars) { const s = state.lang === "en" && EN[fr] != null ? EN[fr] : fr; return interpole(s, vars); }, /** Un mot du lexique seul : L("pieces"). */ L(terme) { return interpole("{" + terme + "}"); }, /** Diagnostic : ce qui n'est pas encore traduit (utilisé par le smoke). */ manquantes(strings) { return strings.filter((s) => EN[s] == null); }, get dictionnaire() { return EN; }, }; })(); /** Hook : re-rend le composant quand la langue ou le lexique change. */ function useLang() { const [, force] = React.useState(0); React.useEffect(() => I18N.subscribe(() => force((n) => n + 1)), []); return { lang: I18N.lang, t: I18N.t, L: I18N.L, setLang: (l) => I18N.set(l) }; } /** Charge le lexique du domaine ACTIF et cale la langue par défaut dessus. * À monter une fois, au sommet de l'application. */ function useDomainLexicon(projectId, ready) { React.useEffect(() => { let vivant = true; G4M.activeDomain(projectId) .then((d) => { if (!vivant || !d) return; I18N.setLexique(d.lexicon || null); // Le titre d'onglet parle aussi la langue du domaine. try { document.title = "Grant4me — " + I18N.t("Vos {demandes}"); } catch (e) {} // La langue par défaut du domaine ne s'impose qu'au PREMIER passage : // un utilisateur qui a choisi sa langue la garde. if (!localStorage.getItem("grant4me.lang") && d.defaultLang) I18N.set(d.defaultLang); }) .catch(() => {}); return () => { vivant = false; }; }, [projectId, ready]); } /** Bloc de texte riche (avec du gras, des liens) : trop structuré pour `t()`. */ function Tr({ fr, en }) { const { lang } = useLang(); return lang === "en" && en ? en : fr; } /** Sélecteur de langue — deux boutons, pas un menu : le choix est binaire. */ function LangSwitch() { const { lang, setLang } = useLang(); return (