Browse Source

Merge pull request #353 from devzwf/main

Added French language pack
MartinNYHC 3 months ago
parent
commit
232f64dbf8
3 changed files with 3355 additions and 1 deletions
  1. 1 0
      CONTRIBUTING.md
  2. 4 1
      frontend/src/i18n/index.ts
  3. 3350 0
      frontend/src/i18n/locales/fr.ts

+ 1 - 0
CONTRIBUTING.md

@@ -166,6 +166,7 @@ Translations live in `frontend/src/i18n/locales/`:
 |------|----------|
 | `en.ts` | English (primary) |
 | `de.ts` | German |
+| `fr.ts` | French |
 | `ja.ts` | Japanese |
 
 ### Adding New Strings

+ 4 - 1
frontend/src/i18n/index.ts

@@ -5,12 +5,14 @@ import LanguageDetector from 'i18next-browser-languagedetector';
 // Import translations directly for bundling
 import en from './locales/en';
 import de from './locales/de';
+import fr from './locales/fr';
 import ja from './locales/ja';
 import it from './locales/it';
 
 const resources = {
   en: { translation: en },
   de: { translation: de },
+  fr: { translation: fr },
   ja: { translation: ja },
   it: { translation: it },
 };
@@ -21,7 +23,7 @@ i18n
   .init({
     resources,
     fallbackLng: 'en',
-    supportedLngs: ['en', 'de', 'ja', 'it'],
+    supportedLngs: ['en', 'de', 'fr', 'ja', 'it'],
 
     detection: {
       // Order of detection methods
@@ -47,6 +49,7 @@ export default i18n;
 export const availableLanguages = [
   { code: 'en', name: 'English', nativeName: 'English' },
   { code: 'de', name: 'German', nativeName: 'Deutsch' },
+  { code: 'fr', name: 'French', nativeName: 'Français' },
   { code: 'ja', name: 'Japanese', nativeName: '日本語' },
   { code: 'it', name: 'Italian', nativeName: 'Italiano' },
 ];

+ 3350 - 0
frontend/src/i18n/locales/fr.ts

@@ -0,0 +1,3350 @@
+export default {
+  // Navigation
+  nav: {
+    printers: 'Imprimantes',
+    archives: 'Archives',
+    queue: 'File d\'attente',
+    stats: 'Statistiques',
+    profiles: 'Profils',
+    maintenance: 'Maintenance',
+    projects: 'Projets',
+    inventory: 'Filament',
+    files: 'Gestionnaire de fichiers',
+    settings: 'Paramètres',
+    system: 'Système',
+    collapseSidebar: 'Réduire la barre latérale',
+    expandSidebar: 'Développer la barre latérale',
+    update: 'Mise à jour',
+    updateAvailable: 'Mise à jour disponible : v{{version}}',
+    updateAvailableBanner: 'La version {{version}} est disponible !',
+    viewUpdate: 'Voir la mise à jour',
+    viewOnGithub: 'Voir sur GitHub',
+    keyboardShortcuts: 'Raccourcis clavier (?)',
+    switchToLight: 'Passer au mode clair',
+    switchToDark: 'Passer au mode sombre',
+    smartSwitches: 'Interrupteurs intelligents',
+    logout: 'Déconnexion',
+  },
+
+  // Common
+  common: {
+    save: 'Enregistrer',
+    saving: 'Enregistrement...',
+    cancel: 'Annuler',
+    delete: 'Supprimer',
+    edit: 'Modifier',
+    add: 'Ajouter',
+    close: 'Fermer',
+    confirm: 'Confirmer',
+    loading: 'Chargement...',
+    error: 'Erreur',
+    success: 'Succès',
+    warning: 'Avertissement',
+    enabled: 'Activé',
+    disabled: 'Désactivé',
+    yes: 'Oui',
+    no: 'Non',
+    on: 'On',
+    off: 'Off',
+    all: 'Tous',
+    none: 'Aucun',
+    search: 'Rechercher',
+    filter: 'Filtrer',
+    sort: 'Trier',
+    refresh: 'Actualiser',
+    download: 'Télécharger',
+    upload: 'Téléverser',
+    actions: 'Actions',
+    status: 'Statut',
+    name: 'Nom',
+    description: 'Description',
+    date: 'Date',
+    time: 'Heure',
+    hours: 'heures',
+    minutes: 'minutes',
+    seconds: 'secondes',
+    days: 'jours',
+    enable: 'Activer',
+    disable: 'Désactiver',
+    permissions: 'Autorisations',
+    noPrinters: 'Aucune imprimante configurée',
+    noData: 'Aucune donnée disponible',
+    linkNotFound: 'Lien non trouvé',
+    required: 'Requis',
+    optional: 'Optionnel',
+    dismiss: 'Ignorer',
+    apply: 'Appliquer',
+    reset: 'Réinitialiser',
+    export: 'Exporter',
+    import: 'Importer',
+    clear: 'Effacer',
+    selectAll: 'Tout sélectionner',
+    deselectAll: 'Tout désélectionner',
+    noChange: '— Aucun changement —',
+    unchanged: 'Inchangé',
+    unassigned: 'Non assigné',
+    unknown: 'Inconnu',
+    unknownError: 'Erreur inconnue',
+    today: 'Aujourd\'hui',
+    asap: 'Dès que possible',
+    overdue: 'En retard',
+    now: 'Maintenant',
+    collapse: 'Réduire',
+    expand: 'Développer',
+    viewArchive: 'Voir l\'archive',
+    viewInFileManager: 'Voir dans le gestionnaire de fichiers',
+    addedBy: 'Ajouté par {{username}}',
+    prints: 'impressions',
+    more: '+{{count}} de plus',
+    ascending: 'Croissant',
+    descending: 'Décroissant',
+    printer: 'Imprimante',
+    remove: 'Retirer',
+    type: 'Type',
+    print: 'Imprimer',
+    rename: 'Renommer',
+    move: 'Déplacer',
+    create: 'Créer',
+    duplicate: 'Dupliquer',
+    left: 'Gauche',
+    right: 'Droite',
+  },
+
+  // Printers page
+  printers: {
+    title: 'Imprimantes',
+    addPrinter: 'Ajouter une imprimante',
+    editPrinter: 'Modifier l\'imprimante',
+    deletePrinter: 'Supprimer l\'imprimante',
+    printerName: 'Nom de l\'imprimante',
+    serialNumber: 'Numéro de série',
+    ipAddress: 'Adresse IP / Nom d\'hôte',
+    accessCode: 'Code d\'accès',
+    model: 'Modèle',
+    nozzleCount: 'Nombre de buses',
+    autoArchive: 'Auto-archivage',
+    status: {
+      available: 'Disponible',
+      idle: 'Inactif',
+      printing: 'Impression en cours',
+      paused: 'En pause',
+      offline: 'Hors ligne',
+      error: 'Erreur',
+      finished: 'Terminé',
+      unknown: 'Inconnu',
+    },
+    temperatures: {
+      nozzle: 'Buse',
+      bed: 'Plateau',
+      chamber: 'Chambre',
+    },
+    progress: '{{percent}}% terminé',
+    timeRemaining: '{{time}} restant',
+    deleteConfirm: 'Êtes-vous sûr de vouloir supprimer "{{name}}" ?',
+    maintenanceOk: 'Maintenance OK',
+    maintenanceWarning: '{{count}} avertissement',
+    maintenanceWarning_plural: '{{count}} avertissements',
+    maintenanceDue: '{{count}} échéance',
+    maintenanceDue_plural: '{{count}} échéances',
+    // Sort options
+    sort: {
+      name: 'Nom',
+      status: 'Statut',
+      model: 'Modèle',
+      location: 'Emplacement',
+      ascending: 'Tri croissant',
+      descending: 'Tri décroissant',
+    },
+    // Card size
+    cardSize: {
+      small: 'Petites cartes',
+      medium: 'Cartes moyennes',
+      large: 'Grandes cartes',
+      extraLarge: 'Très grandes cartes',
+    },
+    // Controls
+    hideOffline: 'Masquer hors ligne',
+    nextAvailable: 'Prochaine disponible',
+    powerOn: 'Allumer',
+    offlinePrintersWithPlugs: 'Imprimantes hors ligne avec prises connectées',
+    noPrintersConfigured: 'Aucune imprimante configurée pour le moment',
+    // Printer card
+    readyToPrint: 'Prête à imprimer',
+    external: 'Externe',
+    deleteArchives: 'Supprimer les archives d\'impression',
+    noLabel: 'Pas d\'étiquette',
+    printPreview: 'Aperçu avant impression',
+    width: 'Largeur',
+    height: 'Hauteur',
+    noObjectsFound: 'Aucun objet trouvé',
+    objectsLoadedOnPrintStart: 'Les objets sont chargés au début de l\'impression',
+    willBeSkipped: 'Sera sauté',
+    name: 'Nom',
+    serialCannotBeChanged: 'Le numéro de série ne peut pas être modifié',
+    locationHelp: 'Utilisé pour grouper les imprimantes et filtrer la file d\'attente',
+    // WiFi signal strength
+    wifiSignal: {
+      veryWeak: 'Très faible',
+      weak: 'Faible',
+      fair: 'Moyen',
+      good: 'Bon',
+      excellent: 'Excellent',
+    },
+    // Maintenance
+    maintenanceUpToDate: 'Maintenance à jour - Cliquez pour voir',
+    // Chamber light
+    chamberLightOn: 'Allumer la lumière de la chambre',
+    chamberLightOff: 'Éteindre la lumière de la chambre',
+    // Files
+    browseFiles: 'Parcourir les fichiers de l\'imprimante',
+    // Smart plug
+    autoOffAfterPrint: 'Extinction auto après impression',
+    autoOffExecuted: 'Extinction auto exécutée - rallumez pour réinitialiser',
+    // HMS errors
+    hmsErrors: 'Erreurs HMS',
+    viewHmsErrors: 'Voir {{count}} erreur(s) HMS',
+    // Actions
+    resume: 'Reprendre',
+    pause: 'Pause',
+    stop: 'Arrêter',
+    camera: 'Caméra',
+    skipObject: 'Sauter l\'objet',
+    reconnect: 'Reconnecter',
+    mqttDebug: 'Débogage MQTT',
+    activeNozzle: 'Active : buse {{nozzle}}',
+    nozzleRack: 'Rack à buses',
+    nozzleDocked: 'Rangée',
+    nozzleMounted: 'Montée',
+    nozzleActive: 'Active',
+    nozzleIdle: 'Inactive',
+    nozzleDiameter: 'Diamètre',
+    nozzleType: 'Type',
+    nozzleStatus: 'Statut',
+    nozzleFilament: 'Filament',
+    nozzleWear: 'Usure',
+    nozzleMaxTemp: 'Temp Max',
+    nozzleSerial: 'Série',
+    nozzleHardenedSteel: 'Acier Trempé',
+    nozzleStainlessSteel: 'Acier Inoxydable',
+    nozzleTungstenCarbide: 'Carbure de Tungstène',
+    nozzleFlow: 'Débit',
+    nozzleHighFlow: 'Haut débit',
+    nozzleStandardFlow: 'Standard',
+    // Firmware
+    firmwareUpdate: 'Mise à jour Firmware',
+    firmwareInstructions: 'Sur l\'écran de l\'imprimante, allez dans',
+    firmwareNav: 'Naviguez vers',
+    settings: 'Paramètres',
+    firmware: 'Firmware',
+    // Discovery
+    discoverPrinters: 'Découvrir les imprimantes',
+    searching: 'Recherche...',
+    manualEntry: 'Saisie manuelle',
+    addFromCloud: 'Ajouter depuis le Cloud',
+    // Toast messages
+    toast: {
+      printerDeleted: 'Imprimante supprimée',
+      printerAdded: 'Imprimante ajoutée',
+      printerUpdated: 'Imprimante mise à jour',
+      failedToDelete: 'Échec de la suppression',
+      failedToAdd: 'Échec de l\'ajout',
+      failedToUpdate: 'Échec de la mise à jour',
+      commandSent: 'Commande envoyée',
+      failedToSendCommand: 'Échec de l\'envoi de la commande',
+      turnedOn: '{{name}} allumée',
+      failedToPowerOn: 'Échec de l\'allumage de {{name}}',
+      scriptTriggered: 'Script déclenché',
+      printStopped: 'Impression arrêtée',
+      printPaused: 'Impression en pause',
+      printResumed: 'Impression reprise',
+      referenceDeleted: 'Référence supprimée',
+      detectionAreaSaved: 'Zone de détection enregistrée',
+      failedToRunScript: 'Échec du script',
+      failedToStopPrint: 'Échec de l\'arrêt',
+      failedToPausePrint: 'Échec de la mise en pause',
+      failedToResumePrint: 'Échec de la reprise',
+      failedToControlChamberLight: 'Échec du contrôle de la lumière',
+      failedToUpdateSetting: 'Échec de mise à jour du paramètre',
+      failedToSkipObjects: 'Échec du saut d\'objets',
+      failedToRereadRfid: 'Échec lecture RFID',
+      failedToCheckPlate: 'Échec vérification plateau',
+      failedToUpdateLabel: 'Échec mise à jour étiquette',
+      failedToDeleteReference: 'Échec suppression référence',
+      failedToSaveDetectionArea: 'Échec enregistrement zone',
+      plateCheckEnabled: 'Vérification plateau activée',
+      plateCheckDisabled: 'Vérification plateau désactivée',
+      calibrationSaved: 'Calibration enregistrée !',
+      calibrationFailed: 'Échec de la calibration',
+      rfidRereadInitiated: 'Lecture RFID initiée',
+    },
+    // Connection status
+    connection: {
+      connected: 'Connecté',
+      offline: 'Hors ligne',
+    },
+    // Queue info
+    queue: {
+      inQueue: '{{count}} impression en file',
+      inQueue_plural: '{{count}} impressions en file',
+    },
+    // Controls section
+    controls: 'Contrôles',
+    // RFID
+    rfid: {
+      reread: 'Relire RFID',
+    },
+    // Permissions
+    permission: {
+      noAdd: 'Pas d\'autorisation pour ajouter',
+      noEdit: 'Pas d\'autorisation pour modifier',
+      noDelete: 'Pas d\'autorisation pour supprimer',
+      noControl: 'Pas d\'autorisation pour contrôler',
+      noFiles: 'Pas d\'autorisation pour les fichiers',
+      noAmsRfid: 'Pas d\'autorisation pour le RFID',
+      noSmartPlugControl: 'Pas d\'autorisation pour les prises',
+    },
+    // Add/Edit modal
+    modal: {
+      addTitle: 'Ajouter une imprimante',
+      editTitle: 'Modifier l\'imprimante',
+      myPrinter: 'Mon imprimante',
+      selectModel: 'Choisir un modèle...',
+      locationGroup: 'Emplacement / Groupe (optionnel)',
+      locationPlaceholder: 'ex: Atelier, Bureau',
+      autoArchiveLabel: 'Auto-archiver les impressions terminées',
+      fromPrinterSettings: 'Depuis les paramètres imprimante',
+      modelOptional: 'Modèle (optionnel)',
+      saveChanges: 'Enregistrer les modifications',
+    },
+    // Skip objects
+    skipObjects: {
+      tooltip: 'Sauter des objets',
+      onlyWhilePrinting: 'Sauter (uniquement pendant l\'impression)',
+      requiresMultiple: 'Sauter (nécessite 2+ objets)',
+      title: 'Sauter des objets',
+      matchIdsInfo: 'Faites correspondre les IDs avec l\'écran de l\'imprimante',
+      printerShowsIds: 'L\'écran affiche les IDs des objets sur le plateau',
+      skipSelected: 'Sauter la sélection',
+      skipping: 'Saut en cours...',
+      noObjectsSelected: 'Aucun objet sélectionné',
+      selectObjectsToSkip: 'Sélectionnez les objets à ignorer',
+      skipped: 'sauté',
+      objectsSkipped: 'Objets sautés',
+      activeCount: '{{count}} actifs',
+      waitForLayer: 'Attendez la couche 2 pour sauter des objets (actuelle : {{layer}})',
+      skip: 'Sauter',
+      confirmTitle: 'Sauter l\'objet ?',
+      confirmMessage: 'Voulez-vous vraiment sauter "{{name}}" ? Cette action est irréversible.',
+    },
+    // Confirm modals
+    confirm: {
+      deleteTitle: 'Supprimer l\'imprimante',
+      deleteMessage: 'Supprimer "{{name}}" ? Cela retirera tous les paramètres de connexion.',
+      deleteArchivesNote: 'Tout l\'historique sera définitivement supprimé.',
+      keepArchivesNote: 'L\'historique sera conservé mais plus associé à cette imprimante.',
+      stopTitle: 'Arrêter l\'impression',
+      stopMessage: 'Arrêter l\'impression sur "{{name}}" ?',
+      stopButton: 'Arrêter',
+      pauseTitle: 'Mettre en pause',
+      pauseMessage: 'Mettre en pause l\'impression sur "{{name}}" ?',
+      pauseButton: 'Pause',
+      resumeTitle: 'Reprendre l\'impression',
+      resumeMessage: 'Reprendre l\'impression sur "{{name}}" ?',
+      resumeButton: 'Reprendre',
+      powerOnTitle: 'Allumer l\'imprimante',
+      powerOnMessage: 'Allumer "{{name}}" ?',
+      powerOnButton: 'Allumer',
+      powerOffTitle: 'Éteindre l\'imprimante',
+      powerOffMessage: 'Éteindre "{{name}}" ?',
+      powerOffWarning: 'ATTENTION : "{{name}}" imprime ! L\'éteindre maintenant peut endommager l\'imprimante.',
+      powerOffButton: 'Éteindre',
+    },
+    // Discovery
+    discovery: {
+      title: 'Découvrir les imprimantes',
+      searching: 'Recherche...',
+      scanning: 'Scan en cours...',
+      scanProgress: 'Scan... {{scanned}}/{{total}}',
+      foundPrinters: '{{count}} imprimante(s) trouvée(s)',
+      noPrintersFound: 'Aucune imprimante trouvée',
+      noPrintersFoundSubnet: 'Aucune imprimante dans ce sous-réseau.',
+      noPrintersFoundNetwork: 'Aucune imprimante sur le réseau.',
+      allConfigured: 'Toutes les imprimantes trouvées sont déjà configurées.',
+      alreadyAdded: 'Déjà ajoutée',
+      select: 'Sélectionner',
+      manualEntry: 'Saisie manuelle',
+      addFromCloud: 'Ajouter depuis le Cloud',
+      subnetToScan: 'Sous-réseau à scanner',
+      dockerNote: 'Docker détecté. Entrez le sous-réseau en notation CIDR. Nécessite network_mode: host.',
+      scanSubnet: 'Scanner le sous-réseau',
+      discoverNetwork: 'Découvrir sur le réseau',
+      scanningSubnet: 'Scan du sous-réseau pour imprimantes Bambu...',
+      scanningNetwork: 'Scan du réseau...',
+      serialRequired: 'Série requis',
+      unknown: 'Inconnu',
+      failedToStart: 'Échec du démarrage de la découverte',
+    },
+    // Filaments section
+    filaments: 'Filaments',
+    // Camera
+    openCameraOverlay: 'Ouvrir la caméra en superposition',
+    openCameraWindow: 'Ouvrir la caméra dans une fenêtre',
+    // Firmware
+    firmwareUpdateAvailable: 'Mise à jour firmware : {{current}} → {{latest}}',
+    firmwareUpToDate: 'Firmware {{version}} — À jour',
+    firmwareUpdateButton: 'Mettre à jour',
+    // Plate detection
+    plateDetection: {
+      noPermission: 'Pas d\'autorisation de modification',
+      enabledClick: 'Vérification activée - Cliquez pour désactiver',
+      disabledClick: 'Vérification désactivée - Cliquez pour activer',
+      manageCalibration: 'Gérer la calibration de détection',
+      calibrationRequired: 'Calibration requise',
+      calibrationInstructions: 'Videz le plateau, puis cliquez sur Calibrer.',
+      calibrationDescription: 'Capture une image de référence du plateau vide.',
+      calibrationTip: 'Conseil : Stockez jusqu\'à 5 références. Le système utilise la meilleure correspondance.',
+      plateEmpty: 'Le plateau semble vide',
+      objectsDetected: 'Objets détectés sur le plateau',
+      confidence: 'Confiance',
+      difference: 'Différence',
+      analysisPreview: 'Aperçu de l\'analyse :',
+      analysisLegend: 'Cadre vert = zone, Rouge = différences',
+      savedReferences: 'Références ({{count}}/{{max}})',
+      deleteReference: 'Supprimer la référence',
+      labelPlaceholder: 'Étiquette...',
+      clickToEdit: '{{label}} - Modifier',
+      clickToAddLabel: 'Ajouter une étiquette',
+    },
+    // Fans
+    fans: {
+      partCooling: 'Ventilateur pièce',
+      auxiliary: 'Ventilateur auxiliaire',
+      chamber: 'Ventilateur chambre',
+    },
+    // HMS errors
+    clickToViewHmsErrors: 'Cliquez pour voir les erreurs HMS',
+    estimatedCompletion: 'Fin estimée',
+    slotOptions: 'Options du slot',
+    // Firmware modal
+    firmwareModal: {
+      title: 'Mise à jour Firmware',
+      titleUpToDate: 'Infos Firmware',
+      currentVersion: 'Actuelle :',
+      latestVersion: 'Dernière :',
+      releaseNotes: 'Notes de version',
+      checkingPrereqs: 'Vérification des prérequis...',
+      sdCardReady: 'Carte SD prête. Cliquez pour téléverser.',
+      uploadedSuccess: 'Firmware téléversé !',
+      applyInstructions: 'Pour appliquer sur l\'imprimante :',
+      step1: 'Sur l\'écran, allez dans Paramètres',
+      step2: 'Allez dans Firmware',
+      step3: 'Sélectionnez "Mettre à jour depuis carte SD"',
+      step4: 'Prévoyez 10-20 minutes',
+      done: 'Terminé',
+      starting: 'Démarrage...',
+      uploadFirmware: 'Téléverser le Firmware',
+      uploadFailed: 'Échec du téléversement : {{error}}',
+      uploadedToast: 'Firmware téléversé ! Lancez la mise à jour sur l\'écran.',
+    },
+    accessCodePlaceholder: 'Laissez vide pour garder l\'actuel',
+    // ROI editor
+    roi: {
+      title: 'Zone de détection (ROI)',
+      xStart: 'Début X',
+      yStart: 'Début Y',
+      width: 'Largeur',
+      height: 'Hauteur',
+      instruction: 'Ajustez le cadre vert pour cibler le plateau.',
+    },
+  },
+
+  // Archives page
+  archives: {
+    title: 'Archives d\'impression',
+    searchPlaceholder: 'Chercher dans les archives...',
+    filterByPrinter: 'Par imprimante',
+    filterByStatus: 'Par statut',
+    sortBy: 'Trier par',
+    sortNewest: 'Plus récent',
+    sortOldest: 'Plus ancien',
+    sortName: 'Nom',
+    sortDuration: 'Durée',
+    sortLargest: 'Plus volumineux',
+    sortSmallest: 'Plus léger',
+    sortSize: 'Taille',
+    noArchives: 'Aucune archive trouvée',
+    noArchivesSearch: 'Aucune archive ne correspond',
+    noArchivesYet: 'Pas encore d\'archive',
+    loadingArchives: 'Chargement...',
+    releaseToUpload: 'Relâcher pour téléverser',
+    showAll: 'Tout afficher',
+    showFavoritesOnly: 'Favoris uniquement',
+    gridView: 'Grille',
+    listView: 'Liste',
+    calendarView: 'Calendrier',
+    manageTags: 'Gérer les tags',
+    showFailedPrints: 'Afficher les échecs',
+    hideFailedPrints: 'Masquer les échecs',
+    printTime: 'Temps d\'impression',
+    filamentUsed: 'Filament utilisé',
+    cost: 'Coût',
+    reprint: 'Réimprimer',
+    preview: 'Aperçu',
+    deleteArchive: 'Supprimer l\'archive',
+    deleteConfirm: 'Supprimer cette archive ?',
+    favorite: 'Favori',
+    unfavorite: 'Retirer des favoris',
+    viewDetails: 'Détails',
+    status: {
+      completed: 'Réussi',
+      failed: 'Échoué',
+      stopped: 'Arrêté',
+    },
+    toast: {
+      source3mfAttached: 'Source 3MF attachée : {{filename}}',
+      failedUploadSource3mf: 'Échec téléversement 3MF',
+      source3mfRemoved: 'Source 3MF retirée',
+      failedRemoveSource3mf: 'Échec retrait 3MF',
+      f3dAttached: 'F3D attaché : {{filename}}',
+      failedUploadF3d: 'Échec téléversement F3D',
+      f3dRemoved: 'F3D retiré',
+      failedRemoveF3d: 'Échec retrait F3D',
+      timelapseAttached: 'Timelapse attaché : {{filename}}',
+      timelapseAlreadyAttached: 'Timelapse déjà présent',
+      noMatchingTimelapse: 'Pas de timelapse correspondant',
+      failedScanTimelapse: 'Échec scan timelapse',
+      failedAttachTimelapse: 'Échec attache timelapse',
+      archiveDeleted: 'Archive supprimée',
+      failedDeleteArchive: 'Échec suppression',
+      addedToFavorites: 'Ajouté aux favoris',
+      removedFromFavorites: 'Retiré des favoris',
+      projectUpdated: 'Projet mis à jour',
+      failedUpdateProject: 'Échec mise à jour projet',
+      linkCopied: 'Lien copié',
+      failedCopyLink: 'Échec copie lien',
+      photoDeleted: 'Photo supprimée',
+      failedDeletePhoto: 'Échec suppression photo',
+      failedDeleteArchives: 'Échec suppression archives',
+      failedUpdateFavorites: 'Échec mise à jour favoris',
+      exportDownloaded: 'Export téléchargé',
+      exportFailed: 'Échec export',
+    },
+    menu: {
+      print: 'Imprimer',
+      schedule: 'Planifier',
+      openInBambuStudio: 'Ouvrir dans le Slicer',
+      slice: 'Découper',
+      externalLink: 'Lien externe',
+      viewOnMakerWorld: 'Voir sur MakerWorld',
+      preview3d: 'Aperçu 3D',
+      viewTimelapse: 'Voir le Timelapse',
+      scanForTimelapse: 'Scanner pour Timelapse',
+      downloadSource3mf: 'Télécharger Source 3MF',
+      uploadSource3mf: 'Téléverser Source 3MF',
+      replaceSource3mf: 'Remplacer Source 3MF',
+      removeSource3mf: 'Retirer Source 3MF',
+      uploadF3d: 'Téléverser F3D',
+      replaceF3d: 'Remplacer F3D',
+      downloadF3d: 'Télécharger F3D',
+      removeF3d: 'Retirer F3D',
+      download: 'Télécharger',
+      copyDownloadLink: 'Copier lien de téléchargement',
+      qrCode: 'Code QR',
+      viewPhotos: 'Voir les photos',
+      viewPhotosCount: 'Voir les photos ({{count}})',
+      projectPage: 'Page du Projet',
+      addToFavorites: 'Ajouter aux favoris',
+      removeFromFavorites: 'Retirer des favoris',
+      edit: 'Modifier',
+      goToProject: 'Aller au Projet : {{name}}',
+      addToProject: 'Ajouter au Projet',
+      removeFromProject: 'Retirer du Projet',
+      loading: 'Chargement...',
+      noProjectsAvailable: 'Aucun projet disponible',
+      select: 'Sélectionner',
+      deselect: 'Désélectionner',
+      delete: 'Supprimer',
+    },
+    permission: {
+      noReprint: 'Pas d\'autorisation de réimpression',
+      noAddToQueue: 'Pas d\'autorisation pour la file',
+      noUpdateArchives: 'Pas d\'autorisation de mise à jour',
+      noUploadFiles: 'Pas d\'autorisation de téléversement',
+      noDownload: 'Pas d\'autorisation de téléchargement',
+      noCopyLink: 'Pas d\'autorisation de copie lien',
+      noDelete: 'Pas d\'autorisation de suppression',
+      noCreate: 'Pas d\'autorisation de création',
+    },
+    card: {
+      previousPlate: 'Plateau précédent',
+      nextPlate: 'Plateau suivant',
+      plateNumber: 'Plateau {{index}}',
+      moreOptions: 'Clic droit pour plus d\'options',
+      addToFavorites: 'Ajouter aux favoris',
+      removeFromFavorites: 'Retirer des favoris',
+      cancelled: 'annulé',
+      failed: 'échoué',
+      duplicate: 'doublon',
+      duplicateTitle: 'Ce modèle a déjà été imprimé',
+      openSource3mf: 'Ouvrir 3MF dans Bambu Studio (clic droit pour plus)',
+      downloadF3d: 'Télécharger fichier Fusion 360',
+      viewTimelapse: 'Voir timelapse',
+      viewPhoto: 'Voir 1 photo',
+      viewPhotos: 'Voir {{count}} photos',
+      openFolder: 'Ouvrir le dossier : {{name}}',
+      slicedFile: 'Fichier découpé - prêt',
+      sourceFile: 'Fichier source uniquement - pas de mapping AMS',
+      gcode: 'GCODE',
+      source: 'SOURCE',
+      project: 'Projet : {{name}}',
+      estimated: 'Estimé : {{time}}',
+      actual: 'Réel : {{time}}',
+      accuracy: 'Précision : {{percent}}%',
+      filament: '{{weight}}g',
+      layer: '{{count}} couche',
+      layers: '{{count}} couches',
+      object: '{{count}} objet',
+      objects: '{{count}} objets',
+      slicedFor: 'Découpé pour {{model}}',
+      uploadedBy: 'Téléversé par',
+      noPermissionReprint: 'Pas d\'autorisation de réimpression',
+      noPermissionEdit: 'Pas d\'autorisation de modification',
+      noPermissionDelete: 'Pas d\'autorisation de suppression',
+      reprint: 'Réimprimer',
+      schedulePrint: 'Planifier',
+      schedule: 'Planifier',
+      openInBambuStudio: 'Ouvrir dans le Slicer',
+      openInBambuStudioToSlice: 'Ouvrir dans le Slicer pour découper',
+      slice: 'Découper',
+      externalLink: 'Lien externe',
+      makerWorld: 'MakerWorld : {{designer}}',
+      viewProject: 'Voir projet',
+      noExternalLink: 'Aucun lien externe',
+      preview3d: 'Aperçu 3D',
+      download: 'Télécharger',
+      edit: 'Modifier',
+      delete: 'Supprimer',
+    },
+    modal: {
+      deleteArchive: 'Supprimer l\'archive',
+      deleteConfirm: 'Supprimer "{{name}}" ? Cette action est irréversible.',
+      deleteButton: 'Supprimer',
+      removeSource3mf: 'Retirer Source 3MF',
+      removeSource3mfConfirm: 'Retirer le fichier 3MF de "{{name}}" ?',
+      removeButton: 'Retirer',
+      removeF3d: 'Retirer F3D',
+      removeF3dConfirm: 'Retirer le fichier Fusion 360 de "{{name}}" ?',
+      timelapse: '{{name}} - Timelapse',
+      selectTimelapse: 'Choisir un Timelapse',
+      selectTimelapseDesc: 'Sélectionnez manuellement le timelapse :',
+      deleteArchives: 'Supprimer les archives',
+      deleteArchivesConfirm: 'Supprimer {{count}} archive(s) ?',
+      deleteCount: 'Supprimer {{count}}',
+    },
+    page: {
+      title: 'Archives',
+      printsCount: '{{filtered}} sur {{total}} impressions',
+      dropFilesHere: 'Déposez les fichiers .3mf ici',
+      releaseToUpload: 'Relâcher pour téléverser',
+      only3mfSupported: 'Seuls les fichiers .3mf sont supportés',
+      close: 'Fermer',
+      selected: '{{count}} sélectionnés',
+      selectAll: 'Tout sélectionner',
+      tags: 'Tags',
+      project: 'Projet',
+      favorite: 'Favori',
+      delete: 'Supprimer',
+      toggledFavorites: 'Favoris mis à jour pour {{count}} archive(s)',
+      failedUpdateFavorites: 'Échec mise à jour favoris',
+      archivesDeleted: '{{count}} archive(s) supprimée(s)',
+      failedDeleteArchives: 'Échec suppression',
+      photoDeleted: 'Photo supprimée',
+      failedDeletePhoto: 'Échec suppression photo',
+    },
+    list: {
+      name: 'Nom',
+      printer: 'Imprimante',
+      date: 'Date',
+      size: 'Taille',
+      actions: 'Actions',
+      hasTimelapse: 'A un timelapse',
+    },
+  },
+
+  // Queue page
+  queue: {
+    title: 'File d\'attente',
+    subtitle: 'Gérez vos travaux d\'impression',
+    addToQueue: 'Ajouter à la file',
+    // Print modal
+    print: 'Imprimer',
+    reprint: 'Réimprimer',
+    schedulePrint: 'Planifier',
+    editQueueItem: 'Modifier l\'élément',
+    printToPrinters: 'Imprimer sur {{count}} imprimantes',
+    queueToPrinters: 'Ajouter à la file pour {{count}} imprimantes',
+    sending: 'Envoi...',
+    sendingProgress: 'Envoi {{current}}/{{total}}...',
+    adding: 'Ajout...',
+    addingProgress: 'Ajout {{current}}/{{total}}...',
+    savingProgress: 'Enregistrement {{current}}/{{total}}...',
+    clearQueue: 'Vider la file',
+    clearHistory: 'Effacer l\'historique',
+    emptyQueue: 'La file est vide',
+    position: 'Position',
+    scheduledTime: 'Heure prévue',
+    moveUp: 'Monter',
+    moveDown: 'Descendre',
+    startNow: 'Démarrer maintenant',
+    printingInProgress: 'Impression en cours...',
+    viewArchive: 'Voir l\'archive',
+    viewInFileManager: 'Voir dans le gestionnaire',
+    itemCount: '{{count}} élément',
+    itemCount_plural: '{{count}} éléments',
+    dragToReorder: 'Glisser pour réordonner (ASAP uniquement)',
+    reorderHint: 'La position n\'affecte que les éléments ASAP.',
+    addedBy: 'Ajouté par {{name}}',
+    nextInQueue: 'Prochain en file',
+    clearPlate: 'Vider plateau & lancer suivant',
+    clearPlateSuccess: 'Plateau vidé — prêt pour l\'impression suivante',
+    plateReady: 'Plateau vidé — prêt pour l\'impression suivante',
+    // Sections
+    sections: {
+      currentlyPrinting: 'En cours',
+      queued: 'En attente',
+      history: 'Historique',
+    },
+    // Status
+    status: {
+      pending: 'En attente',
+      waiting: 'En attente',
+      printing: 'Impression',
+      paused: 'En pause',
+      completed: 'Terminé',
+      failed: 'Échoué',
+      skipped: 'Sauté',
+      cancelled: 'Annulé',
+    },
+    // Summary cards
+    summary: {
+      printing: 'Impressions',
+      queued: 'En attente',
+      totalTime: 'Temps total estimé',
+      history: 'Historique',
+    },
+    // Filters
+    filter: {
+      allPrinters: 'Toutes les imprimantes',
+      unassigned: 'Non assigné',
+      allStatus: 'Tous les statuts',
+      allLocations: 'Tous les emplacements',
+      any: 'Tout',
+    },
+    // Sort
+    sort: {
+      byPosition: 'Par position',
+      byName: 'Par nom',
+      byPrinter: 'Par imprimante',
+      bySchedule: 'Par planification',
+      byDate: 'Par date',
+      ascendingOldest: 'Croissant (plus vieux)',
+      descendingNewest: 'Décroissant (plus récent)',
+    },
+    // Badges
+    badges: {
+      staged: 'Préparé',
+      requiresPrevious: 'Nécessite succès précédent',
+      autoPowerOff: 'Extinction auto',
+    },
+    // Empty state
+    empty: {
+      title: 'Aucune impression prévue',
+      description: 'Planifiez depuis les Archives ou glissez des fichiers ici.',
+    },
+    // Time
+    time: {
+      asap: 'Dès que possible',
+      overdue: 'En retard',
+      now: 'Maintenant',
+      lessThanMinute: 'Dans moins d\'une minute',
+      inMinutes: 'Dans {{count}} min',
+      inHours: 'Dans {{count}} heures',
+    },
+    // Actions
+    actions: {
+      stopPrint: 'Arrêter',
+      startPrint: 'Démarrer',
+      requeue: 'Remettre en file',
+    },
+    // Bulk edit
+    bulkEdit: {
+      title: 'Modifier {{count}} élément',
+      title_plural: 'Modifier {{count}} éléments',
+      description: 'Seuls les changements seront appliqués.',
+      printer: 'Imprimante',
+      noChange: '— Aucun changement —',
+      queueOptions: 'Options de file',
+      staged: 'Préparé (manuel)',
+      autoPowerOff: 'Extinction auto après',
+      requirePrevious: 'Requiert succès précédent',
+      printOptions: 'Options d\'impression',
+      bedLevelling: 'Nivellement plateau',
+      flowCalibration: 'Calibration débit',
+      vibrationCalibration: 'Vibration (Input Shaper)',
+      layerInspection: 'Inspection 1ère couche',
+      timelapse: 'Timelapse',
+      useAms: 'Utiliser AMS',
+      applyChanges: 'Appliquer',
+      selectAll: 'Tout sélectionner',
+      deselectAll: 'Tout désélectionner',
+      selected: '{{count}} sélectionnés',
+      editSelected: 'Modifier la sélection',
+      cancelSelected: 'Annuler la sélection',
+    },
+    // Confirmations
+    confirm: {
+      cancelTitle: 'Annuler l\'impression prévue',
+      cancelMessage: 'Annuler "{{name}}" ?',
+      stopTitle: 'Arrêter l\'impression',
+      stopMessage: 'Arrêter "{{name}}" sur l\'imprimante ?',
+      removeTitle: 'Retirer de l\'historique',
+      removeMessage: 'Retirer "{{name}}" de l\'historique ?',
+      clearHistoryTitle: 'Effacer l\'historique',
+      clearHistoryMessage: 'Retirer les {{count}} éléments ?',
+      cancelButton: 'Annuler l\'impression',
+      stopButton: 'Arrêter l\'impression',
+      thisPrint: 'cette impression',
+      thisItem: 'cet élément',
+    },
+    // Toast messages
+    toast: {
+      cancelled: 'Élément annulé',
+      cancelFailed: 'Échec annulation',
+      removed: 'Élément retiré',
+      removeFailed: 'Échec retrait',
+      stopped: 'Impression arrêtée',
+      stopFailed: 'Échec arrêt',
+      released: 'Libéré dans la file',
+      startFailed: 'Échec démarrage',
+      reorderFailed: 'Échec réorganisation',
+      historyCleared: '{{count}} éléments effacés',
+      clearHistoryFailed: 'Échec effacement',
+      updateFailed: 'Échec mise à jour',
+      bulkCancelled: '{{count}} éléments annulés',
+      bulkCancelFailed: 'Échec annulation',
+    },
+    // Permissions
+    permissions: {
+      noStopPrint: 'Pas d\'autorisation d\'arrêt',
+      noStartPrint: 'Pas d\'autorisation de démarrage',
+      noEdit: 'Pas d\'autorisation de modification',
+      noCancel: 'Pas d\'autorisation d\'annulation',
+      noRequeue: 'Pas d\'autorisation de remise en file',
+      noRemove: 'Pas d\'autorisation de retrait',
+      noClearHistory: 'Pas d\'autorisation historique',
+      noEditItems: 'Pas d\'autorisation modification groupée',
+      noCancelItems: 'Pas d\'autorisation annulation groupée',
+    },
+  },
+
+  // Statistics page
+  stats: {
+    title: 'Tableau de bord',
+    subtitle: 'Glissez les widgets pour réorganiser. Cliquez sur l\'œil pour masquer.',
+    overview: 'Vue d\'ensemble',
+    totalPrints: 'Total impressions',
+    successRate: 'Taux de succès',
+    totalPrintTime: 'Temps total d\'impression',
+    printTime: 'Temps d\'impression',
+    totalFilament: 'Total filament utilisé',
+    filamentUsed: 'Filament utilisé',
+    filamentCost: 'Coût filament',
+    totalCost: 'Coût total',
+    energyUsed: 'Énergie consommée',
+    energyCost: 'Coût énergie',
+    averagePrintTime: 'Temps moyen par impression',
+    printsPerDay: 'Impressions par jour',
+    byPrinter: 'Par imprimante',
+    printsByPrinter: 'Impressions par imprimante',
+    byMaterial: 'Par matériau',
+    byMonth: 'Par mois',
+    last7Days: '7 derniers jours',
+    last30Days: '30 derniers jours',
+    last90Days: '90 derniers jours',
+    allTime: 'Tout le temps',
+    // Widgets
+    quickStats: 'Stats rapides',
+    printActivity: 'Activité d\'impression',
+    filamentTypes: 'Types de filament',
+    filamentTrends: 'Tendances filament',
+    failureAnalysis: 'Analyse des échecs',
+    timeAccuracy: 'Précision du temps',
+    successful: 'Succès :',
+    failed: 'Échecs :',
+    perfectEstimate: '100% = estimation parfaite',
+    noTimeAccuracyData: 'Pas encore de données de précision',
+    noFilamentData: 'Aucune donnée de filament',
+    noPrinterData: 'Aucune donnée d\'imprimante',
+    noPrintData: 'Aucune donnée d\'impression',
+    noPrintDataLast30Days: 'Aucune impression ces 30 derniers jours',
+    failureReasons: 'Raisons des échecs',
+    topFailureReasons: 'Top raisons d\'échec',
+    failedPrintsCount: '{{failed}} / {{total}} impressions ont échoué',
+    lastWeekRate: 'Semaine dernière : {{rate}}%',
+    // Actions
+    resetLayout: 'Réinitialiser la mise en page',
+    recalculateCosts: 'Recalculer les coûts',
+    recalculateCostsHint: 'Recalcule les coûts avec les prix actuels des filaments',
+    exportStats: 'Exporter les stats',
+    exportAsCsv: 'Exporter en CSV',
+    exportAsExcel: 'Exporter en Excel',
+    hiddenCount: '{{count}} Masqués',
+    // Toast
+    exportDownloaded: 'Export téléchargé',
+    exportFailed: 'Échec export',
+    layoutReset: 'Mise en page réinitialisée',
+    recalculatedCosts: 'Coûts recalculés pour {{count}} archives',
+    recalculateFailed: 'Échec du calcul',
+    // Loading
+    loadingStats: 'Chargement des statistiques...',
+    // Permissions
+    noPermissionResetLayout: 'Pas d\'autorisation de réinitialisation',
+    noPermissionRecalculate: 'Pas d\'autorisation de recalcul',
+  },
+
+  // Maintenance page
+  maintenance: {
+    title: 'Maintenance',
+    overview: 'Vue d\'ensemble',
+    allOk: 'Toute la maintenance est à jour',
+    dueCount: '{{count}} tâche à faire',
+    dueCount_plural: '{{count}} tâches à faire',
+    warningCount: '{{count}} avertissement',
+    warningCount_plural: '{{count}} avertissements',
+    totalPrintTime: 'Temps d\'impression total',
+    nextMaintenance: 'Prochaine maintenance',
+    nothingDue: 'Rien de prévu',
+    tasks: 'Tâches',
+    lastPerformed: 'Dernière réalisation',
+    interval: 'Intervalle',
+    hoursRemaining: '{{hours}}h restantes',
+    hoursOverdue: '{{hours}}h de retard',
+    markDone: 'Marquer comme fait',
+    performMaintenance: 'Effectuer la maintenance',
+    history: 'Historique',
+    noHistory: 'Aucun historique',
+    editPrintHours: 'Modifier les heures d\'impression',
+    currentHours: 'Heures actuelles',
+    // Tabs
+    statusTab: 'Statut',
+    settingsTab: 'Paramètres',
+    // Status
+    overdueCount: '{{count}} en retard',
+    dueSoonCount: '{{count}} bientôt',
+    dueSoon: 'Bientôt',
+    allGood: 'Tout va bien',
+    overdueBy: 'Retard de {{duration}}',
+    dueIn: 'Dans {{duration}}',
+    timeLeft: '{{duration}} restant',
+    // Duration formats
+    day: '1 jour',
+    days: '{{count}} jours',
+    week: '1 semaine',
+    weeks: '{{count}} semaines',
+    month: '1 mois',
+    months: '{{count}} mois',
+    year: '1 an',
+    // Settings
+    maintenanceTypes: 'Types de maintenance',
+    maintenanceTypesDescription: 'Types système et tâches personnalisées',
+    addCustomType: 'Ajouter un type',
+    intervalType: 'Type d\'intervalle',
+    intervalValue: 'Intervalle ({{type}})',
+    icon: 'Icône',
+    documentationLink: 'Lien documentation (optionnel)',
+    assignToPrinters: 'Assigner aux imprimantes',
+    selectAtLeastOnePrinter: 'Sélectionnez au moins une imprimante',
+    addType: 'Ajouter le type',
+    custom: 'Personnalisé',
+    printHours: 'Heures d\'impression',
+    calendarDays: 'Jours calendaires',
+    exampleName: 'ex: Remplacement filtre HEPA',
+    viewDocumentation: 'Voir documentation',
+    timeBasedInterval: 'Intervalle temporel',
+    // Interval overrides
+    intervalOverrides: 'Exceptions d\'intervalle',
+    intervalOverridesDescription: 'Intervalles spécifiques par imprimante',
+    // Printer assignment
+    assignedToPrinters: 'Assigné aux imprimantes :',
+    noPrintersAssigned: 'Aucune imprimante assignée',
+    addPrinterShort: 'Ajouter :',
+    printersAssignedClick: '{{count}} imprimante(s) assignée(s) - gérer',
+    removeFromPrinter: 'Retirer de cette imprimante',
+    // Types
+    types: {
+      lubricateCarbonRods: 'Lubrifier les tiges carbone',
+      lubricateRails: 'Lubrifier les rails linéaires',
+      cleanNozzle: 'Nettoyer la buse / hotend',
+      checkBelts: 'Vérifier la tension des courroies',
+      cleanBuildPlate: 'Nettoyer le plateau',
+      checkExtruder: 'Vérifier les engrenages de l\'extrudeur',
+      checkCooling: 'Vérifier les ventilateurs',
+      generalInspection: 'Inspection générale',
+      cleanCarbonRods: 'Nettoyer les tiges carbone',
+      cleanLinearRails: 'Nettoyer les rails linéaires',
+      checkPtfeTube: 'Vérifier le tube PTFE',
+      replaceHepaFilter: 'Remplacer le filtre HEPA',
+      replaceCarbonFilter: 'Remplacer le filtre charbon',
+      lubricateLeftNozzleRail: 'Lubrifier le rail de buse gauche',
+    },
+    // Toast
+    maintenanceComplete: 'Maintenance marquée comme faite',
+    typeUpdated: 'Type mis à jour',
+    typeDeleted: 'Type supprimé',
+    printHoursUpdated: 'Heures mises à jour',
+    printerAssigned: 'Imprimante assignée',
+    printerRemoved: 'Imprimante retirée',
+    // Confirmation
+    deleteTypeConfirm: 'Supprimer "{{name}}" ?',
+    // Permissions
+    noPermissionUpdate: 'Pas d\'autorisation de mise à jour',
+    noPermissionPerform: 'Pas d\'autorisation d\'action',
+    noPermissionEditTypes: 'Pas d\'autorisation de modification types',
+    noPermissionDeleteTypes: 'Pas d\'autorisation de suppression types',
+    noPermissionEditHours: 'Pas d\'autorisation de modification heures',
+    noPermissionRemovePrinter: 'Pas d\'autorisation retrait imprimante',
+    noPermissionAssignPrinter: 'Pas d\'autorisation assignation',
+    noPermissionEditIntervals: 'Pas d\'autorisation modification intervalles',
+    // Configure link
+    configureSettings: 'Configurer types et intervalles',
+  },
+
+  // Settings page
+  settings: {
+    title: 'Paramètres',
+    general: 'Général',
+    // Tab names
+    tabs: {
+      general: 'Général',
+      smartPlugs: 'Prises connectées',
+      notifications: 'Notifications',
+      filament: 'Filament',
+      network: 'Réseau',
+      apiKeys: 'Clés API',
+      virtualPrinter: 'Imprimante virtuelle',
+      users: 'Authentification',
+      backup: 'Sauvegarde',
+      emailAuth: 'Authentification Email',
+    },
+    // Email settings
+    email: {
+      smtpSettings: 'Configuration SMTP',
+      smtpHost: 'Serveur SMTP',
+      smtpPort: 'Port SMTP',
+      security: 'Sécurité',
+      authentication: 'Authentification',
+      username: 'Utilisateur',
+      password: 'Mot de passe',
+      fromEmail: 'Email expéditeur',
+      fromName: 'Nom expéditeur',
+      testConnection: 'Tester la connexion SMTP',
+      testRecipient: 'Email test destinataire',
+      sendTest: 'Envoyer email test',
+      sending: 'Envoi...',
+      save: 'Enregistrer les paramètres',
+      saving: 'Enregistrement...',
+      advancedAuth: 'Authentification avancée',
+      advancedAuthEnabled: 'L\'authentification avancée est activée',
+      advancedAuthEnabledDesc: 'La gestion des utilisateurs par email est active. Les nouveaux utilisateurs recevront un mot de passe auto-généré.',
+      advancedAuthDisabled: 'Authentification avancée désactivée',
+      advancedAuthDisabledDesc: 'Activez pour les fonctionnalités liées à l\'email (mot de passe oublié, etc).',
+      enable: 'Activer',
+      disable: 'Désactiver',
+      feature1: 'Génération auto et envoi de mots de passe par email',
+      feature2: 'Connexion par utilisateur ou email',
+      feature3: 'Réinitialisation mot de passe oublié disponible',
+      feature4: 'Réinitialisation admin par email',
+      // Error messages
+      errors: {
+        requiredFields: 'Remplissez tous les champs requis',
+        usernameRequired: 'L\'utilisateur est requis pour l\'authentification',
+        enterTestEmail: 'Entrez une adresse email de test',
+        smtpServerAndEmail: 'Serveur et expéditeur requis pour le test',
+        usernamePasswordRequired: 'Utilisateur et mot de passe requis pour l\'auth',
+        configureSmtpFirst: 'Configurez et testez le SMTP d\'abord',
+      },
+      // Success messages
+      success: {
+        settingsSaved: 'Paramètres SMTP enregistrés',
+      },
+      // Security options
+      securityOptions: {
+        starttls: 'STARTTLS (Port 587)',
+        ssl: 'SSL/TLS (Port 465)',
+        none: 'Aucun (Port 25)',
+      },
+      // Authentication options
+      authOptions: {
+        enabled: 'Activée',
+        disabled: 'Désactivée',
+      },
+    },
+    appearance: 'Apparence',
+    notifications: 'Notifications',
+    smartPlugs: 'Prises connectées',
+    spoolman: 'Spoolman',
+    updates: 'Mises à jour',
+    language: 'Langue',
+    languageDescription: 'Choisissez votre langue',
+    theme: 'Thème',
+    themeLight: 'Clair',
+    themeDark: 'Sombre',
+    themeSystem: 'Système',
+    defaultView: 'Vue par défaut',
+    defaultViewDescription: 'Page affichée au démarrage',
+    checkForUpdates: 'Vérifier les mises à jour',
+    autoUpdate: 'Mise à jour auto',
+    currentVersion: 'Version actuelle',
+    latestVersion: 'Dernière version',
+    upToDate: 'Bambuddy est à jour',
+    updateAvailable: 'Mise à jour disponible',
+    // Notifications
+    notificationLanguage: 'Langue des notifications',
+    notificationLanguageDescription: 'Langue pour les notifications push',
+    notificationProviders: 'Fournisseurs de notifications',
+    addProvider: 'Ajouter un fournisseur',
+    editProvider: 'Modifier le fournisseur',
+    providerType: 'Type de fournisseur',
+    testNotification: 'Tester la notification',
+    testSuccess: 'Notification de test envoyée',
+    testFailed: 'Échec de l\'envoi du test',
+    quietHours: 'Heures de silence',
+    quietHoursDescription: 'Ne pas déranger pendant ces heures',
+    quietHoursStart: 'Début',
+    quietHoursEnd: 'Fin',
+    events: {
+      title: 'Événements de notification',
+      printStart: 'Impression démarrée',
+      printComplete: 'Impression terminée',
+      printFailed: 'Impression échouée',
+      printStopped: 'Impression arrêtée',
+      printProgress: 'Jalons de progression',
+      printProgressDescription: 'Notifier à 25%, 50%, 75%',
+      printerOffline: 'Imprimante hors ligne',
+      printerError: 'Erreur imprimante',
+      filamentLow: 'Filament bas',
+      maintenanceDue: 'Maintenance due',
+      maintenanceDueDescription: 'Notifier quand une tâche est due',
+    },
+    // Smart Plugs
+    smartPlug: {
+      title: 'Prises connectées',
+      add: 'Ajouter une prise',
+      edit: 'Modifier la prise',
+      name: 'Nom',
+      ipAddress: 'Adresse IP',
+      linkedPrinter: 'Imprimante liée',
+      autoOn: 'Allumage auto',
+      autoOnDescription: 'Allumer au début de l\'impression',
+      autoOff: 'Extinction auto',
+      autoOffDescription: 'Éteindre après l\'impression',
+      offDelay: 'Délai d\'extinction',
+      offDelayMinutes: 'Minutes après fin',
+      offDelayTemp: 'Quand la buse est sous',
+      currentState: 'État actuel',
+      turnOn: 'Allumer',
+      turnOff: 'Éteindre',
+    },
+    // Filament Tracking Mode
+    filamentTracking: 'Suivi de Filament',
+    filamentTrackingDesc: 'Choisissez comment suivre vos bobines. Utilisez l\'inventaire intégré ou connectez un serveur Spoolman.',
+    trackingModeBuiltIn: 'Inventaire Intégré',
+    trackingModeBuiltInDesc: 'Correspondance RFID et suivi de consommation inclus',
+    trackingModeSpoolmanDesc: 'Serveur de gestion externe',
+    builtInFeatureRfid: 'Détecte auto les bobines RFID Bambu Lab dans l\'AMS',
+    builtInFeatureUsage: 'Suit la consommation par impression',
+    builtInFeatureCatalog: 'Gère bobines, couleurs et profils facteur K',
+    // Spoolman settings
+    spoolmanUrl: 'URL Spoolman',
+    spoolmanUrlHint: 'URL de votre serveur Spoolman (ex: http://localhost:7912)',
+    spoolmanConnected: 'Connecté',
+    spoolmanDisconnected: 'Déconnecté',
+    status: 'Statut',
+    connect: 'Connecter',
+    disconnect: 'Déconnecter',
+    howSyncWorks: 'Fonctionnement de la Sync',
+    syncInfoRfidOnly: 'Seules les bobines officielles RFID sont synchronisées',
+    syncInfoAutoCreate: 'Les bobines sont créées dans Spoolman à la 1ère sync',
+    syncInfoThirdPartySkipped: 'Les bobines tierces ou rechargées sont ignorées',
+    linkingExistingSpools: 'Lier des bobines existantes',
+    linkingExistingSpoolsDesc: 'Pour lier une bobine Spoolman, survolez un slot AMS et cliquez sur "Lier à Spoolman".',
+    syncMode: 'Mode de Sync',
+    syncModeAuto: 'Automatique',
+    syncModeManual: 'Manuel uniquement',
+    syncModeAutoDesc: 'Sync auto lors de changements AMS',
+    syncModeManualDesc: 'Sync uniquement sur déclenchement manuel',
+    syncAmsData: 'Synchroniser AMS',
+    syncAmsDataDesc: 'Synchroniser manuellement les données vers Spoolman',
+    allPrinters: 'Toutes les imprimantes',
+    // Default printer
+    noDefaultPrinter: 'Aucune par défaut (demander à chaque fois)',
+    // Sidebar
+    sidebarOrder: 'Ordre de la barre latérale',
+    // Camera
+    saveThumbnails: 'Enregistrer les vignettes',
+    captureFinishPhoto: 'Prendre une photo à la fin',
+    noPrintersConfigured: 'Aucune imprimante configurée',
+    // Archive settings
+    archiveMode: {
+      always: 'Toujours créer une archive',
+      never: 'Ne jamais créer d\'archive',
+      ask: 'Demander à chaque fois',
+    },
+    // Updates
+    checkForUpdatesLabel: 'Vérifier les mises à jour',
+    checkPrinterFirmware: 'Vérifier le firmware imprimante',
+    // Queue
+    enableRetry: 'Activer la rétentative',
+    // Home Assistant
+    homeAssistantDescription: 'Contrôler les prises via Home Assistant',
+    environmentManagedLabel: '(Géré par l\'environnement)',
+    autoEnabledViaEnv: 'Activé via variables d\'environnement',
+    urlFromEnvReadOnly: 'Valeur HA_URL (lecture seule)',
+    tokenFromEnvReadOnly: 'Valeur HA_TOKEN (lecture seule)',
+    // MQTT
+    mqttConnectedTo: 'Connecté à',
+    // Prometheus
+    prometheusDescription: 'Exposer les données au format Prometheus',
+    // Smart plugs empty state
+    noSmartPlugsTitle: 'Aucune prise configurée',
+    noSmartPlugsDescription: 'Ajoutez une prise Tasmota pour suivre l\'énergie et automatiser.',
+    // Notifications empty state
+    noProvidersTitle: 'Aucun fournisseur configuré',
+    noProvidersDescription: 'Ajoutez un fournisseur pour recevoir des alertes.',
+    noTemplatesAvailable: 'Aucun modèle dispo. Redémarrez pour les générer.',
+    // API permissions
+    apiPermissionView: 'Voir statut et file',
+    apiPermissionEdit: 'Gérer la file d\'attente',
+    // API keys
+    apiKeysEmptyTitle: 'Aucune clé API',
+    apiKeysEmptyDescription: 'Créez une clé pour vos intégrations.',
+    // Users
+    noUsersFound: 'Aucun utilisateur trouvé',
+    noGroupsFound: 'Aucun groupe trouvé',
+    noGroupsAvailable: 'Aucun groupe disponible',
+    passwordsDoNotMatch: 'Les mots de passe ne correspondent pas',
+    systemGroupWarning: 'Les noms des groupes système sont fixes',
+    // Auth disabled
+    authDisabledTitle: 'Authentification désactivée',
+    authDisabledFeature1: 'Requis pour accéder au système',
+    authDisabledFeature2: 'Gestion multi-utilisateurs et groupes',
+    authDisabledFeature3: 'Plus de 50 permissions granulaires',
+    // User deletion
+    userHasCreated: 'Cet utilisateur a créé :',
+    userItemsQuestion: 'Que faire de ces éléments ?',
+    deleteUserConfirm: 'Supprimer cet utilisateur ?',
+    actionCannotBeUndone: 'Cette action est irréversible.',
+    // Smart plugs
+    addFirstSmartPlug: 'Ajoutez votre première prise',
+    // Notifications
+    providers: 'Fournisseurs',
+    log: 'Journal',
+    testAll: 'Tout tester',
+    testResults: 'Résultats du test',
+    testPassedCount: '{{count}} succès',
+    testFailedCount: '{{count}} échecs',
+    messageTemplates: 'Modèles de message',
+    messageTemplatesDescription: 'Personnalisez les messages par événement.',
+    // API Keys section
+    apiKeys: 'Clés API',
+    apiKeysDescription: 'Créez des clés pour webhooks et API.',
+    createKey: 'Créer une clé',
+    apiKeyCreated: 'Clé API créée avec succès',
+    apiKeyCopyWarning: "Copiez cette clé maintenant - elle ne sera plus affichée !",
+    useInApiBrowser: 'Utiliser dans l\'explorateur API',
+    createNewApiKey: 'Nouvelle clé API',
+    keyName: 'Nom de la clé',
+    keyNamePlaceholder: 'ex: Home Assistant, OctoPrint',
+    readStatus: 'Lire le statut',
+    readStatusDescription: 'Voir les imprimantes et la file',
+    manageQueue: 'Gérer la file',
+    manageQueueDescription: 'Ajouter/retirer des éléments',
+    controlPrinter: 'Contrôler l\'imprimante',
+    controlPrinterDescription: 'Pause, reprise, arrêt',
+    unnamedKey: 'Clé sans nom',
+    lastUsed: 'Dernière utilisation',
+    read: 'Lecture',
+    control: 'Contrôle',
+    createFirstKey: 'Créez votre première clé',
+    webhookEndpoints: 'Points de terminaison Webhook',
+    webhookApiKeyHint: 'Utilisez la clé dans l\'en-tête X-API-Key.',
+    webhook: {
+      getAllStatus: 'Tous les statuts',
+      getSpecificStatus: 'Statut spécifique',
+      addToQueue: 'Ajouter à la file',
+      pausePrint: 'Pause',
+      resumePrint: 'Reprise',
+      stopPrint: 'Arrêt',
+    },
+    apiBrowser: 'Explorateur API',
+    apiBrowserDescription: 'Testez les endpoints API.',
+    apiKeyForTesting: 'Clé API pour test',
+    apiKeyPlaceholder: 'Collez votre clé pour tester...',
+    apiKeyHint: 'Sera envoyée via l\'en-tête X-API-Key.',
+    deleteApiKeyTitle: 'Supprimer la clé API',
+    deleteApiKeyMessage: 'Les intégrations utilisant cette clé cesseront de fonctionner.',
+    deleteKey: 'Supprimer la clé',
+    // Filament tab
+    amsDisplayThresholds: 'Seuils d\'affichage AMS',
+    amsThresholdsDescription: 'Seuils de couleur pour humidité et température.',
+    humidity: 'Humidité',
+    goodGreen: 'Bon (vert)',
+    fairOrange: 'Moyen (orange)',
+    aboveFairBad: 'Au-dessus = rouge (mauvais)',
+    temperature: 'Température',
+    goodBlue: 'Bon (bleu)',
+    aboveFairHot: 'Au-dessus = rouge (chaud)',
+    historyRetention: 'Rétention d\'historique',
+    keepSensorHistory: 'Garder l\'historique pendant',
+    historyRetentionDescription: 'Les anciennes données seront supprimées.',
+    printModal: 'Fenêtre d\'impression',
+    expandCustomMapping: 'Étendre le mapping personnalisé par défaut',
+    expandCustomMappingDescription: 'Affiche le mapping AMS par imprimante étendu.',
+    // User management
+    authentication: 'Authentification',
+    authEnabledDescription: 'L\'instance est sécurisée',
+    authDisabledDescription: 'Activez pour restreindre l\'accès',
+    authDisabledMessage: 'Activez l\'authentification pour gérer comptes et permissions.',
+    enableAuthentication: 'Activer l\'authentification',
+    currentUser: 'Utilisateur actuel',
+    changePassword: 'Changer le mot de passe',
+    admin: 'Admin',
+    users: 'Utilisateurs',
+    addUser: 'Ajouter un utilisateur',
+    groups: 'Groupes',
+    addGroup: 'Ajouter un groupe',
+    system: 'Système',
+    noDescription: 'Pas de description',
+    userCount: '{{count}} utilisateurs',
+    permissionCount: '{{count}} permissions',
+    createUser: 'Créer un utilisateur',
+    username: 'Nom d\'utilisateur',
+    enterUsername: 'Entrez l\'utilisateur',
+    password: 'Mot de passe',
+    enterPassword: 'Mot de passe (min 6 char)',
+    confirmPassword: 'Confirmer le mot de passe',
+    confirmPasswordPlaceholder: 'Confirmez le mot de passe',
+    // Title tooltips
+    viewReleaseOnGitHub: 'Voir la version sur GitHub',
+    turnAllPlugsOn: 'Tout allumer',
+    turnAllPlugsOff: 'Tout éteindre',
+    // Modal: Clear logs
+    clearNotificationLogs: 'Effacer les journaux',
+    clearLogsMessage: 'Efface définitivement les logs de plus de 30 jours.',
+    clearLogs: 'Effacer les logs',
+    // Modal: Reset UI
+    resetUiPreferences: 'Réinitialiser l\'UI',
+    resetUiPreferencesMessage: 'Réinitialise l\'ordre, thème, widgets, etc. N\'affecte pas vos données.',
+    resetPreferences: 'Réinitialiser',
+    // Modal: Delete group
+    deleteGroupTitle: 'Supprimer le groupe',
+    deleteGroupMessage: 'Les utilisateurs de ce groupe perdront ces permissions.',
+    deleteGroup: 'Supprimer le groupe',
+    // Modal: Disable auth
+    disableAuthenticationTitle: 'Désactiver l\'authentification',
+    disableAuthenticationMessage: 'Instance accessible sans connexion. Les comptes sont conservés.',
+    disableAuthentication: 'Désactiver',
+    // Additional settings
+    configureBambuddy: 'Configurer Bambuddy',
+    systemDefault: 'Défaut système',
+    archiveSettings: 'Réglages Archives',
+    newWindow: 'Nouvelle fenêtre',
+    embeddedOverlay: 'Superposition intégrée',
+    preferredSlicer: 'Slicer préféré',
+    preferredSlicerDescription: 'Application pour ouvrir les fichiers',
+    externalCameras: 'Caméras externes',
+    costTracking: 'Suivi des coûts',
+    printsOnly: 'Impressions uniquement',
+    totalConsumption: 'Consommation totale',
+    dataManagement: 'Gestion des données',
+    clearNotificationLogsDescription: 'Supprimer logs de plus de 30 jours',
+    resetUiPreferencesDescription: 'Réinitialise thèmes et affichage sans toucher aux données.',
+    enableHomeAssistant: 'Activer Home Assistant',
+    enableMqtt: 'Activer MQTT',
+    useTls: 'Utiliser TLS',
+    enableMetricsEndpoint: 'Activer l\'endpoint Metrics',
+    availableMetrics: 'Metrics disponibles',
+    editUser: 'Modifier l\'utilisateur',
+    deleteUserTitle: 'Supprimer l\'utilisateur',
+    groupName: 'Nom du groupe',
+    // Placeholders
+    leaveEmptyForAnonymous: 'Vide pour anonyme',
+    leaveEmptyForNoAuth: 'Vide si pas d\'auth',
+    enterNewPassword: 'Nouveau mot de passe',
+    confirmNewPassword: 'Confirmer nouveau mdp',
+    enterGroupName: 'Entrez le nom du groupe',
+    enterDescriptionOptional: 'Description (optionnel)',
+    enterCurrentPassword: 'Mdp actuel',
+    enterNewPasswordMin6: 'Nouveau mdp (min 6 char)',
+    toast: {
+      keyCopied: 'Clé copiée',
+      copyFailed: 'Échec copie',
+      keyAddedToBrowser: 'Clé ajoutée à l\'explorateur',
+      clearLogsFailed: 'Échec effacement logs',
+      uiPreferencesReset: 'Préférences UI réinitialisées. Rafraîchissement...',
+      authDisabled: 'Authentification désactivée',
+      authDisableFailed: 'Échec désactivation',
+      apiKeyCreated: 'Clé API créée',
+      apiKeyDeleted: 'Clé API supprimée',
+      userCreated: 'Utilisateur créé',
+      userUpdated: 'Utilisateur mis à jour',
+      userDeleted: 'Utilisateur supprimé',
+      groupCreated: 'Groupe créé',
+      groupUpdated: 'Groupe mis à jour',
+      groupDeleted: 'Groupe supprimé',
+      fillRequiredFields: 'Remplissez les champs requis',
+      passwordsDoNotMatch: 'Les mots de passe ne correspondent pas',
+      passwordTooShort: 'Minimum 6 caractères',
+      enterGroupName: 'Entrez un nom de groupe',
+      settingsSaved: 'Paramètres enregistrés',
+      cameraSettingsSaved: 'Réglages caméra enregistrés',
+      enterCameraUrl: 'Entrez une URL caméra',
+      passwordChanged: 'Mot de passe modifié',
+      connectionFailed: 'Échec connexion',
+      testFailed: 'Échec test',
+      cameraConnected: 'Caméra connectée {{resolution}}',
+    },
+    testConnection: 'Tester la connexion',
+    catalog: {
+      spoolCatalog: 'Catalogue de Bobines',
+      spoolCatalogDescription: 'Poids des bobines vides par marque/type. Utilisé pour le calcul auto du poids restant.',
+      searchCatalog: 'Chercher dans le catalogue...',
+      addNewEntry: 'Nouvelle Entrée',
+      namePlaceholder: 'Nom (ex: Bambu Lab - Plastique)',
+      weight: 'Poids',
+      type: 'Type',
+      default: 'Défaut',
+      custom: 'Perso',
+      noMatch: 'Aucune entrée correspondante',
+      empty: 'Catalogue vide',
+      deleteEntry: 'Supprimer l\'entrée',
+      deleteConfirm: 'Supprimer "{{name}}" ?',
+      resetCatalog: 'Réinitialiser le catalogue',
+      resetConfirm: 'Réinitialiser aux valeurs par défaut ? Vos entrées personnalisées seront supprimées.',
+      loadFailed: 'Échec chargement catalogue',
+      nameWeightRequired: 'Nom et poids requis',
+      entryAdded: 'Entrée ajoutée',
+      addFailed: 'Échec ajout',
+      entryUpdated: 'Entrée mise à jour',
+      updateFailed: 'Échec mise à jour',
+      entryDeleted: 'Entrée supprimée',
+      deleteFailed: 'Échec suppression',
+      resetSuccess: 'Catalogue réinitialisé',
+      resetFailed: 'Échec réinitialisation',
+      exported: '{{count}} entrées exportées',
+      imported: '{{added}} entrées importées ({{skipped}} ignorées)',
+      importFailed: 'Échec import : format JSON invalide',
+      exportTooltip: 'Exporter en JSON',
+      importTooltip: 'Importer depuis JSON',
+      resetTooltip: 'Réinitialiser par défaut',
+    },
+    colorCatalog: {
+      title: 'Catalogue de Couleurs',
+      description: 'Couleurs de filament par fabricant. Utilisé pour la recherche auto lors de l\'ajout de bobines.',
+      searchColors: 'Chercher couleurs...',
+      allManufacturers: 'Tous les fabricants',
+      addNewColor: 'Nouvelle Couleur',
+      manufacturer: 'Fabricant',
+      colorName: 'Nom couleur',
+      hex: 'Hex',
+      materialOptional: 'Matériau (optionnel)',
+      showing: 'Affichage {{filtered}} sur {{total}} couleurs',
+      noMatch: 'Aucune couleur correspondante',
+      empty: 'Catalogue vide',
+      deleteColor: 'Supprimer couleur',
+      deleteConfirm: 'Supprimer "{{name}}" ?',
+      resetCatalog: 'Réinitialiser catalogue couleurs',
+      resetConfirm: 'Réinitialiser aux valeurs par défaut ?',
+      sync: 'Sync',
+      starting: 'Démarrage...',
+      syncTooltip: 'Sync depuis FilamentColors.xyz (2000+ couleurs, peut être long)',
+      loadFailed: 'Échec chargement catalogue couleurs',
+      fieldsRequired: 'Fabricant, nom et code Hex requis',
+      colorAdded: 'Couleur ajoutée',
+      addFailed: 'Échec ajout',
+      colorUpdated: 'Couleur mise à jour',
+      updateFailed: 'Échec mise à jour',
+      colorDeleted: 'Couleur supprimée',
+      deleteFailed: 'Échec suppression',
+      resetSuccess: 'Catalogue réinitialisé',
+      resetFailed: 'Échec réinitialisation',
+      syncUpToDate: 'Déjà à jour ({{count}} couleurs vérifiées)',
+      syncComplete: '{{added}} couleurs ajoutées ({{skipped}} déjà présentes)',
+      syncError: 'Erreur de sync',
+      syncFailed: 'Échec sync FilamentColors.xyz',
+      exported: '{{count}} couleurs exportées',
+      imported: '{{added}} couleurs importées ({{skipped}} ignorées)',
+      importFailed: 'Échec import : format JSON invalide',
+    },
+  },
+
+  // Notifications (for push notifications)
+  notification: {
+    printStarted: {
+      title: 'Impression démarrée',
+      body: '{{printer}} : {{filename}} commence l\'impression',
+    },
+    printCompleted: {
+      title: 'Impression terminée',
+      body: '{{printer}} : {{filename}} a réussi',
+    },
+    printFailed: {
+      title: 'Impression échouée',
+      body: '{{printer}} : {{filename}} a échoué',
+    },
+    printStopped: {
+      title: 'Impression arrêtée',
+      body: '{{printer}} : {{filename}} a été arrêtée',
+    },
+    printProgress: {
+      title: 'Progression d\'impression',
+      body: '{{printer}} : {{filename}} est à {{percent}}%',
+    },
+    printerOffline: {
+      title: 'Imprimante hors ligne',
+      body: '{{printer}} est déconnectée',
+    },
+    printerError: {
+      title: 'Erreur imprimante',
+      body: '{{printer}} : {{error}}',
+    },
+    filamentLow: {
+      title: 'Filament bas',
+      body: '{{printer}} : Le filament est presque vide',
+    },
+    maintenanceDue: {
+      title: 'Maintenance due',
+      body: '{{printer}} : {{items}} demandent votre attention',
+    },
+  },
+
+  // Errors
+  errors: {
+    generic: 'Une erreur est survenue',
+    networkError: 'Erreur réseau. Vérifiez votre connexion.',
+    notFound: 'Non trouvé',
+    unauthorized: 'Non autorisé',
+    serverError: 'Erreur serveur',
+    validationError: 'Vérifiez vos saisies',
+    printerConnectionFailed: 'Échec connexion imprimante',
+    saveFailed: 'Échec enregistrement',
+    deleteFailed: 'Échec suppression',
+    loadFailed: 'Échec chargement',
+  },
+
+  // HMS Errors modal
+  hmsErrors: {
+    title: 'Erreurs - {{name}}',
+    noErrors: 'Aucune erreur',
+    viewOnWiki: 'Voir sur le Wiki Bambu Lab',
+    clearInstructions: 'Effacez les erreurs sur l\'imprimante pour les retirer ici.',
+  },
+
+  // MQTT Debug modal
+  mqttDebug: {
+    title: 'Journal de débogage MQTT',
+    searchPlaceholder: 'Chercher topic ou message...',
+    noMessages: 'Aucun message enregistré',
+    startLoggingHint: 'Cliquez sur "Démarrer" pour capturer les messages MQTT',
+    noMessagesMatch: 'Aucun message ne correspond',
+    adjustFilterHint: 'Ajustez votre recherche',
+    incoming: 'Entrant',
+    outgoing: 'Sortant',
+    loggingStopped: 'Enregistrement arrêté',
+    loggingActive: 'Enregistrement actif - rafraîchissement auto',
+    startLogging: 'Démarrer',
+    stopLogging: 'Arrêter',
+    clearLog: 'Effacer le journal',
+    topic: 'Topic',
+    timestamp: 'Horodatage',
+    direction: 'Direction',
+    all: 'Tous',
+  },
+
+  // Printer File Manager modal (printer internal storage)
+  printerFiles: {
+    title: 'Gestionnaire de fichiers',
+    storageUsed: 'Utilisé :',
+    storageFree: 'Libre :',
+    filterPlaceholder: 'Filtrer les fichiers...',
+    deleteButton: 'Supprimer',
+    deleteFiles: 'Supprimer {{count}} fichiers',
+    deleteFileConfirm: 'Supprimer "{{name}}" ?',
+    deleteFilesConfirm: 'Supprimer les {{count}} fichiers sélectionnés ?',
+    noFiles: 'Aucun fichier sur l\'imprimante',
+    loadingFiles: 'Chargement...',
+    failedToLoad: 'Échec chargement fichiers',
+    toast: {
+      filesDeleted: '{{count}} fichier(s) supprimé(s)',
+      deleteFailed: 'Échec suppression : {{error}}',
+    },
+  },
+
+  // Confirmations
+  confirm: {
+    delete: 'Voulez-vous vraiment supprimer cet élément ?',
+    unsavedChanges: 'Changements non sauvegardés. Voulez-vous quitter ?',
+    clearQueue: 'Voulez-vous vraiment vider la file d\'attente ?',
+  },
+
+  // Login page
+  login: {
+    title: 'Connexion Bambuddy',
+    subtitle: 'Connectez-vous à votre compte',
+    username: 'Utilisateur',
+    usernamePlaceholder: 'Entrez votre utilisateur',
+    usernameOrEmail: 'Utilisateur ou Email',
+    usernameOrEmailPlaceholder: 'Utilisateur ou @ Email',
+    password: 'Mot de passe',
+    passwordPlaceholder: 'Entrez votre mot de passe',
+    signIn: 'Se connecter',
+    signingIn: 'Connexion...',
+    forgotPassword: 'Mot de passe oublié ?',
+    loginSuccess: 'Connecté avec succès',
+    loginFailed: 'Échec de connexion',
+    enterCredentials: 'Entrez vos identifiants',
+    forgotPasswordTitle: 'Mot de passe oublié',
+    forgotPasswordMessage: "Contactez votre administrateur pour réinitialiser votre accès.",
+    forgotPasswordEmailMessage: "Entrez votre email pour recevoir un nouveau mot de passe.",
+    emailAddress: 'Adresse Email',
+    emailPlaceholder: 'votre.email@exemple.com',
+    cancel: 'Annuler',
+    sending: 'Envoi...',
+    sendResetEmail: 'Envoyer l\'email',
+    howToReset: 'Comment réinitialiser :',
+    resetStep1: 'Contactez votre admin Bambuddy',
+    resetStep2: 'Demandez une réinitialisation dans la Gestion Utilisateurs',
+    resetStep3: 'Il vous donnera un mot de passe temporaire',
+    resetStep4: 'Connectez-vous et changez-le dans les Paramètres',
+    gotIt: 'Compris',
+  },
+
+  // Setup page
+  setup: {
+    title: 'Configuration Bambuddy',
+    subtitle: 'Configurez l\'authentification',
+    enableAuth: 'Activer l\'authentification',
+    adminAccount: 'Compte Admin',
+    adminAccountDesc: 'Si des admins existent, ils seront utilisés. Sinon, créez-en un ci-dessous.',
+    adminUsername: 'Utilisateur Admin',
+    adminPassword: 'Mot de passe Admin',
+    optionalIfAdminExists: '(optionnel si admin existe)',
+    adminUsernamePlaceholder: 'Nom admin (optionnel)',
+    adminPasswordPlaceholder: 'Mdp admin (optionnel)',
+    confirmPassword: 'Confirmer mdp',
+    confirmPasswordPlaceholder: 'Confirmez mdp admin',
+    settingUp: 'Configuration...',
+    completeSetup: 'Terminer la configuration',
+    toast: {
+      authEnabledAdminCreated: 'Authentification activée et admin créé',
+      authEnabledExistingAdmins: 'Authentification activée avec admins existants',
+      setupCompleted: 'Configuration terminée',
+      enterBothCredentials: 'Entrez les deux ou laissez vide pour utiliser les admins existants',
+      passwordsDoNotMatch: 'Les mots de passe ne correspondent pas',
+      passwordTooShort: 'Minimum 6 caractères',
+    },
+  },
+
+  // Password change
+  changePassword: {
+    title: 'Changer le mot de passe',
+    currentPassword: 'Mot de passe actuel',
+    currentPasswordPlaceholder: 'Entrez mdp actuel',
+    newPassword: 'Nouveau mot de passe',
+    newPasswordPlaceholder: 'Nouveau mdp (min 6 char)',
+    confirmPassword: 'Confirmer nouveau mdp',
+    confirmPasswordPlaceholder: 'Confirmez nouveau mdp',
+    passwordsDoNotMatch: 'Les mots de passe ne correspondent pas',
+    passwordTooShort: 'Minimum 6 caractères',
+    changing: 'Changement...',
+    success: 'Mot de passe modifié',
+    failed: 'Échec modification',
+  },
+
+  // Plate detection alert
+  plateAlert: {
+    title: 'Impression en Pause !',
+    message: 'Objets détectés sur le plateau. L\'impression a été suspendue automatiquement. Videz le plateau avant de reprendre.',
+    understand: 'J\'ai compris',
+  },
+
+  // Camera page
+  camera: {
+    title: 'Vue Caméra',
+    invalidPrinterId: 'ID imprimante invalide',
+    live: 'Direct',
+    snapshot: 'Instantané',
+    restartStream: 'Redémarrer le flux',
+    refreshSnapshot: 'Rafraîchir l\'image',
+    fullscreen: 'Plein écran',
+    exitFullscreen: 'Quitter plein écran',
+    connectingToCamera: 'Connexion caméra...',
+    capturingSnapshot: 'Capture...',
+    connectionLost: 'Connexion perdue',
+    connectionFailed: 'Échec connexion caméra',
+    reconnecting: 'Reconnexion dans {{countdown}}s... (essai {{attempt}}/{{max}})',
+    reconnectNow: 'Reconnexion immédiate',
+    cameraUnavailable: 'Caméra indisponible',
+    cameraUnavailableDesc: 'Vérifiez que l\'imprimante est allumée.',
+    noCamera: 'Aucune caméra disponible',
+    retry: 'Réessayer',
+    cameraStream: 'Flux caméra',
+    zoomOut: 'Zoom arrière',
+    zoomIn: 'Zoom avant',
+    resetZoom: 'Réinitialiser zoom',
+    recording: 'Enregistrement',
+    startRecording: 'Démarrer l\'enregistrement',
+    stopRecording: 'Arrêter l\'enregistrement',
+    chamberLight: 'Basculer lumière chambre',
+  },
+
+  // Groups management
+  groups: {
+    title: 'Gestion des Groupes',
+    subtitle: 'Gérez les permissions pour le contrôle d\'accès',
+    backToSettings: 'Retour aux paramètres',
+    createGroup: 'Créer un groupe',
+    noPermission: 'Accès refusé.',
+    system: 'Système',
+    noDescription: 'Pas de description',
+    usersCount: '{{count}} utilisateurs',
+    permissionsCount: '{{count}} permissions',
+    edit: 'Modifier',
+    delete: 'Supprimer',
+    toast: {
+      created: 'Groupe créé',
+      updated: 'Groupe mis à jour',
+      deleted: 'Groupe supprimé',
+      enterGroupName: 'Entrez un nom de groupe',
+    },
+    modal: {
+      editGroup: 'Modifier le groupe',
+      createGroup: 'Créer un groupe',
+      cancel: 'Annuler',
+      saving: 'Enregistrement...',
+      creating: 'Création...',
+      saveChanges: 'Enregistrer',
+    },
+    form: {
+      groupName: 'Nom du groupe',
+      groupNamePlaceholder: 'Nom du groupe',
+      systemGroupWarning: 'Les groupes système sont fixes',
+      description: 'Description',
+      descriptionPlaceholder: 'Description (optionnel)',
+      permissions: 'Permissions ({{count}} sélectionnées)',
+    },
+    deleteModal: {
+      title: 'Supprimer le groupe',
+      message: 'Les utilisateurs de ce groupe perdront ces permissions.',
+      confirm: 'Supprimer',
+    },
+  },
+
+  // Users management
+  users: {
+    title: 'Gestion des Utilisateurs',
+    subtitle: 'Gérez les accès à Bambuddy',
+    backToSettings: 'Retour aux paramètres',
+    createUser: 'Créer un utilisateur',
+    noPermission: 'Accès refusé.',
+    admin: 'Admin',
+    noGroups: 'Aucun groupe',
+    active: 'Actif',
+    inactive: 'Inactif',
+    edit: 'Modifier',
+    delete: 'Supprimer',
+    system: 'Système',
+    noGroupsAvailable: 'Aucun groupe disponible',
+    table: {
+      username: 'Utilisateur',
+      groups: 'Groupes',
+      status: 'Statut',
+      actions: 'Actions',
+    },
+    toast: {
+      created: 'Utilisateur créé',
+      updated: 'Utilisateur mis à jour',
+      deleted: 'Utilisateur supprimé',
+      fillRequired: 'Remplissez les champs requis',
+      passwordsDoNotMatch: 'Les mots de passe ne correspondent pas',
+      passwordTooShort: 'Minimum 6 caractères',
+    },
+    modal: {
+      createUser: 'Créer utilisateur',
+      editUser: 'Modifier utilisateur',
+      cancel: 'Annuler',
+      creating: 'Création...',
+      saving: 'Enregistrement...',
+      saveChanges: 'Enregistrer',
+      advancedAuthSubtitle: 'avec Authentification Avancée',
+    },
+    form: {
+      username: 'Utilisateur',
+      usernamePlaceholder: 'Nom utilisateur',
+      email: 'Email',
+      emailPlaceholder: 'utilisateur@exemple.com',
+      password: 'Mot de passe',
+      passwordPlaceholder: 'Mot de passe',
+      confirmPassword: 'Confirmer mdp',
+      confirmPasswordPlaceholder: 'Confirmez mdp',
+      newPasswordPlaceholder: 'Nouveau mdp',
+      confirmNewPasswordPlaceholder: 'Confirmez nouveau mdp',
+      leaveBlankToKeep: 'Laissez vide pour conserver l\'actuel',
+      groups: 'Groupes',
+      optional: 'optionnel',
+      autoGeneratedPassword: 'Un mot de passe sera généré et envoyé par email.',
+      passwordManagedByAdvancedAuth: 'Géré par Auth Avancée. Utilisez "Réinitialiser" pour envoyer un nouveau mdp par email.',
+      resetPassword: 'Réinitialiser le mot de passe',
+      resettingPassword: 'Réinitialisation...',
+    },
+    deleteModal: {
+      title: 'Supprimer utilisateur',
+      message: 'Cette action est irréversible.',
+      confirm: 'Supprimer',
+    },
+  },
+
+  // Stream overlay
+  streamOverlay: {
+    title: 'Superposition Flux',
+    invalidPrinterId: 'ID invalide',
+    cameraStream: 'Flux caméra',
+    progress: 'Progression',
+    eta: 'Fin estimée',
+    tomorrow: 'Demain',
+    printerIdle: 'Imprimante inactive',
+    printerOffline: 'Imprimante hors ligne',
+    status: {
+      printing: 'Impression',
+      paused: 'En pause',
+      finished: 'Terminée',
+      failed: 'Échouée',
+      idle: 'Inactive',
+      unknown: 'Inconnue',
+    },
+  },
+
+  // Profiles
+  profiles: {
+    title: 'Profils',
+    subtitle: 'Gérez vos presets slicer et calibrations Pressure Advance',
+    tabs: {
+      cloud: 'Profils Cloud',
+      local: 'Profils Locaux',
+      kprofiles: 'K-Profiles',
+    },
+    localProfiles: {
+      title: 'Profils Locaux',
+      subtitle: 'Gérez vos presets OrcaSlicer',
+      import: 'Importer Profils',
+      importDesc: 'Déposez les fichiers .bbscfg, .bbsflmt, .orca_filament, .zip ou .json',
+      importing: 'Importation...',
+      search: 'Chercher un preset...',
+      noPresets: 'Aucun preset local',
+      badge: 'Local',
+      edit: 'Modifier',
+      delete: 'Supprimer',
+      cancel: 'Annuler',
+      deleteConfirmTitle: 'Supprimer Preset',
+      deleteConfirm: 'Supprimer définitivement ce preset ?',
+      source: 'Source',
+      inheritsFrom: 'Hérite de',
+      filamentType: 'Type',
+      vendor: 'Vendeur',
+      compatiblePrinters: 'Imprimantes',
+      nozzleTemp: 'Temp Buse',
+      cost: 'Coût',
+      density: 'Densité',
+      pressureAdvance: 'Pressure Advance',
+      filament: 'Filament',
+      process: 'Processus',
+      printer: 'Imprimante',
+      toast: {
+        importSuccess: '{{count}} profil(s) importé(s)',
+        importSkipped: '{{count}} profil(s) ignoré(s) (doublons)',
+        importError: '{{count}} erreur(s) d\'import',
+        deleted: 'Preset supprimé',
+        updated: 'Preset mis à jour',
+      },
+    },
+    connectedAs: 'Connecté en tant que',
+    logout: 'Déconnexion',
+    noLogoutPermission: 'Pas d\'autorisation de déconnexion',
+    failedToLoad: 'Échec chargement profils',
+    retry: 'Réessayer',
+    time: {
+      justNow: 'À l\'instant',
+      minsAgo: 'Il y a {{count}}m',
+      hoursAgo: 'Il y a {{count}}h',
+      daysAgo: 'Il y a {{count}}j',
+    },
+    toast: {
+      loggedOut: 'Déconnecté',
+    },
+    login: {
+      title: 'Connexion Bambu Cloud',
+      subtitle: 'Synchronisez vos presets slicer',
+      email: 'Email',
+      password: 'Mot de passe',
+      region: 'Région',
+      regionGlobal: 'Global',
+      regionChina: 'Chine',
+      verificationCode: 'Code de vérification',
+      totpCode: 'Code Authenticator',
+      checkEmail: 'Code envoyé à {{email}}',
+      enterTotpHint: 'Entrez le code 2FA',
+      accessToken: 'Jeton d\'accès (Access Token)',
+      accessTokenHint: 'Collez le jeton (depuis Bambu Studio)',
+      back: 'Retour',
+      loginButton: 'Connexion',
+      verifyButton: 'Vérifier',
+      setTokenButton: 'Définir Jeton',
+      useToken: 'Utiliser jeton d\'accès',
+      useEmail: 'Connexion par email',
+      toast: {
+        loggedIn: 'Connecté avec succès',
+        codeSent: 'Code envoyé par email',
+        enterTotp: 'Entrez le code Authenticator',
+        tokenSet: 'Jeton défini',
+      },
+    },
+    presets: {
+      myPreset: 'Mon preset (modifiable)',
+      duplicate: 'Dupliquer',
+      editable: 'Modifiable',
+      failedToLoadDetails: 'Échec détails preset',
+      deleteConfirm: 'Supprimer ce preset ?',
+      deleteWarning: 'Ceci supprimera "{{name}}" de Bambu Cloud définitivement.',
+      noDuplicatePermission: 'Pas d\'autorisation duplication',
+      noEditPermission: 'Pas d\'autorisation modification',
+      noDeletePermission: 'Pas d\'autorisation suppression',
+      types: {
+        filament: 'Preset filament',
+        printer: 'Preset imprimante',
+        process: 'Preset processus',
+      },
+      toast: {
+        deleted: 'Preset supprimé',
+        created: 'Preset créé',
+        updated: 'Preset mis à jour',
+        duplicated: 'Preset dupliqué',
+        fieldAdded: 'Champ "{{key}}" ajouté',
+        exported: 'Preset exporté',
+      },
+      baseLabel: 'Base : {{name}}',
+      currentLabel: 'Actuel : {{name}}',
+      newPreset: 'Nouveau Preset',
+      editPreset: 'Modifier Preset',
+      duplicatePreset: 'Dupliquer Preset',
+      createNewPreset: 'Créer un nouveau Preset',
+      customizeSettings: 'Personnalisez vos réglages',
+      compareWithBase: 'Comparer avec la base',
+      compare: 'Comparer',
+      // CreatePresetModal - Basic Info
+      basePreset: 'Preset de base',
+      selectBasePreset: 'Choisir preset de base...',
+      presetName: 'Nom du preset',
+      myCustomPreset: 'Mon preset personnalisé',
+      inheritsFrom: 'Hérite de',
+      dropJsonToImport: 'Glissez JSON pour importer',
+      // CreatePresetModal - Tabs
+      tabs: {
+        common: 'Commun',
+        allFields: 'Tous les champs',
+      },
+      // CreatePresetModal - All Fields Tab
+      availableFields: 'Champs disponibles',
+      searchFieldsPlaceholder: 'Chercher un champ...',
+      noMatchingFields: 'Aucun champ trouvé',
+      allFieldsAdded: 'Tous les champs sont ajoutés',
+      addCustomField: 'Ajouter un champ personnalisé',
+      yourOverrides: 'Vos modifications',
+      noOverridesYet: 'Aucune modification',
+      clickFieldsToAdd: 'Cliquez à gauche pour ajouter',
+      saveAsTemplate: 'Enregistrer comme modèle',
+      jsonTip: 'Conseil : Glissez un .json pour importer les réglages',
+    },
+    cloudView: {
+      searchPlaceholder: 'Chercher presets...',
+      templates: 'Modèles',
+      refresh: 'Rafraîchir',
+      newPreset: 'Nouveau Preset',
+      clearFilters: 'Effacer filtres',
+      // Compare mode
+      compareMode: 'Mode Comparaison',
+      selectAnotherPreset: 'Choisir un autre preset {{type}}',
+      clickTwoPresets: 'Choisissez deux presets de même type',
+      selectFirst: '1. Sélectionner premier',
+      selectSecond: '2. Sélectionner second',
+      compareNow: 'Comparer maintenant',
+      // Status row
+      lastSynced: 'Synchronisé :',
+      showingCount: '{{showing}} sur {{total}} presets',
+      noPresetsFound: 'Aucun preset trouvé',
+      // Column headers
+      columns: {
+        filament: 'Filament',
+        process: 'Processus',
+        printer: 'Imprimante',
+      },
+      noFilamentPresets: 'Pas de preset filament',
+      noProcessPresets: 'Pas de preset processus',
+      noPrinterPresets: 'Pas de preset imprimante',
+      // Filters
+      filters: {
+        type: 'Type',
+        owner: 'Propriétaire',
+        printer: 'Imprimante',
+        nozzle: 'Buse',
+        filament: 'Filament',
+        layer: 'Couche',
+        all: 'Tous',
+        myPresets: 'Mes Presets',
+        builtIn: 'Inclus',
+        process: 'Processus',
+      },
+      // Permissions
+      noTemplatesPermission: 'Pas d\'autorisation modèles',
+      noRefreshPermission: 'Pas d\'autorisation rafraîchissement',
+      noCreatePermission: 'Pas d\'autorisation création',
+    },
+    templates: {
+      title: 'Modèles rapides',
+      noTemplates: 'Aucun modèle',
+      createFirst: 'Créez-en depuis l\'éditeur de preset',
+      typeFilter: 'Type :',
+      deleteTitle: 'Supprimer modèle',
+      deleteWarning: 'Action irréversible',
+      deleteConfirm: 'Supprimer "{{name}}" ?',
+      namePlaceholder: 'Nom du modèle',
+      descriptionPlaceholder: 'Description',
+      settingsJson: 'Paramètres (JSON)',
+      fieldsCount: '{{count}} champs',
+      shownInModals: 'Visible dans fenêtres',
+      hiddenInModals: 'Masqué dans fenêtres',
+      apply: 'Appliquer',
+      toast: {
+        deleted: 'Modèle supprimé',
+        updated: 'Modèle mis à jour',
+        created: 'Modèle créé',
+        applied: 'Modèle appliqué',
+      },
+    },
+  },
+
+  // Support/Debug
+  support: {
+    debugLoggingActive: 'Débogage actif',
+    manageLogs: 'Gérer',
+    collectItem7: 'Connectivité et versions firmware',
+    collectItem8: 'Statut intégrations (Spoolman, MQTT, HA)',
+    collectItem9: 'Interfaces réseau (sous-réseaux)',
+    collectItem10: 'Versions packages Python',
+    collectItem11: 'Santé base de données',
+    collectItem12: 'Détails environnement Docker',
+  },
+
+  // File manager
+  fileManager: {
+    title: 'Gestionnaire de fichiers',
+    subtitle: 'Organisez vos fichiers d\'impression',
+    uploadFiles: 'Téléverser fichiers',
+    newFolder: 'Nouveau dossier',
+    folderName: 'Nom du dossier',
+    folderNamePlaceholder: 'ex: Pièces Utiles',
+    renameFile: 'Renommer fichier',
+    renameFolder: 'Renommer dossier',
+    moveFiles: 'Déplacer {{count}} fichier(s)',
+    rootNoFolder: 'Racine (aucun dossier)',
+    current: 'actuel',
+    linkFolder: 'Lier le dossier',
+    linkFolderDescription: 'Lier "{{name}}" à un projet ou archive.',
+    project: 'Projet',
+    archive: 'Archive',
+    noProjectsFound: 'Aucun projet trouvé',
+    noArchivesFound: 'Aucune archive trouvée',
+    unlink: 'Délier',
+    link: 'Lier',
+    dragDropFiles: 'Glissez les fichiers ici',
+    dropFilesHere: 'Déposez ici',
+    orClickToBrowse: 'ou cliquez pour parcourir',
+    allFileTypesSupported: 'Tous types supportés. ZIP extraits.',
+    zipFilesDetected: 'ZIP détectés',
+    zipExtractOptions: 'Choix de structure pour ZIP :',
+    preserveZipStructure: 'Garder structure ZIP',
+    createFolderFromZip: 'Dossier par nom du ZIP',
+    stlThumbnailGeneration: 'Vignettes STL',
+    zipMayContainStl: 'Extraction vignettes possible pour STL.',
+    thumbnailsCanBeGenerated: 'Génération vignettes (peut être long).',
+    generateThumbnailsForStl: 'Générer vignettes STL',
+    threemfDetected: 'Fichiers 3MF détectés',
+    threemfExtractionInfo: 'Réglages extraits auto du 3MF.',
+    willBeExtracted: 'Sera extrait',
+    filesExtracted: '{{count}} fichiers extraits',
+    uploadComplete: 'Terminé : {{succeeded}} succès',
+    uploadFailed: '{{count}} échecs',
+    uploading: 'Téléversement...',
+    changeLink: 'Modifier lien...',
+    linkTo: 'Lier à...',
+    linkToProjectOrArchive: 'Lier à projet ou archive',
+    addToQueue: 'Ajouter à la file',
+    schedulePrint: 'Planifier',
+    generateThumbnail: 'Générer vignette',
+    generateThumbnails: 'Générer vignettes',
+    generateThumbnailsForMissing: 'Vignettes STL manquantes',
+    gridView: 'Grille',
+    listView: 'Liste',
+    lowDiskSpaceWarning: 'Espace disque faible',
+    lowDiskSpaceDetails: '{{free}} libre sur {{total}}. Seuil : {{threshold}} Go.',
+    files: 'Fichiers',
+    folders: 'Dossiers',
+    size: 'Taille',
+    free: 'Libre',
+    allFiles: 'Tous les fichiers',
+    wrap: 'Retour ligne',
+    enableTextWrapping: 'Activer retour ligne',
+    disableTextWrapping: 'Désactiver retour ligne',
+    dragToResizeTooltip: 'Glisser pour redimensionner, double-clic reset',
+    searchFiles: 'Chercher fichiers...',
+    allTypes: 'Tous types',
+    prints: 'Impressions',
+    ascending: 'Croissant',
+    descending: 'Décroissant',
+    resultsCount: '{{showing}} sur {{total}} fichiers',
+    selectAll: 'Tout sélectionner',
+    deselectAll: 'Tout désélectionner',
+    selected: '{{count}} sélectionnés',
+    adding: 'Ajout...',
+    loadingFiles: 'Chargement...',
+    folderIsEmpty: 'Dossier vide',
+    noFilesYet: 'Aucun fichier',
+    folderEmptyDescription: 'Téléversez ou déplacez des fichiers ici.',
+    noFilesDescription: 'Téléversez des fichiers pour organiser.',
+    noMatchingFiles: 'Aucun fichier correspondant',
+    noMatchingFilesDescription: 'Ajustez votre recherche.',
+    clearFilters: 'Effacer filtres',
+    printedCount: 'Imprimé {{count}}x',
+    uploadedBy: 'Téléversé par',
+    deleteFolder: 'Supprimer dossier',
+    deleteFile: 'Supprimer fichier',
+    deleteFilesCount: 'Supprimer {{count}} fichiers',
+    deleteFolderConfirm: 'Supprimer le dossier et son contenu ?',
+    deleteFileConfirm: 'Supprimer ce fichier ?',
+    deleteFilesConfirm: 'Supprimer {{count}} fichiers définitivement ?',
+    deleting: 'Suppression...',
+    noPermissionRenameFolder: 'Pas d\'autorisation renommage',
+    noPermissionLinkFolder: 'Pas d\'autorisation lien',
+    noPermissionDeleteFolder: 'Pas d\'autorisation suppression dossier',
+    noPermissionPrint: 'Pas d\'autorisation impression',
+    noPermissionAddToQueue: 'Pas d\'autorisation file',
+    noPermissionDownload: 'Pas d\'autorisation téléchargement',
+    noPermissionRenameFile: 'Pas d\'autorisation renommage fichier',
+    noPermissionGenerateThumbnail: 'Pas d\'autorisation vignettes',
+    noPermissionDeleteFile: 'Pas d\'autorisation suppression fichier',
+    noPermissionCreateFolder: 'Pas d\'autorisation nouveau dossier',
+    noPermissionUpload: 'Pas d\'autorisation téléversement',
+    noPermissionMoveFiles: 'Pas d\'autorisation déplacement',
+    noPermissionDeleteFiles: 'Pas d\'autorisation suppression groupée',
+    toast: {
+      folderCreated: 'Dossier créé',
+      folderDeleted: 'Dossier supprimé',
+      fileDeleted: 'Fichier supprimé',
+      filesDeleted: '{{count}} fichiers supprimés',
+      filesMoved: 'Fichiers déplacés',
+      folderLinked: 'Dossier lié',
+      folderUnlinked: 'Dossier délié',
+      addedToQueue: '{{count}} fichier(s) ajouté(s)',
+      addedToQueuePartial: '{{added}} ajoutés, {{failed}} échecs',
+      failedToAddToQueue: 'Échec ajout file : {{error}}',
+      fileRenamed: 'Fichier renommé',
+      folderRenamed: 'Dossier renommé',
+      thumbnailsGenerated: '{{count}} vignette(s) générée(s)',
+      thumbnailsGeneratedPartial: '{{succeeded}} succès, {{failed}} échecs',
+      noStlMissingThumbnails: 'Aucun STL sans vignette',
+      failedToGenerateThumbnails: 'Échec vignettes : {{error}}',
+      thumbnailGenerated: 'Vignette générée',
+      failedToGenerateThumbnail: 'Échec vignette : {{error}}',
+    },
+  },
+
+  // Projects
+  projects: {
+    title: 'Projets',
+    subtitle: 'Suivez vos projets d\'impression 3D',
+    newProject: 'Nouveau Projet',
+    editProject: 'Modifier Projet',
+    deleteProject: 'Supprimer Projet',
+    projectName: 'Nom du Projet',
+    description: 'Description',
+    noProjects: 'Aucun projet',
+    noProjectsFiltered: 'Aucun projet {{status}}',
+    noProjectsFilteredHelp: 'Les projets apparaîtront ici quand leur statut changera.',
+    createFirst: 'Créez votre premier projet pour organiser vos builds.',
+    createFirstButton: 'Créer votre premier projet',
+    create: 'Créer',
+    files: 'Fichiers',
+    prints: 'Impressions',
+    plates: 'plateaux',
+    parts: 'pièces',
+    lastModified: 'Modifié le',
+    deleteConfirm: 'Supprimer ce projet ? Les archives seront déliées mais conservées.',
+    addFiles: 'Ajouter fichiers',
+    removeFile: 'Retirer fichier',
+    viewDetails: 'Détails',
+    // Modal fields
+    namePlaceholder: 'ex: Build Voron 2.4',
+    descriptionPlaceholder: 'Description optionnelle...',
+    color: 'Couleur',
+    targetPlates: 'Plateaux cibles',
+    targetPlatesPlaceholder: 'ex: 25',
+    targetPlatesHelp: 'Nombre total de jobs',
+    targetParts: 'Pièces cibles',
+    targetPartsPlaceholder: 'ex: 150',
+    targetPartsHelp: 'Nombre total d\'objets',
+    tagsLabel: 'Tags (séparés par virgules)',
+    tagsPlaceholder: 'ex: voron, cadeau',
+    dueDate: 'Échéance',
+    priority: 'Priorité',
+    priorityLow: 'Basse',
+    priorityNormal: 'Normale',
+    priorityHigh: 'Haute',
+    priorityUrgent: 'Urgente',
+    // Status
+    statusActive: 'Actif',
+    statusCompleted: 'Terminé',
+    statusArchived: 'Archivé',
+    done: 'Fait',
+    completed: 'terminé',
+    failed: 'échoué',
+    inQueue: 'en file',
+    noPrintsYet: 'Aucune impression',
+    // Footer stats
+    printJobs: 'Jobs (plateaux)',
+    partsPrinted: 'Pièces imprimées',
+    failedParts: 'Pièces échouées',
+    // Actions
+    import: 'Importer',
+    export: 'Exporter',
+    importProject: 'Importer projet',
+    exportAll: 'Exporter tous les projets',
+    loading: 'Chargement des projets...',
+    // Permissions
+    noEditPermission: 'Pas d\'autorisation de modification',
+    noDeletePermission: 'Pas d\'autorisation de suppression',
+    noCreatePermission: 'Pas d\'autorisation de création',
+    noImportPermission: 'Pas d\'autorisation d\'import',
+    noExportPermission: 'Pas d\'autorisation d\'export',
+    // Toast
+    toast: {
+      created: 'Projet créé',
+      updated: 'Projet mis à jour',
+      deleted: 'Projet supprimé',
+      imported: 'Projet importé',
+      multipleImported: '{{count}} projets importés',
+      importFailed: 'Échec d\'import',
+      exported: 'Projets exportés (métadonnées)',
+    },
+  },
+
+  // Project detail page
+  projectDetail: {
+    notFound: 'Projet non trouvé',
+    backToProjects: 'Retour aux Projets',
+    export: 'Exporter',
+    exportProject: 'Exporter projet',
+    noExportPermission: 'Pas d\'autorisation export',
+    noEditPermission: 'Pas d\'autorisation modification',
+    partOf: 'Fait partie de :',
+    priorityLabel: 'Priorité :',
+    noPrints: 'Aucune impression dans ce projet',
+    status: {
+      active: 'Actif',
+      completed: 'Terminé',
+      archived: 'Archivé',
+    },
+    priority: {
+      low: 'Basse',
+      normal: 'Normale',
+      high: 'Haute',
+      urgent: 'Urgente',
+    },
+    dueDate: {
+      overdue: 'En retard',
+      today: 'Aujourd\'hui',
+      daysLeft: '{{count}} jours restants',
+    },
+    progress: {
+      platesProgress: 'Progression Plateaux',
+      partsProgress: 'Progression Pièces',
+      printJobs: 'jobs d\'impression',
+      parts: 'pièces',
+      percentComplete: '{{percent}}% terminé',
+      remaining: '{{count}} restant(s)',
+    },
+    stats: {
+      printJobs: 'Jobs d\'Impression',
+      total: 'total',
+      failed: '{{count}} échecs',
+      partsPrinted: '{{count}} pièces imprimées',
+      printTime: 'Temps d\'Impression',
+      filamentUsed: 'Filament utilisé',
+    },
+    cost: {
+      title: 'Suivi des coûts',
+      filamentCost: 'Coût Filament',
+      energy: 'Énergie',
+      budget: 'Budget',
+      remaining: 'Restant',
+    },
+    subProjects: {
+      title: 'Sous-projets ({{count}})',
+    },
+    notes: {
+      title: 'Notes',
+      noEditPermission: 'Pas d\'autorisation modification',
+      placeholder: 'Ajouter des notes...',
+      empty: 'Aucune note. Cliquez sur modifier.',
+    },
+    files: {
+      title: 'Fichiers',
+      linkFolders: 'Liez des dossiers depuis le gestionnaire',
+      forQuickAccess: 'pour un accès rapide.',
+      fileCount: '{{count}} fichier(s)',
+      empty: 'Aucun dossier lié.',
+    },
+    bom: {
+      title: 'BOM (Liste matériel)',
+      acquired: '{{completed}}/{{total}} acquis',
+      showAll: 'Tout afficher',
+      hideDone: 'Masquer acquis',
+      addPart: 'Ajouter matériel',
+      noAddPermission: 'Pas d\'autorisation ajout',
+      partNamePlaceholder: 'Nom (ex: Vis M3x8)',
+      partName: 'Nom de pièce',
+      qty: 'Qté',
+      price: 'Prix ({{currency}})',
+      sourcingUrlPlaceholder: 'Lien d\'achat (optionnel)',
+      remarksPlaceholder: 'Remarques (optionnel)',
+      deletePart: 'Supprimer pièce',
+      deleteConfirm: 'Supprimer "{{name}}" ?',
+      noUpdatePermission: 'Pas d\'autorisation mise à jour',
+      noEditPermission: 'Pas d\'autorisation modification',
+      noDeletePermission: 'Pas d\'autorisation suppression',
+      totalCost: 'Coût total :',
+      empty: 'BOM vide. Ajoutez du matériel ou de l\'électronique.',
+    },
+    timeline: {
+      title: 'Historique d\'activité',
+      empty: 'Aucune activité.',
+    },
+    template: {
+      saveAsTemplate: 'Enregistrer comme modèle',
+      noCreatePermission: 'Pas d\'autorisation modèle',
+    },
+    queue: {
+      title: 'File d\'attente',
+      viewAll: 'Tout voir',
+      printing: '{{count}} en cours',
+      queued: '{{count}} en file',
+    },
+    prints: {
+      title: 'Impressions ({{count}})',
+    },
+    toast: {
+      projectUpdated: 'Projet mis à jour',
+      partAdded: 'Pièce ajoutée',
+      partRemoved: 'Pièce retirée',
+      exportFailed: 'Échec export',
+      projectExported: 'Projet exporté',
+      templateCreated: 'Modèle créé',
+    },
+  },
+
+  // System info
+  system: {
+    title: 'Informations Système',
+    version: 'Version',
+    uptime: 'Temps de fonctionnement',
+    cpuUsage: 'Utilisation CPU',
+    memoryUsage: 'Utilisation RAM',
+    diskUsage: 'Utilisation Disque',
+    networkInfo: 'Infos Réseau',
+    logs: 'Journaux',
+    debugMode: 'Mode Débogage',
+    enableDebug: 'Activer débogage',
+    disableDebug: 'Désactiver débogage',
+    downloadLogs: 'Télécharger logs',
+    clearLogs: 'Effacer logs',
+    dockerInfo: 'Infos Docker',
+    containerName: 'Nom conteneur',
+    imageName: 'Nom image',
+    platform: 'Plateforme',
+    architecture: 'Architecture',
+  },
+
+  // Library (K Profiles)
+  library: {
+    title: 'Bibliothèque Filament',
+    addFilament: 'Ajouter Filament',
+    editFilament: 'Modifier Filament',
+    deleteFilament: 'Supprimer Filament',
+    vendor: 'Vendeur',
+    material: 'Matériau',
+    color: 'Couleur',
+    kFactor: 'Facteur K',
+    temperature: 'Température',
+    noFilaments: 'Bibliothèque vide',
+    deleteConfirm: 'Supprimer ce filament ?',
+    importFromPrinter: 'Importer de l\'imprimante',
+    exportToFile: 'Exporter vers fichier',
+  },
+
+  // Spoolman
+  spoolman: {
+    title: 'Intégration Spoolman',
+    enabled: 'Spoolman Activé',
+    url: 'URL Spoolman',
+    connected: 'Connecté',
+    disconnected: 'Non Connecté',
+    testConnection: 'Tester connexion',
+    sync: 'Synchroniser',
+    syncing: 'Sync...',
+    lastSync: 'Dernière Sync',
+    linkToSpoolman: 'Lier à Spoolman',
+    openInSpoolman: 'Ouvrir Spoolman',
+    unlinkSpool: 'Délier bobine',
+    selectSpool: 'Choisir bobine',
+    noUnlinkedSpools: 'Pas de bobine libre',
+    linkSuccess: 'Lien réussi',
+    linkFailed: 'Échec lien',
+    spoolId: 'ID Bobine',
+    fillSourceLabel: '(Spoolman)',
+    weight: 'Poids',
+    remaining: 'Restant',
+    disableWeightSync: 'Désactiver Sync poids estimé AMS',
+    disableWeightSyncDesc: 'Ne pas utiliser les estimations AMS. Utile si vous préférez le suivi Spoolman.',
+    reportPartialUsage: 'Rapporter consommation partielle pour échecs',
+    reportPartialUsageDesc: 'Si l\'impression échoue, rapporte le filament consommé selon les couches.',
+  },
+
+  // Inventory
+  inventory: {
+    title: 'Inventaire de Bobines',
+    addSpool: 'Ajouter Bobine',
+    editSpool: 'Modifier Bobine',
+    material: 'Matériau',
+    selectMaterial: 'Choisir matériau...',
+    subtype: 'Sous-type',
+    brand: 'Marque',
+    searchBrand: 'Chercher marque...',
+    useCustomBrand: 'Utiliser "{{brand}}"',
+    colorName: 'Nom de couleur',
+    colorNamePlaceholder: 'Jade White, Fire Red...',
+    color: 'Couleur',
+    hexColor: 'Code Hex',
+    pickColor: 'Choisir couleur perso',
+    labelWeight: 'Poids net',
+    coreWeight: 'Poids bobine vide',
+    searchSpoolWeight: 'Chercher poids bobine...',
+    weightUsed: 'Consommé',
+    currentWeight: 'Poids restant',
+    slicerFilament: 'Filament Slicer',
+    slicerFilamentName: 'Nom du Preset Slicer',
+    slicerPreset: 'Preset Slicer',
+    searchPresets: 'Chercher presets...',
+    selectedPreset: 'Sélectionné',
+    noPresetsFound: 'Aucun preset trouvé',
+    tempOverrides: 'Exceptions Température',
+    note: 'Note',
+    notePlaceholder: 'Notes additionnelles sur cette bobine...',
+    archive: 'Archiver',
+    restore: 'Restaurer',
+    noSpools: 'Aucune bobine. Ajoutez votre première bobine pour commencer.',
+    noManualSpools: 'Aucune bobine manuelle disponible. Ajoutez-en une d\'abord.',
+    kProfiles: 'K-Profiles',
+    addKProfile: 'Ajouter K-Profile',
+    assignSpool: 'Assigner Bobine',
+    unassignSpool: 'Désassigner',
+    assignSuccess: 'Bobine assignée et slot AMS configuré',
+    assignFailed: 'Échec assignation',
+    selectSpool: 'Choisir une bobine pour ce slot',
+    assigned: 'Assigné',
+    assigning: 'Assignation...',
+    searchSpools: 'Chercher bobines...',
+    allMaterials: 'Tous Matériaux',
+    filterByBrand: 'Filtrer par marque...',
+    showArchived: 'Afficher archivées',
+    spoolCreated: 'Bobine créée',
+    spoolUpdated: 'Bobine mise à jour',
+    spoolDeleted: 'Bobine supprimée',
+    spoolArchived: 'Bobine archivée',
+    spoolRestored: 'Bobine restaurée',
+    deleteConfirm: 'Supprimer définitivement cette bobine ?',
+    advancedSettings: 'Paramètres Avancés',
+    // Tabs
+    filamentInfoTab: 'Infos Filament',
+    paProfileTab: 'Profil PA',
+    filamentInfo: 'Filament',
+    additional: 'Additionnel',
+    // Cloud
+    loadingPresets: 'Chargement des presets cloud...',
+    cloudConnected: 'Cloud connecté',
+    cloudNotConnected: 'Cloud déconnecté (valeurs par défaut)',
+    // Colors
+    recentColors: 'Récentes',
+    searchColors: 'Chercher couleurs...',
+    searchResults: 'Résultats',
+    allColors: 'Toutes',
+    commonColors: 'Communes',
+    showLess: 'Moins',
+    showAll: 'Toutes',
+    noColorsFound: 'Aucune couleur correspondante',
+    noResults: 'Aucun résultat',
+    // PA Profiles
+    selectMaterialFirst: 'Veuillez choisir un matériau dans l\'onglet Infos Filament.',
+    noPrintersConfigured: 'Ajoutez une imprimante pour utiliser les profils PA.',
+    matchingFilter: 'Correspondant',
+    anyBrand: 'Toute marque',
+    anyVariant: 'Toute variante',
+    autoSelect: 'Auto-sélection',
+    matches: 'correspondances',
+    match: 'correspondance',
+    noMatches: 'Aucune correspondance',
+    connected: 'Connecté',
+    offline: 'Hors ligne',
+    printerOffline: 'Imprimante hors ligne. Connectez-vous pour voir les profils.',
+    noKProfilesMatch: 'Aucun profil K ne correspond au filament.',
+    leftNozzle: 'Buse Gauche',
+    rightNozzle: 'Buse Droite',
+    profilesSelected: 'profil(s) de calibration sélectionné(s)',
+    // Stats & enhanced table
+    totalInventory: 'Total Inventaire',
+    totalConsumed: 'Total Consommé',
+    byMaterial: 'Par Matériau',
+    inPrinter: 'Dans Imprimante',
+    lowStock: 'Stock Bas',
+    sinceTracking: 'Depuis le début du suivi',
+    loadedInAms: 'Chargé dans AMS/Ext',
+    remaining: 'Restant',
+    lowStockThreshold: '<20% restant',
+    search: 'Chercher bobines...',
+    showing: 'Affichage',
+    to: 'à',
+    of: 'sur',
+    show: 'Voir',
+    spools: 'bobines',
+    spool: 'bobine',
+    page: 'Page',
+    noSpoolsMatch: 'Aucun résultat trouvé',
+    noSpoolsMatchDesc: 'Ajustez votre recherche ou vos filtres.',
+    active: 'Actif',
+    archived: 'Archivé',
+    all: 'Tous',
+    used: 'Occasion',
+    new: 'Neuf',
+    clearFilters: 'Effacer filtres',
+    table: 'Tableau',
+    cards: 'Cartes',
+    net: 'Net',
+    // Column config
+    columns: 'Colonnes',
+    configureColumns: 'Configurer Colonnes',
+    configureColumnsDesc: 'Glissez pour ordonner ou utilisez les flèches. Cliquez sur l\'œil pour masquer.',
+    visible: 'visible',
+    reset: 'Reset',
+    cancel: 'Annuler',
+    applyChanges: 'Appliquer',
+    moveUp: 'Monter',
+    moveDown: 'Descendre',
+    hideColumn: 'Masquer',
+    showColumn: 'Afficher',
+    // Tag linking
+    linkToSpool: 'Lier à une Bobine',
+    tagLinked: 'Tag lié à la bobine',
+    tagLinkFailed: 'Échec lien tag',
+    tagAlreadyLinked: 'Tag déjà lié à une autre bobine',
+    unknownTag: 'Tag RFID inconnu détecté',
+    // Usage history
+    usageHistory: 'Historique de Consommation',
+    noUsageHistory: 'Aucune consommation enregistrée',
+    printName: 'Nom Impression',
+    weightConsumed: 'Poids consommé',
+    clearHistory: 'Effacer',
+    historyCleared: 'Historique effacé',
+    fillSourceLabel: '(Inv)',
+  },
+
+  // Timelapse
+  timelapse: {
+    title: 'Timelapse',
+    create: 'Créer Timelapse',
+    download: 'Télécharger',
+    delete: 'Supprimer',
+    preview: 'Aperçu',
+    frameRate: 'Images/sec',
+    quality: 'Qualité',
+    processing: 'Traitement...',
+    noTimelapses: 'Aucun timelapse',
+  },
+
+  // AMS
+  ams: {
+    title: 'AMS',
+    slot: 'Slot',
+    empty: 'Vide',
+    emptySlot: 'Slot vide',
+    unknown: 'Inconnu',
+    humidity: 'Humidité',
+    temperature: 'Température',
+    filamentType: 'Type filament',
+    filamentColor: 'Couleur',
+    remaining: 'Restant',
+    history: 'Historique AMS',
+    noHistory: 'Aucun historique',
+    configureSlot: 'Configurer Slot',
+    externalSpool: 'Bobine externe',
+    profile: 'Profil',
+    kFactor: 'Facteur K',
+    fill: 'Remplir',
+    configure: 'Configurer',
+  },
+
+  // Print modal
+  printModal: {
+    title: 'Lancer l\'impression',
+    selectPrinter: 'Choisir l\'imprimante',
+    selectPlate: 'Choisir le plateau',
+    filamentMapping: 'Mapping Filament',
+    printSettings: 'Réglages d\'impression',
+    bedLeveling: 'Nivellement plateau',
+    flowCalibration: 'Calibration débit',
+    vibrationCalibration: 'Vibration (Input Shaper)',
+    layerInspection: 'Inspection 1ère couche',
+    timelapse: 'Timelapse',
+    startPrint: 'Démarrer',
+    addToQueue: 'Ajouter à la file',
+    cancel: 'Annuler',
+    noPrintersAvailable: 'Aucune imprimante disponible',
+    printerBusy: 'L\'imprimante est occupée',
+    printerOffline: 'L\'imprimante est hors ligne',
+    sameTypeDifferentColor: 'Même type, couleur différente',
+    filamentTypeNotLoaded: 'Type de filament non chargé',
+    openCalendar: 'Ouvrir calendrier',
+    leftNozzle: 'G',
+    rightNozzle: 'D',
+    leftNozzleTooltip: 'Buse gauche',
+    rightNozzleTooltip: 'Buse droite',
+  },
+
+  // Backup
+  backup: {
+    title: 'Sauvegarde & Restauration',
+    createBackup: 'Créer Sauvegarde',
+    restoreBackup: 'Restaurer Sauvegarde',
+    restoreDescription: 'Remplace les données par un fichier de sauvegarde',
+    downloadBackup: 'Télécharger Sauvegarde',
+    uploadBackup: 'Téléverser Sauvegarde',
+    lastBackup: 'Dernière sauvegarde',
+    autoBackup: 'Sauvegarde auto',
+    backupNow: 'Sauvegarder maintenant',
+    restoreWarning: 'Attention : Écrase TOUTES les données actuelles.',
+    includeArchives: 'Inclure Archives',
+    includeSettings: 'Inclure Paramètres',
+    includeProfiles: 'Inclure Profils',
+    backupSuccess: 'Sauvegarde réussie',
+    restoreSuccess: 'Restauration réussie',
+    backupFailed: 'Échec sauvegarde',
+    restoreFailed: 'Échec restauration',
+    restoreNote: 'L\'imprimante virtuelle sera arrêtée pendant la restauration',
+  },
+
+  // Tags
+  tags: {
+    title: 'Tags',
+    addTag: 'Ajouter Tag',
+    editTag: 'Modifier Tag',
+    deleteTag: 'Supprimer Tag',
+    tagName: 'Nom du Tag',
+    tagColor: 'Couleur du Tag',
+    noTags: 'Aucun tag',
+    deleteConfirm: 'Supprimer ce tag ?',
+    manageTags: 'Gérer les Tags',
+  },
+
+  // Upload modal (archives)
+  uploadModal: {
+    title: 'Téléverser des fichiers 3MF',
+    dragDrop: 'Glissez les fichiers .3mf ici',
+    or: 'ou',
+    browseFiles: 'Parcourir',
+    extractionInfo: 'Le modèle d\'imprimante est extrait des métadonnées 3MF.',
+    uploaded: 'téléversé',
+    failed: 'échoué',
+    uploading: 'En cours...',
+    upload: 'Téléverser',
+    uploadFailed: 'Échec du téléversement',
+  },
+
+  // Edit archive modal
+  // Edit Archive Modal
+  editArchive: {
+    title: 'Modifier l\'archive',
+    name: 'Nom',
+    namePlaceholder: 'Nom de l\'impression',
+    printer: 'Imprimante',
+    noPrinter: 'Aucune imprimante',
+    project: 'Projet',
+    noProject: 'Aucun projet',
+    itemsPrinted: 'Nombre de pièces',
+    itemsPrintedHelp: 'Nombre d\'objets produits',
+    notes: 'Notes',
+    notesPlaceholder: 'Notes sur l\'impression...',
+    externalLink: 'Lien externe',
+    externalLinkPlaceholder: 'https://...',
+    externalLinkHelp: 'Lien vers Printables, Thingiverse, etc.',
+    tags: 'Tags',
+    tagsPlaceholder: 'Ajouter des tags...',
+    addMoreTags: 'Plus de tags...',
+    matchingTags: 'Correspondant à "{{query}}"',
+    existingTags: 'Tags existants',
+    clickToAdd: '(cliquer pour ajouter)',
+    status: 'Statut',
+    failureReason: 'Raison de l\'échec',
+    selectReason: 'Choisir raison...',
+    photos: 'Photos du résultat',
+    photosHelp: 'Cliquez sur + pour ajouter des photos',
+    printResult: 'Résultat d\'impression',
+    saving: 'Enregistrement...',
+    // Failure reasons
+    failureReasons: {
+      adhesionFailure: 'Défaut d\'adhésion',
+      spaghettiDetached: 'Spaghetti / Détaché',
+      layerShift: 'Décalage de couche',
+      cloggedNozzle: 'Buse bouchée',
+      filamentRunout: 'Filament fini',
+      warping: 'Warping (Déformation)',
+      stringing: 'Stringing (Cheveux d\'ange)',
+      underExtrusion: 'Sous-extrusion',
+      powerFailure: 'Coupure courant',
+      userCancelled: 'Annulé par l\'utilisateur',
+      other: 'Autre',
+    },
+    // Archive statuses
+    statuses: {
+      completed: 'Réussie',
+      failed: 'Échouée',
+      aborted: 'Annulée',
+      printing: 'Impression',
+    },
+  },
+
+  // K-Profiles
+  kProfiles: {
+    title: 'K-Profiles',
+    noPrintersConfigured: 'Aucune imprimante configurée',
+    addPrinterInSettings: 'Ajoutez une imprimante pour gérer les K-profiles',
+    noActivePrinters: 'Aucune imprimante active',
+    enablePrinterConnection: 'Activez la connexion pour voir les K-profiles',
+    loadingProfiles: 'Chargement des K-Profiles...',
+    printerOffline: 'Imprimante hors ligne',
+    printerOfflineDesc: 'L\'imprimante doit être allumée.',
+    noMatchingProfiles: 'Aucun profil correspondant',
+    noMatchingProfilesDesc: 'Ajustez votre recherche',
+    noKProfiles: 'Aucun K-Profile',
+    noKProfilesDesc: 'Aucun profil trouvé pour une buse de {{diameter}}mm',
+    createFirstProfile: 'Créer le premier profil',
+    // Controls
+    printer: 'Imprimante',
+    nozzle: 'Buse',
+    refresh: 'Rafraîchir',
+    addProfile: 'Ajouter Profil',
+    export: 'Exporter',
+    import: 'Importer',
+    select: 'Choisir',
+    selectAll: 'Tout sélectionner',
+    delete: 'Supprimer',
+    // Filters
+    searchPlaceholder: 'Nom ou filament...',
+    allExtruders: 'Tous les extrudeurs',
+    leftOnly: 'Gauche uniquement',
+    rightOnly: 'Droite uniquement',
+    allFlow: 'Tout débit',
+    hfOnly: 'HF uniquement',
+    sOnly: 'S uniquement',
+    sortName: 'Tri : Nom',
+    sortKValue: 'Tri : Valeur K',
+    sortFilament: 'Tri : Filament',
+    // Dual extruder labels
+    leftExtruder: 'Extrudeur gauche',
+    rightExtruder: 'Extrudeur droit',
+    // Modal
+    modal: {
+      addTitle: 'Ajouter K-Profile',
+      editTitle: 'Modifier K-Profile',
+      profileName: 'Nom du profil',
+      profileNamePlaceholder: 'ex: Mon profil PLA',
+      kValue: 'Valeur K',
+      kValuePlaceholder: '0.020',
+      kValueHelp: 'Plage type : 0.01-0.06 (PLA), 0.02-0.10 (PETG)',
+      filament: 'Filament',
+      selectFilament: 'Choisir filament...',
+      noFilamentsHelp: 'Créez d\'abord un profil dans Bambu Studio.',
+      flowType: 'Type de débit',
+      highFlow: 'Haut Débit (HF)',
+      standard: 'Standard',
+      nozzleSize: 'Taille buse',
+      extruder: 'Extrudeur',
+      extruders: 'Extrudeurs',
+      left: 'Gauche',
+      right: 'Droite',
+      notes: 'Notes (locales)',
+      notesPlaceholder: 'Notes sur ce profil...',
+      notesHelp: 'Enregistré dans Bambuddy, pas sur l\'imprimante',
+      syncing: 'Sync avec l\'imprimante...',
+      savingExtruder: 'Sauvegarde extrudeur {{current}}/{{total}}...',
+      pleaseWait: 'Patientez...',
+    },
+    // Delete confirmation
+    deleteConfirm: {
+      title: 'Supprimer profil',
+      cannotUndo: 'Action irréversible',
+      message: 'Supprimer "{{name}}" de l\'imprimante ?',
+    },
+    // Bulk delete
+    bulkDelete: {
+      title: 'Supprimer les profils',
+      cannotUndo: 'Action irréversible',
+      message: 'Supprimer les {{count}} profils de l\'imprimante ?',
+    },
+    // Toast
+    toast: {
+      profileSaved: 'Profil K enregistré',
+      profilesSaved: 'Profil K enregistré sur {{count}} extrudeur(s)',
+      selectAtLeastOneExtruder: 'Sélectionnez un extrudeur',
+      profileDeleted: 'Profil K supprimé',
+      profilesDeleted: '{{count}} profils supprimés',
+      exportedProfiles: '{{count}} profils exportés',
+      importedProfiles: '{{count}} sur {{total}} profils importés',
+      noProfilesToExport: 'Rien à exporter',
+      invalidFileFormat: 'Format invalide',
+      failedToParseImport: 'Échec analyse fichier',
+      failedToSaveBatch: 'Échec enregistrement groupé',
+      noteSaved: 'Note enregistrée',
+      failedToSaveNote: 'Échec note',
+    },
+    // Permissions
+    permission: {
+      noRead: 'Pas d\'autorisation lecture',
+      noCreate: 'Pas d\'autorisation création',
+      noUpdate: 'Pas d\'autorisation mise à jour',
+      noDelete: 'Pas d\'autorisation suppression',
+      noExport: 'Pas d\'autorisation export',
+      noImport: 'Pas d\'autorisation import',
+    },
+  },
+
+  // Virtual Printer
+  virtualPrinter: {
+    title: 'Imprimante Virtuelle',
+    running: 'En cours',
+    stopped: 'Arrêtée',
+    description: {
+      default: 'Active une imprimante qui apparaît dans Bambu Studio. Les fichiers envoyés sont archivés sans impression.',
+      proxy: 'Active un proxy qui relaie le trafic vers une imprimante réelle, permettant l\'impression à distance.',
+    },
+    enable: {
+      title: 'Activer l\'imprimante virtuelle',
+      visibleInSlicer: 'Visible comme "Bambuddy" dans le Slicer',
+      proxyingTo: 'Proxy vers {{name}}',
+      notActive: 'Inactive',
+    },
+    model: {
+      title: 'Modèle d\'imprimante',
+      description: 'Choisissez le modèle à émuler.',
+      restartWarning: 'Changer le modèle redémarrera le service',
+    },
+    accessCode: {
+      title: 'Code d\'accès',
+      isSet: 'Code défini',
+      notSet: 'Code requis pour activer',
+      placeholder: 'Code 8 char',
+      placeholderChange: 'Entrez nouveau code',
+      hint: 'Exactement 8 caractères. Sert à l\'auth du Slicer.',
+      charCount: '({{count}}/8)',
+    },
+    targetPrinter: {
+      title: 'Imprimante cible',
+      configured: 'Cible configurée',
+      notConfigured: 'Imprimante requise pour mode Proxy',
+      placeholder: 'Choisir imprimante...',
+      hint: 'L\'imprimante doit être en mode LAN.',
+      noPrinters: 'Ajoutez une imprimante réelle d\'abord.',
+    },
+    remoteInterface: {
+      title: 'Exception Interface Réseau',
+      configured: 'Override actif',
+      optional: 'Optionnel - si IP auto est fausse (VPN, Docker, multi-NIC).',
+      placeholder: 'Auto (défaut)...',
+      hint: 'Force l\'IP annoncée via SSDP.',
+    },
+    mode: {
+      title: 'Mode',
+      archive: 'Archiver',
+      archiveDesc: 'Archive immédiatement',
+      review: 'Revue',
+      reviewDesc: 'Attendre revue avant archive',
+      queue: 'File',
+      queueDesc: 'Archiver et ajouter à la file',
+      proxy: 'Proxy',
+      proxyDesc: 'Relais vers imprimante réelle',
+    },
+    setupRequired: {
+      title: 'Configuration requise',
+      description: 'Nécessite des réglages système (ports, pare-feu).',
+      readGuide: 'Lire le guide de configuration',
+    },
+    howItWorks: {
+      title: 'Fonctionnement',
+      titleProxy: 'Fonctionnement (Mode Proxy)',
+      step1: 'Suivez le guide pour votre plateforme',
+      step2: 'Activez et réglez le code d\'accès',
+      step3: 'Dans le Slicer, allez dans "Ajouter Imprimante"',
+      step4: '"Bambuddy" apparaîtra dans la découverte',
+      step5: 'Connectez avec votre code d\'accès',
+      step6: 'Imprimez vers Bambuddy : le 3MF est archivé',
+      proxyStep1: 'Cible réelle en mode LAN',
+      proxyStep2: 'Choisissez l\'interface réseau',
+      proxyStep3: 'Activez le proxy',
+      proxyStep4: 'Connectez avec le code de la vraie imprimante',
+      proxyStep5: 'Le trafic est relayé par Bambuddy',
+      proxyStep6: 'Streaming caméra : voir doc NAT/IP forwarding',
+    },
+    status: {
+      title: 'Détails du statut',
+      printerName: 'Nom',
+      model: 'Modèle',
+      serialNumber: 'Série',
+      mode: 'Mode',
+      pendingFiles: 'Fichiers en attente',
+      targetPrinter: 'Cible',
+      ftpPort: 'Port FTP',
+      mqttPort: 'Port MQTT',
+      ftpConnections: 'Connexions FTP',
+      mqttConnections: 'Connexions MQTT',
+    },
+    toast: {
+      updated: 'Réglages virtuels mis à jour',
+      failedToUpdate: 'Échec mise à jour',
+      accessCodeRequired: 'Code d\'accès requis',
+      targetPrinterRequired: 'Imprimante cible requise',
+      accessCodeEmpty: 'Le code ne peut pas être vide',
+      accessCodeLength: 'Le code doit faire 8 caractères',
+    },
+  },
+
+  // Model Viewer
+  modelViewer: {
+    openInSlicer: 'Ouvrir dans le Slicer',
+    tabs: {
+      model: 'Modèle 3D',
+      gcode: 'Aperçu G-code',
+    },
+    notAvailable: 'indisponible',
+    notSliced: 'pas découpé',
+    plates: 'Plateaux',
+    allPlates: 'Tous les plateaux',
+    plateNumber: 'Plateau {{number}}',
+    plateCount: '{{count}} plateau',
+    plateCount_other: '{{count}} plateaux',
+    objectCount: '{{count}} objet',
+    objectCount_other: '{{count}} objets',
+    filamentCount: '{{count}} filament',
+    filamentCount_other: '{{count}} filaments',
+    eta: 'Fin {{minutes}} min',
+    noPreview: 'Aucun aperçu pour ce fichier',
+    pagination: {
+      pageOf: 'Page {{current}} sur {{total}}',
+      prev: 'Préc',
+      next: 'Suiv',
+    },
+    errors: {
+      failedToLoad: 'Échec chargement fichier',
+      noMeshes: 'Aucun maillage trouvé dans le 3MF',
+      unsupportedFormat: 'Format non supporté',
+    },
+  },
+
+  // Maintenance type descriptions (built-in)
+  maintenanceDescriptions: {
+    lubricateCarbonRods: 'Appliquer du lubrifiant sur les tiges carbone pour un mouvement fluide',
+    lubricateRails: 'Appliquer du lubrifiant sur les rails linéaires',
+    cleanNozzle: 'Nettoyer buse et hotend anti-bouchage',
+    checkBelts: 'Tension des courroies pour la précision',
+    cleanBuildPlate: 'Nettoyage plateau pour l\'adhésion',
+    checkExtruder: 'Usure des engrenages de l\'extrudeur',
+    checkCooling: 'Bon fonctionnement des ventilateurs',
+    generalInspection: 'Inspection générale de la machine',
+    cleanCarbonRods: 'Nettoyer les tiges carbone (friction)',
+    cleanLinearRails: 'Essuyer les rails linéaires (poussière/débris)',
+    checkPtfeTube: 'Usure ou dommage du tube PTFE',
+    replaceHepaFilter: 'Filtre HEPA pour la qualité de l\'air',
+    replaceCarbonFilter: 'Filtre charbon actif (odeurs)',
+    lubricateLeftNozzleRail: 'Lubrifier le rail de buse gauche (Série H2)',
+  },
+
+  // Smart Plugs
+  smartPlugs: {
+    offline: 'Hors ligne',
+    admin: 'Admin',
+    openPlugAdminPage: 'Page admin de la prise',
+    deleteSmartPlug: 'Supprimer la prise',
+    turnOnSmartPlug: 'Allumer la prise',
+    turnOffSmartPlug: 'Éteindre la prise',
+    turnOn: 'Allumer',
+    turnOff: 'Éteindre',
+    addSmartPlug: {
+      scanningNetwork: 'Scan réseau...',
+      chooseEntity: 'Choisir une entité...',
+      connectionFailed: 'Échec connexion',
+      searchEntities: 'Chercher entités...',
+      searchPowerSensors: 'Capteurs puissance...',
+      searchEnergySensors: 'Capteurs énergie...',
+      placeholders: {
+        plugName: 'Prise Salon',
+        mqttStateOnValue: 'ON, true, 1',
+        mqttSameAsPower: 'Identique au topic puissance, ou différent',
+      },
+    },
+  },
+
+  // Rich Text Editor
+  richTextEditor: {
+    bold: 'Gras',
+    italic: 'Italique',
+    underline: 'Souligné',
+    bulletList: 'Liste à puces',
+    numberedList: 'Liste numérotée',
+    alignLeft: 'Aligner à gauche',
+    alignCenter: 'Centrer',
+    alignRight: 'Aligner à droite',
+    addLink: 'Ajouter lien',
+    removeLink: 'Retirer lien',
+  },
+
+  // External Links
+  externalLinks: {
+    noLinksConfigured: 'Aucun lien externe configuré',
+    deleteLink: 'Supprimer lien',
+    removeCustomIcon: 'Retirer icône personnalisée',
+    openInNewTab: 'Ouvrir dans un nouvel onglet',
+    placeholders: {
+      linkName: 'Mon Lien',
+    },
+  },
+
+  // Keyboard Shortcuts Modal
+  keyboardShortcuts: {
+    title: 'Raccourcis Clavier',
+    navigation: 'Navigation',
+    archivesSection: 'Archives',
+    kProfilesSection: 'K-Profiles',
+    generalSection: 'Général',
+    shortcuts: {
+      goToPrinters: 'Aller aux Imprimantes',
+      goToArchives: 'Aller aux Archives',
+      goToQueue: 'Aller à la File',
+      goToStats: 'Aller aux Stats',
+      goToProfiles: 'Aller aux Profils Cloud',
+      goToSettings: 'Aller aux Paramètres',
+      focusSearch: 'Focus recherche',
+      openUploadModal: 'Ouvrir téléversement',
+      clearSelection: 'Tout déselectionner',
+      contextMenu: 'Menu contextuel (cartes)',
+      refreshProfiles: 'Rafraîchir profils',
+      newProfile: 'Nouveau profil',
+      exitSelectionMode: 'Quitter mode sélection',
+      showHelp: 'Afficher cette aide',
+    },
+    footer: 'Échap ou clic extérieur pour fermer',
+  },
+
+  // Notification Log
+  notificationLog: {
+    title: 'Journal de Notification',
+    events: {
+      printStarted: 'Début impression',
+      printComplete: 'Fin impression',
+      printFailed: 'Échec impression',
+      printStopped: 'Arrêt impression',
+      progress: 'Progression',
+      printerOffline: 'Hors ligne',
+      printerError: 'Erreur',
+      lowFilament: 'Filament bas',
+      maintenanceDue: 'Maintenance',
+      test: 'Test',
+    },
+    timeAgo: {
+      justNow: 'À l\'instant',
+      minutesAgo: 'Il y a {{minutes}}m',
+      hoursAgo: 'Il y a {{hours}}h',
+    },
+  },
+
+  // Restore/Backup Modal
+  restoreBackup: {
+    title: 'Restaurer Sauvegarde',
+    restoring: 'Restauration...',
+    restoreComplete: 'Restauration terminée',
+    restoreFailed: 'Échec restauration',
+    importSettings: 'Importer les réglages d\'un fichier',
+    pleaseWait: 'Patientez pendant la restauration',
+    clickToSelect: 'Fichier .json ou .zip',
+    howDuplicateHandling: 'Gestion des doublons :',
+    categories: {
+      printers: 'Imprimantes',
+      smartPlugs: 'Prises',
+      notificationProviders: 'Fournisseurs',
+      filaments: 'Filaments',
+      archives: 'Archives',
+      pendingUploads: 'Téléversements en attente',
+      settingsTemplates: 'Réglages & Modèles',
+    },
+    matchingInfo: {
+      printers: 'par numéro de série',
+      smartPlugs: 'par adresse IP',
+      notificationProviders: 'par nom',
+      filaments: 'par nom+type+marque',
+      archives: 'par empreinte numérique (hash)',
+      pendingUploads: 'par nom de fichier',
+      settingsTemplates: 'toujours écrasés',
+    },
+    replaceExisting: 'Remplacer existant',
+    keepExisting: 'Garder existant',
+    replaceDescription: 'Écrase les doublons avec la sauvegarde',
+    keepDescription: 'Ne restaure que les éléments absents',
+    caution: 'Attention :',
+    cautionText: 'L\'écrasement remplacera vos réglages. Les codes d\'accès imprimantes sont exclus par sécurité.',
+    itemsRestored: 'Éléments restaurés',
+    itemsSkipped: 'Éléments ignorés',
+    restored: 'Restaurés',
+    skipped: 'Ignorés (déjà présents)',
+    filesLabel: 'Fichiers (3MF, vignettes, etc.)',
+    newApiKeysGenerated: 'Nouvelles clés API générées',
+    newApiKeysWarning: 'Copiées maintenant, elles ne seront plus visibles !',
+    processingBackup: 'Traitement du fichier...',
+    noDataFound: 'Aucune donnée trouvée dans le fichier.',
+    failedToRestore: 'Échec restaure. Vérifiez le format.',
+  },
+
+  // Backup Export Modal
+  backupExport: {
+    title: 'Exporter Sauvegarde',
+    selectData: 'Données à inclure',
+    selectAll: 'Tout sélectionner',
+    selectNone: 'Ne rien sélectionner',
+    categoryDescriptions: {
+      settings: 'Langue, thèmes, préférences',
+      notifications: 'ntfy, Pushover, Discord, etc.',
+      templates: 'Modèles de messages personnalisés',
+      smartPlugs: 'Configuration des prises Tasmota',
+      externalLinks: 'Liens externes de la barre latérale',
+      printers: 'Infos imprimantes (codes d\'accès exclus par défaut)',
+      plateDetection: 'Images références des plateaux vides',
+      filaments: 'Types et coûts filaments',
+      maintenance: 'Plannings de maintenance personnalisés',
+      archives: 'Données impressions + fichiers (3MF, vignettes, etc.)',
+      projects: 'Projets, BOM, pièces jointes',
+      pendingUploads: 'En attente revue virtuelle',
+      apiKeys: 'Clés Webhook (nouvelles clés générées à l\'import)',
+    },
+    requiresPrinters: 'Nécessite sélection des imprimantes',
+    zipFileWarning: 'Fichier ZIP créé.',
+    zipFileDescription: 'Contient tous les médias. Peut être volumineux.',
+    includeAccessCodes: 'Inclure Codes d\'accès',
+    includeAccessCodesDescription: 'Pour migrer vers une autre machine',
+    includeAccessCodesWarning: 'Codes en texte clair. Sécurisez ce fichier !',
+    categoriesSelected: '{{selectedCount}} catégories choisies',
+  },
+
+  // Pending Uploads Panel
+  pendingUploads: {
+    placeholders: {
+      notes: 'Notes sur l\'impression...',
+    },
+    discardUpload: 'Rejeter',
+    archiveAllUploads: 'Tout archiver',
+    discardAllUploads: 'Tout rejeter',
+    archive: 'Archiver',
+    timeAgo: {
+      justNow: 'À l\'instant',
+      minutesAgo: 'Il y a {{minutes}}m',
+      hoursAgo: 'Il y a {{hours}}h',
+      daysAgo: 'Il y a {{days}}j',
+    },
+  },
+
+  // API Browser
+  apiBrowser: {
+    placeholders: {
+      requestBody: 'Corps JSON...',
+      searchEndpoints: 'Chercher endpoints...',
+    },
+  },
+
+  // Configure AMS Slot Modal
+  configureAmsSlot: {
+    searchPresets: 'Chercher presets...',
+    colorPlaceholder: 'Nom couleur ou hex (ex: brown, FF8800)',
+    clearCustomColor: 'Effacer couleur perso',
+    noCloudPresets: 'Profils Cloud absents. Connectez-vous.',
+    noMatchingPresets: 'Aucun profil trouvé.',
+    custom: 'Perso',
+    builtin: 'Inclus',
+    settingsSentToPrinter: 'Réglages envoyés',
+    filamentProfile: 'Profil Filament',
+  },
+
+  // GitHub Backup Settings
+  githubBackup: {
+    title: 'Sauvegarde GitHub',
+    history: 'Historique',
+    downloadBackup: 'Télécharger',
+    restoreBackup: 'Restaurer',
+    noBackupsYet: 'Aucune sauvegarde',
+  },
+
+  // Email Settings
+  emailSettings: {
+    placeholders: {
+      fromName: 'BamBuddy',
+    },
+  },
+
+  // Tag Management Modal
+  tagManagement: {
+    searchTags: 'Chercher tags...',
+    renameTag: 'Renommer tag',
+    deleteTag: 'Supprimer tag',
+  },
+
+  // Notification Template Editor
+  notificationTemplates: {
+    placeholders: {
+      title: 'Titre notification...',
+      body: 'Message notification...',
+    },
+  },
+
+  // Batch Tag Modal
+  batchTag: {
+    placeholders: {
+      newTag: 'Nouveau tag...',
+    },
+  },
+
+  // Photo Gallery Modal
+  photoGallery: {
+    deletePhoto: 'Supprimer photo',
+  },
+
+  // Filament Hover Card
+  filamentHoverCard: {
+    copySpoolUuid: 'Copier UUID bobine',
+  },
+
+  // K Profiles View
+  kProfilesView: {
+    hasNote: 'A une note',
+    copyProfile: 'Copier profil',
+  },
+
+  // Layout/Navigation
+  layout: {
+    openMenu: 'Ouvrir menu',
+    noPermissionSystemInfo: 'Pas d\'autorisation système',
+  },
+
+  // Dashboard
+  dashboard: {
+    dragToReorder: 'Glisser pour réorganiser',
+    hideWidget: 'Masquer widget',
+  },
+
+  // Notification Provider Card
+  notificationProviderCard: {
+    deleteNotificationProvider: 'Supprimer fournisseur',
+  },
+
+  // File Manager Modal
+  fileManagerModal: {
+    closeFileManager: 'Fermer gestionnaire',
+    sortFiles: 'Trier fichiers',
+    goToParentFolder: 'Dossier parent',
+    threeView: 'Vue 3D',
+  },
+
+  // Embedded Camera Viewer
+  embeddedCameraViewer: {
+    refreshStream: 'Actualiser flux',
+    close: 'Fermer',
+    zoomOut: 'Zoom -',
+    resetZoom: 'Reset zoom',
+    zoomIn: 'Zoom +',
+    dragToResize: 'Glisser pour dimension',
+  },
+
+  // Timelapse Viewer
+  timelapseViewer: {
+    skipBack5s: '-5s',
+    skipForward5s: '+5s',
+  },
+
+  // Notification Providers
+  notificationProviders: {
+    descriptions: {
+      email: 'Notifications par email SMTP',
+      telegram: 'Via bot Telegram',
+      discord: 'Via webhook Discord',
+      ntfy: 'Push auto-hébergé (ntfy)',
+      pushover: 'Push fiable (Pushover)',
+      callmebot: 'WhatsApp gratuit via CallMeBot',
+      webhook: 'Requête HTTP POST personnalisée',
+    },
+  },
+
+  // Log Viewer
+  logViewer: {
+    searchPlaceholder: 'Message ou nom...',
+    noLogEntries: 'Aucune entrée journal',
+  },
+
+  // Switchbar Popover
+  switchbarPopover: {
+    noSwitchesInSwitchbar: 'Aucun interrupteur',
+  },
+
+  // Project Page Modal
+  projectPageModal: {
+    placeholders: {
+      title: 'Titre',
+      designer: 'Designer',
+      license: 'Licence',
+      description: 'Description...',
+      profileTitle: 'Titre du profil',
+      profileDescription: 'Description du profil...',
+    },
+  },
+
+  // Spoolman Settings
+  spoolmanSettings: {},
+};