Repository Public
1const fr = {2 // ── Common ──3 cAdd: "Ajouter", cCancel: "Annuler", cCopied: "Copié", cCopy: "Copier", cCopyLink: "Copier le lien", cDelete: "Supprimer", cEdit: "Modifier", cOpen: "Ouvrir", cOptional: "facultatif",4 cRefresh: "Actualiser", cSave: "Enregistrer", cUnsaved: "Modifications non enregistrées", cErrForm: "Certains champs sont à corriger.", cErrRange: "Valeur entière entre {min} et {max}.",56 // ── Availability ──7 avTitle: "Disponibilités", avLead: "Vos heures d'ouverture habituelles, puis les exceptions : congés, blocages, absences récurrentes et ouvertures ponctuelles.",8 avWeeklyTitle: "Heures hebdomadaires", avWeeklyLead: "Heures murales dans le fuseau {tz}. Plusieurs plages dans une journée créent des pauses entre elles.",9 avSchedule: "Horaire", avScheduleHint: "Pour donner un horaire distinct à un type de rendez-vous, activez « Disponibilité spécifique » dans ce type.", avDefaultSchedule: "Horaire par défaut",10 avDayClosed: "Fermé", avStart: "début", avEnd: "fin", avAddRange: "Ajouter une plage", avRemoveRange: "Retirer la plage", avCopyWeekdays: "Copier vers les autres jours ouvrables",11 avErrOrder: "La fin doit être après le début.", avErrOverlap: "Les plages de cette journée se chevauchent.", avErrEmpty: "Complétez toutes les dates et heures.",12 avMidnightHint: "Une fin à 00:00 signifie minuit, à la fin de la journée.", avSaved: "Heures enregistrées.", avDiscardConfirm: "Abandonner les modifications non enregistrées de cet horaire ?",13 avExcTitle: "Exceptions et indisponibilités", avExcLead: "Les fermetures sont en heure murale du fuseau {tz}. Une fermeture retire des créneaux à venir ; elle n'annule jamais un rendez-vous déjà confirmé.",14 avExcEmpty: "Aucune exception à venir", avExcEmptyLead: "Ajoutez un congé, un blocage d'heures, une absence récurrente ou une ouverture exceptionnelle.",15 avPast: "Exceptions passées ({n})", avClosed: "Fermé", avOpenExc: "Ouverture exceptionnelle", avAllTypes: "Tous les types", avRecurring: "Récurrent",16 avDescDay: "{day} — journée entière", avDescDays: "Du {from} au {to} — journées entières", avDescHours: "{day}, {from} – {to}", avDescSpan: "Du {from} au {to}",17 avDescWeekly: "Chaque {days} à {time}, durée {dur} min", avDescFrom: "à partir du {date}", avDescUntil: "jusqu'au {date}",18 avExcDeleteTitle: "Supprimer cette exception ?", avExcDeleteLead: "Les créneaux concernés suivront de nouveau les heures hebdomadaires.", avExcDeleted: "Exception supprimée.", avExcSaved: "Exception ajoutée.",19 avExcAddTitle: "Ajouter une exception", avPresetLegend: "Type d'exception",20 avPresetHours: "Bloquer des heures", avPresetHoursHint: "Une période précise, le même jour ou à cheval sur minuit.",21 avPresetDays: "Journée(s) entière(s)", avPresetDaysHint: "Congé, vacances, jour férié.",22 avPresetWeekly: "Absence récurrente", avPresetWeeklyHint: "Chaque semaine, certains jours, à heure fixe.",23 avPresetOpen: "Ouverture exceptionnelle", avPresetOpenHint: "Des heures offertes en dehors de l'horaire habituel.",24 avStartDate: "Date de début", avStartTime: "Heure de début", avEndDate: "Date de fin", avEndTime: "Heure de fin", avFirstDay: "Premier jour", avLastDay: "Dernier jour", avLastDayHint: "Inclus.",25 avWeekdays: "Jours de la semaine", avDuration: "Durée (minutes)", avDurationHint: "Peut dépasser minuit (maximum 1440).", avValidFrom: "À partir du", avValidUntil: "Jusqu'au",26 avScope: "S'applique à", avNote: "Note", avNoteHint: "Visible par vous seulement.",27 avErrRange: "La fin doit être après le début.", avErrDays: "La date de fin précède la date de début.", avErrWeekdays: "Choisissez au moins un jour.", avErrDuration: "Durée entre 1 et 1440 minutes.",2829 // ── Appointment types ──30 tyTitle: "Types de rendez-vous", tyLead: "Ce que les visiteurs peuvent demander : durée, format, règles de réservation et formulaire.", tyNew: "Nouveau type", tyNewTitle: "Nouveau type de rendez-vous", tyEditTitle: "Modifier le type",31 tyEmpty: "Aucun type de rendez-vous", tyEmptyLead: "Créez un premier type pour ouvrir la page publique de réservation.",32 tyMinutes: "{n} min", tyKindVideo: "Visioconférence", tyKindPhone: "Téléphone", tyKindInPerson: "En personne",33 tyApprovalManual: "Approbation manuelle", tyApprovalAuto: "Confirmation automatique", tyInactive: "Inactif", tyCustomHours: "Horaire spécifique",34 tyActive: "Actif", tyActiveHint: "Visible sur la page publique et réservable.", tyInactiveHint: "Masqué de la page publique ; le lien ne permet plus de réserver.", tyActivated: "Type activé.", tyDeactivated: "Type désactivé.",35 tyDeleteTitle: "Supprimer ce type ?", tyDeleteLead: "« {title} » sera supprimé définitivement, avec l'historique de ses demandes.", tyDeleted: "Type supprimé.",36 tyInUse: "Ce type a encore des demandes ouvertes ou des rendez-vous à venir. Désactivez-le plutôt : il disparaîtra de la page publique sans rien annuler.",37 tySaved: "Type enregistré.",38 tyGroupGeneral: "Général", tyGroupFormat: "Format", tyGroupBooking: "Réservation", tyGroupForm: "Formulaire", tyGroupVisitor: "Visiteur", tyGroupAvailability: "Disponibilité", tyGroupStatus: "État",39 tyFieldTitle: "Titre", tyFieldTitleEn: "Titre (anglais)", tyFieldSlug: "Nom du lien", tyFieldDesc: "Description", tyFieldDescEn: "Description (anglais)", tyFieldColor: "Couleur", tyColorCustom: "Autre",40 tyFieldLanguages: "Langues offertes", tyFieldDuration: "Durée (minutes)", tyFieldKind: "Lieu",41 tyFieldDetailVideo: "Lien de visioconférence", tyFieldDetailPhone: "Numéro ou consigne d'appel", tyFieldDetailPlace: "Adresse",42 tyDetailHintVideo: "Envoyé seulement une fois le rendez-vous confirmé. En V1, le lien est saisi à la main : aucune réunion n'est créée automatiquement.", tyDetailHint: "Envoyé seulement une fois le rendez-vous confirmé.",43 tyFieldInstr: "Instructions", tyFieldInstrEn: "Instructions (anglais)", tyInstrHint: "Affichées sur la page publique et rappelées dans la confirmation.",44 tyFieldApproval: "Confirmation", tyApprovalManualHint: "Chaque demande attend votre réponse ; rien n'est confirmé sans vous.", tyApprovalAutoHint: "Le créneau est confirmé dès la demande, après les mêmes vérifications.",45 tyFieldHold: "Demandes en attente", tyHoldHold: "Retenir le créneau", tyHoldHoldHint: "Une demande en attente réserve temporairement son créneau : personne d'autre ne peut le demander.",46 tyHoldNone: "Sans retenue", tyHoldNoneHint: "Plusieurs personnes peuvent demander le même créneau ; une seule demande pourra être approuvée.",47 tyFieldHoldTtl: "Retenue (heures)", tyFieldStep: "Pas des créneaux (min)", tyFieldNotice: "Préavis minimal (heures)", tyFieldHorizon: "Horizon (jours)",48 tyFieldBufferBefore: "Tampon avant (min)", tyFieldBufferAfter: "Tampon après (min)", tyFieldDaily: "Limite par jour", tyFieldWeekly: "Limite par semaine",49 tyLimitsHint: "Limites vides : aucune limite. Les tampons ne s'additionnent pas entre deux rendez-vous : le plus grand des deux s'applique.",50 tyFormHint: "Le nom et le courriel sont toujours demandés.", tyAskOrg: "Demander l'organisation", tyRequireReason: "Motif obligatoire", tyRequireReasonHint: "Le motif reste confidentiel : jamais dans une adresse, un courriel ou une invitation.",51 tyQuestionN: "Question {n}", tyQLabel: "Libellé", tyQLabelEn: "Libellé (anglais)", tyQKind: "Réponse", tyQKindText: "Courte", tyQKindArea: "Longue", tyQRequired: "Obligatoire", tyAddQuestion: "Ajouter une question",52 tyAllowCancel: "Le visiteur peut annuler en ligne", tyAllowReschedule: "Le visiteur peut déplacer en ligne", tyAllowRescheduleHint: "Avec l'approbation manuelle, le rendez-vous garde son heure tant que vous n'avez pas accepté le changement.",53 tyFieldReminder: "Rappel (heures avant)", tyReminderHint: "Vide : aucun rappel.",54 tyCustomAvail: "Disponibilité spécifique", tyCustomAvailHint: "Ce type suit son propre horaire hebdomadaire au lieu de l'horaire par défaut.",55 tyCustomAvailNote: "Sans plages définies pour cet horaire, ce type n'offre aucun créneau.", tyCustomAvailLink: "Définir l'horaire dans Disponibilités",56 tyErrTitle: "Le titre est requis.", tyErrSlug: "Lettres minuscules, chiffres et tirets ; commence et finit par une lettre ou un chiffre.", tyErrSlugTaken: "Ce nom de lien est déjà utilisé.",57 tyErrLanguages: "Choisissez au moins une langue.", tyErrQuestion: "Le libellé est requis.",5859 // ── Contacts ──60 ctTitle: "Contacts", ctLead: "Les personnes qui ont demandé un rendez-vous, avec leur historique.", ctSearch: "Rechercher", ctSearchPh: "Nom, courriel, organisation",61 ctEmpty: "Aucun contact", ctEmptyLead: "Les contacts sont créés à la première demande d'une personne.", ctNoMatch: "Aucun contact ne correspond",62 ctCounts: "{r} demande(s) · {b} rendez-vous", ctLast: "Dernière : {date}", ctSince: "contact depuis le {date}",63 ctName: "Nom", ctOrg: "Organisation", ctNotes: "Notes internes", ctNotesHint: "Jamais montrées au contact.", ctSaved: "Contact enregistré.",64 ctBookings: "Rendez-vous ({n})", ctRequests: "Demandes ({n})", ctNoBookings: "Aucun rendez-vous.", ctNoRequests: "Aucune demande.",65 ctStPending: "En attente", ctStProposal: "Proposition envoyée", ctStApproved: "Approuvée", ctStDeclined: "Refusée", ctStExpired: "Expirée", ctStCancelled: "Annulé", ctStConfirmed: "Confirmé",66 ctPrivacy: "Renseignements personnels", ctPrivacyLead: "Loi 25 : cette personne peut demander une copie de ses renseignements (droit d'accès) ou leur suppression.",67 ctExport: "Exporter (JSON)", ctErase: "Supprimer définitivement", ctEraseTitle: "Supprimer ce contact ?",68 ctEraseLead: "Tout ce qui concerne {name} sera effacé : fiche, demandes, réponses au formulaire, liens de gestion, courriels en file et rendez-vous passés.",69 ctEraseNote: "Cette action est irréversible et consignée dans le journal d'audit, sans renseignement personnel.", ctErased: "Contact supprimé.",70 ctFutureBooking: "Cette personne a encore un rendez-vous confirmé à venir. Annulez-le d'abord dans l'agenda.",7172 // ── Settings ──73 stTitle: "Paramètres", stTabProfile: "Profil", stTabMail: "Courriels", stTabIntegrations: "Intégrations", stTabSecurity: "Sécurité", stTabAudit: "Audit",74 stPublicTitle: "Profil public", stPublicLead: "Ce que les visiteurs voient sur la page de réservation.",75 stAvatarAlt: "Photo de profil", stAvatarAdd: "Ajouter une photo", stAvatarChange: "Changer la photo", stAvatarRemove: "Retirer", stAvatarHint: "PNG, JPEG ou WebP, 1 Mo au maximum.",76 stAvatarErr: "Image PNG, JPEG ou WebP de 1 Mo au maximum.", stAvatarSaved: "Photo enregistrée.", stAvatarRemoved: "Photo retirée.",77 stName: "Nom affiché", stHeadline: "Présentation courte", stHeadlineEn: "Présentation courte (anglais)", stBio: "Présentation", stBioEn: "Présentation (anglais)",78 stBrand: "Couleur d'accent", stBrandHint: "Utilisée pour les accents de la page publique.",79 stRegionTitle: "Fuseau et langue", stTzFilter: "Filtrer les fuseaux", stTz: "Fuseau horaire", stTzHint: "Les heures d'ouverture et l'agenda sont exprimés dans ce fuseau.",80 stTzWarn: "Changement de fuseau : les rendez-vous existants gardent leur instant réel ; les heures hebdomadaires et les exceptions seront relues dans le nouveau fuseau.",81 stLocale: "Langue par défaut", stLocaleHint: "Langue des courriels qui vous sont destinés.",82 stMailTitle: "Courriels", stMailLead: "Adresses utilisées par les notifications.", stNotify: "Adresse des alertes", stNotifyHint: "Où vous recevez les nouvelles demandes. Vide : l'adresse du compte.",83 stReplyTo: "Adresse de réponse", stReplyToHint: "Les visiteurs qui répondent à un courriel écrivent à cette adresse.",84 stDomainsTitle: "Domaines de courriel", stDomainsLead: "Limiter qui peut soumettre une demande, d'après le domaine de l'adresse.",85 stAllowed: "Domaines autorisés", stAllowedHint: "Un par ligne. Vide : tous les domaines sont acceptés.", stBlocked: "Domaines bloqués", stBlockedHint: "Un par ligne. Les sous-domaines sont inclus.",86 stPrivacyTitle: "Conservation", stPrivacyLead: "Les demandes, rendez-vous, contacts inactifs et journaux plus anciens que cette durée sont supprimés automatiquement.",87 stRetention: "Durée de conservation (jours)", stRetentionHint: "Entre 30 et 3650 jours.",88 stExternalTitle: "Calendriers externes", stExternalLead: "Que faire lorsqu'un calendrier connecté n'a pas pu être relu récemment.",89 stStaleMinutes: "Fraîcheur exigée (minutes)", stStaleMinutesHint: "Au-delà, le calendrier est considéré comme périmé.",90 stStalePolicy: "Politique si périmé", stStaleConservative: "Prudente", stStaleIgnore: "Ignorer",91 stStaleConservativeHint: "Les confirmations automatiques sont suspendues : les demandes attendent votre approbation.", stStaleIgnoreHint: "Les confirmations automatiques continuent avec les dernières périodes occupées connues.",92 stSaved: "Paramètres enregistrés.", stErrName: "Le nom affiché est requis.", stErrEmail: "Adresse de courriel invalide.", stErrDomains: "Un domaine valide par ligne (ex. : exemple.ca).", stErrColor: "Couleur invalide.",9394 // ── Notifications ──95 ntTransportTitle: "Transport de courriel", ntConfigured: "Transport configuré : {transport}.", ntNotConfigured: "Aucun transport de courriel n'est configuré.",96 ntNotConfiguredLead: "Aucun courriel ne part. Les notifications sont mises de côté (« non configuré ») et ne sont jamais indiquées comme envoyées ; elles pourront être remises en file une fois le transport configuré sur le serveur.",97 ntTestTo: "Destinataire du test", ntTestSend: "Envoyer un courriel de test", ntTestQueued: "Test mis en file. Le résultat apparaîtra dans le journal.",98 ntTestHint: "Le résultat réel (envoyé, échec ou non configuré) s'affiche dans le journal ci-dessous dès que le service d'envoi l'a traité, en quelques secondes.",99 ntLogTitle: "Journal d'envoi", ntLogLead: "Les 200 dernières notifications. « Envoyé » signifie que le transport a accepté le message.", ntWatching: "Actualisation automatique", ntEmpty: "Aucune notification pour l'instant",100 ntRequeue: "Remettre en file", ntRequeueAll: "Remettre en file ({n})", ntRequeued: "{n} notification(s) remise(s) en file.",101 ntCreated: "Créé {date}", ntSentAt: "Envoyé {date}", ntNextTry: "Prochain essai {date}", ntAttempts: "{n} tentative(s)", ntMessageId: "Identifiant du fournisseur :",102 ntSSent: "Envoyé", ntSQueued: "En file", ntSRetrying: "Nouvel essai prévu", ntSSending: "Envoi en cours", ntSDead: "Échec définitif", ntSUnconfigured: "Non configuré", ntSCancelled: "Annulé (sans objet)",103 ntKRequestReceived: "Accusé de réception de la demande", ntKBookingConfirmed: "Confirmation du rendez-vous", ntKRequestDeclined: "Refus de la demande", ntKRescheduleDeclined: "Refus du changement d'horaire",104 ntKProposal: "Proposition d'un autre moment", ntKBookingCancelled: "Annulation du rendez-vous", ntKBookingRescheduled: "Rendez-vous déplacé", ntKRequestExpired: "Demande expirée", ntKReminder: "Rappel",105 ntKAdminNewRequest: "Alerte : nouvelle demande", ntKAdminNewBooking: "Alerte : rendez-vous confirmé automatiquement", ntKAdminVisitorCancelled: "Alerte : annulation par le visiteur", ntKAdminWithdrawn: "Alerte : demande retirée",106 ntKAdminReschedule: "Alerte : changement d'horaire demandé", ntKAdminAccepted: "Alerte : proposition acceptée", ntKTest: "Courriel de test",107108 // ── Integrations ──109 igIcsTitle: "Abonnements ICS (lecture seule)", igIcsLead: "Collez l'adresse ICS privée d'un calendrier (iCloud, Google « adresse secrète au format iCal », Outlook « publier le calendrier »). SP Calendar y lit seulement les périodes occupées, environ toutes les 10 minutes ; rien n'y est jamais écrit.",110 igEmpty: "Aucun calendrier connecté", igEmptyLead: "Sans calendrier externe, seuls vos blocages et rendez-vous SP Calendar retirent des créneaux.",111 igStConnected: "Connecté", igStError: "En erreur", igStale: "Périmé", igFresh: "À jour",112 igLastSuccess: "Dernière lecture réussie : {date}", igNeverSynced: "Jamais lu avec succès", igLastAttempt: "Dernier essai : {date}", igEvents: "{n} période(s) occupée(s)", igLastError: "Dernière erreur :",113 igBlocks: "Bloque mes disponibilités", igBlocksOn: "Ses périodes occupées retirent des créneaux.", igBlocksOff: "Affiché dans l'agenda seulement ; ne retire aucun créneau.", igBlocksAddHint: "Les périodes occupées de ce calendrier retireront des créneaux publics.",114 igName: "Nom", igRename: "Renommer", igSaved: "Calendrier mis à jour.", igSyncNow: "Synchroniser maintenant", igSyncOk: "Synchronisé : {n} période(s) occupée(s).", igSyncUnchanged: "Synchronisé : aucun changement.", igSyncFailed: "Échec de la synchronisation : {error}",115 igDisconnect: "Déconnecter", igDisconnectTitle: "Déconnecter ce calendrier ?", igDisconnectLead: "L'adresse enregistrée de « {name} » et toutes les périodes occupées qui en proviennent seront supprimées. Les créneaux correspondants redeviendront offerts.", igRemoved: "Calendrier déconnecté.",116 igAddTitle: "Ajouter un calendrier", igLabel: "Nom", igLabelPh: "Personnel, UQO…", igUrl: "Adresse ICS", igUrlHint: "Commence par https:// ou webcal://. L'adresse est chiffrée sur le serveur et n'est plus affichée ensuite.",117 igAdd: "Connecter", igErrUrl: "L'adresse doit commencer par https:// ou webcal://.", igAddOk: "Calendrier connecté : {n} période(s) occupée(s) lue(s).", igAddFailed: "Calendrier enregistré, mais la première lecture a échoué : {error}",118 igStaleExplain: "Un calendrier est périmé après {n} minutes sans lecture réussie. Politique actuelle : {policy}.", igStaleLink: "Modifier dans Profil",119 igOtherTitle: "Autres connecteurs", igOtherLead: "Ces connecteurs (OAuth, synchronisation bidirectionnelle) ne sont pas implémentés dans cette version. Utilisez l'abonnement ICS pour lire vos périodes occupées.", igNotImplemented: "Non implémenté",120 igFeedTitle: "Flux ICS de vos rendez-vous", igFeedLead: "Une adresse privée à laquelle abonner Apple Calendar, Google Calendar ou Outlook pour y voir vos rendez-vous confirmés (titre, heure, lieu — jamais les motifs).",121 igFeedOn: "Activé", igFeedOff: "Désactivé", igFeedEnable: "Activer le flux", igFeedRotate: "Générer une nouvelle adresse", igFeedDisable: "Désactiver", igFeedDisabled: "Flux désactivé.",122 igFeedOnce: "Copiez cette adresse maintenant : elle ne sera plus affichée.", igFeedHint: "Toute personne qui possède cette adresse peut lire vos rendez-vous confirmés. Générez-en une nouvelle si elle a circulé.",123 igFeedConfirm: "L'adresse actuelle cessera de fonctionner immédiatement dans tous les calendriers qui y sont abonnés.",124125 // ── Security ──126 scPasskeysTitle: "Clés d'accès", scPasskeysLead: "Connexion par Touch ID, Face ID ou clé de sécurité. Les données biométriques ne quittent jamais l'appareil : le serveur ne conserve qu'une clé publique.",127 scNoPasskey: "Aucune clé d'accès n'est enregistrée. Ajoutez-en une maintenant pour pouvoir vous reconnecter.", scSingleKey: "Une seule clé est enregistrée. Ajoutez-en une sur un second appareil pour ne pas dépendre des codes de récupération.",128 scKeyCreated: "Ajoutée {date}", scKeyUsed: "utilisée {date}", scKeyNeverUsed: "jamais utilisée", scKeySynced: "Synchronisée (trousseau)", scKeyDeviceOnly: "Liée à l'appareil",129 scKeyName: "Nom de cet appareil", scAddPasskey: "Ajouter une clé d'accès sur cet appareil", scPasskeyAdded: "Clé d'accès ajoutée.", scPasskeyCancelled: "La demande de clé d'accès a été annulée.",130 scPasskeyExists: "Cet appareil possède déjà une clé d'accès pour ce compte.", scUnsupported: "Ce navigateur ne prend pas en charge les clés d'accès (WebAuthn).",131 scRemoveKeyTitle: "Supprimer cette clé d'accès ?", scRemoveKeyLead: "« {name} » ne pourra plus servir à se connecter.", scPasskeyRemoved: "Clé d'accès supprimée.", scLastPasskey: "La dernière clé d'accès ne peut pas être supprimée.",132 scCodesTitle: "Codes de récupération", scCodesLead: "Chaque code ouvre une session une seule fois si vous perdez vos appareils.", scCodesLeft: "{n} code(s) inutilisé(s)",133 scCodesRegenerate: "Générer de nouveaux codes", scCodesConfirm: "Les codes actuels cesseront de fonctionner. Les nouveaux codes ne seront affichés qu'une fois.", scCodesOnce: "Conservez ces codes en lieu sûr : ils ne seront plus affichés.",134 scSessionsTitle: "Sessions actives", scSessionsLead: "Les appareils actuellement connectés à l'administration.", scCurrent: "Cette session", scRevoke: "Révoquer", scSignOut: "Se déconnecter",135 scSessionRevoked: "Session révoquée.", scRevokeOthers: "Déconnecter les autres appareils", scRevokeOthersLead: "Toutes les sessions sauf celle-ci seront fermées immédiatement.", scOthersRevoked: "{n} session(s) fermée(s).",136 scSessionSeen: "Vue {date}", scSessionExpires: "expire {date}", scMethodPasskey: "Clé d'accès", scMethodRecovery: "Code de récupération", scMethodSetup: "Enregistrement",137138 // ── Audit ──139 auTitle: "Journal d'audit", auLead: "Les actions faites dans l'administration, par les visiteurs et par le système. Aucun motif ni réponse de formulaire n'y figure.",140 auEmpty: "Aucun événement", auMore: "Charger plus", auEnd: "Fin du journal.", auActorAdmin: "Admin", auActorVisitor: "Visiteur", auActorSystem: "Système",141};142143const en: typeof fr = {144 // ── Common ──145 cAdd: "Add", cCancel: "Cancel", cCopied: "Copied", cCopy: "Copy", cCopyLink: "Copy link", cDelete: "Delete", cEdit: "Edit", cOpen: "Open", cOptional: "optional",146 cRefresh: "Refresh", cSave: "Save", cUnsaved: "Unsaved changes", cErrForm: "Some fields need to be corrected.", cErrRange: "Whole number between {min} and {max}.",147148 // ── Availability ──149 avTitle: "Availability", avLead: "Your usual opening hours, then the exceptions: leave, blocked time, recurring absences and one-off openings.",150 avWeeklyTitle: "Weekly hours", avWeeklyLead: "Wall-clock hours in the {tz} time zone. Several ranges in a day create breaks between them.",151 avSchedule: "Schedule", avScheduleHint: "To give an appointment type its own schedule, turn on “Specific availability” in that type.", avDefaultSchedule: "Default schedule",152 avDayClosed: "Closed", avStart: "start", avEnd: "end", avAddRange: "Add a range", avRemoveRange: "Remove range", avCopyWeekdays: "Copy to the other working days",153 avErrOrder: "The end must be after the start.", avErrOverlap: "The ranges of this day overlap.", avErrEmpty: "Fill in every date and time.",154 avMidnightHint: "An end at 00:00 means midnight, at the end of the day.", avSaved: "Hours saved.", avDiscardConfirm: "Discard the unsaved changes of this schedule?",155 avExcTitle: "Exceptions and unavailability", avExcLead: "Closures are wall-clock time in the {tz} time zone. A closure removes upcoming slots; it never cancels an appointment that is already confirmed.",156 avExcEmpty: "No upcoming exception", avExcEmptyLead: "Add leave, blocked hours, a recurring absence or an exceptional opening.",157 avPast: "Past exceptions ({n})", avClosed: "Closed", avOpenExc: "Exceptional opening", avAllTypes: "All types", avRecurring: "Recurring",158 avDescDay: "{day} — all day", avDescDays: "{from} to {to} — all day", avDescHours: "{day}, {from} – {to}", avDescSpan: "{from} to {to}",159 avDescWeekly: "Every {days} at {time}, for {dur} min", avDescFrom: "from {date}", avDescUntil: "until {date}",160 avExcDeleteTitle: "Delete this exception?", avExcDeleteLead: "The slots concerned will follow the weekly hours again.", avExcDeleted: "Exception deleted.", avExcSaved: "Exception added.",161 avExcAddTitle: "Add an exception", avPresetLegend: "Kind of exception",162 avPresetHours: "Block hours", avPresetHoursHint: "A precise period, on one day or across midnight.",163 avPresetDays: "Whole day(s)", avPresetDaysHint: "Leave, vacation, public holiday.",164 avPresetWeekly: "Recurring absence", avPresetWeeklyHint: "Every week, on chosen days, at a fixed time.",165 avPresetOpen: "Exceptional opening", avPresetOpenHint: "Hours offered outside the usual schedule.",166 avStartDate: "Start date", avStartTime: "Start time", avEndDate: "End date", avEndTime: "End time", avFirstDay: "First day", avLastDay: "Last day", avLastDayHint: "Included.",167 avWeekdays: "Days of the week", avDuration: "Duration (minutes)", avDurationHint: "May run past midnight (1440 at most).", avValidFrom: "From", avValidUntil: "Until",168 avScope: "Applies to", avNote: "Note", avNoteHint: "Visible to you only.",169 avErrRange: "The end must be after the start.", avErrDays: "The end date is before the start date.", avErrWeekdays: "Choose at least one day.", avErrDuration: "Duration between 1 and 1440 minutes.",170171 // ── Appointment types ──172 tyTitle: "Appointment types", tyLead: "What visitors can ask for: duration, format, booking rules and form.", tyNew: "New type", tyNewTitle: "New appointment type", tyEditTitle: "Edit type",173 tyEmpty: "No appointment type", tyEmptyLead: "Create a first type to open the public booking page.",174 tyMinutes: "{n} min", tyKindVideo: "Video call", tyKindPhone: "Phone", tyKindInPerson: "In person",175 tyApprovalManual: "Manual approval", tyApprovalAuto: "Automatic confirmation", tyInactive: "Inactive", tyCustomHours: "Specific schedule",176 tyActive: "Active", tyActiveHint: "Visible on the public page and bookable.", tyInactiveHint: "Hidden from the public page; the link no longer allows booking.", tyActivated: "Type activated.", tyDeactivated: "Type deactivated.",177 tyDeleteTitle: "Delete this type?", tyDeleteLead: "“{title}” will be deleted permanently, with the history of its requests.", tyDeleted: "Type deleted.",178 tyInUse: "This type still has open requests or upcoming appointments. Deactivate it instead: it will leave the public page without cancelling anything.",179 tySaved: "Type saved.",180 tyGroupGeneral: "General", tyGroupFormat: "Format", tyGroupBooking: "Booking", tyGroupForm: "Form", tyGroupVisitor: "Visitor", tyGroupAvailability: "Availability", tyGroupStatus: "Status",181 tyFieldTitle: "Title", tyFieldTitleEn: "Title (English)", tyFieldSlug: "Link name", tyFieldDesc: "Description", tyFieldDescEn: "Description (English)", tyFieldColor: "Colour", tyColorCustom: "Other",182 tyFieldLanguages: "Languages offered", tyFieldDuration: "Duration (minutes)", tyFieldKind: "Place",183 tyFieldDetailVideo: "Video call link", tyFieldDetailPhone: "Number or calling instructions", tyFieldDetailPlace: "Address",184 tyDetailHintVideo: "Sent only once the appointment is confirmed. In V1 the link is entered by hand: no meeting is created automatically.", tyDetailHint: "Sent only once the appointment is confirmed.",185 tyFieldInstr: "Instructions", tyFieldInstrEn: "Instructions (English)", tyInstrHint: "Shown on the public page and repeated in the confirmation.",186 tyFieldApproval: "Confirmation", tyApprovalManualHint: "Each request waits for your answer; nothing is confirmed without you.", tyApprovalAutoHint: "The slot is confirmed as soon as it is requested, after the same checks.",187 tyFieldHold: "Pending requests", tyHoldHold: "Hold the slot", tyHoldHoldHint: "A pending request temporarily reserves its slot: nobody else can ask for it.",188 tyHoldNone: "No hold", tyHoldNoneHint: "Several people may ask for the same slot; only one request can be approved.",189 tyFieldHoldTtl: "Hold (hours)", tyFieldStep: "Slot step (min)", tyFieldNotice: "Minimum notice (hours)", tyFieldHorizon: "Horizon (days)",190 tyFieldBufferBefore: "Buffer before (min)", tyFieldBufferAfter: "Buffer after (min)", tyFieldDaily: "Daily limit", tyFieldWeekly: "Weekly limit",191 tyLimitsHint: "Empty limits: no limit. Buffers do not add up between two appointments: the larger of the two applies.",192 tyFormHint: "Name and e-mail are always asked.", tyAskOrg: "Ask for the organization", tyRequireReason: "Reason required", tyRequireReasonHint: "The reason stays confidential: never in a URL, an e-mail or an invitation.",193 tyQuestionN: "Question {n}", tyQLabel: "Label", tyQLabelEn: "Label (English)", tyQKind: "Answer", tyQKindText: "Short", tyQKindArea: "Long", tyQRequired: "Required", tyAddQuestion: "Add a question",194 tyAllowCancel: "The visitor can cancel online", tyAllowReschedule: "The visitor can reschedule online", tyAllowRescheduleHint: "With manual approval, the appointment keeps its time until you accept the change.",195 tyFieldReminder: "Reminder (hours before)", tyReminderHint: "Empty: no reminder.",196 tyCustomAvail: "Specific availability", tyCustomAvailHint: "This type follows its own weekly schedule instead of the default one.",197 tyCustomAvailNote: "Without ranges defined for that schedule, this type offers no slot.", tyCustomAvailLink: "Set the schedule in Availability",198 tyErrTitle: "The title is required.", tyErrSlug: "Lowercase letters, digits and hyphens; starts and ends with a letter or digit.", tyErrSlugTaken: "This link name is already used.",199 tyErrLanguages: "Choose at least one language.", tyErrQuestion: "The label is required.",200201 // ── Contacts ──202 ctTitle: "Contacts", ctLead: "The people who asked for an appointment, with their history.", ctSearch: "Search", ctSearchPh: "Name, e-mail, organization",203 ctEmpty: "No contact", ctEmptyLead: "Contacts are created with a person's first request.", ctNoMatch: "No contact matches",204 ctCounts: "{r} request(s) · {b} appointment(s)", ctLast: "Latest: {date}", ctSince: "contact since {date}",205 ctName: "Name", ctOrg: "Organization", ctNotes: "Internal notes", ctNotesHint: "Never shown to the contact.", ctSaved: "Contact saved.",206 ctBookings: "Appointments ({n})", ctRequests: "Requests ({n})", ctNoBookings: "No appointment.", ctNoRequests: "No request.",207 ctStPending: "Pending", ctStProposal: "Proposal sent", ctStApproved: "Approved", ctStDeclined: "Declined", ctStExpired: "Expired", ctStCancelled: "Cancelled", ctStConfirmed: "Confirmed",208 ctPrivacy: "Personal information", ctPrivacyLead: "Québec Law 25: this person may ask for a copy of their information (right of access) or for its deletion.",209 ctExport: "Export (JSON)", ctErase: "Delete permanently", ctEraseTitle: "Delete this contact?",210 ctEraseLead: "Everything about {name} will be erased: record, requests, form answers, management links, queued e-mails and past appointments.",211 ctEraseNote: "This cannot be undone and is recorded in the audit log, without personal information.", ctErased: "Contact deleted.",212 ctFutureBooking: "This person still has an upcoming confirmed appointment. Cancel it first in the agenda.",213214 // ── Settings ──215 stTitle: "Settings", stTabProfile: "Profile", stTabMail: "E-mails", stTabIntegrations: "Integrations", stTabSecurity: "Security", stTabAudit: "Audit",216 stPublicTitle: "Public profile", stPublicLead: "What visitors see on the booking page.",217 stAvatarAlt: "Profile photo", stAvatarAdd: "Add a photo", stAvatarChange: "Change photo", stAvatarRemove: "Remove", stAvatarHint: "PNG, JPEG or WebP, 1 MB at most.",218 stAvatarErr: "PNG, JPEG or WebP image of 1 MB at most.", stAvatarSaved: "Photo saved.", stAvatarRemoved: "Photo removed.",219 stName: "Display name", stHeadline: "Short introduction", stHeadlineEn: "Short introduction (English)", stBio: "Introduction", stBioEn: "Introduction (English)",220 stBrand: "Accent colour", stBrandHint: "Used for the accents of the public page.",221 stRegionTitle: "Time zone and language", stTzFilter: "Filter time zones", stTz: "Time zone", stTzHint: "Opening hours and the agenda are expressed in this zone.",222 stTzWarn: "Changing the zone: existing appointments keep their real instant; weekly hours and exceptions will be read in the new zone.",223 stLocale: "Default language", stLocaleHint: "Language of the e-mails addressed to you.",224 stMailTitle: "E-mails", stMailLead: "Addresses used by notifications.", stNotify: "Alert address", stNotifyHint: "Where you receive new requests. Empty: the account's address.",225 stReplyTo: "Reply-to address", stReplyToHint: "Visitors who reply to an e-mail write to this address.",226 stDomainsTitle: "E-mail domains", stDomainsLead: "Limit who can submit a request, based on the address's domain.",227 stAllowed: "Allowed domains", stAllowedHint: "One per line. Empty: every domain is accepted.", stBlocked: "Blocked domains", stBlockedHint: "One per line. Subdomains are included.",228 stPrivacyTitle: "Retention", stPrivacyLead: "Requests, appointments, inactive contacts and logs older than this period are deleted automatically.",229 stRetention: "Retention period (days)", stRetentionHint: "Between 30 and 3650 days.",230 stExternalTitle: "External calendars", stExternalLead: "What to do when a connected calendar could not be read recently.",231 stStaleMinutes: "Required freshness (minutes)", stStaleMinutesHint: "Beyond this, the calendar is considered stale.",232 stStalePolicy: "Policy when stale", stStaleConservative: "Conservative", stStaleIgnore: "Ignore",233 stStaleConservativeHint: "Automatic confirmations are suspended: requests wait for your approval.", stStaleIgnoreHint: "Automatic confirmations continue with the last known busy periods.",234 stSaved: "Settings saved.", stErrName: "The display name is required.", stErrEmail: "Invalid e-mail address.", stErrDomains: "One valid domain per line (e.g. example.ca).", stErrColor: "Invalid colour.",235236 // ── Notifications ──237 ntTransportTitle: "E-mail transport", ntConfigured: "Transport configured: {transport}.", ntNotConfigured: "No e-mail transport is configured.",238 ntNotConfiguredLead: "No e-mail leaves. Notifications are parked (“not configured”) and never reported as sent; they can be re-queued once the transport is configured on the server.",239 ntTestTo: "Test recipient", ntTestSend: "Send a test e-mail", ntTestQueued: "Test queued. The result will appear in the log.",240 ntTestHint: "The real outcome (sent, failed or not configured) shows in the log below as soon as the sending service has processed it, within seconds.",241 ntLogTitle: "Sending log", ntLogLead: "The last 200 notifications. “Sent” means the transport accepted the message.", ntWatching: "Auto-refreshing", ntEmpty: "No notification yet",242 ntRequeue: "Re-queue", ntRequeueAll: "Re-queue ({n})", ntRequeued: "{n} notification(s) re-queued.",243 ntCreated: "Created {date}", ntSentAt: "Sent {date}", ntNextTry: "Next try {date}", ntAttempts: "{n} attempt(s)", ntMessageId: "Provider id:",244 ntSSent: "Sent", ntSQueued: "Queued", ntSRetrying: "Retry scheduled", ntSSending: "Sending", ntSDead: "Failed permanently", ntSUnconfigured: "Not configured", ntSCancelled: "Cancelled (obsolete)",245 ntKRequestReceived: "Request acknowledgement", ntKBookingConfirmed: "Appointment confirmation", ntKRequestDeclined: "Request declined", ntKRescheduleDeclined: "Reschedule declined",246 ntKProposal: "Another time proposed", ntKBookingCancelled: "Appointment cancellation", ntKBookingRescheduled: "Appointment moved", ntKRequestExpired: "Request expired", ntKReminder: "Reminder",247 ntKAdminNewRequest: "Alert: new request", ntKAdminNewBooking: "Alert: appointment confirmed automatically", ntKAdminVisitorCancelled: "Alert: cancelled by the visitor", ntKAdminWithdrawn: "Alert: request withdrawn",248 ntKAdminReschedule: "Alert: reschedule requested", ntKAdminAccepted: "Alert: proposal accepted", ntKTest: "Test e-mail",249250 // ── Integrations ──251 igIcsTitle: "ICS subscriptions (read-only)", igIcsLead: "Paste the private ICS address of a calendar (iCloud, Google “secret address in iCal format”, Outlook “publish calendar”). SP Calendar only reads busy periods from it, about every 10 minutes; nothing is ever written to it.",252 igEmpty: "No calendar connected", igEmptyLead: "Without an external calendar, only your blocks and SP Calendar appointments remove slots.",253 igStConnected: "Connected", igStError: "In error", igStale: "Stale", igFresh: "Up to date",254 igLastSuccess: "Last successful read: {date}", igNeverSynced: "Never read successfully", igLastAttempt: "Last attempt: {date}", igEvents: "{n} busy period(s)", igLastError: "Last error:",255 igBlocks: "Blocks my availability", igBlocksOn: "Its busy periods remove slots.", igBlocksOff: "Shown in the agenda only; removes no slot.", igBlocksAddHint: "This calendar's busy periods will remove public slots.",256 igName: "Name", igRename: "Rename", igSaved: "Calendar updated.", igSyncNow: "Sync now", igSyncOk: "Synced: {n} busy period(s).", igSyncUnchanged: "Synced: no change.", igSyncFailed: "Sync failed: {error}",257 igDisconnect: "Disconnect", igDisconnectTitle: "Disconnect this calendar?", igDisconnectLead: "The stored address of “{name}” and every busy period that came from it will be deleted. The matching slots will be offered again.", igRemoved: "Calendar disconnected.",258 igAddTitle: "Add a calendar", igLabel: "Name", igLabelPh: "Personal, work…", igUrl: "ICS address", igUrlHint: "Starts with https:// or webcal://. The address is encrypted on the server and never shown again.",259 igAdd: "Connect", igErrUrl: "The address must start with https:// or webcal://.", igAddOk: "Calendar connected: {n} busy period(s) read.", igAddFailed: "Calendar saved, but the first read failed: {error}",260 igStaleExplain: "A calendar is stale after {n} minutes without a successful read. Current policy: {policy}.", igStaleLink: "Change in Profile",261 igOtherTitle: "Other connectors", igOtherLead: "These connectors (OAuth, two-way sync) are not implemented in this version. Use the ICS subscription to read your busy periods.", igNotImplemented: "Not implemented",262 igFeedTitle: "ICS feed of your appointments", igFeedLead: "A private address to subscribe Apple Calendar, Google Calendar or Outlook to, so they show your confirmed appointments (title, time, place — never the reasons).",263 igFeedOn: "Enabled", igFeedOff: "Disabled", igFeedEnable: "Enable the feed", igFeedRotate: "Generate a new address", igFeedDisable: "Disable", igFeedDisabled: "Feed disabled.",264 igFeedOnce: "Copy this address now: it will not be shown again.", igFeedHint: "Anyone holding this address can read your confirmed appointments. Generate a new one if it has leaked.",265 igFeedConfirm: "The current address will stop working at once in every calendar subscribed to it.",266267 // ── Security ──268 scPasskeysTitle: "Passkeys", scPasskeysLead: "Sign-in with Touch ID, Face ID or a security key. Biometric data never leaves the device: the server only keeps a public key.",269 scNoPasskey: "No passkey is enrolled. Add one now to be able to sign in again.", scSingleKey: "Only one passkey is enrolled. Add one on a second device so you do not depend on recovery codes.",270 scKeyCreated: "Added {date}", scKeyUsed: "used {date}", scKeyNeverUsed: "never used", scKeySynced: "Synced (keychain)", scKeyDeviceOnly: "Device-bound",271 scKeyName: "Name of this device", scAddPasskey: "Add a passkey on this device", scPasskeyAdded: "Passkey added.", scPasskeyCancelled: "The passkey request was cancelled.",272 scPasskeyExists: "This device already has a passkey for this account.", scUnsupported: "This browser does not support passkeys (WebAuthn).",273 scRemoveKeyTitle: "Delete this passkey?", scRemoveKeyLead: "“{name}” will no longer sign in.", scPasskeyRemoved: "Passkey deleted.", scLastPasskey: "The last passkey cannot be deleted.",274 scCodesTitle: "Recovery codes", scCodesLead: "Each code opens a session once if you lose your devices.", scCodesLeft: "{n} unused code(s)",275 scCodesRegenerate: "Generate new codes", scCodesConfirm: "The current codes will stop working. The new codes are shown only once.", scCodesOnce: "Keep these codes somewhere safe: they will not be shown again.",276 scSessionsTitle: "Active sessions", scSessionsLead: "The devices currently signed in to the admin area.", scCurrent: "This session", scRevoke: "Revoke", scSignOut: "Sign out",277 scSessionRevoked: "Session revoked.", scRevokeOthers: "Sign out the other devices", scRevokeOthersLead: "Every session except this one will be closed at once.", scOthersRevoked: "{n} session(s) closed.",278 scSessionSeen: "Seen {date}", scSessionExpires: "expires {date}", scMethodPasskey: "Passkey", scMethodRecovery: "Recovery code", scMethodSetup: "Enrolment",279280 // ── Audit ──281 auTitle: "Audit log", auLead: "Actions made in the admin area, by visitors and by the system. No reason or form answer appears here.",282 auEmpty: "No event", auMore: "Load more", auEnd: "End of the log.", auActorAdmin: "Admin", auActorVisitor: "Visitor", auActorSystem: "System",283};284285export const adminConfig = { fr, en };286