/** * French dictionary. * * Typed as `Dictionary` (derived from `en.ts`), so a key added to English but * forgotten here fails the type-check rather than falling through to English * at runtime. */ import type { Dictionary } from '../index'; // CLDR: French puts 0 in the singular ("0 photo", "0 jour"), unlike English. const isOne = (n: number) => n === 0 || n === 1; const plural = (n: number, one: string, other: string) => `${n} ${isOne(n) ? one : other}`; export const fr: Dictionary = { dateLocale: 'fr-FR', nav: { home: 'Accueil', about: 'À propos', map: 'Carte', journal: 'Journal', skipToContent: 'Aller au contenu', mainNavAria: 'Navigation principale', heroNavAria: 'Rubriques', openMenu: 'Ouvrir le menu', closeMenu: 'Fermer le menu', }, common: { backTo: (label: string) => `Retour à ${label}`, backToGallery: 'Retour à la galerie', backToJournal: 'Retour au journal', email: 'E-mail', website: 'Site web', home: 'Accueil', photos: (n: number) => plural(n, 'photo', 'photos'), albums: (n: number) => plural(n, 'album', 'albums'), collections: (n: number) => plural(n, 'collection', 'collections'), prevAlbum: 'Album précédent', nextAlbum: 'Album suivant', prevAlbumAria: (name: string) => `Album précédent : ${name}`, nextAlbumAria: (name: string) => `Album suivant : ${name}`, albumNavAria: 'Navigation entre les albums', prevEntry: 'Article précédent', nextEntry: 'Article suivant', prevEntryAria: (title: string) => `Article précédent : ${title}`, nextEntryAria: (title: string) => `Article suivant : ${title}`, entryNavAria: 'Navigation entre les articles du journal', loadingGallery: 'Chargement de la galerie', gallery: 'Galerie', loadingPhotos: 'Chargement des photos', downloadAlbum: 'Télécharger l’album', }, home: { enter: 'Entrer', pauseSlideshow: 'Mettre le diaporama en pause', playSlideshow: 'Lancer le diaporama', }, error: { notFoundTitle: 'Page introuvable', notFoundText: 'Cette page n’existe pas, ou l’album n’est plus publié.', errorTitle: 'Une erreur est survenue', errorText: 'Cette page n’a pas pu être chargée. C’est généralement temporaire — réessayez dans un instant.', tryAgain: 'Réessayer', reference: (digest: string) => `Référence : ${digest}`, }, download: { unavailableTitle: 'Téléchargement indisponible', notAvailable: 'Ce téléchargement n’est pas disponible.', rateLimited: 'Trop de demandes de téléchargement. Patientez un instant, puis réessayez.', immichUnavailable: 'La photothèque est momentanément indisponible. Veuillez réessayer dans un instant.', back: 'Retour à la galerie', limitReached: 'La limite de téléchargements de ce lien est atteinte.', }, theme: { switchToLight: 'Passer en mode clair', switchToDark: 'Passer en mode sombre', scrollToTop: 'Revenir en haut', }, password: { subtitle: 'Cette galerie est protégée par un mot de passe.', siteSubtitle: 'Ce site est protégé par un mot de passe.', pageSubtitle: 'Cette page est protégée par un mot de passe.', journalSubtitle: 'Cet article du journal est protégé par un mot de passe.', protectedPage: 'Page protégée', placeholder: 'Saisissez le mot de passe', submit: 'Entrer', verifying: 'Vérification…', incorrect: 'Mot de passe incorrect. Veuillez réessayer.', failed: 'Impossible de vérifier le mot de passe. Veuillez réessayer plus tard.', tooManyAttempts: (seconds: number | null) => seconds ? `Trop de tentatives. Veuillez réessayer dans ${seconds} ${seconds === 1 ? 'seconde' : 'secondes'}.` : 'Trop de tentatives. Veuillez réessayer plus tard.', legalNavAria: 'Informations légales', }, about: { kicker: 'À propos', title: 'À propos', metaTitle: (name: string) => `À propos — ${name}`, portraitAlt: 'Portrait', gear: 'Matériel', }, map: { title: 'Carte', kicker: 'Où', subtitle: 'Les lieux où les photos ont été prises', loading: 'Chargement de la carte…', loadFailed: (status: number) => `Échec du chargement des données de la carte (${status})`, initFailed: 'Impossible d’initialiser la carte', zoomIn: 'Zoom avant', zoomOut: 'Zoom arrière', leafletTitle: 'Une bibliothèque JavaScript pour cartes interactives', }, subpage: { collectionKicker: (index: string) => `${index} — Collection`, sectionsNav: 'Sections', coverAria: (albumName: string, count: string) => `${albumName}, ${count}`, nextSubpage: 'Suivant', nextSubpageAria: (name: string) => `Suivant : ${name}`, }, journal: { title: 'Journal', kicker: 'Récits & essais', subtitle: 'Essais photographiques, récits visuels et notes de terrain.', entryDescription: 'Article du journal', empty: 'Aucun article publié pour le moment.', readStory: 'Lire le récit →', minRead: (n: number) => `${n} min de lecture`, draft: 'Brouillon', by: (author: string) => `par ${author}`, notFound: 'Introuvable', }, lightbox: { viewer: 'Visionneuse d’images', position: (n: number, total: number) => `Photo ${n} sur ${total}`, openPhoto: (n: number) => `Afficher la photo ${n}`, close: 'Fermer', closeTitle: 'Fermer (Échap)', previous: 'Photo précédente', previousTitle: 'Photo précédente (flèche gauche)', next: 'Photo suivante', nextTitle: 'Photo suivante (flèche droite)', toggleInfo: 'Afficher/masquer les informations', toggleInfoTitle: 'Afficher/masquer les informations (i)', hideInfo: 'Masquer les infos', info: 'Infos', loading: 'Chargement…', camera: 'Appareil', lens: 'Objectif', focalLength: 'Focale', aperture: 'Ouverture', shutter: 'Vitesse', iso: 'ISO', location: 'Lieu', noExif: 'Aucune donnée EXIF disponible', copyLink: 'Copier le lien de cette photo', copyLinkTitle: 'Copier le lien de cette photo (c)', copyLinkShort: 'Lien', copied: 'Copié', copyManual: 'Copiez ce lien', shortcuts: 'Raccourcis clavier', shortcutNavigate: 'Photo précédente / suivante', shortcutInfo: 'Informations sur la photo', shortcutFullscreen: 'Plein écran', shortcutExitFullscreen: 'Quitter le plein écran', download: 'Télécharger le fichier original', downloadTitle: 'Télécharger le fichier original (d)', downloadShort: 'Original', shortcutDownload: 'Télécharger l’original', shortcutSlideshow: 'Diaporama', shortcutSlideshowRunning: (seconds: number) => `Diaporama — toutes les ${seconds} s`, slideshowStopped: 'Diaporama arrêté', slideshowRunning: (seconds: number) => `Diaporama en cours, photo suivante toutes les ${seconds} secondes`, shortcutCopyLink: 'Copier le lien de cette photo', shortcutList: 'Cette liste', shortcutClose: 'Fermer la visionneuse', zoomIn: 'Zoomer en pleine résolution', zoomInTitle: 'Zoomer en pleine résolution (+ ou double-clic)', zoomOut: 'Ajuster la photo à l’écran', zoomOutTitle: 'Ajuster à l’écran (0 ou Échap)', zoomLoading: 'Chargement de la pleine résolution…', zoomUnavailable: 'La pleine résolution n’est pas disponible pour cette photo.', shortcutZoom: 'Zoom avant / arrière', shortcutZoomReset: 'Ajuster à l’écran', }, proofing: { addFavorite: 'Ajouter aux favoris', removeFavorite: 'Retirer des favoris', addToFavorites: 'Ajouter aux favoris', removeFromFavorites: 'Retirer des favoris', saved: 'Enregistré', favorite: 'Favori', showAll: 'Tout afficher', filterEmpty: 'Aucune photo sélectionnée.', selected: (n: number) => `❤️ ${n} ${isOne(n) ? 'sélectionnée' : 'sélectionnées'}`, shareExport: 'Partager & exporter', modalTitle: (n: number) => `❤️ Sélection (${n})`, closeModal: 'Fermer la fenêtre', intro: (n: number) => `Vous avez sélectionné ${plural(n, 'photo', 'photos')}. Choisissez une option d’export ci-dessous pour partager votre sélection :`, copyLink: 'Copier le lien de partage', linkCopied: 'Lien copié !', copyList: 'Copier la liste (#1, #2…)', listCopied: 'Liste copiée !', copyManualLink: 'Copiez ce lien', copyManualList: 'Copiez cette liste', sendEmail: '✉️ Envoyer un e-mail au photographe', downloadSelected: 'Télécharger la sélection (.zip)', clearSelection: 'Vider la sélection', confirmClear: 'Retirer tous les favoris sélectionnés ?', listEmpty: (albumName: string) => `${albumName} : aucune photo sélectionnée.`, listSummary: (albumName: string, count: number, indices: string) => `${albumName} — Photos sélectionnées (${count}) : ${indices}`, mailSubject: (n: number) => `Sélection de photos (${n})`, mailBody: (list: string, url: string) => `Bonjour,\n\nVoici ma sélection de photos :\n\n${list}\n\nLien de partage : ${url}\n\nCordialement,`, }, proofSession: { greeting: (name: string) => `Sélection pour ${name}`, intro: 'Touchez le cœur sur les photos que vous souhaitez. Votre sélection est enregistrée au fur et à mesure — vous pouvez revenir avec ce lien à tout moment.', saving: 'Enregistrement…', saved: 'Sélection enregistrée', saveFailed: 'Votre sélection n’a pas pu être enregistrée. Vérifiez votre connexion et réessayez.', review: 'Vérifier & envoyer', modalTitle: (n: number) => `Votre sélection (${n})`, empty: 'Aucune photo sélectionnée pour le moment.', submit: 'Envoyer la sélection', submitting: 'Envoi…', confirmSubmit: (n: number) => `Envoyer ${plural(n, 'photo', 'photos')} ? La sélection ne pourra plus être modifiée ensuite.`, submitted: 'Merci — votre sélection a été envoyée.', locked: 'Cette sélection a été envoyée et ne peut plus être modifiée.', validUntil: (date: string) => `Ce lien est valable jusqu’au ${date}.`, expiredTitle: 'Ce lien a expiré', expiredText: 'Demandez un nouveau lien à votre photographe.', downloadSelection: 'Télécharger la sélection (.zip)', downloadAll: 'Télécharger toutes les photos (.zip)', downloadsLeft: (n: number) => `${plural(n, 'téléchargement restant', 'téléchargements restants')}`, }, legal: { navLabel: 'Mentions légales', title: 'Mentions légales', subtitle: 'Informations conformément au § 5 DDG', address: 'Adresse', contact: 'Contact', email: 'E-mail', phone: 'Téléphone', contactForm: 'Formulaire de contact', taxSection: 'Informations fiscales', taxId: 'Numéro fiscal', vatId: 'Numéro de TVA', extraInfo: 'Informations complémentaires', }, contact: { navLabel: 'Contact', title: 'Contact', subtitle: 'Écrivez-moi un message', name: 'Nom', email: 'E-mail', message: 'Message', submit: 'Envoyer le message', sending: 'Envoi…', successTitle: 'Merci', successText: 'Votre message est bien arrivé. Je vous répondrai par e-mail.', invalid: 'Veuillez remplir tous les champs avec une adresse e-mail valide.', tooMany: 'Trop de messages en peu de temps. Réessayez dans une minute.', failed: 'Le message n’a pas pu être envoyé. Réessayez plus tard.', privacy: (days: number) => `Votre message est conservé sur le serveur de ce site, sert uniquement à vous répondre et est supprimé après ${days} ${isOne(days) ? 'jour' : 'jours'}.`, }, privacy: { navLabel: 'Confidentialité', title: 'Politique de confidentialité', }, };