/**
 * French translations for Cyber-Assistant
 * Outil de gestion SMSI conforme ISO 27001:2022 / ISO 27002:2022 et NIS2
 */
(function() {
  'use strict';

  const translations = {
    // Application
    app: {
      title: 'Cyber-Assistant',
      subtitle: 'Système de management de la sécurité',
      loading: 'Chargement de l\'application SMSI...',
      skipLink: 'Aller au contenu principal',
      loadingAria: 'Chargement en cours'
    },

    // Header buttons
    header: {
      manual: 'Manuel d\'utilisation',
      logout: 'Déconnexion',
      presentation: 'Présentation',
      settings: 'Paramètres',
      editMode: 'Mode édition',
      exitEditMode: 'Quitter édition',
      readOnlyMode: 'Mode lecture seule',
      editModeSubtitle: 'Mode édition actif : vous pouvez modifier les données et publier vers le serveur.',
      readOnlyNotice: 'Mode lecture seule : activez le mode édition pour modifier.',
      viewerReadOnly: 'Votre rôle est Lecteur — mode lecture seule permanent.',
      darkMode: 'Mode sombre',
      lightMode: 'Mode clair',
      powderMode: 'Mode poudre',
      authRequired: 'Authentification requise',
      editPasswordPrompt: 'Mot de passe d\'édition :',
      passwordLabel: 'Mot de passe',
      validate: 'Valider',
      auditLog: 'Traçabilité',
      backToDashboard: 'Retour au Dashboard',
      themeToggleAria: 'Basculer le thème',
      themeToggleTitle: 'Changer de thème',
      autoSaveTitle: 'Dernière sauvegarde automatique',
      connectedUsers: 'Utilisateurs connectés',
      traceability: 'Traçabilité',
      // Refonte header 2026-07 : menu utilisateur + pastille de synchronisation
      userMenu: 'Menu utilisateur',
      themeLabel: 'Thème :',
      syncSynced: 'Synchronisé',
      syncSaving: 'Sauvegarde…',
      syncError: 'Échec sync',
      syncLocal: 'Sauvegarde auto'
    },

    // Mode banner
    mode: {
      readOnly: 'Mode lecture seule',
      editing: 'Mode édition',
      editingSubtitle: 'Les modifications sont enregistrées automatiquement'
    },

    // Bandeau "édition" et coordination du verrou global serveur
    modeBanner: {
      readOnly: 'Lecture seule',
      editingByYou: 'Mode édition actif',
      editingByOther: 'Édité par',
      untilExpiry: 'avant expiration du verrou',
      // FIX-BANNER-HONESTY (audit co-édition 2026-07-17) : détenteur actif = pas de décompte.
      holderActive: 'édition en cours',
      // === CSI-CO === (Lot 4, 2026-07-17) « Demander la main » — demande courtoise au détenteur.
      requestHand: 'Demander la main',
      requestHandTitle: 'Prévenir la personne qui édite ce module que vous attendez',
      requestHandSent: 'Demande envoyée',
      requestHandConfirmed: 'Demande envoyée — {{name}} sera prévenu(e) que vous attendez ce module.',
      requestHandFailed: 'Demande impossible pour le moment — réessayez.',
      handRequested: '{{name}} attend le module « {{module}} » — naviguez vers un autre module ou quittez l\'édition pour le libérer.',
      lockExpiringSoon: "verrou en attente d'expiration",
      lockedShort: 'Verrouillé',
      takeover: 'Reprendre la main',
      takeoverTitle: 'Forcer la libération du verrou (admin uniquement)',
      takeoverConfirm: 'Forcer la libération du verrou détenu par {{name}} ? Ses modifications non enregistrées seront perdues.',
      takeoverSuccess: 'Verrou repris avec succès',
      takeoverFailed: 'Impossible de reprendre le verrou',
      takeoverDenied: 'Action réservée aux administrateurs',
      acquireOtherTab: "Vous éditez déjà dans une autre fenêtre (autre onglet, autre navigateur ou autre appareil). Quittez-y le mode édition, puis réessayez ici.",
      acquireFailed: 'Édition impossible : {{name}} édite déjà',
      lockStolen: "L'administrateur a repris la main. Vous êtes en lecture seule.",
      lockExpired: "Votre verrou d'édition a expiré (perte de connexion). Repassez en mode édition pour continuer.",
      autoQuitInactivity: 'Mode édition désactivé après 5 min sans modification',
      // FIX-I18N-KEYS (audit 2026-06-10)
      acquireNetworkError: 'Impossible de vérifier le verrou d\'édition (problème réseau). Réessayez.',
      // === CSI-CO === co-édition par grappes (bandeau contextuel au module affiché)
      editingModule: 'Module : {{module}}',
      moduleEditedBy: 'Module {{module}} — édité par',
      clusterBusy: 'Module « {{module}} » en cours d\'édition par {{name}} — lecture seule ici.',
      clickToRetry: 'cliquez pour réessayer'
    },

    // === CSI-BUILD === Bandeau de mise à jour (onglet resté ouvert pendant une MAJ serveur)
    updateBanner: {
      newVersion: 'Une nouvelle version de l\'application est disponible.',
      reload: 'Mettre à jour',
      hardReload: 'La mise à jour n\'a pas été prise en compte — faites un rechargement forcé (Ctrl+F5, ou Cmd+Maj+R sur Mac).',
      dismiss: 'Ignorer'
    },

    // === CSI-UPD === Mise à jour du serveur par paquet ZIP signé (édition Serveur, admin)
    serverUpdate: {
      adminOnly: 'Réservé aux administrateurs en mode serveur.',
      unavailable: 'Service de mise à jour indisponible.',
      timeout: 'Délai dépassé — la mise à jour est peut-être toujours en cours côté serveur. Rechargez cette page dans un instant pour vérifier.',
      notDeployed: 'Module de mise à jour absent du serveur.',
      notDeployedHelp: "Cette installation ne dispose pas encore du module de mise à jour (update.php). Déployez-le une première fois manuellement ; les mises à jour suivantes se feront depuis cet écran.",
      cardVersionTitle: 'Version installée',
      cardVersionDesc: "État de l'installation et prérequis techniques.",
      installedVersion: 'Version',
      unknownVersion: 'inconnue',
      lastUpdate: 'Dernière mise à jour',
      never: 'jamais par cet écran',
      capZip: 'Extension ZIP',
      capWrite: "Droits d'écriture",
      capDisk: 'Espace disque libre',
      cardUploadTitle: 'Mettre à jour par paquet',
      cardUploadDesc: "Téléversez le paquet .zip fourni par l'éditeur. Il est vérifié (signature et empreintes) avant toute modification.",
      chooseFile: 'Choisir un paquet…',
      notAZip: 'Le fichier doit être une archive .zip.',
      fileTooBig: "Paquet trop volumineux pour les limites de cet hébergement (6,5 Mo maximum).",
      readError: 'Lecture du fichier impossible.',
      checking: 'Vérification du paquet…',
      planFrom: 'Version installée :',
      planTo: 'Version du paquet :',
      planChanged: 'Fichiers remplacés :',
      planAdded: 'Fichiers ajoutés :',
      planRemoved: 'Fichiers supprimés :',
      planUnchanged: 'Fichiers inchangés :',
      applyBtn: 'Appliquer la mise à jour',
      confirmTitle: 'Appliquer la mise à jour ?',
      confirmBody: "Une sauvegarde du code et un instantané des données sont créés avant toute écriture. En cas d'échec, la version précédente est restaurée automatiquement.",
      applying: 'Mise à jour en cours — ne fermez pas cette page…',
      applyOk: 'Mise à jour appliquée.',
      applyPartial: 'Mise à jour appliquée mais des fichiers ne correspondent pas au manifeste — vérifiez le serveur.',
      editorsActiveTitle: 'Des utilisateurs éditent en ce moment',
      forceHelp: 'Forcer la mise à jour interrompra leur édition en cours.',
      forceAnyway: 'Forcer la mise à jour',
      reloadNow: "Recharger l'application",
      cardRollbackTitle: 'Retour arrière',
      cardRollbackDesc: 'Restaure le code de la version précédente. Les données ne sont pas modifiées.',
      backupAvailable: 'Version sauvegardée :',
      noBackup: 'Aucune sauvegarde disponible.',
      rollbackBtn: 'Restaurer la version précédente',
      rollbackConfirmTitle: 'Restaurer la version précédente ?',
      rollbackConfirmBody: 'Le code du serveur sera remplacé par la version sauvegardée. Les données et les comptes ne sont pas modifiés.',
      rollbackOk: 'Version précédente restaurée.',
      showcaseTitle: 'Mise à jour du serveur',
      showcaseBody: "Sur l'édition Serveur, les mises à jour s'appliquent depuis l'application : vous déposez le paquet fourni par l'éditeur, et le serveur s'en charge.",
      showcaseHowTitle: 'Comment cela fonctionne',
      showcaseHow1: "Le paquet est signé par l'éditeur : un fichier modifié ou d'origine inconnue est refusé avant toute écriture.",
      showcaseHow2: 'Vos données, comptes, paramètres et configuration SSO ne sont jamais touchés — seul le code applicatif est remplacé.',
      showcaseHow3: 'Une sauvegarde est créée avant chaque mise à jour, avec un retour arrière en un clic.',
      showcaseMeanwhile: 'En attendant : sur cette édition, les mises à jour se font en remplaçant les fichiers de l\'application (procédure du guide d\'installation).',
      errors: {
        signatureInvalid: "Signature du paquet invalide — ce paquet ne provient pas de l'éditeur ou a été modifié.",
        manifestMissing: "Ce fichier n'est pas un paquet de mise à jour Cyber-Assistant.",
        manifestNotCanonical: 'Manifeste du paquet illisible ou non conforme.',
        manifestInvalid: 'Manifeste du paquet invalide.',
        formatUnsupported: 'Format de paquet non pris en charge par cette version du serveur.',
        editionMismatch: "Ce paquet n'est pas destiné à l'édition Serveur.",
        migrationsUnsupported: 'Ce paquet requiert une migration non prise en charge par cette version du serveur.',
        pathRejected: 'Le paquet contient un fichier non autorisé — mise à jour refusée.',
        undeclaredEntry: 'Le paquet contient un fichier non déclaré — mise à jour refusée.',
        hashMismatch: 'Le contenu du paquet ne correspond pas à son manifeste (fichier altéré).',
        entryMissing: 'Le paquet est incomplet.',
        downgrade: 'Ce paquet est antérieur à la version installée. Utilisez le retour arrière pour revenir en arrière.',
        minVersion: 'Ce paquet exige une version installée plus récente.',
        stagingTampered: 'Le paquet en attente a été altéré — téléversez-le à nouveau.',
        noStaging: "Aucun paquet en attente — téléversez d'abord un fichier.",
        zipUnavailable: "L'extension PHP « zip » est absente de cet hébergement : la mise à jour par paquet n'est pas disponible ici (procédure manuelle dans le guide serveur).",
        tooLarge: "Paquet trop volumineux pour les limites de cet hébergement.",
        tooLargePhp: "Paquet trop volumineux pour les limites PHP de cet hébergement.",
        badZip: "L'archive est illisible.",
        badBase64: 'Le fichier envoyé est illisible.',
        noPackage: 'Aucun paquet reçu.',
        backupFailed: "Sauvegarde impossible avant mise à jour — rien n'a été modifié.",
        rolledBack: 'La mise à jour a échoué — la version précédente a été restaurée.',
        noBackup: 'Aucune sauvegarde disponible.',
        backupCorrupt: 'La sauvegarde est illisible.'
      }
    },

    // === CSI-CO === Libellés humains des grappes de co-édition (jamais « grappe » à l'écran)
    clusters: {
      coeur: 'Pilier SMSI',
      pilotage: 'Pilotage & documents',
      analyse: 'Analyses de risques',
      config: 'Configuration'
    },

    // Navigation
    nav: {
      dashboard: 'Dashboard',
      controlsISO: 'Contrôles ISO27002',
      controlsISO27002: 'Contrôles ISO27002',
      controlsNIS2: 'Contrôles NIS2',
      recyfControls: 'Mesures ReCyF',
      soa: 'Déclaration d\'applicabilité',
      docReview: 'Revue normative',
      actions: 'Plan d\'actions',
      risks: 'Risques SMSI',
      threats: 'Menaces',
      nonConformities: 'Non-conformités',
      audits: 'Audits',
      managementReviews: 'Revues de direction',
      stakeholders: 'Parties prenantes',
      documents: 'Structure documentaire',
      kpis: 'KPIs',
      nis2Program: 'Budget Cybersécurité',
      nis2Socle: 'Socle Sécurité',
      criticalAssets: 'Actifs essentiels',
      projectRisks: 'Risques projets',
      riskAnalysis: 'Analyse des risques',
      impactMatrices: 'Matrice d\'impacts',
      frameworkMapping: 'Mapping transversal',
      bar1Title: 'Fondations du SMSI',
      bar2Title: 'Gouvernance du SMSI',
      bar3Title: 'Contrôles du SMSI',
      bar4Title: 'Gestion des risques projets',
      bar5Title: 'Conformité NIS2',
      ariaLabel: 'Navigation principale'
    },

    // Dashboard
    dashboard: {
      title: 'Dashboard SMSI',
      subtitle: 'Vue d\'ensemble de la conformité ISO 27001:2022',
      conformityRate: 'Conformité globale',
      implementedControls: 'Contrôles implémentés',
      totalActions: 'Actions en cours',
      criticalRisks: 'Risques critiques',
      openNonConformities: 'Non-conformités',
      projectRiskAnalyses: 'Analyses risques projets',
      criticalAssets: 'Actifs critiques',
      identifiedThreats: 'Menaces identifiées',
      plannedAudits: 'Audits planifiés',
      documentStructure: 'Structure documentaire',
      riskAnalysesTile: 'Analyses de risques',
      managementReviewsTile: 'Revues de direction',
      exportPdf: 'Exporter en PDF',
      alertsTitle: 'Alertes & priorités',
      alertCriticalRisks: 'risque(s) critique(s) à traiter',
      alertOverdueActions: 'action(s) en retard',
      alertUpcomingAudits: 'audit(s) dans les 30 jours',
      alertProjectsAtRisk: 'projet(s) à risque élevé',
      noAlerts: 'Aucune alerte en cours',
      badgeUrgent: 'Urgent',
      badgeOverdue: 'Retard',
      badgePlanned: 'Planifié',
      badgeProjects: 'Projets',
      chartImplemented: 'Implémentés',
      chartRemaining: 'Restants',
      maturityISO: 'Maturité ISO27002',
      radarNote: 'Une valeur de 0 indique l\'absence de contrôle associé.',
      scoreSMSI: 'Score SMSI',
      scoreISO: 'ISO 27001',
      scoreCyFun: 'NIS2',
      scoreRisks: 'Risques maîtrisés',
      riskDistribution: 'Répartition des risques',
      maturityCMM: 'Maturité CMM',
      riskMatrix: 'Matrice des risques',
      actionsStatus: 'Statut actions',
      controlsByDomain: 'Contrôles par domaine',
      projectRisks: 'Risques projets',
      recentActivity: 'Activité récente',
      iso27001: 'ISO 27001',
      controls: 'Contrôles',
      actions: 'Actions',
      risks: 'Risques',
      nc: 'NC',
      noActions: 'Aucune action',
      noProjects: 'Aucun projet',
      cmmLevels: 'Niveaux de maturité',
      filtersNotImplemented: 'Filtrage temporel bientôt disponible',
      openAuditTrail: 'Ouvrir la traçabilité',
      conformityByCategory: 'Conformité par catégorie',
      actionsByPriority: 'Actions par priorité',
      risksByLevel: 'Risques par niveau',
      actionsEvolution: 'Évolution des actions',
      noRecentActivity: 'Aucune activité récente',
      viewSwitchAria: 'Vue du dashboard',
      viewLabel: 'Vue',
      currentPerimeter: 'Périmètre courant',
      allEntities: 'Toutes les entités',
      consolidatedNote: 'Vue consolidée en lecture seule des éléments métier.',
      consolidatedLoadError: 'Vue consolidée indisponible pour le moment.',
      maturityByEntity: 'Maturité par entité',
      maturityByEntityHint: 'Les scores de conformité restent calculés séparément pour chaque entité.',
      referential: 'Référentiel',
      controlScore: 'Contrôles',
      iso27001Conformity: 'Conformité ISO 27001',
      iso27002Maturity: 'Maturité ISO 27002',
      // (audit 2026-07-10) libellé neutre : en ReCyF la valeur est un taux de
      // conformité, pas une maturité — « Score NIS2 » couvre les deux référentiels.
      nis2MaturityScore: 'Maturité NIS2 (évaluées)',
      evaluatedControls: 'Évalués',
      noMaturityData: 'Aucune maturité renseignée.',
      alertOverdueAudits: 'audit(s) en retard'
    },

    // Charts
    charts: {
      iso27002Maturity: 'Maturité ISO27002',
      nis2Maturity: 'Maturité NIS2',
      riskDistribution: 'Répartition des risques',
      riskDistributionSubtitle: 'Classification par niveau de criticité : évaluation objective des incidents/actions sur une échelle (faible à critique) pour orienter les ressources.',
      controlMaturity: 'Maturité des contrôles',
      controlMaturitySubtitle: 'Répartition par niveau CMM : cartographie des processus sur cinq niveaux de maturité pour structurer et piloter l\'amélioration continue.',
      riskMatrix: 'Matrice des risques',
      riskMatrixSubtitle: 'Impact x Probabilité : matrice croisant gravité et fréquence des événements pour hiérarchiser les risques et définir les plans de mitigation.',
      actionsEvolution: 'Évolution des actions',
      actionsEvolutionSubtitle: 'Progression du plan d\'actions par priorité : hiérarchisation des tâches selon urgence et impact, avec jalons clairs et suivi régulier.',
      noControlNote: 'Une valeur à 0 indique qu\'il n\'y a pas de contrôle associé.',
      actionCount: 'Nombre d\'actions',
      months: 'Mois',
      actionsHistoryBuilding: 'L\'historique se construit au fil des mois. La courbe d\'évolution apparaîtra dès qu\'au moins deux mois de données auront été enregistrés.'
    },

    // Controls table headers
    controls: {
      ref: 'Réf.',
      clickToExpand: 'Cliquer pour développer/réduire',
      control: 'Contrôle',
      attributes: 'Attributs',
      owner: 'Propriétaire',
      status: 'Statut',
      maturity: 'Maturité',
      lastEval: 'Dernière évaluation',
      evidence: 'Preuve'
    },

    // Controls ISO27002
    controlsISO: {
      title: 'Contrôles ISO27002',
      subtitle: 'Contrôles ISO 27002:2022 par domaine, statut et niveau de maturité',
      allDomains: 'Tous les domaines',
      organizational: 'Organisationnel',
      human: 'Humain',
      physical: 'Physique',
      technological: 'Technologique',
      unclassified: 'Non classé',
      allStatuses: 'Tous les statuts',
      notImplemented: 'Non implémenté',
      inProgress: 'En cours',
      implemented: 'Implémenté',
      verified: 'Vérifié',
      allLevels: 'Tous les niveaux',
      initial: 'Initial',
      repeatable: 'Répétable',
      defined: 'Défini',
      managed: 'Géré',
      optimized: 'Optimisé',
      allCapabilities: 'Toutes les capacités',
      exportExcel: 'Export Excel',
      newControl: 'Nouveau contrôle',
      num: 'Num',
      titleCol: 'Titre',
      description: 'Description',
      capability: 'Capacité',
      status: 'Statut',
      linkedActions: 'Actions liées',
      cmmLevel: 'Niveau de maturité CMM',
      notEvaluated: 'Non évalué'
    },

    // Controls CyFun (NIS2)
    controlsNIS2: {
      title: 'Contrôles NIS2',
      allFunctions: 'Toutes les fonctions',
      allCategories: 'Toutes les catégories',
      function: 'Fonction',
      category: 'Catégorie',
      justification: 'Justification',
      cmmMaturity: 'Maturité CMM',
      ref: 'Réf.',
      owner: 'Responsable',
      reviewer: 'Relecteur',
      reviewFrequency: 'Fréquence de revue',
      lastEvaluation: 'Dernière évaluation',
      nextReviewDate: 'Prochaine revue',
      docMaturity: 'Mat. Doc.',
      implMaturity: 'Mat. Impl.',
      status: 'Statut',
      avg: 'Moyenne',
      filterFunction: 'Fonction',
      filterCategory: 'Catégorie',
      filterLevel: 'Niveau',
      allFunctions: 'Fonction : toutes',
      allCategories: 'Catégorie : toutes',
      allLevels: 'Niveau : tous',
      filterMeasure: 'Mesure',
      allMeasures: 'Mesures : toutes',
      keyMeasures: 'Mesures clés',
      otherMeasures: 'Autres mesures',
      filterScoring: 'Évaluation',
      filterOwner: 'Responsable',
      filterReview: 'Revue',
      allScoring: 'Évaluation : toutes',
      scored: 'Évalués',
      unscored: 'Non évalués',
      allOwners: 'Responsable : tous',
      allReviews: 'Revue : toutes',
      unassignedOwner: 'Sans responsable',
      reviewOverdue: 'Revue échue',
      reviewNext30: 'Revue à 30 jours',
      description: 'Description',
      average: 'Moy.'
    },

    // ReCyF (Référentiel Cyber France / ANSSI)
    recyfControls: {
      title: 'Mesures ReCyF',
      ref: 'Réf.',
      objective: 'Objectif',
      theme: 'Thématique',
      measure: 'Mesure',
      target: 'Cible',
      owner: 'Responsable',
      reviewer: 'Relecteur',
      reviewFrequency: 'Fréquence de revue',
      lastEvaluation: 'Dernière évaluation',
      nextReviewDate: 'Prochaine revue',
      evidence: 'Preuves / Artefacts',
      evidencePlaceholder: 'Documents, logs, captures…',
      conformity: 'Conformité',
      justification: 'Justification',
      justificationPlaceholder: 'Justification, mesure alternative mise en œuvre, plan d\'action…',
      justificationMissing: 'Justification manquante',
      modalTitle: 'Mesure ReCyF',
      conformityRate: 'Conformité (mesures évaluées)',
      evaluatedCount: 'Évaluées',
      naCount: 'N/A',
      totalCount: 'Total',
      eiEe: 'Entités Importante et Essentielle',
      eeOnly: 'Entité Essentielle uniquement',
      editJustification: 'Détails / justification',
      filterObjective: 'Objectif',
      filterTheme: 'Thématique',
      filterTarget: 'Cible',
      filterConformity: 'Conformité',
      filterOwner: 'Responsable',
      filterReview: 'Revue',
      allObjectives: 'Objectif : tous',
      allThemes: 'Thématique : toutes',
      allTargets: 'Cible : toutes',
      allConformity: 'Conformité : toutes',
      allOwners: 'Responsable : tous',
      allReviews: 'Revue : toutes',
      unassignedOwner: 'Sans responsable',
      reviewOverdue: 'Revue échue',
      reviewNext30: 'Revue à 30 jours',
      radarTitle: 'Conformité ReCyF par objectif'
    },

    // CyFun 2025
    cyfun: {
      levelBasic: 'BASIC',
      levelImportant: 'IMPORTANT',
      levelEssential: 'ESSENTIAL',
      docMaturity: 'Maturité documentation',
      implMaturity: 'Maturité implémentation',
      keyMeasure: 'Mesure clé',
      managementLinked: 'Contrôle lié au management',
      scoring: 'Scoring NIS2',
      threshold: 'Seuil de conformité',
      compliant: 'CONFORME',
      nonCompliant: 'NON CONFORME',
      selectLevel: 'Sélectionnez le niveau d\'assurance NIS2',
      evidence: 'Preuves / Artefacts',
      evidencePlaceholder: 'Documents, logs, captures...',
      keyMeasureInfo: 'Oui - Cette mesure est critique pour la conformité',
      mgmtLinkedInfo: 'Oui - Revue obligatoire à chaque audit',
      avgScore: 'Score moyen',
      keyMeasuresScore: 'Score mesures clés',
      categoryMin: 'Minimum par catégorie',
      coverage: 'Couverture',
      unevaluatedWarn: 'Mesure non évaluée = 0 dans le calcul du seuil (méthode CCB). Catégories non évaluées : {{n}}.',
      functions: {
        GV: 'Gouverner',
        ID: 'Identifier',
        PR: 'Protéger',
        DE: 'Détecter',
        RS: 'Répondre',
        RC: 'Rétablir'
      }
    },

    // Statement of Applicability
    soa: {
      controlNotApplicable: 'Ce contrôle est déclaré non applicable',
      justificationLabel: 'Justification',
      seeInDeclaration: "Voir dans la Déclaration d'applicabilité",
      title: 'Déclaration d\'applicabilité',
      all: 'Tous',
      applicable: 'Applicable',
      notApplicable: 'Non applicable',
      reference: 'Référence',
      applicability: 'Applicabilité',
      subtitle: 'Conformité ISO 27001:2022 - Clause 6.1.3',
      colControl: 'Contrôle',
      colApplicable: 'Applicabilité',
      colImplementation: 'Implémentation',
      colRisks: 'Risques liés',
      colDocumentation: 'Documentation',
      colJustification: 'Justification',
      colSource: 'Source de l\'exigence',
      colImplStatus: 'État d\'implémentation',
      comments: 'Commentaires du contrôle',
      implDate: 'Date d\'implémentation',
      evidenceRef: 'Référence preuves',
      lastReviewDate: 'Dernière revue',
      exclusionReason: 'Motif d\'exclusion',
      pdfPublic: 'PDF Public',
      pdfAudit: 'PDF Audit',
      pdfPublicTitle: 'Version publique simplifiée',
      pdfAuditTitle: 'Version complète pour audit',
      implemented: 'Implémentés',
      declaredNonApplicable: 'Déclaré non applicable dans la DdA',
      nonApplicable: 'Non applicable',
      viewInSoa: 'Voir dans la Déclaration d\'applicabilité',
      multiSelectHelp: 'Maintenez Ctrl (ou Cmd) pour sélectionner plusieurs risques'
    },

    // Document Review
    docReview: {
      title: 'Revue documentaire 27001',
      reviewOverdue: 'Revue en retard',
      nextReviewLabel: 'Prochaine',
      subtitle: 'Clauses 4 à 10 - Exigences du SMSI et preuves de conformité',
      requirement: 'Exigence',
      evidence: 'Outil / Preuve',
      colClause: 'Clause',
      colRequirement: 'Exigence',
      colClauseExigence: 'Clause / Exigence',
      colConformite: 'Conformité',
      colStatus: 'Statut',
      colOwner: 'Responsable',
      colJustification: 'Justification',
      colEvidence: 'Preuve / Document',
      colDocumentation: 'Documentation',
      colLastReview: 'Dernière revue',
      colRevue: 'Revue',
      comments: 'Commentaires de la clause',
      expandJustification: 'Justification',
      status: 'Statut de conformité',
      tool: 'Document / preuve',
      documentLink: 'Lien document',
      lastReview: 'Dernière revue',
      nextReview: 'Prochaine revue',
      pdfAudit: 'PDF Audit',
      pdfAuditTitle: 'Pack audit certification ISO 27001',
      conforming: 'Conformes',
      partial: 'Partiels',
      nonConforming: 'Non conformes',
      complianceRate: 'Taux de conformité'
    },

    // Actions
    actions: {
      title: 'Plan d\'actions',
      sortPriority: 'Tri : Priorité',
      sortId: 'Tri : ID',
      sortLink: 'Tri : Élément lié',
      sortDueDate: 'Tri : Échéance',
      sortProgress: 'Tri : Avancement',
      filterAll: 'Filtre : Tous',
      filterRisk: 'Filtre : Risque',
      filterNc: 'Filtre : Non-conformité',
      filterAudit: 'Filtre : Audit',
      filterThreat: 'Filtre : Menace',
      filterOwner: 'Filtre : Responsable',
      filterContinuous: 'Filtre : Amélioration continue',
      newAction: 'Nouvelle action',
      id: 'ID',
      action: 'Action',
      link: 'Lien',
      criticalAssets: 'Actifs critiques',
      priority: 'Priorité',
      statusCol: 'Statut',
      progress: 'Avancement',
      dueDate: 'Échéance',
      owner: 'Responsable',
      comments: 'Commentaires',
      colTitle: 'Titre',
      colPriority: 'Priorité',
      colStatus: 'Statut',
      colDueDate: 'Échéance',
      colAssignedTo: 'Responsable',
      colProgress: 'Progression',
      colId: 'ID',
      colLink: 'Lien',
      colAssets: 'Actifs critiques',
      colComments: 'Commentaires',
      linkType: 'Type de lien',
      linkedElement: 'Élément lié',
      manageComments: 'Commentaires de l\'action',
      overdue: 'En retard'
    },

    // Non-Conformities table columns
    nc: {
      colTitle: 'Titre',
      colType: 'Type',
      colStatus: 'Statut',
      colOwner: 'Responsable',
      colDate: 'Date détection',
      colAudit: 'Audit lié',
      colActions: 'Actions liées',
      colAssets: 'Actifs critiques',
      colDescription: 'Description',
      linkedActionsCount: '{n} action(s)',
      newNc: 'Nouvelle non-conformité'
    },

    // Risks
    risks: {
      title: 'Risques SMSI',
      newRisk: 'Nouveau Risque',
      importFromAnalysis: 'Importer depuis une analyse',
      importTitle: 'Promouvoir des risques d\'analyse au registre SMSI',
      importApply: 'Promouvoir la sélection',
      importDone: 'Risques promus : ',
      importNoAnalysis: 'Aucune analyse avec des risques.',
      alreadyImported: 'déjà promu',
      risk: 'Risque',
      impact: 'Impact',
      probability: 'Probabilité',
      score: 'Score',
      level: 'Niveau',
      treatment: 'Traitement',
      codirDate: 'Date CODIR',
      manageComments: 'Commentaires du risque',
      columns: {
        risk: 'Risque',
        impact: 'Impact',
        probability: 'Probabilité',
        level: 'Niveau',
        linkedActions: 'Actions liées',
        treatment: 'Traitement',
        codirDate: 'Date CODIR'
      }
    },

    // Threats
    threats: {
      title: 'Menaces',
      newThreat: 'Nouvelle Menace',
      proposeFromCatalog: 'Proposer depuis un référentiel',
      proposeTitle: 'Proposer des menaces depuis un référentiel',
      proposeHint: 'Cotation proposée (vraisemblance×impact) à revoir après insertion.',
      proposeApply: 'Ajouter la sélection',
      proposeDone: 'Menaces ajoutées : ',
      alreadyImported: 'déjà importée',
      columns: {
        title: 'Titre',
        description: 'Description',
        impact: 'Impact',
        probability: 'Probabilité',
        score: 'Score',
        level: 'Niveau',
        status: 'Statut',
        linkedActions: 'Actions liées',
        criticalAssets: 'Actifs critiques',
        links: 'Liens'
      },
      linkedActionsCount: '{n} action(s)',
      linkedAssetsCount: '{n} actif(s)'
    },

    // Non-Conformities
    nonConformities: {
      title: 'Non-conformités',
      sortType: 'Tri : Type',
      sortStatus: 'Tri : Statut',
      sortDate: 'Tri : Date de détection',
      sortAudit: 'Tri : Audit lié',
      sortOwner: 'Tri : Responsable',
      filterAllAudits: 'Filtre : Tous les audits',
      filterAllOwners: 'Filtre : Tous les responsables',
      newNc: 'Nouvelle non-conformité',
      type: 'Type',
      detectionDate: 'Date de détection',
      linkedAudit: 'Audit lié',
      operations: 'Opérations'
    },

    // Audits
    audits: {
      title: 'Audits',
      newAudit: 'Nouvel Audit',
      scope: 'Périmètre',
      plannedDate: 'Date planifiée',
      auditor: 'Auditeur',
      overdue: 'Audit en retard',
      columns: {
        title: 'Titre',
        type: 'Type',
        scope: 'Périmètre',
        plannedDate: 'Date planifiée',
        auditor: 'Auditeur',
        status: 'Statut',
        linkedActions: 'Actions liées'
      }
    },

    // Mapping transversal
    mapping: {
      title: 'Mapping Transversal des Référentiels',
      subtitle: 'Correspondances entre les référentiels de sécurité',
      allTypes: 'Tous les types',
      search: 'Rechercher un contrôle...',
      noMappings: 'Aucune correspondance trouvée pour ces critères.',
      noLink: 'Aucun lien',
      noResults: 'Aucun résultat pour cette recherche.',
      notAvailable: 'Module de mapping non disponible.',
      needTwo: 'Activez au moins deux référentiels dans les paramètres.',
      listView: 'Vue liste',
      heatmapView: 'Vue heatmap',
      viewList: 'Vue liste',
      viewHeatmap: 'Vue matrice',
      conflict: 'Conflit de statut détecté',
      heatmap: {
        caption: 'Matrice de couverture entre référentiels source et cible',
        avgCoverage: 'couverture moy.',
        relations: 'relations',
        unavailable: 'Vue matrice indisponible pour ce référentiel. Utilisez la vue liste.'
      },
      col: {
        ref: 'Réf.',
        title: 'Titre',
        status: 'Statut',
        mappings: 'Correspondances'
      },
      stats: {
        totalMappings: 'Correspondances',
        avgCoverage: 'Couverture moyenne',
        mapped: 'Contrôles mappés',
        covered: 'Couverture'
      },
      status: {
        notImplemented: 'Non implémenté',
        inProgress: 'En cours',
        implemented: 'Implémenté',
        verified: 'Vérifié'
      },
      relationship: {
        equivalent: 'Équivalent',
        covers: 'Couvre',
        coveredBy: 'Couvert par',
        related: 'Lié'
      },
      settings: {
        title: 'Référentiels de sécurité',
        description: 'Activez ou désactivez les référentiels disponibles.',
        alwaysActive: 'Toujours actif',
        controls: 'contrôles',
        mappingsLoaded: 'correspondances chargées'
      }
    },

    // Top-level status labels
    status: {
      notImplemented: 'Non impl.',
      inProgress: 'En cours',
      implemented: 'Impl.',
      verified: 'Vérifié'
    },

    // Management Reviews
    reviews: {
      title: 'Revues de direction',
      newReview: 'Nouvelle Revue',
      date: 'Date',
      participants: 'Participants',
      inputs: 'Entrées',
      decisions: 'Décisions',
      manageComments: 'Commentaires de revue',
      newComment: 'Nouveau commentaire',
      addComment: 'Ajouter le commentaire',
      maxComments: 'Maximum 10 commentaires atteint.',
      commentAdded: 'Commentaire ajouté.',
      columns: {
        date: 'Date',
        participants: 'Participants',
        inputs: 'Entrées',
        decisions: 'Décisions',
        comments: 'Commentaires'
      }
    },

    // Stakeholders
    stakeholders: {
      title: 'Parties prenantes',
      newStakeholder: 'Nouvelle Partie prenante',
      name: 'Nom',
      role: 'Rôle',
      contact: 'Contact',
      filterRole: 'Rôle',
      allRoles: 'Rôle : tous',
      columns: {
        name: 'Nom',
        role: 'Rôle',
        contact: 'Contact',
        comments: 'Commentaires'
      }
    },

    // Rôles normalisés des parties prenantes (Lot 1b)
    stakeholderRoles: {
      internal: 'Interne',
      supplier: 'Fournisseur',
      client: 'Client',
      authority: 'Autorité',
      partner: 'Partenaire',
      other: 'Autre',
      currentValue: '(valeur actuelle)'
    },

    // Documents
    documents: {
      title: 'Structure documentaire',
      newDocument: 'Nouveau Document',
      levelCol: 'Niveau',
      typeCol: 'Type',
      tool: 'Outil',
      linkCol: 'Lien',
      columns: {
        level: 'Niveau',
        type: 'Type',
        tool: 'Outil',
        link: 'Lien'
      }
    },

    // Document categories
    docCategories: {
      policy: 'Politique',
      process: 'Processus',
      procedure: 'Procédure',
      record: 'Enregistrement'
    },

    // KPIs
    kpis: {
      title: 'KPIs',
      newKpi: 'Nouveau KPI',
      comment: 'Commentaire',
      progressCol: 'Progression'
    },

    // CyFun Program
    nis2Program: {
      title: 'Budget Cybersécurité',
      printPdf: 'Imprimer / PDF',
      exportHtml: 'Export HTML',
      newDomain: 'Nouveau Domaine',
      newAction: 'Nouvelle Action',
      budgetCategories: 'Catégories budget',
      newBudgetLine: 'Nouvelle ligne',
      manageYears: 'Gérer les années',
      manageYearsTitle: 'Gérer les années budgétaires',
      totalBudget: 'Budget total',
      lineLabel: 'Intitulé',
      lineOwner: 'Responsable',
      lineStatus: 'Statut',
      lineCategory: 'Catégorie',
      lineTotal: 'Total',
      lineSingular: 'ligne',
      linesPlural: 'lignes',
      amountForYear: 'Montant',
      grandTotal: 'Total général',
      subtotal: 'Sous-total',
      rowType: 'Type',
      rowTypeLine: 'Ligne',
      rowTypeSubtotal: 'Sous-total',
      rowTypeTotal: 'Total',
      noFilterMatch: 'Aucune ligne ne correspond aux filtres sélectionnés.',
      filteredTotal: 'Total (filtré)',
      untitledLine: 'Sans intitulé',
      noBudgetData: 'Aucune donnée budgétaire à afficher',
      budgetEmptyTitle: 'Aucune ligne budgétaire',
      budgetEmptyHint: 'Ajoutez votre première ligne de budget cybersécurité avec le bouton « Nouvelle ligne ».',
      chartByYear: 'Budget par année',
      chartByYearSubtitle: 'Répartition du budget cybersécurité par exercice',
      chartByCategory: 'Répartition par catégorie',
      chartByCategorySubtitle: 'Part du budget total par catégorie de dépense',
      filterCategoryLabel: 'Catégorie',
      filterStatusLabel: 'Statut',
      allCategories: 'Toutes les catégories',
      allStatuses: 'Tous les statuts',
      maturity: 'Maturité NIS2',
      maturitySubtitle: 'Maturité actuelle comparée aux objectifs 2027/2028',
      keyStatuses: 'Statuts clés',
      keyStatusesSubtitle: 'Enregistrement, maturité et jalons réglementaires',
      addStatus: 'Ajouter un statut clé',
      nis2Actions: 'Actions NIS2',
      nis2ActionsSubtitle: 'Répartition des actions par statut et dynamique globale',
      actionsByDomain: 'Actions par Domaine',
      actionsByDomainSubtitle: 'Répartition des actions par domaine du plan NIS2',
      actionPlan: 'Plan d\'actions NIS2',
      allPhases: 'Toutes les phases',
      phase1: 'Phase 1 (2026)',
      phase2: 'Phase 2 (2027)',
      phase3: 'Phase 3 (2028)',
      allPillars: 'Tous les piliers',
      pillar: 'Pilier',
      infoBox: 'Pilotez votre budget cybersécurité par lignes : associez chaque dépense à une catégorie, un responsable, un statut (planifié, engagé, réalisé) et un montant par année. Ajoutez ou renommez les années via « Gérer les années ».',
      actionsCyFun: 'Actions NIS2',
      actionsCyFunSubtitle: 'Répartition des actions par statut et dynamique globale',
      filterPhaseLabel: 'Phase',
      filterPillarLabel: 'Fonction',
      infoBoxText: 'Ce plan d\'action dédié à NIS2 est indépendant du plan d\'actions ISO. Ajoutez vos domaines et actions, filtrez par phase ou pilier, et mettez à jour les statuts pour suivre vos jalons 2026-2028.',
      showLegend: 'Afficher la légende du radar',
      manageBudgetCategoriesTitle: 'Gérer les catégories de budget',
      addStatusTitle: 'Ajouter un statut clé',
      pillarGV: 'Gouverner (GV)',
      pillarID: 'Identifier (ID)',
      pillarPR: 'Protéger (PR)',
      pillarDE: 'Détecter (DE)',
      pillarRS: 'Répondre (RS)',
      pillarRC: 'Rétablir (RC)'
    },

    // NIS2 Socle
    nis2Socle: {
      title: 'Socle Sécurité',
      editPillar: 'Modifier le pilier', // FIX-I18N-KEYS (audit 2026-06-10)
      subtitle: 'Les 5 Piliers Structurants',
      infoBox: 'Cadre stratégique priorisé basé sur le top 10 des risques majeurs, stratégie Zero Trust et conformité NIS2.'
    },


    securityBaseline: {
      title: 'Socle de sécurité',
      subtitle: 'Les 5 Piliers Structurants',
      infoBoxText: 'Cadre stratégique priorisé basé sur le top 10 des risques majeurs, stratégie Zero Trust et conformité NIS2.'
    },

    kpi: {
      title: 'KPI',
      newKpi: 'Nouveau KPI',
      description: 'Description',
      comment: 'Commentaire',
      progress: 'Progression'
    },

    // Critical Assets
    criticalAssets: {
      title: 'Actifs critiques',
      form: {
        priority: 'Priorité',
        beneficiary: 'Bénéficiaire',
        productCode: 'Produit (code)',
        productName: 'Produit (nom)',
        productTags: 'Tags produit (séparés par des virgules)',
        availability: 'Disponibilité',
        availabilityNote: 'Note disponibilité',
        confidentiality: 'Confidentialité',
        dacpSensitive: 'DACP sensible',
        mfaStatus: 'Obligation MFA',
        mfaDetail: 'Détail MFA'
      },
      subtitle: 'Inventaire des actifs critiques et exigences de continuité.',
      rename: 'Renommer',
      newAsset: 'Nouvel Actif',
      beneficiary: 'Bénéficiaire',
      availability: 'Disponibilité',
      reset: 'Réinitialiser',
      priorityCol: 'Priorité',
      product: 'Produit',
      rto: 'RTO',
      rpo: 'RPO',
      confidentiality: 'Conf.',
      impactCol: 'Impact',
      dacpSensitive: 'DACP sensible',
      mfaObligation: 'Obligation MFA',
      columns: {
        priority: 'Priorité',
        beneficiary: 'Bénéficiaire',
        product: 'Produit',
        assetType: 'Type',
        importance: 'Importance',
        rto: 'RTO',
        rpo: 'RPO',
        rtoRpo: 'RTO / RPO',
        availability: 'Disponibilité',
        confidentiality: 'Conf.',
        integrity: 'Intég.',
        impact: 'Impact',
        dacpSensitive: 'DACP sens.',
        mfaObligation: 'Obligation MFA'
      },
      addBtn: 'Ajouter un actif',
      colName: 'Nom',
      colType: 'Type',
      colOwner: 'Propriétaire',
      colCriticality: 'Criticité',
      renameBtn: 'Renommer',
      filterBeneficiary: 'Bénéficiaire',
      filterAvailability: 'Disponibilité',
      filterImpact: 'Impact',
      openAsset: 'Voir l\'actif'
    },

    // Empty States
    emptyStates: {
      noThreats: 'Aucune menace identifiée. Cliquez sur "Nouvelle Menace" pour commencer.',
      noAudits: 'Aucun audit enregistré. Cliquez sur "Nouvel Audit" pour planifier un audit.',
      noReviews: 'Aucune revue de direction. Cliquez sur "Nouvelle Revue" pour en créer une.',
      noDocuments: 'Aucun document enregistré. Cliquez sur "Nouveau Document" pour commencer.',
      noStakeholders: 'Aucune partie prenante. Cliquez sur "Nouvelle Partie prenante" pour en ajouter.',
      noRisks: 'Aucun risque identifié.',
      noComments: 'Aucun commentaire.',
      noActions: 'Aucune action en cours',
      noNonconformities: 'Aucune non-conformité',
      noCriticalAssets: 'Aucun actif critique'
    },

    // Système générique de commentaires
    comments: {
      manage: 'Commentaires',
      new: 'Nouveau commentaire',
      add: 'Ajouter le commentaire',
      max: 'Maximum {n} commentaires atteint.',
      added: 'Commentaire ajouté.',
      none: 'Aucun commentaire.',
      deleteConfirm: 'Supprimer ce commentaire ?',
      close: 'Fermer'
    },

    // Project Risks
    projectRisks: {
      title: 'Risques projets',
      subtitle: 'Suivi des analyses de risques projets et recommandations associées.',
      newAnalysis: 'Nouvelle Analyse',
      search: 'Rechercher',
      searchPlaceholder: 'Nom, bénéficiaire, rapport, description',
      statusFilter: 'Statut',
      pendingFilter: 'Recommandations non implémentées',
      projectName: 'Nom du Projet',
      reportNumber: 'Numéro du rapport',
      revisionNumber: 'Numéro de révision',
      projectDescription: 'Description du Projet',
      riskAnalysisLink: 'Lien analyse des risques',
      completionDate: 'Date de réalisation',
      kpiAnalyses: 'Analyses réalisées',
      kpiRecos: 'Recommandations implémentées',
      priority: 'Priorité',
      priorityLabel: 'Priorité',
      priorityCritical: 'P0 - Critique', // FIX-I18N-PRIORITY-CRITICAL (audit 2026-06-10)
      priorityHigh: 'P1 - Haute',
      priorityMedium: 'P2 - Moyenne',
      priorityLow: 'P3 - Basse',
      openAnalysis: 'Ouvrir l\'analyse',
      allBeneficiaries: 'Tous les bénéficiaires',
      allStatuses: 'Tous les statuts',
      noResults: 'Aucun résultat.',
      noData: 'Aucune analyse de risque projet.',
      recoTitle: 'Recommandations',
      recoAdd: 'Ajouter',
      recoTitleLabel: 'Titre de recommandation',
      recoTextLabel: 'Recommandation',
      recoImplemented: 'Implémenté',
      recoRemove: 'Supprimer',
      recoEmpty: 'Aucune recommandation ajoutée.',
      note: 'Note',
      resetFilters: 'Réinitialiser',
      beneficiaryLabel: 'Bénéficiaire',
      statusFilterLabel: 'Statut',
      statusCol: 'Statut',
      beneficiary: 'Bénéficiaire',
      sortLabel: 'Tri',
      sortName: 'Nom du projet',
      sortBeneficiary: 'Bénéficiaire',
      sortStatus: 'Statut',
      sortDate: 'Date',
      sortPriority: 'Priorité',
      autoSyncBadge: 'Auto',
      autoSyncBanner: 'Cette entrée est synchronisée automatiquement depuis l\'analyse de risques « {title} ». Certains champs sont mis à jour automatiquement.',
      autoSyncReadonly: 'Ce champ est mis à jour automatiquement.',
      consolidatedAnalysesTitle: 'Analyses de risques réalisées',
      consolidatedAnalysesHint: 'Cette table liste le portefeuille des risques projets. Les analyses détaillées disposent d\'une vue consolidée dédiée.',
      openConsolidatedAnalyses: 'Voir toutes les analyses',
      tagPlaceholder: 'Ajouter un tag...'
    },

    // Settings
    settings: {
      title: 'Paramètres',
      subtitle: 'Configuration, sauvegardes et synchronisation serveur.',
      nav: {
        general: 'Général',
        security: 'Sécurité',
        data: 'Données',
        storage: 'Stockage',
        sync: 'Sync Pro',
        license: 'Licence',
        advanced: 'Avancé',
        danger: 'Zone Danger',
        users: 'Utilisateurs',
        mcp: 'Accès IA',
        maintenance: 'Maintenance serveur'
      },
      users: 'Utilisateurs',
      general: 'Configuration générale',
      appTitle: 'Titre de l\'application',
      theme: 'Thème',
      themeClair: 'Clair',
      themeSombre: 'Sombre',
      themePoudre: 'Poudre',
      isoTarget: 'Cible ISO',
      isoTargetHelp: 'Niveau de maturité visé (1-5).',
      entities: 'Multi-entités',
      nis2Target: 'Cible NIS2',
      backup: 'Sauvegarde',
      export: 'Exporter',
      import: 'Importer',
      importAnalyse: 'Import Analyse',
      advancedExport: 'Export avancé',
      pdfDraftNumber: 'BROUILLON (hors mode édition)',
      pdfReport: 'Rapport PDF',
      excelExport: 'Export Excel',
      serverSync: 'Synchronisation serveur',
      baseUrl: 'URL de base',
      user: 'Utilisateur',
      password: 'Mot de passe',
      quality: 'Qualité & Historique',
      analyze: 'Analyser',
      snapshots: 'Snapshots',
      demoData: 'Données de démonstration',
      loadDemo: 'Charger la démo',
      tests: 'Tests',
      reset: 'Réinitialiser',
      resetData: 'Réinitialiser les données',
      language: 'Langue',
      chooseLanguage: 'Choisissez votre langue',
      complete: 'Complet',
      global: 'Global',
      logoTitle: 'Logo de l\'entreprise',
      logoDescription: 'Importez le logo qui sera utilisé dans les exports PDF.',
      logoUpload: 'Sélectionner un fichier (PNG, JPEG, SVG)',
      logoNone: 'Aucun logo configuré',
      logoSave: 'Enregistrer le logo',
      logoRemove: 'Supprimer le logo',
      logoSaved: 'Logo enregistré avec succès',
      logoRemoved: 'Logo supprimé',
      logoTooLarge: 'Le fichier est trop volumineux (max 500 Ko)',
      // General settings card (bundle.js)
      generalTitle: 'Configuration générale',
      generalDesc: 'Personnalisez le titre, le thème et les cibles de maturité.',
      appTitleLabel: 'Titre de l\'application',
      themeLabel: 'Thème',
      theme_clair: 'Clair',
      theme_sombre: 'Sombre',
      theme_poudre: 'Poudre',
      theme_bleu: 'Bleu',
      saveBtn: 'Enregistrer les paramètres',
      saved: 'Paramètres sauvegardés',
      nis2TargetHelp: 'Valeur cible (1-5) pour toutes les catégories.',
      cyfunLevel: 'Niveau d\'assurance NIS2',
      cyfunLevelChanged: 'Niveau NIS2 changé : ',
      cyfunLang: 'Langue du référentiel CyFun',
      cyfunLangChanged: 'Langue du référentiel CyFun changée.',
      recyfDegree: 'Degré de l\'entité (ReCyF)',
      recyfDegreeChanged: 'Degré ReCyF : ',
      nis2Referential: 'Référentiel NIS2 actif',
      nis2RefBE: 'NIS2 Belgique — CyFun 2025 (CCB)',
      nis2RefFR: 'NIS2 France — ReCyF (ANSSI)',
      nis2ReferentialChanged: 'Référentiel NIS2 actif : ',
      nis2ReferentialHint: 'Détermine les onglets NIS2 affichés (CyFun Belgique ou ReCyF France).',
      nis2RefLocked: 'Référentiel verrouillé. Une réinitialisation est nécessaire pour en changer.',
      nis2RefLockedNote: 'Référentiel verrouillé. Pour en changer, réinitialisez l\'application (les données seront effacées).',
      nis2RefLockedToast: 'Référentiel verrouillé : une réinitialisation est nécessaire pour en changer.',
      nis2RefActive: 'Référentiel NIS2 actif',
      nis2RefInactive: 'Référentiel NIS2 — non sélectionné',
      // Display options card
      displayTitle: 'Options d\'affichage',
      displayDesc: 'Personnalisez l\'apparence et la densité de l\'interface.',
      compactMode: 'Mode compact',
      compactModeHelp: 'Réduit l\'espacement et la taille des éléments pour afficher plus d\'informations.',
      compactEnabled: 'Mode compact activé',
      compactDisabled: 'Mode compact désactivé',
      // Security card
      editPasswordTitle: 'Mot de passe du mode édition',
      editPasswordDesc: 'Minimum {{min}} caractères, 1 majuscule, 1 minuscule, 1 caractère spécial.',
      newPassword: 'Nouveau mot de passe',
      minCharsPlaceholder: 'Minimum {{min}} caractères',
      confirmation: 'Confirmation',
      retypePassword: 'Ressaisir le mot de passe',
      customPasswordActive: 'Mot de passe personnalisé actif.',
      defaultPasswordActive: 'Mot de passe par défaut actif.',
      updatePassword: 'Mettre à jour le mot de passe',
      passwordNonCompliant: 'Mot de passe non conforme.',
      changeServerPassword: 'Changer mon mot de passe',
      changeServerPasswordDesc: 'Modifiez votre mot de passe de connexion.',
      changePasswordBtn: 'Changer le mot de passe',
      // Backup card
      backupTitle: 'Sauvegarde',
      backupDesc: 'Exportez ou importez vos données SMSI.',
      // Snapshot card
      snapshotTitle: 'Historique & Snapshots',
      snapshotDesc: 'Créez des points de sauvegarde locaux.',
      snapshotLabel: 'Nom du snapshot',
      snapshotPlaceholder: 'Ex. : comité sécurité T2',
      createSnapshot: 'Créer',
      manualSnapshot: 'Snapshot manuel',
      cleanSnapshots: 'Nettoyer',
      backupBeforeReset: 'Backup avant réinitialisation',
      backupBeforeRestore: 'Backup avant restauration',
      backupBeforeImport: 'Backup avant import',
      backupBeforeDemo: 'Backup avant données de démonstration',
      // Storage card
      storageTitle: 'Stockage & Santé',
      storageDesc: 'Surveillance de l\'occupation localStorage.',
      storageUsage: 'Occupation localStorage',
      storageTitleServer: 'Cache local',
      storageDescServer: 'En mode serveur, les données sont stockées sur le serveur. Le navigateur conserve un cache local.',
      storageUsageServer: 'Occupation du cache local',
      storageServerNote: 'Vos données sont principalement stockées sur le serveur. Ce cache local permet de travailler hors connexion.',
      dataSize: 'Taille données',
      lastAutosave: 'Dernier autosave',
      storageLow: 'Espace de stockage faible. Exportez vos données.',
      storageFull: 'Stockage presque plein : exportez vos données ou supprimez des snapshots.',
      storageInsufficient: 'Espace de stockage insuffisant',
      storageWarning: 'Attention : stockage presque plein',
      storageExportHint: 'Pensez à exporter vos données.',
      never: 'Jamais',
      // License settings
      license: {
        statusTitle: 'Statut de la licence',
        statusDesc: 'Informations sur votre licence ou période d\'essai.',
        activateTitle: 'Activer une licence',
        activateDesc: 'Collez votre clé CSI2-... pour activer ou renouveler votre licence.'
      },
      // Sync card
      syncTitle: 'Synchronisation serveur',
      syncDesc: 'Partagez un snapshot via l\'API /data/export et /data/import.',
      syncUrlLabel: 'URL de base (optionnel)',
      syncUser: 'Utilisateur',
      syncPassword: 'Mot de passe',
      rememberPassword: 'Mémoriser le mot de passe',
      test: 'Tester',
      openSync: 'Ouvrir Sync',
      noTestRun: 'Aucun test exécuté.',
      testInProgress: 'Test en cours...',
      invalidUrl: 'URL invalide',
      networkError: 'Erreur réseau',
      authDenied: 'Auth refusée',
      // Tests card
      testsTitle: 'Tests',
      testsDesc: 'Vérification rapide des fonctions principales.',
      runTests: 'Lancer les tests',
      // Demo reset card
      demoResetTitle: 'Réinitialisation des données démo',
      demoResetDesc: 'Recharge les données de démonstration originales.',
      demoMode: 'Mode démonstration',
      demoModeLabel: 'Mode démonstration',
      demoAutoReload: 'Les données sont automatiquement rechargées toutes les heures.',
      demoManualReset: 'Utilisez ce bouton pour réinitialiser manuellement.',
      demoResetInfo: 'Les données sont automatiquement rechargées toutes les heures. Utilisez ce bouton pour réinitialiser manuellement.',
      reloadDemoData: 'Recharger les données démo',
      reloadDemoBtn: 'Recharger les données démo',
      // Reset card
      resetTitle: 'Réinitialisation',
      resetDesc: 'Réinitialise l\'application aux paramètres d\'origine.',
      warning: 'Attention :',
      resetWarningTitle: 'Attention :',
      resetWarningText: 'Cette action supprimera toutes vos données. Un snapshot de sécurité sera créé automatiquement avant la réinitialisation.',
      resetWarning: 'Cette action supprimera toutes vos données.',
      resetWarningDelete: 'Cette action supprimera toutes vos données.',
      resetWarningSnapshot: 'Un snapshot de sécurité sera créé automatiquement avant la réinitialisation.',
      resetSnapshot: 'Un snapshot de sécurité sera créé automatiquement avant la réinitialisation.',
      resetApp: 'Réinitialiser l\'application',
      resetBtn: 'Réinitialiser l\'application',
      resetAdminOnly: 'Réinitialisation réservée à un compte administrateur.',
      confirmReset: 'Confirmer la réinitialisation',
      confirmResetMessage: 'Cette action va réinitialiser l\'application à son état initial. Toutes vos données seront définitivement supprimées. Êtes-vous sûr ?',
      // FIX-I18N-AUTH (audit 2026-06-10, auth-manager.js:656) : cartes Paramètres serveur
      storageServerTitle: 'Stockage serveur',
      storageServerDesc: 'Vos données sont stockées et synchronisées sur le serveur.',
      storageServerActive: 'Le serveur gère le stockage principal. Toutes les modifications sont synchronisées automatiquement.',
      serverStorageTitle: 'Stockage serveur',
      serverStorageDesc: 'Les données sont stockées exclusivement sur le serveur. Aucun cache local utilisé.',
      lastServerPull: 'Dernière réception',
      lastServerPush: 'Dernier envoi',
      auditLog: 'Journal d\'audit',
      auditLogDesc: 'Historique des événements de sécurité du serveur.',
      securityDashboard: 'Tableau de bord sécurité',
      securityRecommendations: 'Recommandations de sécurité',
      securityRecommendationsDesc: 'Conseils contextuels basés sur votre posture de sécurité.',
      ipFiltering: 'Filtrage IP',
      ipFilteringDesc: 'Restreindre l\'accès par adresse IP (supporte la notation CIDR).',
      passwordPolicy: 'Politique de mots de passe',
      passwordPolicyDesc: 'Configurez les règles de sécurité des mots de passe.',
      // FIX-I18N-WIZARD (audit 2026-06-10, bundle.js:2713) : verrouillage niveau CyFun
      cyfunLevelLocked: 'Niveau verrouillé pour cette organisation. Pour déverrouiller, contactez l\'administrateur.',
      cyfunLevelLockedNote: 'Niveau verrouillé pour cette organisation. Modification désactivée.',
      cyfunLevelLockedToast: 'Niveau verrouillé : modification refusée.'
    },

    // Common
    common: {
      save: 'Enregistrer',
      cancel: 'Annuler',
      delete: 'Supprimer',
      readOnly: 'Lecture seule',
      edit: 'Modifier',
      actions: 'Actions',
      add: 'Ajouter',
      close: 'Fermer',
      search: 'Rechercher...',
      filter: 'Filtrer',
      all: 'Tous',
      none: 'Aucun',
      yes: 'Oui',
      no: 'Non',
      loading: 'Chargement...',
      saving: 'Enregistrement...',
      saved: 'Enregistré',
      savedAt: 'Sauvegardé à',
      error: 'Erreur',
      success: 'Succès',
      warning: 'Attention',
      info: 'Information',
      confirm: 'Confirmer',
      discardConfirm: 'Abandonner les modifications non enregistrées ?',
      confirmDelete: 'Êtes-vous sûr de vouloir supprimer cet élément ? Cette action est irréversible.',
      noData: 'Aucune donnée disponible',
      required: 'Ce champ est obligatoire',
      invalid: 'Valeur invalide',
      exportSuccess: 'Export réussi',
      exportError: 'Export échoué. Vérifiez que des données existent.',
      importSuccess: 'Import réussi',
      importError: 'Import échoué. Vérifiez le format du fichier.',
      saveError: 'Échec de la sauvegarde. Vos données sont conservées localement.',
      syncSuccess: 'Synchronisation réussie',
      syncError: 'Synchronisation échouée',
      moveUp: 'Monter',
      moveDown: 'Descendre',
      sortBy: 'Tri :',
      refresh: 'Rafraîchir',
      later: 'Plus tard',
      enabled: 'Activé',
      disabled: 'Désactivé',
      requirements: 'exigences',
      measures: 'mesures',
      skip: 'Passer',
      new: 'Nouveau',
      status: 'Statut',
      other: 'Autres',
      open: 'Ouvrir',
      select: 'Sélectionner',
      searchControl: 'Rechercher un contrôle',
      // FIX-I18N-KEYS (audit 2026-06-10)
      retry: 'Réessayer',
      never: 'Jamais'
    },

    // Sort labels
    // Toolbar v2 (section-toolbar.js)
    sectionToolbar: {
      reset: 'Réinitialiser',
      moreFilters: 'Filtres'
    },

    sort: {
      reference: 'Réf.',
      title: 'Titre',
      status: 'Statut',
      maturity: 'Maturité',
      date: 'Date',
      name: 'Nom',
      value: 'Valeur',
      level: 'Niveau',
      priority: 'Priorité',
      score: 'Score',
      impact: 'Impact',
      probability: 'Probabilité',
      function: 'Fonction',
      docMaturity: 'Doc.',
      implMaturity: 'Impl.',
      average: 'Moy.',
      applicability: 'Applicabilité',
      implementation: 'Implémentation',
      clause: 'Clause',
      lastReview: 'Dernière revue',
      id: 'ID',
      dueDate: 'Échéance',
      progress: 'Progression',
      link: 'Lien',
      type: 'Type',
      audit: 'Audit',
      owner: 'Responsable',
      ascending: 'croissant',
      descending: 'décroissant'
    },

    // Priorities
    priorities: {
      critical: 'Critique',
      high: 'Haute',
      medium: 'Moyenne',
      low: 'Faible'
    },

    // Statuses
    statuses: {
      notStarted: 'Non démarré',
      inProgress: 'En cours',
      completed: 'Terminé',
      blocked: 'Bloqué',
      cancelled: 'Annulé',
      open: 'Ouvert',
      closed: 'Fermé',
      planned: 'Planifié',
      realized: 'Réalisé',
      todo: 'À faire',
      suspended: 'Suspendu'
    },

    statusLabels: {
      todo: 'À réaliser',
      inProgress: 'En cours',
      suspended: 'Suspendu',
      done: 'Réalisé'
    },

    soaSourceLabels: {
      risk: 'Risque identifié',
      legal: 'Exigence légale',
      contractual: 'Exigence contractuelle',
      bestPractice: 'Bonne pratique',
      regulatory: 'Exigence réglementaire',
      business: 'Exigence métier'
    },

    // Months
    months: {
      january: 'Janvier',
      february: 'Février',
      march: 'Mars',
      april: 'Avril',
      may: 'Mai',
      june: 'Juin',
      july: 'Juillet',
      august: 'Août',
      september: 'Septembre',
      october: 'Octobre',
      november: 'Novembre',
      december: 'Décembre'
    },

    // First launch
    firstLaunch: {
      title: 'Bienvenue sur Cyber-Assistant',
      subtitle: 'Veuillez sélectionner votre langue préférée',
      continue: 'Continuer',
      changeSettings: 'Vous pouvez changer la langue à tout moment dans les Paramètres'
    },

    // Footer
    footer: {
      createdBy: 'Conçu par Jean-François Avart',
      contactMe: 'Me contacter',
      terms: 'Conditions générales',
      onlineManual: 'Manuel en ligne'
    },

    // Search
    search: {
      placeholder: 'Rechercher (actions, risques, contrôles, documents...)',
      noResults: 'Aucun résultat trouvé',
      results: 'résultats',
      ariaLabel: 'Recherche globale',
      scopeNote: 'Recherche limitée au périmètre :'
    },

    // Global search results
    searchResults: {
      action: 'Action',
      risk: 'Risque',
      control: 'Contrôle',
      document: 'Document',
      audit: 'Audit',
      nc: 'Non-conformité',
      threat: 'Menace',
      stakeholder: 'Partie prenante',
      kpi: 'KPI',
      asset: 'Actif critique',
      review: 'Revue',
      nis2Control: 'Contrôle NIS2',
      criticalAsset: 'Actif critique',
      projectRisk: 'Risque projet',
      // FIX-I18N-KEYS (audit 2026-06-10)
      recyfControl: 'Mesure ReCyF'
    },

    // Server mode
    serverMode: {
      notAvailable: 'Le mode serveur n\'est pas disponible dans cette version. Contactez l\'éditeur pour obtenir le module de synchronisation.'
    },

    // Licence / Activation
    license: {
      detecting: 'Détection de la licence...',
      valid: 'Licence valide',
      notFound: 'Aucune licence détectée',
      title: 'Activation',
      trialActive: 'Période d\'essai active',
      trialExpired: 'Période d\'essai expirée',
      daysLeft: '{days} jours restants',
      pasteKey: 'Collez votre clé d\'activation',
      pasteHint: 'Collez la clé CSI2-... reçue par email',
      activate: 'Activer la licence',
      continueTrial: 'Continuer l\'essai',
      success: 'Licence activée avec succès',
      error: 'Clé de licence invalide',
      expired: 'Licence expirée',
      organization: 'Organisation',
      readOnlyNotice: 'Mode lecture seule — activez une licence pour modifier les données',
      expiresAt: 'Expire le {date}',
      renewNeeded: 'Licence expirée — entrez une nouvelle clé pour réactiver',
      validUntil: 'Licence valide jusqu\'au {date}',
      enterKey: 'Entrer une clé de licence',
      trialInfo: 'Vous disposez d\'une période d\'essai de {days} jours pour évaluer la solution.',
      trialBanner: 'Essai : {days} j. restants',
      trialExpiredBanner: 'Essai expiré',
      active: 'Licence active',
      // FIX-I18N-LICENSE (audit 2026-06-10, bundle.js:5479) : bandeau d'essai,
      // mur de licence et étape d'activation du wizard
      wallTitle: 'Période d\'essai terminée',
      wallDesc: 'Veuillez entrer votre clé de licence CSI2-... pour continuer à utiliser l\'application.',
      trialBannerText: 'Essai gratuit — {days} jours restants sur 14',
      trialDetail: 'Essai gratuit — {days} jours restants sur 14. Toutes les fonctionnalités sont disponibles.',
      activateBtn: 'Activer',
      activated: 'Activée',
      mustActivate: 'Veuillez activer votre licence avant de continuer',
      noLicense: 'Aucune licence active',
      noLicenseDetail: 'Activez une clé de licence ci-dessous.'
    },

    // Authentification
    auth: {
      login: 'Se connecter',
      logout: 'Se déconnecter',
      register: 'S\'inscrire',
      username: 'Nom d\'utilisateur',
      password: 'Mot de passe',
      confirmPassword: 'Confirmer le mot de passe',
      setupTitle: 'Configuration initiale',
      setupPrompt: 'Vous serez l\'administrateur.',
      createAccount: 'Créer un compte',
      createAdminAccount: 'Créer le compte admin',
      loginRequired: 'Accéder au Système de Management de la Sécurité',
      loginFailed: 'Échec de connexion',
      maxUsersReached: 'Nombre maximum d\'utilisateurs atteint',
      userCreated: 'Compte créé',
      accountCreated: 'Compte admin créé',
      sessionExpired: 'Session expirée',
      passwordPolicy: '18+ caractères, majuscule, minuscule, caractère spécial',
      passwordMismatch: 'Les mots de passe ne correspondent pas',
      fieldsRequired: 'Tous les champs sont requis',
      noAccount: 'Pas encore de compte ?',
      backToLogin: 'Retour à la connexion',
      yourName: 'Votre nom',
      nameRequired: 'Nom requis',
      passwordInvalid: 'Mot de passe',
      chars18: '18+ caractères',
      uppercase: 'majuscule',
      lowercase: 'minuscule',
      specialChar: 'caractère spécial',
      newPassword: 'Nouveau mot de passe',
      // Password validation (i18n for validatePwd)
      pwdMinChars: '18+ caractères',
      pwdUppercase: 'majuscule',
      pwdLowercase: 'minuscule',
      pwdSpecial: 'caractère spécial',
      // FIX-I18N-AUTH (audit 2026-06-10, auth-manager.js:656) : écrans serveur
      // (login, setup, mot de passe, erreurs) — clés absentes des deux locales
      adminAccess: 'Accès administrateur',
      hideAdminAccess: 'Masquer',
      ssoLogin: 'Se connecter via SSO entreprise',
      serverUnavailable: 'Serveur momentanément indisponible — la connexion peut échouer.',
      serverError: 'Serveur indisponible',
      sessionTimeout: 'Formulaire expiré par inactivité. Veuillez ressaisir vos identifiants.',
      setupAdminNotice: 'Le premier utilisateur créé sera administrateur avec tous les droits de gestion.',
      setupFailed: 'Erreur lors de la configuration',
      registrationFailed: 'Erreur lors de l\'inscription',
      changePassword: 'Changer le mot de passe',
      changePasswordBtn: 'Changer',
      changePasswordFailed: 'Erreur lors du changement de mot de passe',
      mustChangePassword: 'Changement de mot de passe obligatoire',
      mustChangePasswordHint: 'Votre mot de passe temporaire doit être changé.',
      passwordChanged: 'Mot de passe changé',
      currentPassword: 'Mot de passe actuel',
      cooldown: 'Trop de tentatives. Réessayez dans ',
      lastLogin: 'Dernière connexion',
      capsLockOn: 'Verrouillage majuscules activé',
      or: 'ou',
      attemptWarning: 'Tentative {n}/{max} — verrouillage après {max} échecs',
      httpBlockedTitle: 'Connexion non sécurisée',
      httpBlockedMsg: 'Cyber-Assistant transmet des données d\'authentification sensibles. L\'accès en HTTP non chiffré est bloqué en mode serveur. Utilisez HTTPS pour accéder à cette application.',
      httpsAccessBtn: 'Accéder en HTTPS',
      httpBlockedNote: 'Si vous utilisez un certificat auto-signé, acceptez l\'exception de sécurité dans votre navigateur.',
      iframeBlocked: 'L\'application ne peut pas être affichée dans un iframe pour des raisons de sécurité.',
      connEncrypted: 'Connexion chiffrée',
      connUnencrypted: 'Connexion non chiffrée',
      useHttpsProd: 'utilisez HTTPS en production',
      httpsProdWarning: 'Les données transitent en clair. Activez HTTPS en production.'
    },

    // Verrouillage onglets
    locks: {
      lockedBy: 'Cet onglet est édité par',
      lockAcquired: 'Onglet verrouillé',
      lockDenied: 'Onglet déjà verrouillé',
      lockReleased: 'Onglet déverrouillé',
      lockExpired: 'Verrouillage expiré. Repassez en mode édition.',
      connectedUsers: 'Utilisateurs connectés',
      readOnlyLocked: 'Lecture seule — édité par un autre utilisateur',
      readOnlyTab: 'Lecture seule.'
    },

    // Gestion utilisateurs
    users: {
      title: 'Gestion des utilisateurs',
      description: 'Créer, suspendre ou supprimer des comptes utilisateurs.',
      noAccess: 'Accès réservé aux administrateurs.',
      noUsers: 'Aucun utilisateur trouvé.',
      count: '{count} / {max} utilisateurs',
      countFiltered: '{shown} / {count} utilisateurs (filtrés)',
      searchPlaceholder: 'Rechercher (nom, email, rôle)…',
      addUser: 'Ajouter un utilisateur',
      name: 'Nom',
      role: 'Rôle',
      admin: 'Administrateur',
      editor: 'Éditeur',
      status: 'Statut',
      actions: 'Actions',
      active: 'Actif',
      suspended: 'Suspendu',
      you: '(vous)',
      suspend: 'Suspendre',
      reactivate: 'Réactiver',
      resetPassword: 'Réinit. MdP',
      resetPasswordFor: 'Réinitialiser le mot de passe de',
      newPassword: 'Nouveau mot de passe (18+ car.)',
      confirmPassword: 'Confirmer',
      password: 'Mot de passe',
      passwordHelp: 'Minimum 18 caractères, 1 majuscule, 1 minuscule, 1 caractère spécial.',
      delete: 'Supprimer',
      deleteConfirm: 'Supprimer cet utilisateur ?',
      confirmDelete: 'Supprimer définitivement cet utilisateur ?',
      confirmDeleteDouble: 'Cette action est irréversible. Confirmer la suppression ?',
      confirmSuspend: 'Suspendre cet utilisateur ?',
      confirmReactivate: 'Réactiver cet utilisateur ?',
      create: 'Créer un utilisateur',
      createDesc: 'Ajoutez un nouveau compte utilisateur.',
      createBtn: 'Créer le compte',
      createSuccess: 'Utilisateur créé',
      deleteSuccess: 'Utilisateur supprimé',
      suspendSuccess: 'Utilisateur suspendu',
      reactivateSuccess: 'Utilisateur réactivé',
      resetSuccess: 'Mot de passe réinitialisé',
      loadError: 'Impossible de charger les utilisateurs.',
      errorNameShort: 'Le nom doit contenir au moins 2 caractères.',
      errorPwdShort: 'Le mot de passe doit contenir au moins 18 caractères.',
      errorPwdWeak: 'Le mot de passe doit contenir majuscule, minuscule et caractère spécial.',
      errorPwdMismatch: 'Les mots de passe ne correspondent pas.',
      accountSuspended: 'Compte suspendu',
      currentUser: 'Vous',
      userCount: '{{count}}/{{max}} utilisateurs',
      roleAdmin: 'Admin',
      roleEditor: 'Éditeur',
      roleViewer: 'Lecteur',
      roleLabel: 'Rôle',
      roleHelp: 'Éditeur = peut modifier les données. Lecteur = lecture seule.',
      changeRoleTitle: 'Changer le rôle',
      changeRoleConfirm: 'Changer le rôle de {name} en {role} ?',
      roleChangeSuccess: 'Rôle modifié',
      usernamePlaceholder: 'utilisateur',
      pwdMinPlaceholder: '18 caractères min.',
      confirmPwdPlaceholder: 'Confirmer le mot de passe',
      deleteTitle: 'Supprimer l\'utilisateur',
      confirmDeleteBtn: 'Supprimer définitivement',
      suspendTitle: 'Suspendre',
      reactivateTitle: 'Réactiver',
      usersLabel: 'utilisateurs',
      // FIX-I18N-AUTH (audit 2026-06-10) : badge mot de passe temporaire
      tempPassword: 'MdP temp.',
      // FIX-SSO-EMAIL-LINK (audit 2026-06-10, complément client) : champ email
      email: 'Email',
      emailOptional: 'Email (optionnel)',
      emailPlaceholder: 'utilisateur@exemple.com',
      emailHelp: 'Permet la liaison du compte avec le SSO entreprise.',
      editEmail: 'Email',
      editEmailTitle: 'Modifier l\'email (liaison SSO)',
      emailClearHint: 'Laissez vide puis enregistrez pour supprimer l\'email.',
      emailUpdateSuccess: 'Email mis à jour',
      // === CSI-ME === multi-entités
      entityMain: 'Entité principale',
      entityLabel: 'Entité(s)',
      entityHelp: 'Une sous-entité ne voit que ses propres encodages.',
      entityHelpMulti: 'Une sous-entité ne voit que ses propres encodages. Sélection multiple possible (Ctrl/Cmd) — « Entité principale » ne se combine pas.',
      editEntities: 'Entité(s)',
      editEntitiesTitle: 'Modifier le rattachement aux sous-entités',
      canEditSubEntities: 'Peut éditer les données des sous-entités (compte du périmètre principal uniquement)',
      editEntitiesHint: 'Sélection multiple possible (Ctrl/Cmd). « Entité principale » = aucun rattachement. Retirer la dernière sous-entité suspend le compte (fail-closed).',
      entitiesUpdateSuccess: 'Rattachement mis à jour',
      lastEntityDetach: 'Ce compte n\'aura plus aucune sous-entité et obtiendrait un accès au périmètre principal. Confirmer ?',
      ssoDefaultEntity: 'Sous-entité par défaut des nouveaux utilisateurs SSO',
      ssoCardTitle: 'Authentification SSO (OIDC)',
      ssoLoading: 'Chargement de la configuration SSO…',
      ssoLoadFailed: 'Impossible de charger la configuration SSO.',
      ssoEnable: "Activer l'authentification SSO",
      ssoIssuer: 'Issuer URL',
      ssoClientId: 'Client ID',
      ssoClientSecret: 'Client Secret',
      ssoMode: "Mode d'authentification",
      ssoModeOnly: 'SSO uniquement (recommandé)',
      ssoModeMixed: 'SSO + mot de passe',
      ssoDefaultRole: 'Rôle par défaut des nouveaux utilisateurs SSO',
      ssoRoleEditor: 'Éditeur',
      ssoRoleViewer: 'Lecteur',
      ssoMaxUsers: "Nombre max. d'utilisateurs (tous comptes)",
      ssoAllowedDomains: 'Domaines email autorisés (vide = tous)',
      ssoAdvanced: 'Options avancées (IAM local / on-premise)',
      ssoAllowHttp: 'Autoriser HTTP (IAM local sans certificat TLS)',
      ssoCaPath: 'Chemin du certificat CA (PKI interne)',
      ssoSkipVerify: 'Désactiver la vérification TLS (dev/test uniquement !)',
      ssoSkipVerifyWarn: 'Attention : désactiver la vérification TLS expose les échanges SSO à des attaques man-in-the-middle. À utiliser uniquement en environnement de test.',
      ssoPasswordNote: 'Le login par mot de passe reste toujours disponible pour le compte administrateur, même en mode SSO uniquement.',
      ssoCallbackUrl: 'Callback URL (à configurer dans votre IdP)',
      ssoTestBtn: 'Tester la connexion',
      ssoTesting: 'Test en cours…',
      ssoTestFailedPrefix: 'Échec du test SSO : ',
      ssoIssuerRequired: "Veuillez renseigner l'Issuer URL.",
      ssoSaveBtn: 'Enregistrer',
      ssoSaving: 'Enregistrement…',
      ssoSaved: 'Configuration SSO enregistrée.',
      ssoErrorPrefix: 'Erreur : ',
      ssoRequiredFields: 'Issuer URL, Client ID et Client Secret sont requis pour activer le SSO.',
      ssoCaInvalid: 'Chemin CA invalide. Utilisez un chemin absolu sans ".." (ex: /etc/ssl/certs/ca.pem)',
      ssoDefaultEntityNone: 'Entité principale (aucune)',
      ssoAllowedDomainsWarn: 'Aucun domaine autorisé : tout compte renvoyé par l\'IdP peut obtenir un accès. Renseignez vos domaines, surtout avec un IdP multi-tenant (Google, Azure « common »).',
      ssoMapSection: 'Mapping des groupes (rôles & entités)',
      ssoMapInfo: 'Attribuez automatiquement un rôle et/ou une entité selon les groupes envoyés par l\'IdP. Sans correspondance, le rôle/entité par défaut s\'applique.',
      ssoMapAddRow: '+ Ajouter une règle',
      ssoGroupClaim: 'Nom du claim de groupe (ex. groups, roles)',
      ssoScopes: 'Scopes OIDC (vide = openid email profile)',
      ssoGroupToRole: 'Groupe → rôle',
      ssoGroupToEntity: 'Groupe → entité',
      ssoGroupPlaceholder: 'Groupe IdP',
      ssoStrictMapping: 'Refuser les comptes sans groupe mappé (strict)',
      ssoReconcile: 'Ré-appliquer le mapping à chaque connexion',
      ssoSecSection: 'Sécurité renforcée (recommandé)',
      ssoVerifySig: 'Vérifier la signature des jetons (JWKS) — recommandé',
      ssoRequireEmailVerified: 'Exiger un email vérifié pour créer un compte — recommandé',
      ssoIdpLogout: 'Déconnexion aussi côté fournisseur (SSO logout)',

      // === CSI-MCP === Interface MCP (accès IA en lecture seule)
      mcpCardTitle: 'Accès IA (MCP)',
      mcpCardDesc: 'Ouvrez un accès en lecture seule à vos données de gouvernance pour un assistant IA, via MCP (Model Context Protocol), le standard d\'interopérabilité des assistants IA.',
      mcpAskTitle: 'Ce que vous pourrez demander à votre IA',
      mcpAsk1: 'Quels risques critiques n\'ont aucun plan d\'action ?',
      mcpAsk2: 'Où en est ma maturité NIS2, fonction par fonction ?',
      mcpAsk3: 'Quelles actions sont en retard, et chez qui ?',
      mcpAsk4: 'Prépare la synthèse conformité pour le comité de direction.',
      mcpAskFoot: 'Votre assistant répond sur vos données réelles, à jour, sans copier-coller ni export manuel.',
      mcpSharedUs: 'Ce que Cyber-Assistant sécurise',
      mcpSharedYou: 'Ce que votre organisation sécurise',
      mcpSharedUsList: 'Jetons nominatifs et révocables · Lecture seule · Périmètre limité au compte · Journal des consultations',
      mcpSharedYouList: 'Réseau interne · VPN · Reverse proxy · Filtrage IP · mTLS · Passerelle d\'identité',
      mcpHowTitle: 'Comment cela fonctionne',
      mcpHow1: 'Cyber-Assistant expose une interface MCP standard : tout assistant compatible s\'y connecte avec un jeton que vous générez ici.',
      mcpHow2: 'L\'accès est en lecture seule — aucun assistant ne peut modifier vos données.',
      mcpHow3: 'Chaque jeton est nominatif : il hérite du périmètre d\'entités du compte auquel il est rattaché, tout accès est journalisé, et vous le révoquez en un clic.',
      mcpSharedTitle: 'Modèle de responsabilité partagée',
      mcpSharedApp: 'Cyber-Assistant sécurise l\'accès applicatif : jetons nominatifs et révocables, lecture seule, périmètre de données limité au compte, journal des consultations.',
      mcpSharedOrg: 'Votre organisation sécurise l\'exposition de cette interface, selon sa politique et son architecture : réseau interne, VPN, reverse proxy, filtrage IP, mTLS ou passerelle d\'identité.',
      mcpSharedReco: 'Recommandation : n\'exposez cette interface qu\'au sein de votre réseau de confiance.',
      mcpChoiceTitle: 'Choix de l\'assistant IA',
      mcpChoiceBody: 'Les données consultées quittent l\'application vers l\'assistant que vous connectez et sont traitées selon les conditions de son fournisseur. Privilégiez une IA exécutée sur votre infrastructure ou proposée par un acteur souverain, et vérifiez son alignement avec votre politique : localisation des données, non-réutilisation à des fins d\'entraînement, conformité RGPD et NIS2.',
      mcpEnableLabel: 'Activer l\'accès IA (MCP)',
      mcpEndpointLabel: 'Adresse de l\'interface MCP',
      mcpEndpointHint: 'Collez cette adresse dans votre client IA, avec l\'en-tête Authorization: Bearer <jeton>.',
      mcpBanner: 'Accès IA actif. Les données consultées sont transmises aux assistants connectés. Vérifiez régulièrement la liste des jetons et privilégiez une IA locale ou souveraine conforme à votre politique.',
      mcpTokensTitle: 'Jetons d\'accès',
      mcpTokensEmpty: 'Aucun jeton pour le moment.',
      mcpTokenLabel: 'Libellé',
      mcpTokenAccount: 'Compte lié',
      mcpTokenNoAccount: 'Aucun compte éligible : créez un compte actif avant de générer un jeton.',
      mcpTokenUsersFailed: 'Liste des comptes indisponible — vérifiez la connexion au serveur, puis rouvrez cette fenêtre.',
      mcpTokenCreated: 'Créé le',
      mcpTokenExpires: 'Expire le',
      mcpTokenLastUsed: 'Dernier usage',
      mcpTokenNever: 'Jamais',
      mcpTokenRevoked: 'Révoqué',
      mcpTokenCreate: 'Générer un jeton',
      mcpTokenRevoke: 'Révoquer',
      mcpTokenRevokeConfirm: 'Révoquer ce jeton ? Le client IA qui l\'utilise perdra immédiatement l\'accès.',
      mcpTokenOnce: 'Copiez ce jeton maintenant : il ne sera plus jamais affiché.',
      mcpTokenCreatedOk: 'Jeton créé.',
      mcpTokenRevokedOk: 'Jeton révoqué.',
      mcpTest: 'Tester',
      mcpTestOk: 'Interface MCP joignable et opérationnelle.',
      mcpTestFail: 'Test impossible.',
      mcpTestPartial: 'Interface joignable, mais des points restent à corriger.',
      mcpTokensLoadFailed: 'Impossible de lire la liste des jetons.',
      mcpDisabledTokensHint: 'La fonction est désactivée : l\'interface ne répond plus. Ces jetons ne sont PAS supprimés pour autant — ils redeviendront valides à la réactivation. Révoquez ceux qui ne doivent plus servir.',
      mcpCheckEnabled: 'Fonction activée',
      mcpCheckLicense: 'Licence valide',
      mcpCheckHtaccess: 'Fichiers de données protégés (.htaccess)',
      mcpCheckUserIni: 'Durcissement PHP présent (.user.ini)',
      mcpSaved: 'Configuration enregistrée.',
      mcpSaveFailed: 'Enregistrement impossible.',
      mcpLoadFailed: 'Chargement de la configuration MCP impossible.',
      mcpNotDeployed: 'mcp.php n\'est pas déployé sur le serveur — téléversez le fichier puis rechargez la page.',
      mcpModalTitle: 'Activer l\'accès IA (MCP) ?',
      mcpModalIntro: 'Vous allez ouvrir un accès en lecture seule à vos données de gouvernance — conformité, risques, actifs, plan d\'action — pour les assistants IA que vous autoriserez par jeton.',
      mcpModalControl: 'Ce qui reste sous votre contrôle : lecture seule, un jeton par utilisateur limité à son périmètre d\'entités, journal de toutes les consultations, révocation immédiate et désactivation globale à tout moment.',
      mcpModalArchi: 'Ce qui relève de votre architecture : l\'exposition de cette interface (réseau interne, VPN, reverse proxy, filtrage IP, passerelle d\'identité). Nous recommandons de la maintenir dans votre réseau de confiance.',
      mcpModalGov: 'Ce qui engage votre gouvernance : les données consultées sont transmises à l\'assistant IA connecté. Privilégiez une IA locale ou souveraine et vérifiez sa conformité à votre politique (localisation des données, non-entraînement sur vos contenus, RGPD/NIS2).',
      mcpModalCheck: 'J\'ai pris connaissance de ces éléments et je valide l\'ouverture de l\'accès MCP.',
      mcpModalConfirm: 'Activer',
      mcpModalCancel: 'Annuler',
      mcpShowcaseTitle: 'Accès IA (MCP)',
      mcpShowcaseBadge: 'Édition Serveur',
      mcpShowcaseBadgeShort: 'Serveur',
      mcpShowcaseBody: 'Connectez un assistant IA à votre SMSI pour qu\'il réponde sur vos données de conformité, en lecture seule et sous accès nominatif révocable.',
      mcpShowcaseAvail: 'Disponible en édition Serveur.',
      mcpShowcaseMeanwhile: 'En attendant : vous pouvez exporter vos données au format JSON et les joindre à une conversation avec votre assistant IA — en tenant compte de leur sensibilité et de votre politique de confidentialité.',
      entShowcaseTitle: 'Multi-entités',
      entShowcaseBody: 'Pilotez jusqu\'à 50 entités depuis une seule installation : tableau de bord consolidé pour le groupe, cloisonnement strict des données par site, import/export par entité.',
      entShowcaseAvail: 'Disponible en édition Serveur.',
      entShowcaseWhoTitle: 'Pour qui ?',
      entShowcaseWho1: 'Groupe multi-sites : chaque site encode, la direction consolide.',
      entShowcaseWho2: 'Entités à SMSI séparés : données cloisonnées, méthode commune.',
      entShowcaseWho3: 'Prestataire (MSSP) : un espace étanche par client, une seule installation.',
      entShowcaseFeat1: 'Jusqu\'à 50 entités',
      entShowcaseFeat1d: 'Une seule installation, un périmètre par site, entité ou client.',
      entShowcaseFeat2: 'Tableau de bord consolidé',
      entShowcaseFeat2d: 'Risques, actions, non-conformités et actifs de toutes les entités, en un écran.',
      entShowcaseFeat3: 'Cloisonnement strict',
      entShowcaseFeat3d: 'Données séparées côté serveur ; un compte de site ne voit jamais les autres.',
      entShowcaseFeat4: 'Droits par section',
      entShowcaseFeat4d: 'Rien / Lecture / Écriture pour chaque section, par entité. Une nouvelle entité démarre sans aucun droit.',
      entShowcaseFeat5: 'Import/export par entité',
      entShowcaseFeat5d: 'Chaque export est estampillé ; le serveur refuse un réimport dans le mauvais périmètre.',
      entShowcaseFeat6: 'Navigation sans confusion',
      entShowcaseFeat6d: 'Sélecteur de périmètre, bandeau permanent, titre d\'onglet et favicon badgés.',
      mcpShowcaseHowTitle: 'Comment cela marchera',
      mcpShowcaseHow1: 'Un jeton nominatif que vous générez, révocable en un clic.',
      mcpShowcaseHow2: 'Lecture seule : aucun assistant ne peut modifier vos données.',
      mcpShowcaseHow3: 'Compatible avec les assistants du marché comme avec une IA hébergée chez vous.'
    },

    entities: {
      // === CSI-ME === libellés de la feature multi-entités (entity-ui.js)
      cardTitle: 'Multi-entités',
      cardDesc: 'Cloisonnez des sous-entités (directions, établissements, sites…) qui n\'accèdent qu\'à leurs propres encodages.',
      notInLicense: 'Cette fonction n\'est pas incluse dans votre licence actuelle.',
      loadConfigFailed: 'Impossible de charger la configuration multi-entités.',
      opsTitle: 'Multi-entités — opérations',
      opsDesc: 'Sauvegarde et restauration de TOUTES les partitions (entité principale + sous-entités).',
      backupBtn: 'Télécharger la sauvegarde complète',
      restoreBtn: 'Restaurer une sauvegarde complète…',
      opsHint: 'La restauration remplace chaque partition (instantané automatique avant écrasement, rotation 20). Si une partition est en cours d\'édition, la restauration est refusée — vous pourrez alors reprendre les verrous.',
      perimeter: 'Périmètre',
      allEntities: 'Toutes les entités',
      allEntitiesTitle: 'Vue consolidée en lecture seule (toutes les entités confondues)',
      consolidatedHint: 'lecture seule',
      truncatedTitle: 'Affichage limité pour préserver la fluidité.',
      truncatedHint: 'Liste partielle — affinez par recherche ou entité.',
      mainEntity: 'Entité principale',
      archivedTag: '(archivée)',
      backupFailedPrefix: 'Sauvegarde impossible : ',
      confirmScopeEdit: 'Vous êtes sur le périmètre « {{name}} ».\n\nActiver le mode édition sur CE périmètre ?',
      crossImportConfirm: "Ce fichier provient d'un autre périmètre ({{origin}}).\n\nImporter ici REMPLACERA les données du périmètre courant ({{target}}). Confirmer ?",
      prefillTitle: "Copier les défauts sûrs de l'entité principale (échelles, référentiel, cible) — jamais les données métier",
      restoreErrorPrefix: 'Restauration : ',
      restoreTakeoverConfirm: 'Reprendre les verrous et restaurer quand même ?',
      sections: {
        'risks': 'Risques', 'threats-section': 'Menaces', 'actions': 'Actions',
        'nonconformities': 'Non-conformités', 'critical-assets': 'Actifs critiques',
        'audits': 'Audits', 'documents': 'Documents', 'stakeholders': 'Parties prenantes',
        'kpis': 'Indicateurs', 'managementReviews': 'Revues de direction',
        'project-risks': 'Risques projets', 'risk-analysis': 'Analyses de risques',
        'nis2-program': 'Budget / Programme', 'docReview': 'Revue documentaire',
        'nis2-socle': 'Socle NIS2', 'app-config': 'Configuration (langue, référentiel)'
      },
      cols: {
        title: 'Intitulé', category: 'Catégorie', likelihoodShort: 'V', impactShort: 'I',
        status: 'Statut', threat: 'Menace', type: 'Type', priority: 'Priorité',
        dueDate: 'Échéance', assignee: 'Responsable', severity: 'Sévérité', name: 'Nom',
        importance: 'Importance', date: 'Date', version: 'Version', role: 'Rôle',
        indicator: 'Indicateur', value: 'Valeur', target: 'Cible', item: 'Élément'
      },
      moveTargetAria: 'Périmètre cible du déplacement',
      actionsCol: 'Actions',
      shownCountSingular: '{{n}} élément affiché',
      shownCountPlural: '{{n}} éléments affichés',
      shownTotal: '{{total}} au total (1000 max chargés)',
      selectionCol: 'Sélection',
      selectItemAria: 'Sélectionner : {{title}} ({{entity}})',
      switchFailed: 'Bascule vers « {{name}} » impossible (serveur injoignable) — périmètre inchangé.',
      switchDirtyConfirm: 'Des modifications ne sont pas encore enregistrées sur le serveur :\n\n{{list}}\n\nChanger de périmètre les abandonnera (une copie de secours sera téléchargée).\n\nContinuer quand même ?',
      switchDirtyBackedUp: 'Copie de secours de vos modifications non enregistrées : {{n}} fichier(s).',
      switchRenderFailed: 'Périmètre changé, mais un écran n\'a pas pu s\'afficher correctement — rechargez la page si l\'affichage semble incohérent.',
      switchFlushPending: "Des modifications sont encore en cours d'envoi — réessayez dans un instant.",
      readonlySectionNote: "Section en lecture seule pour votre périmètre — les modifications n'y seront pas enregistrées.",
      readonlyNav: 'Lecture seule (droits du périmètre)',
      myEntity: 'Mon entité',
      consoleTitle: 'Vue consolidée — toutes les entités',
      consoleHint: 'Lecture seule. Chaque ligne porte l\'entité d\'origine. L\'édition se fait dans le périmètre concerné.',
      sectionLabel: 'Section',
      refresh: 'Actualiser',
      loading: 'Chargement…',
      loadFailed: 'Chargement impossible',
      networkError: 'Erreur réseau',
      noItems: 'Aucun élément.',
      entityCol: 'Entité',
      readOnly: 'Lecture seule',
      sectionViewAria: 'Vue de la section',
      entityFilterAll: 'Toutes les entités',
      sectionSearchPlaceholder: 'Rechercher dans la vue consolidée…',
      openInEntity: 'Ouvrir dans l\'entité',
      openedInEntity: 'Périmètre source ouvert. L\'élément reste en consultation.',
      exportGroupTag: 'entite-principale',
      selectedN: '{{n}} sélectionné(s)',
      moveTo: '→ déplacer vers',
      move: 'Déplacer',
      scopeBanner: 'Périmètre : {{name}} — vous consultez/éditez une sous-entité',
      spaceLabel: 'Espace {{name}}',
      spaceGeneric: 'Espace sous-entité',
      groupDataBtn: 'Données du groupe (lecture)',
      groupConsoleTitle: 'Données de l\'entité principale — lecture seule',
      groupConsoleHint: 'Sections partagées en lecture par l\'entité principale. Pour lier un de ces éléments à vos encodages, déclinez-le localement dans votre espace.',
      noSharedSection: 'Aucune section partagée.',
      noSharedItems: 'Aucun élément partagé dans cette section (ou données pas encore synchronisées).',
      tileTitle: 'Vue groupe — activité des sous-entités',
      subEntitiesN: '{{n}} sous-entité(s)',
      tileEmpty: 'Aucune sous-entité configurée. Ajoutez-en depuis Réglages ▸ Multi-entités.',
      colSubEntity: 'Sous-entité',
      colLastActivity: 'Dernière activité',
      colBy: 'Par',
      colSections: 'Sections',
      colState: 'État',
      archivedTag: '(archivée)',
      disabledTag: '(désactivée)',
      inEdition: 'En édition · {{name}}',
      free: 'Libre',
      consult: 'Consulter',
      noActivity: 'aucune activité',
      justNow: 'à l\'instant',
      minsAgo: 'il y a {{n}} min',
      hoursAgo: 'il y a {{n}} h',
      daysAgo: 'il y a {{n}} j',
      activateHint: 'Activez le mode pour créer des sous-entités. L\'activation n\'écrit aucune donnée : vos encodages actuels deviennent l\'entité principale.',
      activated: 'Mode multi-entités activé',
      deactivated: 'Mode désactivé',
      addPlaceholder: 'Nom de la sous-entité',
      capReached: 'Plafond de licence atteint ({{max}}).',
      clusterKeys: 'risques, menaces, actions, SoA, contrôles, audits, NC, actifs',
      clusterName: 'Bloc SMSI cœur',
      configChangedReload: 'Configuration modifiée ailleurs — rechargement',
      configInvalid: 'Configuration invalide',
      countMax: '{{count}} / {{max}} sous-entités',
      created: 'Sous-entité créée (droits fermés — ouvrez-les via le profil et assignez des comptes)',
      deactivateConfirm: 'Désactiver le mode multi-entités ?\n\nLes {{n}} sous-entité(s) et leurs données seront CONSERVÉES mais invisibles jusqu\'à réactivation. Les comptes assignés seront bloqués.',
      deleteConfirm: 'Supprimer la sous-entité « {{name}} » ?',
      deleteConfirmStrong: 'SUPPRIMER définitivement « {{name}} » ?\n\n• Ses données deviendront INACCESSIBLES (preuves d\'audit incluses).\n• Le nom « {{name}} » restera RÉSERVÉ et ne pourra pas être recréé sans intervention serveur.\n\nPréférez « Archiver » (réversible, aucune perte). Un export de secours va être téléchargé avant la suppression.\n\nConfirmer la suppression ?',
      deleteFailed: 'Échec (comptes encore assignés ?)',
      archive: 'Archiver',
      unarchive: 'Désarchiver',
      archiveTitle: 'Masquer et exclure du quota de licence — réversible, aucune donnée perdue',
      archived: 'Sous-entité archivée (réversible)',
      unarchived: 'Sous-entité désarchivée',
      deleted: 'Sous-entité supprimée',
      invalidBackup: 'Fichier invalide : attendu une sauvegarde complète (csi-backup-all-v1).',
      modeActivate: 'Activer le mode multi-entités',
      modeOn: 'Mode activé',
      modifiedReload: 'Modifié ailleurs — rechargement',
      moveConfirm: 'Déplacer {{n}} élément(s) vers « {{name}} » ?\n\nLes éléments sont copiés puis vérifiés avant suppression de la source (aucune perte). L\'édition reste possible ensuite dans le périmètre cible.\n\n⚠ Seuls les éléments de cette section sont déplacés — les objets LIÉS (actions, contrôles, actifs rattachés…) restent dans le périmètre source. Déplacez-les séparément si besoin, ou re-liez-les localement dans le périmètre cible.',
      moveDone: '{{n}} élément(s) déplacé(s)',
      moveErrors: '{{n}} échec(s)',
      moveSkipped: '{{n}} ignoré(s) (déjà présents)',
      moveTargetSame: 'Les éléments sélectionnés sont déjà dans le périmètre cible.',
      nameInvalid: 'Nom invalide',
      nameRequired: 'Nom requis',
      newEntityHint: 'Une nouvelle sous-entité démarre VIDE et sans droits (fail-closed). Ouvrez ses sections via le profil, puis assignez des comptes dans « Utilisateurs ».',
      prefill: 'Pré-remplir',
      prefillConfirm: 'Pré-remplir « {{name}} » avec les défauts de l\'entité principale (échelles d\'impact, référentiel, cible de maturité) ?\n\nAucune donnée métier (risques, actions…) n\'est copiée.',
      prefilled: 'Défauts copiés vers « {{name}} »',
      profileTitle: 'Profil « Sous-entité standard » — droits par section',
      restoreConfirm: 'RESTAURATION COMPLÈTE\n\nCeci va REMPLACER les données de l\'entité principale et de {{n}} sous-entité(s) par le contenu de la sauvegarde{{when}}.\n\nUn instantané de l\'état actuel est pris automatiquement avant écrasement. Continuer ?',
      rightNone: 'Rien',
      rightRead: 'Lecture',
      rightWrite: 'Écriture',
      rightsUpdated: 'Droits mis à jour',
      saveFailed: 'Échec',
      scalesImposed: 'imposés par l\'entité principale',
      scalesLocked: 'Lecture (verrouillé)',
      scalesName: 'Échelles & référentiel',
      subEntitiesLabel: 'Sous-entités',
      // === CSI-ME === (import/export par entité, 2026-07-09)
      impexpTitle: 'Multi-entités — export / import par entité',
      impexpDesc: 'Exportez une entité individuelle (ré-importable en version locale), tout le groupe, ou importez un fichier pour l\'ajouter comme nouvelle entité ou écraser une entité existante.',
      exportEntityLabel: 'Exporter une entité individuelle :',
      exportEntityBtn: 'Exporter cette entité',
      exportGroupLabel: 'Exporter tout le groupe :',
      exportBundleBtn: 'Bundle unique (toutes)',
      exportPerFileBtn: 'Un fichier par entité',
      exportPerFileDone: 'Export par fichier terminé ({{n}} fichier(s))',
      exportFailedPrefix: 'Export impossible : ',
      importLabel: 'Importer un fichier d\'entité ou une sauvegarde :',
      importEntityBtn: 'Importer une entité…',
      importTitle: 'Importer une entité',
      importIntro: 'Importez un export d\'entité (fichier individuel) ou une sauvegarde complète. Vous pourrez l\'ajouter comme NOUVELLE entité, ou ÉCRASER une entité existante.',
      chooseFile: 'Choisir un fichier…',
      fileReadError: 'Lecture du fichier impossible.',
      invalidFile: 'Fichier JSON invalide.',
      importedEntity: 'Entité importée',
      noDataInFile: 'Ce fichier ne contient aucune entité exploitable (pas de données).',
      bundleDetected: 'Sauvegarde complète détectée ({{n}} entité(s) avec données). Choisissez la source à importer, ou ajoutez-les toutes comme nouvelles entités.',
      importAllAsNew: 'Ajouter TOUTES comme nouvelles entités',
      modeConsolidate: 'Consolider — ajouter comme NOUVELLE entité',
      modeOverwrite: 'Écraser une entité EXISTANTE',
      newEntityNamePh: 'Nom de la nouvelle entité',
      newEntityNameLabel: 'Nom de la nouvelle entité :',
      overwriteTargetLabel: 'Entité à écraser :',
      overwriteWarn: '⚠ Le contenu de l\'entité choisie sera REMPLACÉ. Un instantané est pris automatiquement avant écrasement.',
      importConfirmBtn: 'Importer',
      importInProgress: 'Import en cours…',
      importCancelled: 'Import annulé.',
      importErrorPrefix: 'Import : ',
      importLockConfirm: 'La partition cible est en cours d\'édition par {{who}}. Reprendre le verrou et importer quand même ?',
      overwriteConfirm: 'ÉCRASER l\'entité « {{name}} » avec ces données ?\n\nToutes ses données actuelles seront remplacées. Un instantané est pris avant écrasement.',
      overwriteGroupConfirm: 'ÉCRASER l\'ENTITÉ PRINCIPALE avec ces données ?\n\nLes échelles imposées du groupe sont préservées, mais toutes les autres données de la principale seront remplacées. Un instantané est pris avant écrasement.',
      createdOk: 'Entité créée : {{name}} (id {{id}}).',
      overwrittenOk: 'Entité écrasée : {{id}}.',
      lockStolen: '(verrou repris à {{who}})',
      bundleImportDone: 'Terminé : {{ok}} créée(s), {{fail}} échec(s).',
      pickEntityToLoadTitle: 'Charger une entité',
      pickEntityToLoad: 'Quelle entité charger dans cet espace de travail ?'
    },

    // Operational capabilities (spider/radar chart)
    capabilities: {
      gouvernance: 'Gouvernance',
      gestionActifs: 'Gestion des actifs',
      protectionInformations: 'Protection des informations',
      securiteRH: 'Sécurité des ressources humaines',
      securitePhysique: 'Sécurité physique',
      securiteSystemeReseau: 'Sécurité système et réseau',
      securiteApplications: 'Sécurité des applications',
      configurationSecurisee: 'Configuration sécurisée',
      gestionIdentitesAcces: 'Gestion des identités et des accès',
      gestionMenacesVulnerabilites: 'Gestion des menaces et des vulnérabilités',
      continuite: 'Continuité',
      securiteRelationsFournisseurs: 'Sécurité des relations fournisseurs',
      reglementationConformite: 'Réglementation et conformité',
      gestionEvenementsSI: 'Gestion des événements de sécurité de l\'information',
      assuranceSI: 'Assurance de sécurité de l\'information'
    },

    // Chart labels
    chartLabels: {
      target: 'Cible',
      averageCMM: 'Moyenne CMM',
      globalTarget: 'Cible globale',
      averageMaturity: 'Maturité moyenne',
      docMaturity: 'Documentation',
      implMaturity: 'Implémentation'
    },

    // Control status options
    controlStatuses: {
      nonImplemente: 'Non implémenté',
      enCours: 'En cours',
      implemente: 'Implémenté',
      verifie: 'Vérifié'
    },

    // Domain options
    domains: {
      organisationnel: 'Organisationnel',
      humain: 'Humain',
      physique: 'Physique',
      technologique: 'Technologique',
      nonClasse: 'Non classé'
    },

    // CMM levels
    cmmLevels: {
      initial: 'Initial',
      repetable: 'Répétable',
      defini: 'Défini',
      gere: 'Géré',
      optimise: 'Optimisé'
    },

    // Risk levels (from calculateRiskLevel)
    riskLevels: {
      critical: 'Critique',
      high: 'Grave',
      medium: 'Significatif',
      low: 'Mineur',
      negligible: 'Insignifiant'
    },

    // Treatment options
    treatments: {
      reduction: 'Réduction',
      acceptation: 'Acceptation',
      transfert: 'Transfert',
      evitement: 'Évitement'
    },

    // Action priority options
    actionPriorities: {
      critical: 'Critique',
      high: 'Haute',
      medium: 'Moyenne',
      low: 'Faible'
    },

    // Action link types (PDF reports)
    actionLinkTypes: {
      control: 'Contrôle',
      risk: 'Risque',
      nc: 'Non-conformité',
      audit: 'Audit',
      threat: 'Menace',
      continuous: 'Amélioration continue'
    },

    // Action status options
    actionStatuses: {
      planifie: 'Planifié',
      enCours: 'En cours',
      termine: 'Terminé',
      annule: 'Annulé'
    },

    // NC status options
    ncStatuses: {
      detection: 'Détection',
      analyse: 'Analyse',
      action: 'Action',
      cloture: 'Clôture'
    },

    // NC type options
    ncTypes: {
      majeure: 'Majeure',
      mineure: 'Mineure'
    },

    // Audit options
    auditStatuses: {
      planifie: 'Planifié',
      realise: 'Réalisé',
      enCours: 'En cours',
      annule: 'Annulé'
    },
    auditTypes: {
      interne: 'Audit interne',
      externe: 'Audit externe',
      certification: 'Certification',
      surveillance: 'Surveillance'
    },

    // Threat statuses
    threatStatuses: {
      reduction: 'Réduction',
      acceptation: 'Acceptation',
      transfert: 'Transfert',
      evitement: 'Évitement'
    },

    // SOA source options
    soaSources: {
      select: '— Sélectionner —',
      risk: 'Risque identifié',
      legal: 'Exigence légale',
      contractual: 'Exigence contractuelle',
      bestPractice: 'Bonne pratique',
      regulatory: 'Exigence réglementaire',
      business: 'Exigence métier'
    },

    // SOA implementation status
    soaImplStatuses: {
      select: '— État —',
      notStarted: 'Non démarré',
      planned: 'Planifié',
      inProgress: 'En cours',
      implemented: 'Implémenté',
      verified: 'Vérifié'
    },

    // Document review statuses
    docReviewStatuses: {
      select: '— Statut —',
      conforme: 'Conforme',
      partiel: 'Partiellement conforme',
      nonConforme: 'Non conforme',
      na: 'Non applicable'
    },

    // Critical asset options
    assetAvailability: {
      level1: 'Niveau 1 - Haute disponibilité',
      level2: 'Niveau 2 - Reprise rapide',
      level3: 'Niveau 3 - Reprise standard',
      level4: 'Niveau 4 - Reprise prolongée'
    },
    assetConfidentiality: {
      sensible: 'Sensible',
      tresSensible: 'Très sensible',
      restreint: 'Restreint',
      public: 'Public'
    },
    assetIntegrity: {
      faible: 'Faible',
      moderee: 'Modérée',
      elevee: 'Élevée',
      critique: 'Critique'
    },
    assetType: {
      hardware: 'Matériel',
      software: 'Logiciel',
      sourceCode: 'Code source',
      network: 'Réseau',
      service: 'Service',
      document: 'Document',
      employee: 'Employé',
      site: 'Locaux',
      organization: 'Organisation'
    },
    assetImportance: {
      normal: 'Normal',
      important: 'Important',
      critique: 'Critique'
    },
    assetImpact: {
      societal: 'Sociétal',
      operationnel: 'Opérationnel',
      financier: 'Financier',
      reputation: 'Réputation',
      reglementaire: 'Réglementaire'
    },
    assetMfa: {
      nonImplemente: 'Non implémenté',
      partiel: 'Partiel',
      implemente: 'Implémenté',
      externe: 'Externe'
    },
    assetDacp: {
      oui: 'Oui',
      non: 'Non'
    },

    // Project risk statuses
    projectRiskStatuses: {
      red: 'Rouge',
      yellow: 'Jaune',
      green: 'Vert',
      todo: 'À réaliser',
      suspended: 'Suspendue'
    },

    // NIS2 statuses
    nis2Statuses: {
      todo: 'À réaliser',
      inProgress: 'En cours',
      suspended: 'Suspendu',
      done: 'Réalisé'
    },
    nis2Urgency: {
      high: 'Urgence haute',
      medium: 'Priorité moyenne',
      standard: 'Priorité standard'
    },
    nis2ActionTypes: {
      service: 'Service',
      projet: 'Projet',
      initiative: 'Initiative',
      programme: 'Programme'
    },
    nis2Phases: {
      outOfPhase: 'Hors phase',
      phase1: 'Phase 1 (2026)',
      phase2: 'Phase 2 (2027)',
      phase3: 'Phase 3 (2028)'
    },

    // Toast messages
    toasts: {
      demoDataReloaded: 'Données de démonstration rechargées automatiquement.',
      recyfConfigured: 'Référentiel NIS2 : France (ReCyF) — {{deg}}',
      tooManyActions: 'Trop d\'actions en peu de temps. Veuillez patienter quelques secondes.',
      noInconsistency: 'Aucune incohérence détectée',
      snapshotSaved: 'Snapshot enregistré',
      snapshotError: 'Impossible de créer le snapshot : {{message}}',
      snapshotRestored: 'Snapshot restauré, rechargement...',
      snapshotHistoryCleared: 'Historique des snapshots vidé',
      snapshotHistoryError: 'Impossible de supprimer l\'historique',
      chartLibUnavailable: 'Erreur : bibliothèque de graphiques non disponible',
      enterPassword: 'Veuillez saisir un mot de passe.',
      requiredFields: 'Veuillez remplir les champs obligatoires.',
      passwordMismatch: 'Les mots de passe ne correspondent pas.',
      passwordSaved: 'Mot de passe enregistré',
      readOnlyStart: 'L\'application démarre en mode lecture seule. Cliquez sur le cadenas pour passer en mode édition.',
      wrongPassword: 'Mot de passe incorrect',
      serverModeActivated: 'Mode serveur activé ! La fonctionnalité est maintenant disponible.',
      syncPanelLoading: 'Panneau de synchronisation en cours de chargement...',
      itemDeleted: 'Élément supprimé',
      dataRefreshed: 'Données actualisées (modifiées par un autre utilisateur)',
      budgetLineSaved: 'Ligne budgétaire enregistrée',
      budgetLineDeleted: 'Ligne budgétaire supprimée',
      budgetLineLabelRequired: 'Un intitulé est requis',
      budgetYearsUpdated: 'Années budgétaires mises à jour',
      budgetYearMin: 'Au moins une année requise',
      noDataToExport: 'Aucune donnée à exporter',
      excelExportSuccess: 'Export Excel réussi',
      excelExportError: 'Impossible d\'exporter. Vérifiez que des données existent.',
      exportTableNotFound: 'Table d\'export introuvable',
      exportNotSupported: 'Export Excel non supporté pour cette section',
      selectAtLeastOneSection: 'Sélectionnez au moins une section.',
      exportSuccess: 'Export réussi',
      exportError: 'Impossible d\'exporter les données.',
      importNis2Success: 'Import réussi - Plan NIS2 initialisé (ancien format)',
      importNis2Hint: 'Retrouvez vos budgets dans l\'onglet Budget Cybersécurité (Gouvernance)',
      importSuccess: 'Import réussi',
      importError: 'Impossible d\'importer le fichier. Vérifiez son format.',
      testsRunning: 'Exécution des tests en cours...',
      settingsSaved: 'Paramètres enregistrés',
      passwordUpdated: 'Mot de passe mis à jour',
      passwordSaveError: 'Impossible d\'enregistrer le mot de passe',
      pdfUnavailable: 'Génération PDF indisponible.',
      syncConfigSaved: 'Configuration synchronisation sauvegardée',
      syncConfigError: 'Impossible d\'enregistrer la configuration',
      syncPanelUnavailable: 'Panneau Sync serveur indisponible',
      demoDataLoaded: 'Données de démonstration chargées',
      demoDataLoadError: 'Impossible de charger les données.',
      resetDone: 'Réinitialisation terminée',
      resetServerFailed: 'Réinitialisation locale effectuée, mais le serveur n\'a pas pu être mis à jour. Reprenez la main (mode édition) et réessayez, sinon les anciennes données réapparaîtront au rechargement.',
      resetError: 'Impossible de réinitialiser les données.',
      quotaExceeded: 'Quota localStorage dépassé. Vos données ont été téléchargées en backup.',
      saveError: 'La sauvegarde a échoué. Vos données sont conservées localement.',
      noRisksDefined: 'Aucun risque défini. Créez d\'abord des risques dans le module Risques SMSI.',
      soaRisksUpdated: 'Risques associés mis à jour',
      addNis2DomainFirst: 'Ajoutez d\'abord un domaine NIS2 avant de créer une action.',
      filterApplied: 'Filtre appliqué : {{filter}}',
      activityRefreshed: 'Activité actualisée',
      preparingPdf: 'Préparation du PDF...',
      dashboardExported: 'Dashboard exporté',
      useSaveAsPdf: 'Utilisez "Enregistrer en PDF" dans la boîte de dialogue',
      soaPdfReady: 'SOA prête — Utilisez "Enregistrer en PDF"',
      auditPackReady: 'Pack Audit Doc Review prêt — Utilisez "Enregistrer en PDF"',
      dataSaved: 'Données sauvegardées',
      appLoaded: 'Application chargée avec succès',
      appLoadError: 'Erreur lors du chargement : {{message}}',
      demoBlocked: 'Cette fonctionnalité est désactivée en mode démonstration.',
      editModeEnabled: 'Mode édition activé',
      editModeDisabled: 'Mode lecture seule activé',
      justNow: "À l'instant",
      riskAnalysisModuleNotLoaded: "Module d'analyse de risques non chargé.",
      duplicateControlRef: 'Un contrôle avec cette référence existe déjà.',
      factoryPasswordWarning: 'Vous utilisez le mot de passe par défaut. Veuillez le changer dans les paramètres de sécurité.',
      popupBlocked: 'Veuillez autoriser les popups pour exporter en PDF.',
      fileTooLarge: 'Le fichier est trop volumineux (max 10 MB).',
      importIntegrityWarnings: 'Import terminé avec des avertissements d\'intégrité',
      invalidFileType: 'Format de fichier invalide. Veuillez sélectionner un fichier .json ou .smsi.',
      budgetCatMin: 'Au moins une catégorie requise',
      budgetCatUpdated: 'Catégories de budget mises à jour',
      saveFailed: 'Erreur de sauvegarde — les données importées n\'ont pas été persistées. Réessayez.',
      importSyncFailed: 'Import appliqué en mémoire mais NON enregistré sur le serveur : {{msg}}. Reprenez la main (mode édition) puis réimportez ; ne fermez pas l\'onglet.',
      importEpochConflict: 'Les données ont été rechargées suite à un import, une restauration ou une modification de configuration d\'un autre utilisateur. Une copie de vos modifications non enregistrées a été sauvegardée.',
      entityContextChanged: "Votre rattachement d'entité a changé — l'application va se recharger pour appliquer votre nouveau périmètre. Une copie de vos modifications non enregistrées a été téléchargée.",
      importIgnoredSections: "Sections en lecture seule pour votre périmètre, non modifiées par l'import : {{list}}",
      bundleNoData: 'La sauvegarde ne contient aucune entité exploitable.',
      sectionReadonly: "Cette section est en LECTURE SEULE pour votre périmètre — vos modifications n'ont pas été enregistrées.",
      pushEntityUnknown: "Votre périmètre n'est plus disponible (il vient d'être archivé ou supprimé). Vos modifications ne peuvent plus être enregistrées — contactez un administrateur avant de fermer l'onglet.",
      pushEntityArchived: 'Ce périmètre est ARCHIVÉ : il est en lecture seule. Un administrateur doit le réactiver dans Réglages ▸ Multi-entités pour permettre les modifications.',
      pushCrossEdit: "Votre compte n'est pas habilité à modifier les données des sous-entités. Un administrateur peut vous l'accorder dans Réglages ▸ Utilisateurs ▸ Entité(s).",
      pushKeysOutOfSection: "Anomalie applicative : le serveur a refusé le contenu de cette section. Vos modifications ne sont pas enregistrées — signalez-le au support avec le nom de l'écran.",
      pushForbidden: 'Écriture refusée par le serveur (droits insuffisants) — modifications non enregistrées.',
      syncGenericError: 'échec de synchronisation',
      syncFailed: 'Synchronisation serveur échouée — les données sont sauvegardées localement.',
      lockExpired: 'Le verrou sur cet onglet a expiré. Vos modifications ne seront pas synchronisées.',
      lockConflict: 'Un autre utilisateur détient le verrou. Vos modifications locales n\'ont pas été envoyées.',
      nis2Migration: 'Migration vers NIS2 terminée. Veuillez vérifier vos scores.',
      nis2LevelConfigured: 'Niveau NIS2 configuré : {{level}} ({{lang}})',
      // FIX-I18N-KEYS (audit 2026-06-10) : toasts critiques jusque-là en dur ou sans clé
      dataCorrupted: 'Données locales corrompues ou illisibles : une copie de secours (smsi_backup_corrupted.json) a été téléchargée. L\'application a démarré vide — ne sauvegardez pas avant d\'avoir mis cette copie à l\'abri.',
      editLockPushRefused: 'Verrou d\'édition non détenu — vos modifications restent en mémoire et ne sont pas enregistrées sur le serveur. Reprenez la main (mode édition) pour les enregistrer ; ne fermez pas l\'onglet avant.',
      // FIX-TOAST-423-CLUSTER (audit co-édition 2026-07-17) : variantes en mode édition — nommer
      // le module refusé au lieu du conseil « Reprenez la main » (absurde quand on édite déjà).
      editLockPushRefusedCluster: 'Module « {{module}} » non détenu — vos modifications restent en mémoire. Ouvrez un écran de ce module pour les enregistrer.',
      editLockPushRefusedClusterBusy: 'Module « {{module}} » occupé par {{name}} — vos modifications restent en mémoire et seront enregistrées via un écran de ce module quand il sera libre.',
      // FIX-OPTIMISTIC-REV (2026-06-11) : messages du parachute anti-écrasement
      pushConflict: 'Ces données ont été modifiées par un autre utilisateur. Vos modifications n\'ont pas été écrasées : elles ont été téléchargées dans un fichier de secours, et l\'écran affiche la version du serveur.',
      pushConflictRetry: 'Ces données ont été modifiées par un autre utilisateur — nouvelle tentative d\'enregistrement de votre version en cours…',
      pushConflictRetryBackup: 'Ces données ont été modifiées par un autre utilisateur — votre version va être enregistrée ; une copie de la version distante a été mise de côté (fichier « smsi_conflit_serveur_… »).',
      dirtyBackedUpBeforeRepull: '{{n}} modification(s) non enregistrée(s) ont été sauvegardées dans un fichier de secours avant le rechargement de l\'état du serveur.',
      multiTabConflict: 'Données modifiées dans un autre onglet. Rechargez cette page pour éviter d\'écraser votre travail.',
      restoreNeedsLock: 'Restauration non appliquée au serveur : passez en mode édition (ou reprenez la main) puis recommencez.',
      restoreSyncFailed: 'Échec de synchronisation de la restauration — non appliquée au serveur. Réessayez.',
      configNotPersisted: 'Configuration non enregistrée sur le serveur (un autre utilisateur édite) — elle sera appliquée à votre prochaine entrée en mode édition.',
      // FIX-CONFIG-LOCK-EDITING (revue adversariale 2026-07-17) : échec non lié au verrou.
      configPersistFailed: 'Configuration non enregistrée sur le serveur (erreur réseau ou serveur) — elle sera re-tentée à la prochaine synchronisation.',
      serverConflict: 'Conflit serveur — vos données sont en mémoire.',
      licenseExpired: 'Licence expirée — mode lecture seule.',
      syncFailedRetry: 'Échec de synchronisation serveur — vos données sont en mémoire. Ne fermez pas le navigateur.',
      syncFailedReload: 'Échec synchronisation — rechargement en cours',
      nis2LegacyMigrated: 'Contrôles NIS2 migrés depuis l\'ancien format (23 contrôles). Vérifiez les scores.',
      restoreFailed: 'Impossible de restaurer le snapshot',
      testsCompleted: 'Tests terminés : {passed}/{total} réussis',
      testsCompletedFailed: 'Tests terminés : {passed}/{total} réussis, {failed} échoué(s)',
      crossImportCancelled: 'Import inter-périmètre annulé — données inchangées.'
    },

    // Validation messages
    validation: {
      blocked: 'Sauvegarde bloquée : ',
      warnings: 'Données sauvegardées avec avertissements'
    },

    // Legacy import module
    legacyImport: {
      modalTitle: 'Analyse du fichier importé',
      versionDetected: 'Version détectée',
      confidence: 'Confiance',
      fieldMapping: 'Correspondance des champs',
      matched: 'Correspondants',
      missing: 'Absents (valeurs par défaut)',
      migrated: 'Migrés',
      ignored: 'Ignorés',
      migrations: 'Migrations à appliquer',
      warnings: 'Avertissements',
      crossRefIssues: 'Problèmes de références croisées',
      sizeEstimate: 'Estimation de la taille',
      canImport: 'Import possible',
      cannotImport: 'Import impossible',
      importWithMigrations: 'Importer avec migrations',
      importBtn: 'Importer',
      cancelBtn: 'Annuler',
      postImportOk: 'Import validé — aucun problème d\'intégrité détecté',
      postImportWarnings: 'Import terminé avec des avertissements d\'intégrité',
      detectedVersion: 'Version détectée',
      dataSummary: 'Résumé des données',
      section: 'Section',
      elements: 'Éléments',
      missingFields: 'Champs absents (valeurs par défaut) :',
      field: 'Champ',
      defaultValue: 'Valeur par défaut',
      unknownFields: 'Champs inconnus (ignorés) :',
      crossReferences: 'Références croisées',
      // FIX-I18N-KEYS (audit 2026-06-10) : clés manquantes de la modale d'import legacy
      andMoreIssues: '... et',
      moreItems: 'autres',
      autoMigrations: 'Migrations automatiques',
      importBlocked: 'Import bloqué',
      quotaRisk: 'Risque de quota'
    },

    // Import
    import: {
      oldFormatDetected: 'Ancien format détecté : le plan NIS2 et les budgets',
      willBeInitialized: 'seront initialisés avec les valeurs par défaut.',
      warningOverwrite: 'Attention : cette opération va écraser les données locales.',
      file: 'Fichier',
      importedFile: 'Fichier importé',
      summaryBeforeImport: 'Résumé avant import',
      importBtn: 'Importer'
    },

    // Sync Manager
    sync: {
      syncing: 'Synchronisation en cours',
      synced: 'Synchronisé avec le serveur',
      retrying: 'Nouvelle tentative de synchronisation',
      authError: 'Erreur d\'authentification - vérifiez le mot de passe',
      licenseExpired: 'Licence ou essai expiré — mode lecture seule',
      syncError: 'Erreur de synchronisation',
      licenseLabel: 'Licence',
      editLocked: 'Synchronisation différée — verrou d\'édition non détenu'
    },

    // Server Setup
    serverSetup: {
      configureTitle: 'Configurer le serveur',
      configureSub: 'Choisissez un mot de passe pour protéger vos données.',
      connectionTitle: 'Connexion au serveur',
      connectionSub: 'Entrez le mot de passe du serveur pour vous connecter.',
      serverPassword: 'Mot de passe serveur',
      connect: 'Se connecter',
      configure: 'Configurer',
      configuring: 'Configuration...',
      configSuccess: 'Serveur configuré avec succès !',
      passwordInvalid: 'Le mot de passe ne respecte pas les exigences.',
      passwordMismatch: 'Les mots de passe ne correspondent pas.',
      configError: 'Erreur de configuration',
      syncEnabled: 'Synchronisation activée',
      passwordRequired: 'Mot de passe requis',
      requirements: 'Exigences :',
      reqLength: '18 caractères minimum',
      reqUpper: '1 majuscule',
      reqLower: '1 minuscule',
      reqSpecial: '1 caractère spécial',
      minChars: 'minimum {{min}} caractères',
      confirmation: 'Confirmation'
    },

    // Modal titles
    modals: {
      dataQuality: 'Qualité des données',
      setPassword: 'Définir le mot de passe',
      editKpi: 'Modifier un KPI',
      addKpi: 'Ajouter un KPI',
      globalExcelExport: 'Export global Excel',
      confirmImport: 'Confirmer l\'import',
      nis2ControlTracking: 'Suivi du contrôle NIS2',
      controlTracking: 'Suivi du contrôle',
      addControl: 'Ajouter un contrôle',
      editAction: 'Modifier une action',
      addAction: 'Ajouter une action',
      renameSection: 'Renommer la section',
      editRisk: 'Modifier un risque',
      addRisk: 'Ajouter un risque',
      editNc: 'Modifier une non-conformité',
      addNc: 'Ajouter une non-conformité',
      editAudit: 'Modifier un audit',
      addAudit: 'Ajouter un audit',
      addReview: 'Ajouter une revue de direction',
      editReview: 'Modifier une revue de direction',
      addStakeholder: 'Ajouter une partie prenante',
      editStakeholder: 'Modifier une partie prenante',
      addDocument: 'Ajouter un document',
      editDocument: 'Modifier un document',
      editCriticalAsset: 'Modifier un actif critique',
      addCriticalAsset: 'Nouvel actif critique',
      addNis2Domain: 'Nouveau domaine NIS2',
      editNis2Domain: 'Modifier un domaine NIS2',
      addNis2Action: 'Nouvelle action NIS2',
      editNis2Action: 'Modifier une action NIS2',
      addNis2Status: 'Nouveau statut clé',
      editNis2Status: 'Modifier un statut clé',
      addThreat: 'Ajouter une menace',
      editThreat: 'Modifier une menace',
      addProjectRisk: 'Nouvelle analyse de risque projet',
      editProjectRisk: 'Modifier une analyse de risque projet',
      viewProjectRisk: 'Consulter une analyse de risque projet',
      budgetCategories: 'Catégories de budget',
      associatedRisks: 'Risques associés',
      editSoaControl: 'Modifier le contrôle',
      editDocReview: 'Modifier la clause',
      editPillar: 'Modifier le pilier',
      nis2Block: 'Bloc NIS2',
      budgetBlock: 'Bloc budget',
      addBudgetLine: 'Nouvelle ligne budgétaire',
      editBudgetLine: 'Modifier la ligne budgétaire',
      manageYears: 'Gérer les années budgétaires',
      controlDetails: 'Détails du contrôle',
      riskDetails: 'Détails du risque',
      threatDetails: 'Détails de la menace'
    },

    // Form field labels
    fields: {
      title: 'Titre',
      budgetYearsList: 'Une année par ligne (min. 1)',
      budgetYearsHelp: 'Ajoutez, retirez ou renommez des années (une par ligne). Les montants restent associés au libellé de chaque année ; un renommage à même position conserve la valeur.',
      auditTitle: 'Titre de l\'audit',
      description: 'Description',
      status: 'Statut',
      type: 'Type',
      priority: 'Priorité',
      owner: 'Responsable',
      dueDate: 'Échéance',
      progress: 'Avancement',
      comments: 'Commentaires',
      existingComments: 'Commentaires existants',
      newComment: 'Nouveau commentaire',
      impact: 'Impact',
      probability: 'Probabilité',
      level: 'Niveau',
      treatment: 'Traitement',
      criticalAssets: 'Actifs critiques',
      detectionDate: 'Date de détection',
      scope: 'Périmètre',
      plannedDate: 'Date prévue',
      auditor: 'Auditeur',
      date: 'Date',
      participants: 'Participants',
      inputElements: 'Éléments d\'entrée',
      decisions: 'Décisions',
      name: 'Nom',
      role: 'Rôle',
      contact: 'Contact',
      documentLevel: 'Niveau',
      documentType: 'Type',
      tool: 'Outil',
      link: 'Lien',
      target: 'Cible',
      current: 'Actuel',
      comment: 'Commentaire',
      beneficiary: 'Bénéficiaire',
      productCode: 'Produit (code)',
      productName: 'Produit (nom)',
      productTags: 'Tags produit (séparés par des virgules)',
      rto: 'RTO',
      rpo: 'RPO',
      availability: 'Disponibilité',
      confidentiality: 'Confidentialité',
      integrity: 'Intégrité',
      assetType: 'Type d\'actif',
      importance: 'Importance',
      mfaStatus: 'Statut MFA',
      dacpSensitive: 'DACP sensible',
      context: 'Contexte',
      likelihood: 'Vraisemblance',
      linkedAudit: 'Audit lié',
      correctiveAction: 'Action corrective',
      linkType: 'Type de lien',
      linkedElement: 'Élément lié',
      password: 'Mot de passe',
      confirmPassword: 'Confirmer le mot de passe',
      sectionName: 'Nom de la section',
      domainTitle: 'Titre du domaine',
      objective: 'Objectif',
      pillar: 'Pilier',
      urgencyHigh: 'Urgence haute',
      urgencyMedium: 'Priorité moyenne',
      urgencyStandard: 'Priorité standard',
      domain: 'Domaine',
      actionDescription: 'Description de l\'action',
      phase: 'Phase',
      workType: 'Type (Service / Projet / Initiative / Programme)',
      actionOwner: 'Responsable de l\'action',
      budget2026: 'Budget 2026',
      budget2027: 'Budget 2027',
      budget2028: 'Budget 2028',
      budgetGlobal: 'Budget global (optionnel)',
      budgetCategory: 'Catégorie budget',
      reference: 'Référence',
      measure: 'Mesure',
      recommendations: 'Recommandations',
      category: 'Catégorie',
      cmm: 'Niveau CMM',
      linkedActions: 'Actions liées',
      justification: 'Justification',
      score: 'Score',
      operations: 'Opérations',
      executionDate: 'Date d\'exécution',
      findings: 'Constatations',
      reviewInputs: 'Entrées de la revue',
      reviewDecisions: 'Décisions et actions',
      budgetCategoriesList: 'Une catégorie par ligne (min. 1)',
      deliverableType: 'Type de livrable',
      toolUsed: 'Outil utilisé',
      accessLink: 'Lien d\'accès',
      numbering: 'Numérotation',
      cmmLevel: 'Niveau de maturité CMM',
      controlOwner: 'Propriétaire du contrôle',
      ownerPlaceholder: 'Nom du responsable',
      ownerOrStakeholderPlaceholder: 'Nom libre ou partie prenante',
      ownerOrStakeholderHelp: 'Saisissez un nom libre ou choisissez une partie prenante existante.',
      riskOwner: 'Propriétaire du risque',
      // FIX-I18N-NIS2-PLAN (audit 2026-07-10) : modale pilier du socle
      subtitle: 'Sous-titre',
      keyItems: 'Éléments clefs (un par ligne)',
      projectLead: 'Chef de projet',
      reviewer: 'Relecteur',
      lastEvaluation: 'Dernière évaluation',
      nextReviewDate: 'Prochaine revue',
      reviewFrequency: 'Fréquence de revue',
      effectiveness: 'Efficacité mesurée',
      evidence: 'Preuves / Artefacts',
      evidencePlaceholder: 'Documents, logs, captures...',
      kpiRef: 'KPI associé',
      kpiPlaceholder: 'Référence du KPI mesurant l\'efficacité',
      select: 'Sélectionner' // FIX-I18N-KEYS (audit 2026-06-10)
    },

    // Control type labels
    controlType: {
      preventive: 'Préventif',
      detective: 'Détectif',
      corrective: 'Correctif',
      undefined: 'Non défini'
    },

    // Effectiveness labels
    effectiveness: {
      effective: 'Efficace',
      partial: 'Partiel',
      partiallyEffective: 'Partiellement efficace',
      ineffective: 'Non efficace',
      notTested: 'Non testé',
      notEvaluated: 'Non évaluée'
    },

    // Confirm dialog messages
    confirms: {
      deleteRisk: 'Supprimer ce risque ?',
      deleteThreat: 'Supprimer cette menace ?',
      deleteNc: 'Supprimer cette non-conformité ?',
      deleteAudit: 'Supprimer cet audit ?',
      deleteReview: 'Supprimer cette revue ?',
      deleteStakeholder: 'Supprimer cette partie prenante ?',
      deleteDocument: 'Supprimer ce document ?',
      deleteAction: 'Supprimer cette action ?',
      deleteKpi: 'Supprimer ce KPI ?',
      deleteAsset: 'Supprimer cet actif critique ?',
      resetData: 'Voulez-vous vraiment réinitialiser toutes les données ? Cette action est irréversible.',
      loadDemoData: 'Charger les données de démonstration ? Les données actuelles seront écrasées.',
      deleteSnapshot: 'Supprimer ce snapshot ?',
      clearSnapshots: 'Supprimer tout l\'historique des snapshots ?',
      restoreSnapshot: 'Restaurer ce snapshot ? Les données actuelles seront remplacées.',
      deleteProjectRisk: 'Supprimer cette analyse de risque projet ?',
      deleteControl: 'Supprimer ce contrôle ?',
      deleteDomain: 'Supprimer ce domaine et ses actions ?',
      deletePhase: 'Supprimer cette phase ? Les actions seront déplacées vers la phase de secours.',
      deleteKeyStatus: 'Supprimer ce statut clé ?',
      budgetCategoriesList: 'Une catégorie par ligne (min. 1)',
      deleteTitle: 'Supprimer ?',
      deleteComment: 'Supprimer ce commentaire ?',
      deleteBudgetLine: 'Supprimer cette ligne budgétaire ?'
    },

    // Budget categories
    budgetCategories: {
      infra: 'Infrastructure',
      cyber: 'Cybersécurité',
      divers: 'Divers',
      cyberBudget3y: 'Budget Cybersécurité 3 ans'
    },

    // Budget line statuses
    budgetStatus: {
      planifie: 'Planifié',
      engage: 'Engagé',
      realise: 'Réalisé'
    },

    // Edit mode actions
    editMode: {
      manageBudgetCategories: 'gérer les catégories de budget',
      editBudgetLine: 'éditer une ligne budgétaire',
      deleteBudgetLine: 'supprimer une ligne budgétaire',
      manageBudgetYears: 'gérer les années budgétaires'
    },

    // Common labels used in various places
    labels: {
      none: 'Aucune',
      noAsset: 'Aucun',
      all: 'Tous',
      notApplicable: 'N/A',
      pillar: 'Pilier {{number}}',
      phase: 'Phase {{number}}',
      completed: 'terminées',
      todo: 'à faire',
      noneM: 'Aucun',
      openAction: 'Ouvrir l\'action',
      select: 'Sélectionner',
      atRisk: 'à risque' // FIX-I18N-KEYS (audit 2026-06-10)
    },

    // Impact and probability levels (for risk/threat forms and exports)
    impactLevels: {
      1: 'Négligeable',
      2: 'Mineur',
      3: 'Modéré',
      4: 'Majeur',
      5: 'Grave'
    },
    probabilityLevels: {
      1: 'Très improbable',
      2: 'Improbable',
      3: 'Possible',
      4: 'Probable',
      5: 'Très probable'
    },

    // PDF Report
    pdfReportLabels: {
      // Cover page
      coverTitle: 'Rapport SMSI',
      coverSubtitle: 'Système de Management de la Sécurité de l\'Information',
      generatedOn: 'Rapport généré le',
      confidential: 'Document confidentiel',
      conformityISO: 'Conformité ISO27002',
      implementedControls: 'Contrôles implémentés',
      actionsInProgress: 'Actions en cours',
      criticalRisks: 'Risques critiques',

      // Table of contents
      tableOfContents: 'Table des matières',
      dashboardAndIndicators: 'Dashboard et indicateurs',

      // Dashboard
      dashboardTitle: 'Dashboard SMSI',
      conformity: 'Conformité',
      controls: 'Contrôles',
      actions: 'Actions',

      // Chart labels
      maturityISO: 'Maturité ISO27002',
      maturityNIS2: 'Maturité NIS2',
      riskDistribution: 'Répartition des risques',
      riskMatrix: 'Matrice des risques',
      maturityCMM: 'Maturité CMM',
      probability: 'Probabilité',
      impact: 'Impact',

      // Pagination
      pageOf: 'Page {{current}} sur {{total}}',
      page: 'Page {{current}}',

      // Section labels
      continued: '(suite)',
      elements: 'élément',
      elementsPlural: 'éléments',
      noData: 'Aucune donnée',

      // Modal
      sectionsTitle: 'Sections du rapport PDF',
      selectAtLeastOne: 'Sélectionnez au moins une section',
      pdfGeneratedSuccess: 'Rapport PDF généré avec succès',
      pdfExportDisabled: 'L\'export PDF est désactivé en mode démonstration.'
    },

    // Report sections (PDF + Excel)
    reportSections: {
      controls: 'Contrôles ISO27002',
      soa: 'Déclaration d\'applicabilité',
      nis2Controls: 'Contrôles NIS2',
      nis2Program: 'Budget Cybersécurité',
      nis2Socle: 'Socle de sécurité',
      actions: 'Plan d\'actions',
      risks: 'Risques SMSI',
      threats: 'Menaces',
      nonconformities: 'Non-conformités',
      audits: 'Audits',
      managementReviews: 'Revues de direction',
      docReview: 'Revue documentaire 27001',
      documents: 'Structure documentaire',
      stakeholders: 'Parties prenantes',
      kpis: 'KPI',
      criticalAssets: 'Actifs critiques',
      projectRisks: 'Risques projets'
    },

    // PDF table headers
    pdfTableHeaders: {
      hash: '#',
      num: 'Num',
      title: 'Titre',
      status: 'Statut',
      cmm: 'CMM',
      reference: 'Référence',
      applicable: 'Applicable',
      justification: 'Justification',
      function: 'Fonction',
      category: 'Catégorie',
      domain: 'Domaine',
      action: 'Action',
      phase: 'Phase',
      progression: 'Progression',
      link: 'Lien',
      dueDate: 'Échéance',
      owner: 'Responsable',
      risk: 'Risque',
      impact: 'Impact',
      prob: 'Prob.',
      score: 'Score',
      level: 'Niveau',
      treatment: 'Traitement',
      threat: 'Menace',
      type: 'Type',
      detectionDate: 'Date détection',
      date: 'Date',
      participants: 'Participants',
      decisions: 'Décisions',
      exigence: 'Exigence',
      tool: 'Outil / preuve',
      docLevel: 'Niveau',
      docType: 'Type',
      docTool: 'Outil',
      docLink: 'Lien',
      name: 'Nom',
      role: 'Rôle',
      contact: 'Contact',
      description: 'Description',
      beneficiary: 'Bénéficiaire',
      product: 'Produit',
      rto: 'RTO',
      rpo: 'RPO',
      availability: 'Disponibilité',
      project: 'Projet',
      recommendations: 'Recommandations',
      pillar: 'Pilier',
      element: 'Élément',
      subtitle: 'Sous-titre',
      auditor: 'Auditeur',
      scope: 'Périmètre',
      plannedDate: 'Date planifiée',
      yes: 'Oui',
      no: 'Non',
      noAction: 'Aucune action',
      noAsset: 'Aucun',
      pending: 'en attente',
      outOfPhase: 'Hors phase',
      priority: 'Priorité',
      detailedRecommendations: 'Recommandations détaillées',
      autoSyncNote: '* Risque synchronisé depuis l\'analyse',
      auditExecutionDate: 'Date d\'exécution',
      auditFindings: 'Constatations',
      auditRecommendations: 'Recommandations'
    },

    // SoA PDF export labels
    pdfSoa: {
      title: "Déclaration d'applicabilité (SoA)",
      subtitle: 'ISO 27001:2022 - Clause 6.1.3 - Annexe A',
      fullAuditVersion: 'DOCUMENT AUDIT COMPLET',
      publicVersion: 'VERSION PUBLIQUE',
      issueDate: "Date d'émission:",
      docRef: 'Référence document',
      scope: 'Périmètre',
      refStandard: 'Norme de référence',
      classification: 'Classification',
      confidential: 'Confidentiel',
      internal: 'Interne',
      execSummary: 'Synthèse exécutive',
      applicableControls: 'Contrôles applicables',
      implRate: "Taux d'implémentation",
      verifiedControls: 'Contrôles vérifiés',
      notApplicable: 'Non applicables',
      docQuality: 'Qualité de la documentation',
      withOwner: 'avec propriétaire',
      withEvidence: 'avec preuves',
      linkedToRisks: 'liés à des risques',
      reviewedLast6m: 'revus <6 mois',
      selectionSources: 'Sources de sélection',
      domainCoverage: 'Couverture par domaine ISO 27002:2022',
      domain: 'Domaine',
      total: 'Total',
      applicable: 'Applicables',
      implemented: 'Implémentés',
      verified: 'Vérifiés',
      progression: 'Progression',
      controlDetails: 'Détail des contrôles ISO 27002:2022',
      ref: 'Réf.',
      control: 'Contrôle',
      applic: 'Applic.',
      source: 'Source',
      state: 'État',
      owner: 'Propriétaire',
      evidence: 'Preuves',
      risks: 'Risques',
      justification: 'Justification',
      excluded: 'Exclu:',
      approvals: 'Approbations et signatures',
      ismsManager: 'Responsable SMSI',
      generalManagement: 'Direction Générale',
      securityOfficer: 'Responsable Sécurité',
      nameField: 'Nom: ________________________________',
      dateField: 'Date: ________________________________',
      signatureField: 'Signature:',
      versionHistory: 'Historique des versions',
      version: 'Version',
      date: 'Date',
      author: 'Auteur',
      changes: 'Modifications',
      currentVersionAuto: 'Version actuelle - Génération automatique',
      initialRevision: 'Révision initiale',
      footerRef: 'Référence:',
      footerGenerated: 'Document généré par Cyber-Assistant | Conforme ISO 27001:2022 Clause 6.1.3',
      footerConfidential: 'DOCUMENT CONFIDENTIEL - DIFFUSION RESTREINTE - USAGE AUDIT UNIQUEMENT'
    },

    // Doc Review PDF export labels
    pdfDocReview: {
      title: 'Revue documentaire SMSI',
      subtitle: 'ISO 27001:2022 - Clauses 4 à 10',
      generatedOn: 'Généré le',
      auditLabel: 'PACK AUDIT CERTIFICATION',
      conforming: 'Conformes',
      partial: 'Partiels',
      nonConforming: 'Non conformes',
      conformityRate: 'Taux de conformité',
      clause: 'Clause',
      requirement: 'Exigence',
      status: 'Statut',
      responsible: 'Responsable',
      justificationEvidence: 'Justification / Preuve',
      review: 'Revue',
      toEvaluate: 'À évaluer',
      evidence: 'Preuve:',
      document: 'Document',
      comments: 'commentaire(s)',
      lastReview: 'Dernière:',
      nextReview: 'Prochaine:',
      checklistTitle: 'Checklist Préparation Audit ISO 27001:2022',
      checklistSubtitle: "Points de contrôle pour l'auditeur externe",
      documented: 'Documenté',
      footerTitle: 'Pack Audit Certification ISO 27001:2022',
      footerRef: 'Référence:',
      footerGenerated: 'Document généré par Cyber-Assistant',
      footerConfidential: 'DOCUMENT CONFIDENTIEL - PRÉPARATION AUDIT',
      checkContext: "Contexte de l'organisation",
      checkContextItems: 'Enjeux internes/externes documentés|Parties intéressées identifiées|Domaine d\'application défini',
      checkLeadership: 'Leadership',
      checkLeadershipItems: 'Politique SSI signée et communiquée|Rôles et responsabilités attribués|Engagement de la direction documenté',
      checkPlanning: 'Planification',
      checkPlanningItems: "Processus d'appréciation des risques|Plan de traitement des risques|Déclaration d'applicabilité (SoA)|Objectifs SSI mesurables",
      checkSupport: 'Supports',
      checkSupportItems: 'Ressources allouées|Compétences documentées|Programme de sensibilisation|Plan de communication|Maîtrise documentaire',
      checkOperation: 'Fonctionnement',
      checkOperationItems: 'Processus opérationnels documentés|Appréciations des risques à jour|Traitement des risques en cours',
      checkPerformance: 'Évaluation de la performance',
      checkPerformanceItems: "Programme d'audit interne|Indicateurs de performance (KPI)|Revue de direction planifiée|Procès-verbaux de revue",
      checkImprovement: 'Amélioration',
      checkImprovementItems: "Processus d'amélioration continue|Gestion des non-conformités|Actions correctives tracées"
    },

    // Excel export headers
    excelHeaders: {
      // Controls
      controlNum: 'Num',
      controlTitle: 'Titre',
      controlDescription: 'Description',
      controlCapability: 'Capacité',
      controlStatus: 'Statut',
      controlLinkedActions: 'Actions liées',
      controlCmm: 'Niveau de maturité CMM',

      // NIS2 Controls
      nis2Function: 'Fonction',
      nis2Category: 'Catégorie',
      nis2Description: 'Description',
      nis2Status: 'Statut',
      nis2Cmm: 'Maturité (dérivée)',
      nis2Justification: 'Justification',

      // SOA
      soaReference: 'Référence',
      soaTitle: 'Titre',
      soaApplicability: 'Applicabilité',
      soaJustification: 'Justification',
      soaApplicable: 'Applicable',
      soaNonApplicable: 'Non applicable',

      // Doc Review
      docReference: 'Référence',
      docExigence: 'Exigence',
      docJustification: 'Justification',
      docTool: 'Outil / preuve',

      // Actions
      actionId: 'ID',
      actionTitle: 'Action',
      actionLink: 'Lien',
      actionAssets: 'Actifs critiques',
      actionPriority: 'Priorité',
      actionProgress: 'Avancement',
      actionDueDate: 'Échéance',
      actionOwner: 'Responsable',
      actionStatus: 'Statut',
      actionComments: 'Commentaires',

      // Risks
      riskId: 'ID',
      riskTitle: 'Risque',
      riskDescription: 'Description',
      riskImpact: 'Impact',
      riskProbability: 'Probabilité',
      riskScore: 'Score',
      riskLevel: 'Niveau',
      riskLinkedActions: 'Actions liées',
      riskAssets: 'Actifs critiques',
      riskTreatment: 'Traitement',
      riskOwner: 'Propriétaire',
      riskCodirDate: 'Date CODIR',
      riskComments: 'Commentaires',

      // Threats
      threatTitle: 'Titre',
      threatDescription: 'Description',
      threatImpact: 'Impact',
      threatProbability: 'Probabilité',
      threatScore: 'Score',
      threatLevel: 'Niveau',
      threatStatus: 'Statut',
      threatLinkedActions: 'Actions liées',
      threatAssets: 'Actifs critiques',

      // Non-conformities
      ncTitle: 'Titre',
      ncType: 'Type',
      ncStatus: 'Statut',
      ncDetectionDate: 'Date détection',
      ncOwner: 'Responsable',
      ncLinkedAudit: 'Audit lié',
      ncLinkedActions: 'Actions liées',
      ncAssets: 'Actifs critiques',
      ncOperations: 'Opérations',

      // Audits
      auditTitle: 'Titre',
      auditType: 'Type',
      auditScope: 'Périmètre',
      auditPlannedDate: 'Date planifiée',
      auditAuditor: 'Auditeur',
      auditStatus: 'Statut',
      auditLinkedActions: 'Actions liées',
      auditExecutionDate: 'Date d\'exécution',
      auditFindings: 'Constatations',
      auditRecommendations: 'Recommandations',

      // Reviews
      reviewDate: 'Date',
      reviewParticipants: 'Participants',
      reviewInputs: 'Entrées',
      reviewDecisions: 'Décisions',
      reviewComments: 'Commentaires',

      // Stakeholders
      stakeholderName: 'Nom',
      stakeholderRole: 'Rôle',
      stakeholderContact: 'Contact',
      stakeholderComments: 'Commentaires',

      // Documents
      documentLevel: 'Niveau',
      documentType: 'Type',
      documentTool: 'Outil',
      documentLink: 'Lien',

      // KPIs
      kpiTitle: 'Titre',
      kpiDescription: 'Description',
      kpiComment: 'Commentaire',
      kpiProgress: 'Progression',

      // NIS2 Program
      nis2Domain: 'Domaine',
      nis2Pillar: 'Pilier',
      nis2Urgency: 'Urgence',
      nis2Objective: 'Objectif',
      nis2Action: 'Action',
      nis2Type: 'Type',
      nis2Phase: 'Phase',
      nis2ProgramStatus: 'Statut',
      nis2Owner: 'Responsable',
      nis2Progression: 'Progression (%)',
      nis2Budget2026: 'Budget 2026',
      nis2Budget2027: 'Budget 2027',
      nis2Budget2028: 'Budget 2028',
      nis2BudgetTotal: 'Budget total',
      nis2BudgetCategory: 'Catégorie budget',

      // NIS2 Socle
      soclePillar: 'Pilier',
      socleTitle: 'Titre',
      socleSubtitle: 'Sous-titre',
      socleElement: 'Élément',
      socleOwner: 'Responsable',

      // Critical Assets
      assetPriority: 'Priorité',
      assetBeneficiary: 'Bénéficiaire',
      assetProduct: 'Produit',
      assetType: 'Type',
      assetImportance: 'Importance',
      assetRto: 'RTO',
      assetRpo: 'RPO',
      assetAvailability: 'Disponibilité',
      assetConfidentiality: 'Conf.',
      assetIntegrity: 'Intégrité',
      assetImpact: 'Impact',
      assetDacp: 'DACP sens.',
      assetMfa: 'Obligation MFA',

      // Project Risks
      projectName: 'Nom du projet',
      projectBeneficiary: 'Bénéficiaire',
      projectReportNum: 'Numéro du rapport',
      projectRevision: 'Nombre de révision',
      projectDescription: 'Description projet',
      projectAnalysisLink: 'Lien vers l\'analyse des risques',
      projectCompletionDate: 'Date de réalisation',
      projectStatus: 'Statut',

      // Common
      none: 'Aucune',
      noAsset: 'Aucun',
      na: 'N/A',
      continuousImprovement: 'Amélioration continue',
      projectPriority: 'Priorité'
    },

    // Export modal labels
    exportLabels: {
      exportExcelBtn: 'Exporter Excel',
      cancelBtn: 'Annuler',
      selectSections: 'Sélectionnez les sections à exporter. Chaque section sera un onglet Excel.',
      selectAll: 'Tout sélectionner',
      deselectAll: 'Tout désélectionner',
      selectAtLeastOne: 'Sélectionnez au moins une section.',
      exportNotSupported: 'Export Excel non supporté pour cette section',
      htmlExportDisabled: 'L\'export HTML est désactivé en mode démonstration.',
      pdfExportNis2Disabled: 'L\'export PDF est désactivé en mode démonstration.',
      printDisabledDemo: 'L\'impression est désactivée en mode démonstration.',
      preparingExport: 'Préparation de l\'export...',
      loadingDependencies: 'Chargement des dépendances...',
      preparingContent: 'Préparation du contenu...',
      capturingScreen: 'Capture de l\'écran...',
      creatingPdf: 'Création du PDF...',
      downloadingPdf: 'Téléchargement du PDF...',
      pdfSuccess: 'PDF généré avec succès!',
      htmlExportSuccess: 'Export HTML réussi!',
      nis2ModuleNotFound: 'Module NIS2 non trouvé',
      nis2NotFound: 'Module NIS2 introuvable.',
      popupBlocked: 'Popup bloqué',
      printError: 'Impression NIS2 impossible. Réessayez après avoir rechargé la page.',
      generation: 'Génération...',
      programNIS2: 'Budget Cybersécurité',
      exportedOn: 'Exporté le:',
      normReference: 'Cyber-Assistant - Norme ISO27001 & 27002:2022',
      htmlStandaloneExport: 'Export HTML autonome - Créé avec Cyber-Assistant',
      htmlNis2Content: 'Ce fichier contient tous les styles et données de la section Budget Cybersécurité',
      preparingPdf: 'Préparation du PDF...',
      pdfUnavailable: 'Génération PDF indisponible.'
    },

    // Default templates and reference data
    templates: {
      // NIS2 phases
      outOfPhase: 'Hors phase',

      // ISO 27001 document review chapters
      chapter4: '4 - Contexte de l\'organisation',
      chapter5: '5 - Leadership',
      chapter6: '6 - Planification',
      chapter7: '7 - Supports',
      chapter8: '8 - Fonctionnement',
      chapter9: '9 - Évaluation de la performance',
      chapter10: '10 - Amélioration',

      // Default socle pillar titles
      pillar1Title: 'Gouverner (GV)',
      pillar1Subtitle: 'Gouvernance et politique cyber',
      pillar2Title: 'Identifier (ID)',
      pillar2Subtitle: 'Actifs, risques et amélioration',
      pillar3Title: 'Protéger (PR)',
      pillar3Subtitle: 'Accès, données et infrastructure',
      pillar4Title: 'Détecter (DE)',
      pillar4Subtitle: 'Surveillance et analyse',
      pillar5Title: 'Répondre (RS)',
      pillar5Subtitle: 'Gestion et communication des incidents',
      pillar6Title: 'Rétablir (RC)',
      pillar6Subtitle: 'Reprise et communication de crise',
      defaultOwner: 'Chef de projet : à désigner',

      // Default NIS2 plan domains
      domainGovernance: 'Gouvernance & responsabilité',
      domainRiskMgmt: 'Gestion des risques (SMSI)',
      domainIncident: 'Gestion des incidents & notification',
      domainBcpDrp: 'Continuité d\'activité & gestion de crise (BCP/DRP)',
      domainSupplyChain: 'Sécurité de la chaîne d\'approvisionnement',
      domainDevSec: 'Sécurité dans l\'acquisition, le développement & la maintenance',
      domainTraceability: 'Traçabilité et auditabilité',
      domainVulnerability: 'Gestion des vulnérabilités',
      domainAwareness: 'Sensibilisation & formation',
      domainCryptography: 'Cryptographie',
      domainPhysical: 'Sécurité physique',
      domainAccessMgmt: 'Gestion des accès au SI',

      // Default NIS2 budget blocks
      budgetTotal: 'Budget total mise en conformité',
      budget2026: 'Budget 2026',
      budget2027: 'Budget 2027',
      budget2028: 'Budget 2028',
      budgetInfra: 'Budget Infrastructure',
      budgetSSI: 'Budget Cybersécurité',

      // Default NIS2 custom blocks
      budgetEngaged: 'Budget engagé',
      globalProgress: 'Progression globale',
      completedActions: 'Actions terminées',

      // NIS2 maturity labels
      maturityAssetMgmt: 'Gestion d\'actifs',
      maturityOpEnv: 'Environnement opérationnel',
      maturityGovernance: 'Gouvernance',
      maturityRiskEval: 'Évaluation des risques',
      maturityRiskStrategy: 'Stratégie de gestion des risques',
      maturitySupplyChain: 'Gestion des risques liés à la chaîne d\'approvisionnement',
      maturityIAM: 'Gestion des identités, authentification, contrôle d\'accès',
      maturityAwareness: 'Sensibilisation et formation',
      maturityDataSec: 'Sécurité des données',
      maturityInfoProtection: 'Processus et procédures de protection de l\'information',
      maturityMaintenance: 'Maintenance',
      maturityProtectionTech: 'Technologie de protection',
      maturityAnomalies: 'Anomalies et événements',
      maturityMonitoring: 'Surveillance continue',
      maturityDetection: 'Processus de détection',
      maturityResponsePlan: 'Planification de la réponse',
      maturityComms: 'Communications',
      maturityAnalysis: 'Analyse',
      maturityMitigation: 'Atténuation',
      maturityImprovements: 'Améliorations',
      maturityRecoveryPlan: 'Planification du rétablissement',
      domainAssetRisk: 'Actifs et évaluation des risques',
      domainDataInfra: 'Sécurité données et infrastructure'
    },


    // Setup wizard (non-demo first launch)
    setup: {
      langHint: 'Vous pourrez modifier ce choix dans les paramètres.',
      welcomeTitle: 'Bienvenue sur Cyber-Assistant',
      welcomeSubtitle: 'Votre outil de pilotage SMSI conforme ISO 27001:2022 et NIS2',
      featureCompliance: 'Pilotez votre conformité en un seul outil',
      featureDashboards: 'Tableaux de bord',
      featureDashboardsDesc: 'Suivez vos indicateurs et votre maturité',
      featureExports: 'Exports & rapports',
      featureExportsDesc: 'Générez PDF, Excel et JSON en un clic',
      importTitle: 'Importer des données',
      importSubtitle: 'Vous pouvez importer un fichier JSON exporté précédemment.',
      importYes: 'Importer un fichier JSON',
      importYesDesc: 'Restaurer des données depuis une sauvegarde',
      importNo: 'Commencer sans données',
      importNoDesc: 'Les 93 contrôles ISO 27002 seront pré-chargés',
      importHint: 'Vous pourrez importer ou exporter des données à tout moment via Paramètres.',
      importSuccess: 'Fichier importé avec succès',
      importError: 'Erreur : fichier JSON invalide ou format non reconnu.',
      frameworksTitle: 'Référentiels de sécurité',
      frameworksSubtitle: 'Choisissez les référentiels à activer',
      frameworksHint: 'Modifiable dans Paramètres > Référentiels',
      frameworksLocked: 'Obligatoire',
      frameworksControls: 'contrôles',
      btnPrevious: 'Précédent',
      btnNext: 'Suivant',
      btnStart: 'Démarrer'
    },

    // Risk Analysis Module
    riskAnalysis: {
      title: 'Analyse des risques de sécurité',
      subtitle: 'Réalisez une analyse de risques pragmatique alignée ISO 27005.',
      importAnalyse: 'Importer une analyse',
      perimeterRequired: 'Le périmètre est obligatoire.',
      newAnalysis: 'Nouvelle analyse',
      statusDraft: 'Brouillon',
      statusComplete: 'Terminée',
      noAnalyses: 'Aucune analyse de risques.',
      noAnalysesHint: 'Créez votre première analyse pour évaluer et piloter vos risques.',
      createFirst: 'Créer une analyse',
      confirmDelete: 'Supprimer cette analyse de risques ?',
      duplicated: 'Analyse dupliquée.',
      deleted: 'Analyse supprimée.',
      saved: 'Analyse sauvegardée.',
      listColumns: {
        title: 'Titre',
        created: 'Créée le',
        status: 'Statut',
        score: 'Score',
        light: 'Feu',
        actions: 'Actions'
      },
      moreActions: 'Plus d’actions',
      steps: {
        context: 'Contexte',
        cia: 'CIA',
        continuity: 'Continuité',
        architecture: 'Documentation',
        controls: 'Contrôles',
        risks: 'Risques',
        mesures: 'Mesures & Revue',
        results: 'Résultats',
        exportPdf: 'Export PDF',
        preview: 'Prévisualisation'
      },
      mesures: {
        subtitle: 'Définissez vos recommandations clefs et planifiez la prochaine revue.'
      },
      nav: {
        previous: 'Précédent',
        next: 'Suivant',
        finish: 'Terminer',
        backToList: 'Retour à la liste'
      },
      context: {
        titleField: 'Titre de l\'analyse',
        perimeter: 'Périmètre',
        perimeterHint: 'Décrivez le périmètre couvert par cette analyse.',
        description: 'Description',
        stakeholders: 'Parties prenantes',
        stakeholdersHint: 'Séparez par des virgules.',
        sourceFramework: 'Catalogue de risques',
        sourceFrameworkNone: '— Non précisé —',
        sourceFrameworkHint: 'Alimente les risques proposés à l\'étape Risques. « Catalogue intégré » = entrées fournies ; sinon la méthode est simplement citée dans le rapport.',
        analysisMethod: 'Méthode d\'analyse',
        analysisMethodHint: 'Présélectionne la matrice d\'impact correspondante ; le choix de matrice reste modifiable.',
        methodDefault: 'Approche pragmatique Cyber-Assistant',
        methodEbios: 'EBIOS RM (compatible ISO 27005)',
        methodNist: 'NIST SP 800-30',
        catalogBuiltin: 'Catalogue générique Cyber-Assistant',
        catalogIntegrated: 'catalogue intégré',
        catalogLegacy: 'cité dans le rapport',
        ebiosCouples: 'Couples source de risque × objectif visé (EBIOS RM, atelier 2)',
        ebiosCouplesHint: 'Sélection recommandée : 3 à 6 couples (guide ANSSI v1.5). Repris dans l\'aperçu et le rapport, sans effet sur la cotation.',
        ebiosCouplesShort: 'Sources de risque (EBIOS RM)',
        personalData: 'Données personnelles traitées',
        dataSensitivity: 'Sensibilité des données',
        sensitivityLow: 'Faible',
        sensitivityMedium: 'Moyenne',
        sensitivityHigh: 'Élevée',
        subtitle: 'Décrivez le contexte et le périmètre de l\'analyse.',
        perimeterPlaceholder: 'Ex: Application web de gestion des stocks, serveurs et bases de données.',
        descriptionPlaceholder: 'Ex: Analyse réalisée dans le cadre de la mise en conformité ISO 27001.'
      },
      identity: {
        sectionTitle: 'Identité du projet',
        encoder: 'Encodage de l\'analyse (Nom - Prénom)',
        validator: 'Validation de l\'analyse (Nom - Prénom)',
        controlBody: 'Nom de l\'organisme de contrôle',
        beneficiary: 'Nom du bénéficiaire/client',
        projectManager: 'Nom du chef de projet'
      },
      cia: {
        title: 'Classification CIA',
        subtitle: 'Évaluez les besoins en Confidentialité, Intégrité et Disponibilité.',
        confidentiality: 'Confidentialité',
        integrity: 'Intégrité',
        availability: 'Disponibilité',
        justification: 'Justification',
        justificationHint: 'Expliquez les choix de classification.',
        level1: 'Faible',
        level2: 'Moyen',
        level3: 'Élevé',
        level1Desc: 'Impact limité en cas de compromission.',
        level2Desc: 'Impact significatif sur l\'activité.',
        level3Desc: 'Impact critique, conséquences graves.'
      },
      gdpr: {
        title: 'RGPD — Protection des données',
        subtitle: 'Évaluez les implications en matière de protection des données personnelles.',
        personalData: 'Présence de données à caractère personnel',
        personalDataExplain: 'Toute information se rapportant à une personne physique identifiée ou identifiable (nom, email, adresse IP, n° de sécurité sociale, etc.) au sens de l\'article 4 du RGPD.',
        sensitiveData: 'Présence de données à caractère sensible',
        sensitiveDataExplain: 'Données révélant l\'origine raciale/ethnique, les opinions politiques, les convictions religieuses, l\'appartenance syndicale, les données génétiques/biométriques, les données de santé, la vie sexuelle (article 9 du RGPD). Leur traitement est interdit sauf exceptions.',
        processingRegistry: 'Registre des traitements réalisé pour ce projet ?',
        processingRegistryExplain: 'Le registre des activités de traitement (article 30 du RGPD) est obligatoire pour les organismes de plus de 250 salariés, ou en cas de traitement régulier de données sensibles.',
        registryYes: 'Oui',
        registryNo: 'Non',
        registryPlanned: 'Planifié'
      },
      continuity: {
        title: 'Continuité (RTO/RPO)',
        subtitle: 'Définissez les objectifs de reprise et de perte de données tolérée.',
        rtoLabel: 'RTO (heures)',
        rtoHint: '≤4h = très strict, 8h = strict, 24h = standard, 72h = souple',
        rpoLabel: 'RPO (heures)',
        rpoHint: '≤1h = très strict, 6h = strict, 24h = standard, 72h = souple',
        strict: 'Très strict',
        moderate: 'Strict',
        standard: 'Standard',
        relaxed: 'Souple',
        commentLabel: 'Commentaire continuité',
        commentPlaceholder: 'Justification des objectifs RTO/RPO, contraintes métier...'
      },
      architecture: {
        title: 'Documentation',
        subtitle: 'Documentation technique et gestion des identités.',
        techArchTitle: 'Architecture technique',
        hosting: 'Hébergement',
        hostingOnprem: 'On-premise',
        hostingCloud: 'Cloud',
        hostingHybrid: 'Hybride',
        internetExposed: 'Exposé sur Internet',
        iamTitle: 'Gestion des identités (IAM)',
        sso: 'SSO (Single Sign-On)',
        mfa: 'MFA (Authentification multi-facteurs)',
        adminSeparation: 'Séparation des comptes administrateurs',
        architectureDocTitle: 'Architecture',
        architectureDoc: 'Dossier d\'architecture complété'
      },
      controls: {
        title: 'Questionnaire Contrôles',
        subtitle: 'Évaluez la maturité de vos contrôles sur 8 domaines opérationnels.',
        implemented: 'Implémenté',
        partial: 'Partiel',
        planned: 'Planifié',
        toVerify: 'À vérifier',
        plannedAutoComment: '[Planifié] Implémentation prévue — justification : ',
        plannedBanner: '{count} contrôle(s) marqué(s) comme « Planifié » — Le score actuel est conditionnel à leur implémentation effective.',
        plannedBadge: 'dont planifié(s)',
        plannedControlsTitle: 'Contrôles planifiés (conditionnels)',
        plannedDisclaimer: 'Les scores de maturité ci-dessus intègrent {count} contrôle(s) marqué(s) comme « Planifié ». Le score final est conditionnel à leur implémentation effective. Une réévaluation est recommandée après leur mise en œuvre.',
        plannedAssumption: 'Attention : {count} contrôle(s) sont marqué(s) comme « Planifié ». Les scores de maturité intègrent ces contrôles de manière conditionnelle. Le niveau de risque réel dépendra de leur implémentation effective dans les délais prévus.',
        importAnalyse: 'Importer',
        exportAnalyseFile: 'Exporter .analyse',
        importAnalyseSuccess: 'Analyse importée avec succès.',
        importAnalyseError: 'Fichier .analyse invalide.',
        importAnalyseSummary: 'Résumé de l\'analyse à importer :',
        importConfirm: 'Importer cette analyse ?',
        importSource: 'Source',
        imported: 'importé',
        analyseExported: 'Fichier .analyse exporté.',
        no: 'Non',
        na: 'N/A',
        comment: 'Commentaire',
        answeredOf: 'sur',
        statusLabel: 'Statut',
        warningTitle: 'Attention — Contrôles planifiés',
        improvedWarning: 'Le résultat d\'analyse des risques repose sur le fait que les mesures et contrôles planifiés seront correctement implémentés — il sera indispensable de réaliser une analyse de risques préalablement au lancement en production du projet.',
        pdfControls: 'Mesures & Contrôles'
      },
      risks: {
        title: 'Risques',
        subtitle: 'Sélectionnez et évaluez les risques applicables.',
        selectFromCatalog: 'Sélectionnez les risques du catalogue',
        addCustom: 'Ajouter un risque personnalisé',
        customTitle: 'Risque personnalisé',
        customTitlePlaceholder: 'Nom du risque',
        deleteCustom: 'Supprimer ce risque',
        confirmDeleteCustom: 'Supprimer ce risque personnalisé ?',
        customScenario: 'Décrivez le scénario de risque',
        likelihood: 'Vraisemblance',
        impact: 'Impact',
        inherentScore: 'Score inhérent',
        residualScore: 'Score résiduel',
        treatment: 'Traitement',
        treatReduce: 'Réduire',
        treatAccept: 'Accepter',
        treatTransfer: 'Transférer',
        treatAvoid: 'Éviter',
        treatNa: 'Non applicable (exclu du scoring)',
        naJustification: 'Justification de non-applicabilité',
        naJustifPlaceholder: 'Pourquoi ce risque ne s\'applique pas (trace ISO 27001, imprimée au rapport)',
        naMissing: 'Justification manquante — exigée par ISO 27001 §6.1.3.d',
        notes: 'Notes',
        likelihoodLevels: {
          1: 'Inconnue',
          2: 'Très faible',
          3: 'Basse',
          4: 'Moyenne',
          5: 'Haute'
        },
        impactLevels: {
          1: 'Insignifiant',
          2: 'Mineur',
          3: 'Significatif',
          4: 'Grave',
          5: 'Critique'
        },
        owner: 'Propriétaire du risque',
        ownerPlaceholder: 'Nom du responsable'
      },
      results: {
        title: 'Résultats & Recommandations',
        subtitle: 'Synthèse automatique de votre analyse de risques.',
        globalLight: 'Feu global',
        globalScore: 'Score global',
        posture: 'Posture contrôles',
        keyPoints: 'Points clés',
        domainSynthesis: 'Synthèse par domaine',
        riskRegister: 'Registre des risques',
        recommendations: 'Recommandations',
        maturity: 'Maturité',
        computing: 'Calcul en cours...',
        noRisks: 'Aucun risque sélectionné.',
        scoreLabels: {
          1: 'Très bon',
          2: 'Bon',
          3: 'Acceptable',
          4: 'Préoccupant',
          5: 'Critique'
        },
        riskLevel: 'Niveau',
        tabSynthese: 'Synthèse',
        tabRisques: 'Risques',
        tabRecommandations: 'Recommandations',
        tabMesures: 'Mesures & Revue'
      },
      filters: {
        search: 'Rechercher...',
        status: 'Statut',
        statusAll: 'Tous les statuts',
        statusDraft: 'Brouillon',
        statusComplete: 'Terminée',
        sortDateDesc: 'Plus récente',
        sortDateAsc: 'Plus ancienne',
        sortTitle: 'Titre A-Z',
        sortScore: 'Score ↓'
      },
      reviewDate: {
        title: 'Prochaine revue',
        enable: 'Activer la date de prochaine revue',
        overdue: 'En retard',
        upcoming: 'Prochainement',
        column: 'Revue'
      },
      exportPdf: {
        title: 'Export PDF',
        subtitle: 'Générez le rapport d\'analyse de risques au format PDF.',
        generatePdf: 'Générer le PDF',
        generating: 'Génération en cours...',
        sections: 'Le rapport contiendra :',
        sectionList: {
          cover: 'Page de garde',
          executive: 'Résumé exécutif',
          context: 'Contexte & périmètre',
          cia: 'Classification CIA & RTO/RPO',
          architecture: 'Documentation',
          controls: 'Mesures & Contrôles',
          domains: 'Synthèse des domaines',
          risks: 'Registre des risques',
          recommendations: 'Recommandations',
          assumptions: 'Hypothèses & limites',
          spot: 'Analyse de sécurité',
          keyRecommendations: 'Mesures de mitigation prioritaires',
          methodology: 'Cadre méthodologique'
        },
        analyseTitle: 'Export .analyse',
        analyseDesc: 'Exporte l\'analyse complète au format JSON réimportable. Inclut la matrice d\'impacts et les seuils de risque liés.'
      },
      priority: { P1: 'P1 - Critique', P2: 'P2 - Important', P3: 'P3 - Recommandé' },
      effort: { S: 'Petit', M: 'Moyen', L: 'Grand' },
      light: { green: 'Vert', yellow: 'Jaune', red: 'Rouge' },
      domains: {
        IAM: 'Identité & Accès',
        SDLC: 'Développement Sécurisé',
        VULN: 'Vulnérabilités',
        LOG: 'Logs & Détection',
        DATA: 'Protection des Données',
        INFRA: 'Infrastructure',
        NETCRYPTO: 'Réseau & Crypto',
        BCP: 'Continuité'
      },
      spot: {
        title: 'Résultats de l\'évaluation (Sécurité)',
        inherentCriticality: 'Criticité de l\'actif (risque inhérent)',
        measuresPercent: 'Niveau d\'implémentation des mesures',
        residualScore: 'Niveau de risque résiduel',
        residualPlusOpen: 'Risque résiduel + risque ouvert',
        inherentCriticalityHint: 'Évalue le niveau d\'exposition intrinsèque de l\'actif, basé sur la classification CIA, l\'exposition Internet et la sensibilité des données.',
        measuresPercentHint: 'Pourcentage moyen d\'implémentation des contrôles de sécurité sur l\'ensemble des 8 domaines évalués.',
        residualScoreHint: 'Niveau de risque après application des mesures de sécurité. Basé sur le pire score résiduel parmi les risques identifiés.',
        residualPlusOpenHint: 'Score résiduel augmenté des risques ouverts non encore traités (vulnérabilités connues, actions en attente).',
        openRiskAdj: 'Ajustement risque ouvert',
        openRiskHint: 'Ajoutez un point si des risques connus ne sont pas encore traités (ex : vulnérabilités identifiées, actions en attente). Cela augmente le score résiduel final.',
        openRiskNone: '0 - Aucun risque ouvert',
        openRiskModerate: '1 - Quelques risques ouverts',
        openRiskSignificant: '2 - Risques ouverts importants',
        avisCommentLabel: 'Commentaire de l\'évaluateur',
        avisCommentHint: 'Ajoutez ici vos observations ou nuances sur le résultat de l\'évaluation (ex : contexte particulier, points d\'attention).',
        avisOverrideLabel: 'Correction manuelle de l\'avis',
        avisOverrideHint: 'Si l\'avis calculé automatiquement ne reflète pas la réalité (ex : facteurs externes à l\'analyse), vous pouvez le forcer manuellement. Laissez « — » pour conserver le calcul automatique.',
        avisOverrideActive: 'L\'avis automatique était : ',
        avisOverrideJustifLabel: 'Justification de la correction de l\'avis',
        avisOverrideJustifHint: 'Expliquez pourquoi vous corrigez l\'avis calculé (obligatoire si une correction est appliquée).',
        residualOverrideLabel: 'Correction manuelle du score résiduel',
        residualOverrideHint: 'Si le score résiduel calculé automatiquement ne reflète pas la réalité, vous pouvez le remplacer manuellement. Laissez « — » pour conserver le calcul automatique.',
        residualOverrideAuto: 'calcul automatique',
        residualOverrideJustifLabel: 'Justification de la correction',
        residualOverrideJustifHint: 'Expliquez pourquoi vous corrigez le score calculé (obligatoire si une correction est appliquée).',
        residualCorrectedLabel: 'Commentaire sur le risque résiduel',
        residualCorrectedHint: 'Commentaire libre sur le niveau de risque résiduel après prise en compte des mesures de sécurité.',
        avisLabels: {
          green: 'Avis favorable',
          yellow: 'Avis favorable moyennant la mise en œuvre des recommandations clefs',
          red: 'Avis défavorable'
        }
      },
      finalRecs: {
        title: 'Recommandations clefs',
        mitigationTitle: 'Mesures de mitigation prioritaires',
        mitigationSubtitle: 'Actions prioritaires identifiées pour réduire le niveau de risque',
        add: 'Ajouter une recommandation clef',
        titlePlaceholder: 'Titre de la recommandation',
        detailsPlaceholder: 'Détails, actions, contexte...',
        statusTodo: 'À faire',
        statusDone: 'Fait'
      },
      preview: {
        reportTitle: 'Analyse des risques en sécurité de l\'information - Cybersécurité',
        reportNumber: 'Numéro du rapport',
        reportDate: 'Date du rapport',
        treatmentDistribution: 'Répartition des traitements',
        riskLevel: 'Niveau de risque',
        riskMatrix: 'Matrice de risque',
        infoText: 'Prévisualisation du rapport. Vérifiez les informations avant l\'export PDF.',
        toc: 'Sommaire',
        assumptions: 'Hypothèses'
      },
      impactMatrix: {
        selectMatrix: 'Matrice d\'impact',
        selectHint: 'Choisissez une matrice pour évaluer l\'impact de chaque risque selon plusieurs dimensions (ex : financier, réputation, juridique…). Si aucune n\'est sélectionnée, l\'impact sera évalué sur une simple échelle de 1 à 5.',
        noMatrix: 'Aucune (évaluation manuelle 1-5)',
        evaluateVia: 'Évaluer via matrice',
        evaluateHint: 'Utilisez la matrice d\'impact pour évaluer ce risque selon plusieurs dimensions',
        modalTitle: 'Évaluation d\'impact',
        modalHint: 'Pour chaque dimension, sélectionnez le niveau d\'impact qui correspond le mieux à ce risque. Le texte descriptif vous aide à choisir le bon niveau. L\'impact global est calculé automatiquement (maximum des niveaux sélectionnés).',
        computedImpact: 'Impact global',
        computedMethod: 'Méthode de calcul',
        aggregationMax: 'le niveau maximum parmi les dimensions évaluées',
        apply: 'Appliquer',
        cancel: 'Annuler',
        evaluated: 'dim. évaluée(s)',
        matrixNotFound: 'Matrice introuvable',
        matrixUsed: 'Matrice d\'impact utilisée',
        configureHint: 'Vous pouvez configurer des matrices d\'impacts dans la section dédiée « Matrices d\'impacts » pour évaluer les risques selon plusieurs dimensions.'
      },
      pdfTitle: 'Analyse des risques en sécurité de l\'information',
      pdfSubject: 'Rapport d\'analyse de risques',
      pdfUntitled: 'Sans titre',
      pdfReport: 'Rapport',
      pdfDate: 'Date',
      pdfStatus: 'Statut',
      pdfComplete: 'Terminée',
      pdfDraft: 'Brouillon',
      pdfGlobalScore: 'Score global',
      pdfControlPosture: 'Posture contrôles',
      pdfRiskCount: 'Risques identifiés',
      pdfConfidential: 'Document confidentiel',
      pdfGeneratedBy: 'Généré par Cyber-Assistant',
      pdfTOC: 'Table des matières',
      pdfSecurityResults: 'Résultats de l\'évaluation (Sécurité)',
      pdfInherentCriticality: 'Criticité de l\'actif (risque inhérent)',
      pdfMeasuresImpl: 'Niveau d\'implémentation des mesures',
      pdfResidualLevel: 'Niveau de risque résiduel',
      pdfResidualPlusOpen: 'Risque résiduel + risque ouvert',
      pdfSecurityComment: 'Commentaire avis Sécurité',
      pdfResidualComment: 'Commentaire résiduel corrigé',
      pdfExecSummary: 'Résumé exécutif',
      pdfGlobalLight: 'Feu global',
      pdfContext: 'Contexte & Périmètre',
      pdfPerimeter: 'Périmètre',
      pdfDescription: 'Description',
      pdfStakeholders: 'Parties prenantes',
      pdfSourceFramework: 'Référentiel source',
      pdfPersonalData: 'Données personnelles',
      pdfSensitivity: 'Sensibilité',
      pdfImpactMatrix: 'Matrice d\'impact',
      pdfCIA: 'Classification CIA & Continuité',
      pdfConfidentiality: 'Confidentialité',
      pdfIntegrity: 'Intégrité',
      pdfAvailability: 'Disponibilité',
      pdfJustification: 'Justification',
      pdfArchitecture: 'Documentation',
      pdfHosting: 'Hébergement',
      pdfInternetExposed: 'Exposé Internet',
      pdfAdminSep: 'Séparation admin',
      pdfDomainSynthesis: 'Synthèse des domaines',
      pdfDomain: 'Domaine',
      pdfMaturity: 'Maturité',
      pdfLight: 'Feu',
      pdfRiskRegister: 'Registre des risques',
      pdfRisk: 'Risque',
      pdfThreat: 'Menace',
      pdfScenario: 'Scénario',
      pdfMethodTitle: 'Méthode de cotation',
      pdfMethodInherent: 'Risque inhérent = vraisemblance (1-5) × impact (1-5), soit 1 à 25.',
      pdfMethodResidual: 'Risque résiduel = inhérent réduit jusqu\'à 40 % selon la maturité moyenne des domaines de contrôle liés au risque, puis majoré (+1) par : exposition Internet (événements adverses uniquement), classification C/I/D élevée, RTO ≤ 8 h ou RPO ≤ 6 h.',
      pdfMethodNa: 'Les risques marqués « non applicable » restent listés avec leur justification mais sont exclus des scores et du feu global ; un domaine de contrôle entièrement N/A est exclu des moyennes.',
      pdfMethodThresholds: 'Les niveaux (feux) proviennent de l\'échelle de risque active, consultable et modifiable dans « Seuils de risque » du module Analyse des risques.',
      pdfInherent: 'Inh.',
      pdfResidual: 'Rés.',
      pdfTreatment: 'Traitement',
      pdfImpactDetail: 'Détail évaluation impact',
      pdfMatrix: 'matrice',
      pdfKeyRecs: 'Recommandations clefs',
      pdfDone: 'Fait',
      pdfTodo: 'À faire',
      pdfRecTitle: 'Titre',
      pdfRecDetails: 'Détails',
      pdfRecStatus: 'Statut',
      pdfRecommendations: 'Recommandations',
      pdfPriority: 'Priorité',
      pdfRecommendation: 'Recommandation',
      pdfEffort: 'Effort',
      pdfRationale: 'Justification',
      pdfAssumptions: 'Hypothèses & limites',
      pdfAssumptionsText1: 'Cette analyse reflète la posture à la date de réalisation. Les scores sont indicatifs et ne remplacent pas un audit formel.',
      pdfAssumptionsText2: 'Les recommandations sont générées automatiquement sur la base des réponses fournies.',
      pdfEncoder: 'Encodage',
      pdfValidator: 'Validation',
      pdfControlBody: 'Organisme de contrôle',
      pdfBeneficiary: 'Bénéficiaire/Client',
      pdfProjectManager: 'Chef de projet',
      pdfArchitectureDoc: 'Dossier d\'architecture',
      pdfGenerated: 'PDF généré',
      syncToProject: 'Sync vers Risques projets',
      syncSuccess: 'Risque projet créé avec succès.',
      syncAlreadySynced: 'Risque projet mis à jour.',
      syncDuplicateTitle: 'Doublon détecté',
      syncDuplicateMsg: 'Un risque projet avec le même nom existe déjà. Que souhaitez-vous faire ?',
      syncOptionNew: 'Créer nouveau',
      syncOptionOverwrite: 'Écraser existant',
      syncOptionCancel: 'Annuler',
      thresholds: {
        title: 'Seuils de risque',
        subtitle: 'Matrice Probabilité × Gravité avec niveaux de risque',
        new: 'Nouveau',
        newName: 'Nouveau seuil',
        duplicate: 'Dupliquer',
        delete: 'Supprimer',
        activate: 'Activer',
        active: 'Actif',
        editName: 'Nom',
        editDescription: 'Description',
        riskLevels: 'Niveaux de risque',
        matrix: 'Matrice Probabilité × Gravité',
        matrixTitle: 'Matrice de risque',
        probability: 'Probabilité',
        gravity: 'Gravité',
        clickToChange: 'Cliquez sur une cellule pour changer son niveau',
        confirmDelete: 'Supprimer ce seuil de risque ?',
        levels: {
          minimum: 'Minimum',
          faible: 'Faible',
          modere: 'Modéré',
          eleve: 'Élevé',
          tresEleve: 'Très élevé'
        }
      },
      methodology: {
        title: 'Cadre méthodologique',
        objective: 'Objectif',
        objectiveText: 'Cette analyse vise à identifier, évaluer et traiter les risques de sécurité de l\'information en s\'alignant sur les lignes directrices d\'ISO/IEC 27005:2022.',
        normativeRef: 'Référence normative',
        normativeRefText: 'ISO/IEC 27005:2022 — Technologies de l\'information — Gestion des risques liés à la sécurité de l\'information. Cette norme fournit les lignes directrices pour le processus de gestion des risques de sécurité de l\'information dans le cadre d\'un SMSI (ISO/IEC 27001).',
        processTitle: 'Processus d\'analyse en 8 étapes',
        step1: 'Contexte & périmètre — Définition du périmètre, des parties prenantes et des critères d\'évaluation',
        step2: 'Classification CIA & RGPD — Évaluation de la confidentialité, intégrité, disponibilité et impact RGPD',
        step3: 'Continuité d\'activité — Objectifs RTO/RPO et contraintes métier',
        step4: 'Documentation — Architecture technique, gestion des identités, documentation',
        step5: 'Mesures & Contrôles — Évaluation de 24 mesures de sécurité sur 8 domaines',
        step6: 'Identification des risques — Sélection et évaluation des scénarios de risque',
        step7: 'Résultats & évaluation — Synthèse automatisée, scoring, recommandations',
        step8: 'Traitement du risque — Décisions de traitement (réduire, accepter, transférer, éviter)',
        scoringTitle: 'Formule de scoring',
        scoringFormula: 'Risque résiduel = Vraisemblance × Impact × (1 − Maturité contrôles × 0.40)',
        scoringAdjust: 'Ajustements contextuels : +1 si exposition Internet, +1 si CIA élevé, +1 si RTO/RPO strict.',
        scaleTitle: 'Échelle des risques',
        pdcaTitle: 'Cycle PDCA',
        pdcaPlan: 'Établir le contexte, identifier les risques',
        pdcaDo: 'Implémenter les mesures de traitement',
        pdcaCheck: 'Surveiller, contrôler, réévaluer',
        pdcaAct: 'Améliorer, mettre à jour l\'analyse'
      }
    },

    // Impact Matrices
    impactMatrices: {
      title: 'Matrices d\'impacts',
      subtitle: 'Définissez et personnalisez vos matrices d\'impact pour l\'analyse de risques.',
      listTitle: 'Matrices',
      newMatrix: 'Nouvelle',
      newMatrixName: 'Nouvelle matrice',
      active: 'Active',
      activate: 'Activer',
      duplicate: 'Dupliquer',
      delete: 'Supprimer',
      copy: 'copie',
      selectOrCreate: 'Sélectionnez ou créez une matrice',
      generalInfo: 'Informations générales',
      matrixName: 'Nom',
      matrixDescription: 'Description',
      levelsTitle: 'Niveaux de gravité',
      addLevel: 'Ajouter',
      levelLabel: 'Libellé',
      levelBand: 'Bande',
      levelPriority: 'Priorité',
      levelCapability: 'Capacité de réponse',
      newLevelLabel: 'Niveau',
      maxLevels: 'Maximum 5 niveaux (aligné sur l’échelle de cotation des risques 1-5).',
      dimensionsTitle: 'Dimensions',
      addDimension: 'Ajouter',
      newDimensionLabel: 'Dimension',
      gridTitle: 'Grille d\'impacts',
      cardLevels: 'niveaux',
      cardDimensions: 'dimensions',
      dimension: 'Dimension',
      aggregationTitle: 'Méthode d\'agrégation',
      aggregationMethod: 'Calcul de l\'impact global',
      aggregationNotes: 'Notes',
      confirmDelete: 'Supprimer cette matrice ?',
      toastCreated: 'Matrice créée',
      toastDuplicated: 'Matrice dupliquée',
      toastDeleted: 'Matrice supprimée',
      toastActivated: 'Matrice activée',
      toastCannotDeleteLast: 'Impossible de supprimer la dernière matrice'
    },

    audit: {
      title: 'Traçabilité des modifications',
      localUser: 'Utilisateur local',
      actionAdd: 'Ajout',
      actionEdit: 'Modification',
      actionDelete: 'Suppression',
      actionImport: 'Import',
      actionExport: 'Export',
      actionConfig: 'Configuration',
      columnDate: 'Date / Heure',
      columnUser: 'Utilisateur',
      columnAction: 'Action',
      columnCategory: 'Catégorie',
      columnTarget: 'Élément',
      columnDetails: 'Détails',
      emptyState: 'Aucune action enregistrée',
      clearHistory: 'Vider l\'historique',
      clearConfirm: 'Supprimer tout l\'historique de traçabilité ?',
      activityTitle: 'Activité récente',
      noActivity: 'Aucune activité récente',
      catControls: 'Contrôles',
      catActions: 'Actions',
      catRisks: 'Risques',
      catAudits: 'Audits',
      catNc: 'Non-conformités',
      catReviews: 'Revues',
      catKpis: 'KPI',
      catDocuments: 'Documents',
      catStakeholders: 'Parties prenantes',
      catThreats: 'Menaces',
      catRiskAnalysis: 'Analyse risques',
      catProjectRisks: 'Risques projets',
      catCriticalAssets: 'Actifs critiques',
      catImpactMatrices: 'Matrices',
      catNis2: 'NIS2',
      catSoa: 'SOA',
      catSettings: 'Paramètres',
      catSystem: 'Système',
      filterAll: 'Toutes',
      clearTitle: 'Effacer le journal',
      importFile: 'Import fichier',
      logoRemoved: 'Logo supprimé',
      logoUploaded: 'Logo uploadé',
      passwordChanged: 'Mot de passe modifié'
    },

    // Wizard
    wizard: {
      serverCheck: 'Vérification du serveur',
      serverCheckSub: 'Vérification de la disponibilité des services',
      serverReady: 'Serveur prêt',
      serverError: 'Problème détecté',
      checkSync: 'Point d\'accès synchronisation',
      checkUsers: 'Point d\'accès utilisateurs',
      checkSysInfo: 'Informations système',
      checkLicense: 'État de la licence',
      checkServer: 'Configuration serveur',
      recheck: 'Re-vérifier',
      noWriteAccess: 'Pas d\'accès écriture',
      lowDiskSpace: 'Espace disque insuffisant',
      sysInfoUnavailable: 'Info système indisponible',
      freeSpace: 'libre',
      // Runtime detection
      checkRuntime: 'Environnement d\'exécution',
      runtimeNode: 'Node.js',
      runtimePHP: 'Apache/PHP',
      runtimeDetected: 'Détecté : {runtime}',
      // Network security slide
      networkSecTitle: 'Sécurité réseau',
      networkSecSub: 'Information importante',
      networkSecWarning: 'Cette application est conçue pour un usage en réseau local (LAN/intranet) uniquement.',
      networkSecExplain: 'Cyber-Assistant intègre une authentification et des contrôles d\'accès, mais n\'est pas conçu pour être exposé sur Internet. Si l\'application est hébergée sur un réseau local, il est essentiel de restreindre les accès au niveau du réseau (pare-feu, VLAN, VPN) car elle ne dispose pas de protections suffisantes contre les attaques depuis Internet.',
      networkSecRecTitle: 'Précautions recommandées :',
      networkSecRec1: 'Déployer derrière un pare-feu d\'entreprise ou un VPN',
      networkSecRec2: 'Restreindre l\'accès au réseau interne uniquement',
      networkSecRec3: 'Utiliser HTTPS avec un certificat TLS valide',
      networkSecRec4: 'Ne jamais exposer l\'application sur Internet',
      networkSecRec5: 'Mettre à jour régulièrement l\'environnement serveur',
      networkSecRec6: 'Limiter l\'accès à l\'application aux seuls utilisateurs autorisés',
      networkSecRec7: 'Ne pas laisser l\'application en libre accès sur le réseau sans authentification',
      networkSecAck: 'Je m\'engage à restreindre l\'accès à cette application aux seuls utilisateurs autorisés et à ne pas l\'exposer en libre accès sur le réseau',
      adminSetup: 'Compte administrateur',
      trialExplain: 'Essai gratuit de 14 jours pour tester le mode serveur.',
      trialExpiry: 'Les modifications seront bloquées après l\'expiration.',
      // Local password step
      localPwdTitle: 'Protection par mot de passe',
      localPwdSub: 'Optionnel mais recommandé',
      localPwdExplain: 'Définissez un mot de passe pour protéger l\'accès au mode édition. Ce mot de passe empêche les modifications accidentelles de vos données.',
      localPwdLabel: 'Mot de passe',
      localPwdPlaceholder: 'Minimum 18 caractères',
      localPwdConfirmLabel: 'Confirmer le mot de passe',
      localPwdConfirmPlaceholder: 'Répétez le mot de passe',
      localPwdHint: 'Vous pouvez sauter cette étape et configurer un mot de passe plus tard dans les Paramètres.',
      localPwdWeak: 'Le mot de passe ne respecte pas les critères requis.',
      localPwdMismatch: 'Les mots de passe ne correspondent pas.',
      // Transversality slide
      transTitle: 'Transversalité des référentiels',
      transSub: 'Un effort, de multiples conformités',
      transTimeSave: 'Gain de temps',
      transTimeSaveDesc: 'Documentez une mesure ISO 27002 : elle couvre automatiquement les exigences NIS2, CyFun et NIST CSF correspondantes.',
      transConsistency: 'Cohérence garantie',
      transConsistencyDesc: 'Les mappings automatiques entre référentiels assurent une cohérence de bout en bout, sans ressaisie ni oubli.',
      transVisibility: 'Visibilité unifiée',
      transVisibilityDesc: 'Un tableau de bord unique reflète votre conformité sur l\'ensemble des référentiels activés.',
      // Server promo slide (local only)
      serverPromoTitle: 'Version Serveur disponible',
      serverPromoSub: 'Collaborez en équipe sur votre SMSI',
      serverPromoCoEdit: 'Co-édition en temps réel',
      serverPromoCoEditDesc: 'Travaillez à plusieurs simultanément sur le même SMSI avec un système de verrouillage intelligent.',
      serverPromoUsers: 'Gestion des utilisateurs',
      serverPromoUsersDesc: 'Rôles administrateur et éditeur, jusqu\'à 100 utilisateurs avec authentification sécurisée.',
      serverPromoSync: 'Synchronisation automatique',
      serverPromoSyncDesc: 'Données centralisées sur le serveur, accessibles depuis n\'importe quel poste connecté.',
      serverPromoLink: 'En savoir plus sur cyber-assistant.com',
      // NIS2 assurance level step
      nis2LevelTitle: 'Niveau d\'assurance NIS2',
      nis2LevelSub: 'Définissez le niveau CyFun correspondant à votre organisation',
      nis2LevelAdviceLabel: 'Conseil :',
      nis2LevelAdvice: 'Avant de choisir, nous vous recommandons d\'utiliser l\'outil d\'auto-identification du',
      nis2LevelAdvice2: 'pour déterminer votre niveau d\'assurance NIS2.',
      nis2LevelAdvice3: 'Ce choix définit le nombre d\'exigences à évaluer et les seuils de conformité.',
      nis2LevelSelect: 'Sélectionnez le niveau d\'assurance NIS2 correspondant à votre organisation :',
      nis2Requirements: 'exigences',
      nis2KeyMeasures: 'mesures clés',
      nis2LevelBasicDesc: 'Pour les organisations qui débutent leur démarche NIS2. Seuil de conformité : 2.5/5.',
      nis2LevelImportantDesc: 'Pour les entités importantes au sens NIS2. Seuil de conformité : 3/5.',
      nis2LevelEssentialDesc: 'Pour les entités essentielles au sens NIS2. Seuil de conformité : 3.5/5 + minimum par catégorie.',
      nis2Lang: 'Langue des contrôles :',
      nis2LangHint: 'La langue des titres et descriptions des exigences NIS2.',
      // ReCyF / référentiel NIS2 (étape combinée)
      nis2SetupTitle: 'Référentiel NIS2',
      nis2SetupSub: 'Choisissez le référentiel et le niveau adaptés à votre organisation',
      nis2RefSelect: 'Quel référentiel NIS2 souhaitez-vous utiliser ?',
      nis2RefBEDesc: 'Cadre belge (CCB) basé sur NIST CSF 2.0. Niveaux Basic / Important / Essential, évaluation par maturité.',
      nis2RefFRDesc: 'Référentiel Cyber France (ANSSI). 20 objectifs de sécurité, degrés Entité Importante / Essentielle, moyens acceptables de conformité.',
      recyfAdvice: 'Le degré dépend de la qualification de votre entité au titre de NIS2 : Entité Importante (EI) ou Entité Essentielle (EE).',
      recyfObj115: 'objectifs 1 à 15',
      recyfObj120: 'objectifs 1 à 20',
      recyfDegreeSelect: 'Sélectionnez le degré de votre entité (ReCyF) :',
      recyfEIDesc: 'Pour les entités importantes au sens NIS2.',
      recyfEEDesc: 'Pour les entités essentielles (dont approche par les risques, audit, supervision).',
      // Server capabilities slide (server only)
      serverCapTitle: 'Fonctionnalités serveur',
      serverCapSub: 'Cette version serveur vous permet\u2026',
      serverCapCoEdit: 'Co-édition',
      serverCapCoEditDesc: 'Travaillez à plusieurs simultanément avec un verrouillage automatique par section.',
      serverCapUsers: 'Gestion des utilisateurs',
      serverCapUsersDesc: 'Rôles admin et éditeur, jusqu\'à 100 utilisateurs avec sessions sécurisées.',
      serverCapSync: 'Synchronisation',
      serverCapSyncDesc: 'Données centralisées et synchronisées automatiquement entre tous les postes.',
      serverCapLock: 'Verrouillage',
      serverCapLockDesc: 'Système de heartbeat empêchant les conflits d\'édition entre collaborateurs.',
      // === CSI-MCP === capacités serveur ajoutées + slide vitrine éditions locales
      serverCapEntities: 'Multi-entités',
      serverCapEntitiesDesc: 'Pilotez jusqu\'à 50 entités : tableau de bord consolidé pour le groupe, cloisonnement strict par site.',
      serverCapMcp: 'Accès IA (MCP)',
      serverCapMcpDesc: 'Connectez votre assistant IA à votre SMSI via le standard MCP — en lecture seule et sous votre contrôle. Idéalement une IA hébergée chez vous ou souveraine.',
      mcpSlideTitle: 'Allez plus loin avec l\'édition Serveur',
      mcpSlideSubtitle: 'Deux capacités qui changent la donne',
      mcpSlideHead: 'Votre SMSI, interrogeable par votre IA',
      mcpSlideBody: 'L\'édition Serveur expose une interface <strong>MCP</strong> standard : votre assistant IA répond directement sur vos données de conformité, en lecture seule, avec un accès nominatif et révocable. Compatible avec les assistants du marché comme avec une IA hébergée sur votre infrastructure.',
      mcpSlideEntHead: 'Pilotez plusieurs entités',
      mcpSlideEntBody: 'Jusqu\'à 50 entités dans une seule installation : vision consolidée pour le groupe, isolation stricte par site, import/export par entité.',
      mcpSlideAvail: 'Disponible en édition Serveur.',
      mcpSlideServerOk: 'Votre édition Serveur inclut le multi-entités et l\'accès IA (MCP).',
      multiEntTitle: 'Multi-entités',
      multiEntSub: 'Un SMSI, plusieurs périmètres cloisonnés',
      multiEntIsolation: 'Cloisonnement',
      multiEntIsolationDesc: 'Plusieurs entités ou sites dans une seule installation — les données de chaque périmètre (risques, actions, contrôles…) sont strictement séparées.',
      multiEntAccounts: 'Comptes rattachés',
      multiEntAccountsDesc: 'Chaque compte rattaché ne voit que son périmètre, avec des droits par section (lecture / écriture). Multi-appartenance possible.',
      multiEntGroup: 'Vue groupe consolidée',
      multiEntGroupDesc: 'Dashboard « Toutes les entités » et sections consolidées en lecture seule, avec badges, pastilles d’entités et ouverture du périmètre source pour éditer.',
      multiEntTransfer: 'Répartition maîtrisée',
      multiEntTransferDesc: 'Assistant de déplacement entre périmètres, exports nommés par entité et garde-fou anti-import croisé.',
      multiEntAvailServer: 'Fonction activable dans Réglages > Multi-entités (option de licence multi-entités).',
      multiEntAvailLocal: 'Disponible en mode serveur (option de licence).',
      // Wizard status labels
      alreadyConfigured: 'Le serveur est déjà configuré.',
      configured: 'Configuré',
      firstSetup: 'Premier démarrage',
      loginHint: 'Connectez-vous après le wizard pour accéder au mode édition.',
      serverUnavailable: 'Serveur indisponible',
      syncMissing: 'Non déployé',
      trialBadge: 'Essai gratuit — {days} jours restants sur 14',
      usersMissing: 'Non déployé',
      // FIX-I18N-WIZARD (audit 2026-06-10, bundle.js:2713) : clés déplacées depuis
      // snapshots.* où elles étaient rangées par erreur (jamais résolues par t())
      disclaimerTitle: 'Référentiels de sécurité',
      disclaimerSubtitle: 'Information importante',
      disclaimerInfoTitle: 'Référentiels ouverts',
      disclaimerInfoBody: 'Cette édition utilise les référentiels ouverts « Open Security Controls » et « Open Security Management Framework », reformulations originales inspirées des objectifs de sécurité des normes ISO/IEC 27002:2022 et ISO/IEC 27001:2022.',
      disclaimerWarningTitle: 'Avertissement',
      disclaimerWarningBody: 'Ces référentiels ne sont pas des normes ISO officielles et ne se substituent pas à l\'acquisition des documents originaux auprès de l\'ISO. Pour une conformité certifiable, veuillez vous procurer les normes officielles sur iso.org.',
      corporateUpsellSlideTitle: 'Édition Corporate',
      corporateUpsellSlideSubtitle: 'Allez plus loin',
      corporateUpsellTitle: 'Envie d\'aller plus loin ?',
      corporateUpsellBody: 'La <strong>version Corporate</strong> intègre les normes <strong>ISO/IEC 27001:2022</strong> et <strong>ISO/IEC 27002:2022</strong> officielles — idéale si vous visez une certification ou un audit formel.',
      corporateFeatureCollab: 'Co-édition multi-collaborateurs en temps réel',
      corporateFeatureServer: 'Mode serveur centralisé avec synchronisation',
      corporateFeatureISO: 'Normes ISO/IEC 27001 & 27002 officielles intégrées',
      corporateFeatureLang: 'Anglais natif avancé (traductions professionnelles)',
      corporateUpsellContact: 'Contactez-nous pour en savoir plus\u00a0: <a href="mailto:info@cyber-assistant.com" style="color:var(--color-info,#3b82f6);text-decoration:underline;">info@cyber-assistant.com</a>',
      transMeasures: 'mesures'
    },

    // Manuel d'utilisation

    // Password policy
    passwordPolicy: {
      title: 'Exigences du mot de passe :',
      minLength: 'Au moins {{min}} caractères',
      uppercase: 'Au moins une majuscule',
      lowercase: 'Au moins une minuscule',
      special: 'Au moins un caractère spécial',
      ok: 'OK',
      missing: 'Manque',
      missingRequirements: 'Exigences manquantes'
    },

    // Review frequency options
    reviewFreq: {
      monthly: 'Mensuelle',
      quarterly: 'Trimestrielle',
      biannual: 'Semestrielle',
      annual: 'Annuelle',
      onChange: 'Sur changement'
    },

    // Test results
    tests: {
      passed: 'Tests terminés : {{passed}}/{{total}} réussis',
      failed: 'Tests terminés : {{passed}}/{{total}} réussis, {{failed}} échoué(s)'
    },

    // Snapshots
    snapshots: {
      empty: 'Aucun snapshot enregistré',
      historyEmpty: 'Historique vide.',
      kept: 'Snapshots conservés : {{count}}/{{limit}}',
      displayed: 'Affichés : {{count}}',
      latest: 'Dernier snapshot : {{date}}',
      totalSize: 'Taille cumulée : {{size}}',
      noMatch: 'Aucun snapshot ne correspond aux filtres.',
      tagAuto: 'Auto',
      tagManual: 'Manuel',
      restore: 'Restaurer',
      export: 'Exporter',
      // FIX-I18N-KEYS (audit 2026-06-10) : libellés des snapshots automatiques
      backupBeforeRestore: 'Sauvegarde avant restauration',
      backupBeforeImport: 'Sauvegarde avant import',
      backupBeforeReset: 'Sauvegarde avant réinitialisation',
      backupBeforeDemo: 'Sauvegarde avant données de démonstration'
    },

    // NIS2 Plan
    nis2Plan: {
      planPhases: 'Phases du plan',
      addPhase: 'Ajouter une phase',
      editPhase: 'Modifier la phase',
      deletePhase: 'Supprimer la phase',
      editAction: 'Modifier l\'action',
      deleteAction: 'Supprimer l\'action',
      noActionsForDomain: 'Aucune action pour ce domaine.',
      noActionsMatchFilters: 'Aucune action ne correspond à vos filtres actuels.',
      actionsFiltered: 'actions (filtre appliqué)',
      completed: 'réalisées',
      inProgressTodo: 'en cours / à faire',
      avgProgress: 'Avancement moyen',
      cumulativeBudget: 'Budget cumulé',
      budget: 'Budget',
      // FIX-I18N-KEYS (audit 2026-06-10)
      editDomain: 'Modifier le domaine',
      editKeyStatus: 'Modifier le statut clé',
      // FIX-I18N-NIS2-PLAN (audit 2026-07-10) : en-têtes et libellés du plan
      colAction: 'Action',
      colBudgetTotal: 'Budget total',
      colOwner: 'Responsable',
      colPhase: 'Phase',
      colProgress: 'Avancement',
      colStatus: 'Statut',
      colActions: 'Actions',
      pillar: 'Pilier',
      domain: 'Domaine',
      delivered: 'livrées',
      addAction: 'Ajouter une action'
    },

    // Demo mode
    demo: {
      thisFeature: 'Cette fonction',
      disabledInDemo: 'est désactivée en mode démonstration.',
      limitReached: 'Limite atteinte',
      maxInDemo: 'maximum en mode démo',
      storageLimitReached: 'Limite de stockage atteinte en mode démo',
      banner: {
        text: 'Version de démonstration',
        backWebsite: 'Retour au site',
        download: 'Télécharger l\'application',
        contact: 'Nous contacter'
      }
    },

    // Warnings
    warnings: {
      missingSubcategory: 'Sous-catégorie manquante pour {{count}} contrôle(s)'
    },

    // FIX-I18N-AUTH (audit 2026-06-10) : écran « serveur inaccessible » au boot
    errors: {
      serverUnreachable: 'Serveur inaccessible',
      serverUnreachableDesc: 'Impossible de charger les données depuis le serveur. Vérifiez votre connexion réseau et que le serveur est en cours d\'exécution.'
    },

    // I18N-ADMINUI (2026-07-10) : chaînes du panneau d'administration serveur/sécurité (bundle.js)
    adminUi: {
      checkWebCrypto: 'Web Crypto API disponible',
      checkEditPassword: 'Mot de passe d\'édition défini',
      checkHashAlgo: 'Algorithme de hachage (PBKDF2 600k)',
      checkRandomUuid: 'crypto.randomUUID() supporté',
      checkSecureProtocol: 'Protocole sécurisé (file:// ou https://)',
      checksOkSuffix: 'contrôles OK',
      serverStats: 'Statistiques serveur',
      recoEditPassword: 'Définissez un mot de passe d\'édition robuste pour protéger vos données.',
      recoExportBackup: 'Exportez régulièrement vos données en tant que sauvegarde.',
      recoModernBrowser: 'Utilisez un navigateur moderne avec support de Web Crypto API.',
      recoHttps: 'Activez HTTPS pour des communications chiffrées.',
      recoCors: 'Configurez une origine CORS spécifique plutôt que * (wildcard).',
      recoUpdates: 'Mettez à jour régulièrement le serveur et ses dépendances.',
      recoBackups: 'Activez les sauvegardes automatiques sur le serveur.',
      recoAuditLogs: 'Vérifiez les journaux d\'audit régulièrement.',
      filterByType: 'Filtrer par type :',
      allEvents: 'Tous les événements',
      colDate: 'Date',
      colEvent: 'Événement',
      colUser: 'Utilisateur',
      colIp: 'IP',
      colDetails: 'Détails',
      auditLoadError: 'Erreur lors du chargement du journal.',
      loadMore: 'Charger plus',
      ipModeDisabled: 'Désactivé',
      ipModeAllowlist: 'Liste blanche (Allowlist)',
      ipModeDenylist: 'Liste noire (Denylist)',
      ipAddressesLabel: 'Adresses IP (une par ligne, notation CIDR supportée) :',
      save: 'Enregistrer',
      saving: 'Enregistrement...',
      serverRefusedConfig: 'Le serveur a refusé la configuration.',
      ipFilterErrorPrefix: 'Erreur filtrage IP : ',
      ipFilterSaved: 'Configuration de filtrage IP enregistrée.',
      ipFilterSaveError: 'Erreur lors de l\'enregistrement du filtrage IP.',
      currentPolicy: 'Politique actuelle :',
      policyRules: '18 caractères minimum, 1 majuscule, 1 minuscule, 1 caractère spécial obligatoire.',
      passwordExpiration: 'Expiration des mots de passe :',
      expirationDisabled: 'Désactivée (pas d\'expiration)',
      days30: '30 jours',
      days60: '60 jours',
      days90: '90 jours',
      policyErrorPrefix: 'Erreur politique de mots de passe : ',
      policySaved: 'Politique de mots de passe enregistrée.',
      policySaveError: 'Erreur lors de l\'enregistrement de la politique.',
      ssoCardDesc: 'Connectez un fournisseur d\u2019identité (Azure AD, Google Workspace, Okta\u2026) pour l\u2019authentification unique.',
      ssoTestRefused: 'Le serveur a refusé le test SSO.',
      ssoTestOk: 'Connexion SSO OK : le fournisseur a répondu.',
      ssoCertAutoFetched: 'Certificat TLS récupéré automatiquement',
      ssoUnreachable: 'Impossible de contacter le fournisseur SSO. Vérifiez l\'URL et la connectivité réseau.',
      demoDataUnavailable: 'Données de démonstration non disponibles',
      userPlaceholder: 'utilisateur',
      loadedSuffix: 'chargés'
    },

    // FIX-I18N-AUTOSAVE (audit 2026-06-10, bundle.js:12866) : indicateur d'auto-sauvegarde
    autoSave: {
      saving: 'Sauvegarde en cours...',
      savedToServer: 'Sauvegardé sur le serveur',
      syncFailed: 'Échec synchronisation',
      saved: 'Sauvegarde réalisée'
    }
  };

  // Load translations into i18n module
  if (window.CSI_i18n) {
    window.CSI_i18n.loadTranslations('fr', translations);
  } else {
    // Store for later loading
    window._pendingTranslations = window._pendingTranslations || {};
    window._pendingTranslations.fr = translations;
  }

})();
