SPB Git

Repository Public

admin-config.ts 39.9 KB 286 lines typescript

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
Files main
Menu

Theme