{ "filter.all": "TOUS", "legend.title": "LÉGENDE", "action.close": "Fermer", "action.remove": "Retirer", "action.add": "Ajouter", "app.loading": "Chargement…", "app.error.generic": "Une erreur est survenue", "error.generic": "Erreur inattendue", "error.not_found": "Ressource introuvable", "error.forbidden": "Accès refusé", "error.unauthorized": "Authentification requise", "error.validation_failed": "La validation a échoué (règle bloquante)", "assignment.duplicate": "Ce bénévole est déjà affecté à ce créneau", "assignment.wrong_edition": "Bénévole ou créneau hors de cette édition", "volunteer.duplicate_email": "Un bénévole avec cet email existe déjà", "shift.ends_not_after_starts": "La fin doit être après le début", "shift.position_wrong_edition": "Le poste n'appartient pas à cette édition", "auth.invalid_credentials": "Email ou mot de passe incorrect", "auth.invalid_token": "Ce lien de connexion est invalide ou expiré", "role.coordinator": "Coordination", "role.lead": "Référent", "role.volunteer": "Bénévole", "auth.logout": "Déconnexion", "auth.email": "Email", "auth.password": "Mot de passe", "auth.signIn": "Se connecter", "auth.signingIn": "Connexion…", "auth.admin.title": "Espace coordination", "auth.demoCredentials": "Démo : {email} · mot de passe « {password} »", "auth.notAdmin": "Bénévole ou référent ?", "auth.magicLinkLink": "Recevoir un lien de connexion", "auth.isAdmin": "Vous êtes de la coordination ?", "auth.adminLink": "Connexion par mot de passe", "auth.magic.title": "Connexion bénévole / référent", "auth.magic.lead": "Entrez votre email : vous recevrez un lien de connexion, sans mot de passe.", "auth.magic.send": "Envoyer le lien", "auth.magic.sending": "Envoi…", "auth.magic.sent": "Si un compte correspond à cet email, un lien de connexion vient d'être envoyé.", "auth.magic.devHint": "Démo (email stubé) — cliquez ce lien :", "auth.magic.another": "Utiliser un autre email", "auth.magic.verifyTitle": "Connexion en cours", "auth.magic.verifying": "Vérification du lien…", "auth.magic.retry": "Demander un nouveau lien", "header.title": "GESTION DES BÉNÉVOLES", "header.meta": "BÉNÉVOLAT · {count} INSCRITS", "header.mockMode": "DONNÉES DE DÉMO", "tab.grille": "Grille des besoins", "tab.volunteers": "Vue par bénévole", "tab.mobileVolunteer": "Bénévole · mobile", "tab.mobileLead": "Référent · mobile", "tab.config": "Configuration", "position.category.bar": "Bar", "position.category.ticketing": "Billetterie", "position.category.welcome": "Accueil", "position.category.parking": "Parking", "position.category.cleaning": "Propreté", "position.category.catering": "Catering", "position.category.setup": "Montage", "position.category.stage": "Régie", "position.category.other": "Autre", "validation.SHIFT_OVERLAP": "Se chevauche avec un autre créneau", "validation.SHIFT_OVERLAP.at": "Déjà affecté sur {position} au même moment", "validation.SHIFT_OVERLAP.rule": "Deux créneaux d'un même bénévole se chevauchent.", "validation.OUTSIDE_AVAILABILITY": "Hors disponibilités déclarées", "validation.OUTSIDE_AVAILABILITY.unavailable": "Déclaré indisponible sur ce créneau", "validation.OUTSIDE_AVAILABILITY.rule": "Une demi-journée du créneau est indisponible ou sans déclaration.", "validation.DAILY_HOURS_EXCEEDED": "Plus de 8 h sur la journée ({hours})", "validation.DAILY_HOURS_EXCEEDED.rule": "Plus de 8 h 00 d'affectations cumulées sur une même journée.", "validation.INSUFFICIENT_REST": "Moins de 8 h de repos entre deux créneaux ({rest})", "validation.INSUFFICIENT_REST.rule": "Moins de 8 h 00 entre la fin d'un créneau et le début du suivant.", "validation.MISSING_REQUIRED_SKILL": "Compétence requise manquante : {skill}", "validation.MISSING_REQUIRED_SKILL.rule": "Le bénévole n'a pas une compétence requise par le créneau.", "grille.filter.day": "JOUR", "grille.filter.position": "POSTE", "grille.legend.critical": "SOUS-EFFECTIF CRITIQUE", "grille.legend.incomplete": "INCOMPLET", "grille.legend.complete": "COMPLET", "grille.positionsCount": "{count} POSTES", "grille.assignedRequired": "AFFECTÉS / IDÉAL", "grille.footnote": "Chaque cellule est un créneau. Nombre = bénévoles affectés, / = effectif idéal. Cliquer ouvre le panneau d'affectation à droite.", "grille.panel.empty.title": "Cliquez une cellule de la grille pour affecter des bénévoles.", "grille.panel.empty.body": "Le panneau s'ouvre ici, sans quitter la grille : candidats triés par charge, alertes bloquantes et avertissements du moteur de validation.", "grille.panel.slotDuration": "CRÉNEAU DE {hours} H", "grille.panel.assigned": "AFFECTÉS", "grille.panel.min": "MINIMUM {count}", "grille.panel.ideal": "IDÉAL {count}", "grille.panel.assignmentsTitle": "AFFECTATIONS ({count})", "grille.panel.noneAssigned": "Personne n'est encore affecté sur ce créneau.", "grille.panel.hoursTotal": "{hours} H AU TOTAL", "grille.panel.candidates": "CANDIDATS", "grille.panel.candidatesHint": "LES MOINS CHARGÉS D'ABORD", "grille.panel.hoursAssigned": "{hours} H · {slots} CRÉNEAUX", "grille.panel.assign": "AFFECTER", "grille.panel.blocked": "BLOQUÉ", "grille.panel.blockingPrefix": "BLOQUANT — {reason}", "grille.panel.warningsTitle": "⚠ AVERTISSEMENTS — AFFECTATION POSSIBLE", "volunteers.filter.show": "AFFICHER", "volunteers.filter.all": "TOUS", "volunteers.filter.overloaded": "SURCHARGÉS", "volunteers.filter.unassigned": "SANS AFFECTATION", "volunteers.legend.assigned": "AFFECTATION", "volunteers.count": "{count} BÉNÉVOLES", "volunteers.totalHours": "TOTAL H", "volunteers.name": "NOM", "volunteers.cumulative": "CUMUL", "volunteers.badge.overloaded": "▲ SURCHARGE", "volunteers.badge.unassigned": "○ OUBLIÉ", "volunteers.empty": "Aucun bénévole ne correspond à ce filtre — bonne nouvelle. Repassez sur « TOUS » pour revoir l'ensemble de l'équipe.", "volunteers.footnote": "Surcharge = plus de 8 h sur une même journée ou moins de 8 h entre deux créneaux. Oublié = aucune affectation.", "design.noteTitle": "CHOIX DE CONCEPTION", "mobileVol.statusTime": "9:41", "mobileVol.kicker": "MON PLANNING BÉNÉVOLE", "mobileVol.greeting": "SALUT {name}", "mobileVol.slots": "{count} CRÉNEAUX", "mobileVol.hours": "{count} HEURES", "mobileVol.location": "📍 {location}", "mobileVol.slotAssigned": "✓ TU ES ATTENDU SUR CE CRÉNEAU", "mobileVol.noSlots": "Aucun créneau pour l'instant. La coordination t'affectera bientôt.", "mobileVol.noAccount": "Ce compte n'est rattaché à aucun bénévole. Contactez la coordination.", "mobileVol.detailsUnavailable": "Le détail des créneaux (poste, horaires) n'est pas encore exposé aux bénévoles par l'API.", "mobileVol.designNote": "Lisibilité plein soleil : fonds opaques, texte noir sur jaune ou blanc, aucun gris clair. Cibles tactiles à 52–62 px de haut. Une seule action par créneau. Les données proviennent des affectations réelles de l'API.", "mobileLead.statusTime": "18:07", "mobileLead.kicker": "RÉFÉRENT DE POSTE", "mobileLead.inProgress": "CRÉNEAU · {hours}", "mobileLead.present": "{present}/{total} POINTÉS PRÉSENTS", "mobileLead.absenceAlert": "⚠ {count} ABSENCE(S) SUR LE CRÉNEAU", "mobileLead.requestBackup": "DEMANDER UN RENFORT À LA COORDINATION", "mobileLead.teamTitle": "POINTAGE DE L'ÉQUIPE", "mobileLead.badgePresent": "✓ PRÉSENT", "mobileLead.badgeAbsent": "✕ ABSENT", "mobileLead.markPresent": "PRÉSENT", "mobileLead.markAbsent": "ABSENT", "mobileLead.emptyTeam": "Aucun bénévole affecté à ce créneau.", "mobileLead.designNote": "Le référent ne voit que son poste et un créneau. Le pointage est un geste unique par personne. Il est local à cette maquette : le pointage sur site est hors périmètre (CLAUDE.md §4).", "config.admin": "ADMINISTRATION", "config.reserved": "RÉSERVÉ À LA COORDINATION", "config.tab.grid": "POSTES & CRÉNEAUX", "config.tab.volunteers": "BÉNÉVOLES & IMPORT", "config.tab.mail": "MESSAGES (MAQUETTE)", "config.tab.rules": "RÈGLES & ÉDITION", "config.grid.positionsHeader": "POSTES · {count} CRÉNEAUX", "config.grid.slotsCount": "{count} créneaux", "config.grid.addPosition": "+ AJOUTER UN POSTE", "config.grid.addShift": "+ AJOUTER UN CRÉNEAU (12–17)", "config.grid.newPositionName": "Nouveau poste", "config.grid.minTotal": "BESOIN MINIMUM · TOTAL", "config.grid.idealTotal": "BESOIN IDÉAL · TOTAL", "config.grid.min": "MIN", "config.grid.ideal": "IDÉAL", "config.grid.noShifts": "Aucun créneau sur ce poste. Ajoutez-en un pour qu'il apparaisse dans la grille.", "config.grid.note": "Les modifications d'effectif (min / idéal) et les créneaux sont enregistrés immédiatement via l'API et se répercutent sur la grille des besoins (onglet 01).", "config.vol.importTitle": "IMPORTER DES INSCRIPTIONS", "config.vol.importHint": "L'import de fichier CSV / Excel se fait via l'endpoint dédié. Ce bouton crée 4 bénévoles d'exemple via l'API.", "config.vol.importButton": "CRÉER 4 EXEMPLES", "config.vol.profiles": "PROFILS ENREGISTRÉS", "config.vol.colName": "NOM", "config.vol.colPhone": "TÉLÉPHONE", "config.vol.colEmail": "EMAIL", "config.vol.colSkills": "COMPÉTENCES", "config.vol.ficheKicker": "FICHE BÉNÉVOLE", "config.vol.firstName": "PRÉNOM", "config.vol.lastName": "NOM", "config.vol.phone": "TÉLÉPHONE", "config.vol.email": "EMAIL (LIEN MAGIQUE)", "config.vol.tshirt": "TAILLE DE T-SHIRT", "config.vol.skills": "COMPÉTENCES", "config.vol.noSkills": "Aucune compétence déclarée", "config.vol.skillPlaceholder": "Code (ex. CAISSE)", "config.vol.delete": "SUPPRIMER (RGPD — EFFACEMENT COMPLET)", "config.vol.deleteConfirm": "Supprimer définitivement ce bénévole et toutes ses données (disponibilités, affectations) ?", "config.vol.note": "Modifications enregistrées immédiatement via l'API. La suppression est un effacement complet en cascade (RGPD).", "config.mail.draftBanner": "Écran maquette : l'envoi d'emails / SMS est hors périmètre. Ces réglages ne sont pas enregistrés.", "config.mail.templateTitle": "MODÈLE DE MESSAGE DE PUBLICATION", "config.mail.from": "EXPÉDITEUR", "config.mail.replyTo": "RÉPONDRE À", "config.mail.subject": "OBJET", "config.mail.body": "CORPS DU MESSAGE", "config.mail.variables": "VARIABLES DISPONIBLES", "config.mail.previewTitle": "APERÇU", "config.mail.previewFrom": "DE : {from}", "config.mail.cta": "VOIR MON PLANNING →", "config.rules.editionTitle": "ÉDITION & CONNEXION", "config.rules.editionId": "Identifiant d'édition", "config.rules.apiMode": "Mode API", "config.rules.volunteersCount": "Bénévoles", "config.rules.positionsCount": "Postes", "config.rules.shiftsCount": "Créneaux", "config.rules.editionNote": "Il n'y a pas encore d'endpoint de configuration d'édition : nom, dates et rétention se règlent en base. En mode HTTP, VITE_EDITION_ID désigne l'édition.", "config.rules.thresholdsTitle": "MOTEUR DE VALIDATION", "config.rules.maxDaily": "Maximum d'heures par journée", "config.rules.minRest": "Repos minimum entre deux créneaux", "config.rules.thresholdsNote": "Seuils figés côté back-end (CLAUDE.md §3) : non paramétrables. Le double emploi au même créneau est toujours bloquant.", "config.rules.rulesTitle": "RÈGLES APPLIQUÉES", "config.rules.rolesTitle2": "RÔLES ET ACCÈS", "config.rules.roleCoordinator": "Coordination", "config.rules.roleCoordinatorDesc": "Accès complet, construit et publie les plannings", "config.rules.roleLead": "Référent de poste", "config.rules.roleLeadDesc": "Lecture sur l'édition, écriture sur ses postes", "config.rules.roleVolunteer": "Bénévole", "config.rules.roleVolunteerDesc": "Ses seules données, lien magique par email" }