export const messagesFr = {
  auth: {
    logoutSuccess: "Deconnexion reussie",
    invalidCredentials: "Email ou mot de passe incorrect",
    sessionExpired: "Votre session a expire, veuillez vous reconnecter",
    appName: "Dadycar",
    loginSubtitle: "Connectez-vous a votre compte Super Admin",
    emailPlaceholder: "admin@fleet43.com",
    passwordPlaceholder: "Votre mot de passe",
    submit: "Se connecter",
    forgotPasswordLink: "Mot de passe oublié ?",
    forgotPassword: {
      title: "Mot de passe oublié",
      subtitle: "Entrez votre email pour recevoir un lien de réinitialisation.",
      submit: "Envoyer le lien",
      success: "Si un compte existe pour cet email, un lien de réinitialisation a été envoyé.",
      back: "Retour à la connexion",
    },
    resetPassword: {
      title: "Définir votre mot de passe",
      subtitle: "Choisissez un mot de passe pour votre compte.",
      newPassword: "Nouveau mot de passe",
      confirmPassword: "Confirmer le mot de passe",
      submit: "Définir le mot de passe",
      successTitle: "Mot de passe défini",
      successMessage: "Votre mot de passe a été enregistré. Vous pouvez maintenant vous connecter.",
      backToLogin: "Aller à la connexion",
      invalidLinkTitle: "Lien invalide",
      invalidLinkMessage: "Ce lien est invalide ou a expiré. Veuillez en demander un nouveau.",
    },
  },
  pages: {
    dashboard: { title: "Vue d'ensemble", subtitle: "Tableau de bord principal" },
    companies: { title: "Entreprises", subtitle: "Gestion des entreprises" },
    users: { title: "Utilisateurs", subtitle: "Gestion de tous les utilisateurs" },
    internalUsers: { title: "Utilisateurs internes", subtitle: "Gestion des membres de l'équipe admin, rôles et permissions" },
    vehicles: { title: "Vehicules", subtitle: "Gestion de la flotte vehicules" },
    sites: { title: "Sites", subtitle: "Gestion des sites et emplacements" },
    subscriptions: { title: "Abonnements", subtitle: "Gestion des abonnements et plans" },
    tickets: { title: "Tickets", subtitle: "Gestion des tickets de support" },
    ticketDetail: { title: "Detail du ticket", subtitle: "Informations et gestion du ticket" },
    activityLogs: { title: "Journaux d'activite", subtitle: "Suivi des actions et modifications" },
    helpCenterCreate: { title: "Nouvel article", subtitle: "Centre d'Aide" },
    helpCenter: { title: "Centre d'Aide", subtitle: "Gérez les articles, sections et analysez les retours utilisateurs" },
    telematics: { title: "Boitiers telematique", subtitle: "Gerez les commandes des gestionnaires de flotte et le catalogue des produits disponibles" },
    telematicsOrderDetail: { title: "Detail commande telematique", subtitle: "Recapitulatif de la commande" },
    installations: {
      title: "Historique",
      subtitle: (n: number) => `${n} installation${n !== 1 ? "s" : ""} — toute l'équipe`,
    },
    installers: {
      title: "Installateurs",
      subtitle: (n: number) => `${n} installateur${n !== 1 ? "s" : ""}`,
    },
    antai: { title: "ANTAI", subtitle: "Suivi et gestion des vehicules lies a l'integration ANTAI" },
    antaiVehicleDetail: { title: "Detail vehicule ANTAI", subtitle: "Etat ANTAI, visibilite et gestion des exceptions" },
    rfidBatches: { title: "Cartes RFID", subtitle: "Traitement des lots de cartes RFID soumis par les entreprises" },
    rfidBatchDetail: { title: "Détail du lot RFID", subtitle: "Changements et traitement du lot" },
    health: { title: "Tableau de bord exécutif", subtitle: "Santé, adoption et engagement de l'ensemble des comptes clients" },
    healthClients: { title: "Scores de santé client", subtitle: "Chaque compte noté 0–100 selon l'activité, l'adoption, la fréquence, la complétude des données et la croissance" },
    healthProfile: { title: "Profil client", subtitle: "Santé, activité, adoption et comparaison" },
    healthConfig: { title: "Configuration santé", subtitle: "Ajustez le modèle de score et les seuils d'alerte sans code" },
    anomalyRules: {
      title: "Règles d'anomalies",
      subtitle: (n: number) => `${n} règle${n !== 1 ? "s" : ""} — les valeurs de départ de tous les clients`,
      searchPlaceholder: "Rechercher une règle...",
      empty: "Aucune règle ne correspond",
      filters: { all: "Toutes", customized: "Personnalisées par des clients", off: "Désactivées par défaut", withdrawn: "Retirées" },
      withdrawn: "Retirée",
      defaultOn: "Active par défaut",
      defaultOff: "Désactivée par défaut",
      customized: (n: number) => `${n} client${n !== 1 ? "s" : ""}`,
      disabledBy: (n: number) => `${n} l'${n !== 1 ? "ont" : "a"} désactivée`,
      severityByCase: "Selon le cas",
      channels: { mobile: "Push conducteur", fleet: "Push flotte", email: "E-mail" },
      sheet: {
        title: "Valeurs Dadycar de la règle",
        intro: "Ces valeurs s'appliquent à chaque client qui n'a pas changé la règle, dès la prochaine détection. Un client qui l'a personnalisée garde ses propres réglages.",
        condition: "Ce que vérifie la règle",
        available: "Règle disponible pour les clients",
        availableHint: "Retirée, la règle ne tourne plus pour personne et disparaît de l'écran des clients.",
        enabledByDefault: "Active par défaut",
        enabledByDefaultHint: "Pour les clients qui n'ont pas choisi eux-mêmes.",
        thresholds: "Seuils",
        noThreshold: "Cette règle n'a pas de seuil : elle constate un fait.",
        factory: (value: string) => `Valeur d'origine : ${value}`,
        severity: "Gravité par défaut",
        severityByCaseHint: "La règle donne à chaque anomalie sa propre gravité ; ce choix sert quand elle n'en donne pas.",
        notifications: "Notifications par défaut",
        mobile: "Notification push au conducteur",
        fleet: "Notification dans l'application flotte",
        email: "E-mail",
        emailSending: "Envoi des e-mails",
        save: "Enregistrer pour tous les clients",
        saved: "Règle mise à jour pour tous les clients",
        noChange: "Aucun changement",
        error: "Impossible d'enregistrer la règle",
        clientsTitle: "Clients qui l'ont personnalisée",
        noClients: "Aucun client n'a changé cette règle.",
        clientOff: "Désactivée",
        historyTitle: "Derniers changements",
        noHistory: "Aucun changement enregistré.",
        dadycar: "Dadycar",
        resetAction: "Rétablie aux valeurs Dadycar",
      },
    },
    integrations: {
      title: "Connecteurs",
      subtitle: (n: number) => `${n} connecteur${n !== 1 ? "s" : ""}`,
      searchPlaceholder: "Rechercher par nom ou code de connecteur...",
      empty: "Aucun connecteur trouvé",
      emptyHint: "Assurez-vous que le nom est correct ou modifiez vos filtres.",
      results: (n: number) => `${n} résultat${n !== 1 ? "s" : ""}`,
      connectionsCount: (n: number) => `${n} connexion${n !== 1 ? "s" : ""}`,
      filters: {
        title: "Filtres",
        status: "Statut",
        allStatuses: "Tous les statuts",
        category: "Catégorie",
        allCategories: "Toutes les catégories",
        reset: "Réinitialiser",
      },
      statusLabels: {
        enabled: "Activé",
        disabled: "Désactivé",
      } as Record<string, string>,
      connectionMethodLabels: {
        sftp: "SFTP",
        manual: "Manuel",
        api: "API",
        oauth: "OAuth",
      } as Record<string, string>,
      categories: {
        fuel_cards: "Cartes Carburant",
        telepeage: "Télépéage",
        electric_recharge: "Recharge Électrique",
        accounting: "Comptabilité",
        leasing_companies: "Loueurs LLD",
        telematics: "Télématique",
        insurance: "Assurance",
        payroll: "Paie & RH",
        expenses: "Notes de Frais",
      } as Record<string, string>,
      detail: {
        title: "Détails du connecteur",
        editTitle: "Modifier le connecteur",
        generalInfo: "Informations Générales",
        activeConnections: "Connexions Actives",
        requirements: "Prérequis",
        activationSteps: "Étapes d'activation",
        supportedModules: "Modules Supportés",
        noConnections: "Aucune connexion active pour ce connecteur.",
        noRequirements: "Aucun prérequis spécifique défini.",
        noActivationSteps: "Aucune étape d'activation spécifique définie.",
        noModules: "Aucun module supporté.",
        noConnectionDate: "Aucune date de connexion",
        actions: {
          enable: "Activer le connecteur",
          disable: "Désactiver le connecteur",
          edit: "Modifier les détails",
          save: "Enregistrer les modifications",
          cancel: "Annuler",
          saving: "Enregistrement...",
        },
        fields: {
          name: "Nom du connecteur",
          code: "Code du connecteur",
          description: "Description",
          category: "Catégorie",
          connectionMethod: "Méthode de connexion",
          syncFrequency: "Fréquence de synchronisation",
          activationMode: "Mode d'activation",
          modules: "Modules",
          status: "Statut",
        },
        syncFrequencies: {
          real_time: "Temps réel",
          hourly: "Horaire",
          daily: "Quotidien",
          weekly: "Hebdomadaire",
        } as Record<string, string>,
        activationModes: {
          immediate: "Immédiat",
          on_request: "Sur demande",
        } as Record<string, string>,
        toasts: {
          enabled: "Connecteur activé avec succès",
          disabled: "Connecteur désactivé avec succès",
          updated: "Connecteur mis à jour avec succès",
          error: "Une erreur est survenue",
        },
        connectionColumns: {
          company: "Entreprise",
          connectedAt: "Connecté le",
          lastSync: "Dernière synchro",
          status: "Statut",
        },
      },
    },
    integrationConnections: {
      title: "Connexions des connecteurs",
      subtitle: (n: number) => `${n} connexion${n !== 1 ? "s" : ""}`,
      searchPlaceholder: "Rechercher par entreprise, connecteur ou statut...",
      empty: "Aucune connexion trouvée",
      emptyHint: "Modifiez vos filtres ou vérifiez l'orthographe du terme de recherche.",
      results: (n: number) => `${n} résultat${n !== 1 ? "s" : ""}`,
      filters: {
        title: "Filtres",
        status: "Statut",
        allStatuses: "Tous les statuts",
        company: "Entreprise",
        allCompanies: "Toutes les entreprises",
        category: "Catégorie",
        allCategories: "Toutes les catégories",
        reset: "Réinitialiser",
      },
      statusLabels: {
        disconnected: "Déconnecté",
        connected: "Connecté",
        requested: "Demandé",
        rejected: "Refusé",
        error: "Erreur",
      } as Record<string, string>,
      table: {
        integration: "Connecteur",
        company: "Entreprise",
        status: "Statut",
        connectedAt: "Connecté le",
        lastSync: "Dernière synchro",
        actions: "Actions",
        viewDetails: "Voir détails",
      },
      detail: {
        title: "Détails de la connexion",
        editTitle: "Modifier la connexion",
        integrationInfo: "Informations du connecteur",
        companyInfo: "Informations de l'entreprise",
        connectionInfo: "Informations de connexion",
        credentials: "Identifiants",
        noCredentials: "Aucun identifiant défini.",
        rawJson: "Configuration JSON brute",
        editJson: "Modifier en JSON",
        editFields: "Modifier les champs",
        invalidJson: "Format JSON invalide.",
        retry: "Réessayer",
        code: "Code",
        previewNotAvailable: "Aperçu indisponible pour ce type de fichier",
        downloadFile: "Télécharger le fichier",
        toasts: {
          updated: "Connexion mise à jour avec succès",
          error: "Échec de la mise à jour de la connexion",
        },
        actions: {
          edit: "Modifier la connexion",
          save: "Enregistrer les modifications",
          cancel: "Annuler",
        },
        fields: {
          status: "Statut",
          connectedAt: "Connecté le",
          lastSyncAt: "Dernière synchro le",
          name: "Nom",
          email: "Email",
          createdAt: "Créé le",
          updatedAt: "Mis à jour le",
        },
      },
    },
  },
  nav: {
    overview: "Vue d'ensemble",
    companies: "Entreprises",
    users: "Utilisateurs",
    dormantAccounts: "Comptes dormants",
    internalUsers: "Utilisateurs internes",
    vehicles: "Vehicules",
    sites: "Sites",
    subscriptions: "Abonnements",
    tickets: "Support",
    activityLogs: "Journaux",
    helpCenter: "Centre d'Aide",
    telematics: "Boitiers telematique",
    installations: "Installations",
    installers: "Installateurs",
    antai: "ANTAI",
    rfidCards: "Cartes RFID",
    health: "Santé & Adoption client",
    integrations: "Connecteurs",
    integrationConnections: "Connexions",
    anomalyRules: "Règles d'anomalies",
  },
  navCategories: {
    main: "Principal",
    management: "Gestion",
    commercial: "Commercial",
    technical: "Technique",
    system: "Systeme",
    administration: "Administration",
  },
  notifications: {
    title: "Notifications",
    empty: "Aucune notification",
    viewAll: "Voir tout",
    markAllRead: "Tout marquer comme lu",
    unreadBadge: (n: number) => (n > 99 ? "99+" : String(n)),
  },
  account: {
    myAccount: "Mon compte",
    profile: "Profil",
    security: "Securite",
    logout: "Deconnexion",
    defaultName: "Super Admin",
    defaultEmail: "admin@dadycar.fr",
    searchPlaceholder: "Rechercher...",
  },
  support: {
    title: "Support",
    subtitle: "Conversations avec les clients, en temps réel",
    views: {
      mine: "Mes conversations",
      unassigned: "Non assignées",
      open: "Toutes",
      resolved: "Résolues",
    },
    searchPlaceholder: "Rechercher un client, une entreprise…",
    live: "En direct",
    autoRefresh: "Actualisation auto",
    emptyTitle: "Aucune conversation",
    emptyDescription: "Tout est à jour pour cette vue.",
    noResults: "Aucune conversation ne correspond à la recherche",
    selectTitle: "Choisissez une conversation",
    selectDescription: "Les messages des clients arrivent ici en temps réel.",
    you: "Vous",
    note: "Note",
    previewFrom: (who: string, text: string) => `${who} : ${text}`,
    voiceMessage: "Message vocal",
    image: "Image",
    file: "Fichier",
    unassigned: "Non assignée",
    awaitingReply: "Attend une réponse",
    assignToMe: "M'assigner",
    assign: "Assigner",
    resolve: "Marquer comme traitée",
    reopen: "Rouvrir",
    resolvedBadge: "Résolue",
    statuses: {
      Open: "Ouverte",
      "In Progress": "En cours",
      Resolved: "À confirmer par le client",
      Closed: "Terminée",
    } as Record<string, string>,
    loadError: "Impossible de charger la conversation",
    toasts: {
      resolved: "Marquée comme traitée : le client doit confirmer",
      reopened: "Conversation rouverte",
      assigned: "Conversation assignée",
    },
    thread: {
      newMessages: "Nouveaux messages",
      today: "Aujourd'hui",
      yesterday: "Hier",
      internalNote: "Note interne",
      awaitingConfirmation: (date: string) => `Marquée comme traitée le ${date} · en attente de la confirmation du client`,
      closedOn: (date: string) => `Conversation terminée le ${date}`,
      subject: "Sujet",
      urgency: "Urgence",
      startedOn: (date: string) => `Conversation démarrée le ${date}`,
    },
    composer: {
      reply: "Répondre",
      note: "Note interne",
      replyPlaceholder: "Écrire au client…",
      notePlaceholder: "Note visible uniquement par l'équipe · @ pour mentionner",
      noteHint: "Visible uniquement par l'équipe Dadycar",
      repliesClosed: "Conversation terminée : rouvrez-la pour répondre au client. Les notes internes restent possibles.",
      send: "Envoyer",
      addNote: "Ajouter la note",
      attach: "Joindre un fichier",
      emoji: "Emoji",
      record: "Enregistrer un message vocal",
      recording: "Enregistrement…",
      sendingVoice: "Envoi du message vocal…",
      cancel: "Annuler",
      enterHint: "Entrée pour envoyer · Maj+Entrée pour un retour à la ligne",
      micBlocked: "Micro bloqué pour ce site : autorisez-le depuis l'icône de la barre d'adresse, puis réessayez.",
      micMissing: "Aucun micro détecté.",
      micBusy: "Le micro est utilisé par une autre application.",
      emptyVoice: "Le message vocal est vide, réessayez.",
      fileTooLarge: (name: string) => `${name} dépasse 10 Mo`,
      mentionHeader: "Mentionner",
      retry: "Réessayer",
      sendFailed: "Le message n'a pas pu être envoyé",
    },
    panel: {
      client: "Client",
      company: "Entreprise",
      email: "E-mail",
      phone: "Téléphone",
      conversationsCount: (n: number) => `${n} conversation${n > 1 ? "s" : ""}`,
      details: "Détails",
      status: "Statut",
      priority: "Priorité",
      category: "Catégorie",
      assignee: "Assignée à",
      createdAt: "Démarrée le",
      otherConversations: "Autres conversations du client",
      noOtherConversations: "Aucune autre conversation",
      activity: "Activité",
      noCategory: "Aucune",
    },
  },
  common: {
    add: "Ajouter",
    edit: "Modifier",
    delete: "Supprimer",
    save: "Enregistrer",
    create: "Creer",
    cancel: "Annuler",
    confirm: "Confirmer",
    yes: "Oui",
    no: "Non",
    all: "Tous",
    allF: "Toutes",
    none: "Aucun",
    loading: "Chargement...",
    search: "Rechercher...",
    noData: "Aucune donnee disponible",
    resultsCount: (n: number) => `${n} resultat${n !== 1 ? "s" : ""}`,
    resultsCountFor: (n: number, query: string) => `${n} resultat${n !== 1 ? "s" : ""} pour "${query}"`,
    activate: "Activer",
    deactivate: "Desactiver",
    active: "Actif",
    inactive: "Inactif",
    activeM: "Actifs",
    pending: "En attente",
    disabled: "Desactive",
    new30d: "Nouveaux (30j)",
    new30dF: "Nouvelles (30j)",
    createdAt: "Cree le",
    date: "Date",
    impersonate: "Impersonner",
    tokenCopied: "Token copie dans le presse-papiers",
    unnamed: "Sans nom",
    retry: "Réessayer",
  },
  mcpToken: {
    menuLabel: "Générer un token MCP",
    dialogTitle: "Token MCP",
    dialogDescription: (name: string) => `Générer des identifiants d'accès MCP pour ${name}. Le client se connecte sans email ni mot de passe.`,
    nameLabel: "Nom de l'identifiant",
    namePlaceholder: "ex. Connecteur Claude du client",
    ttlLabel: "Durée du token (minutes)",
    ttlHint: "Durée de vie du token prêt à l'emploi (5 à 1440, défaut 60).",
    expiresLabel: "Expiration des identifiants (jours)",
    expiresHint: "Vide = n'expire jamais.",
    generate: "Générer le token",
    regenerate: "Générer un nouveau token",
    warning: "Copiez ces valeurs maintenant : le client secret n'est affiché qu'une seule fois.",
    accessToken: "Access token (Bearer)",
    accessTokenHint: (min: number) => `À coller en en-tête « Authorization: Bearer ». Expire dans ${min} min.`,
    clientId: "Client ID",
    clientSecret: "Client secret",
    clientSecretHint: "Affiché une seule fois — durable et révocable.",
    mcpUrl: "URL du serveur MCP",
    tokenEndpoint: "Endpoint de rafraîchissement",
    credentialExpires: "Expiration des identifiants",
    never: "Jamais",
    copy: "Copier",
    copied: "Copié",
    copyAll: "Tout copier",
    done: "Terminé",
    toastGenerated: "Token MCP généré",
    usageTitle: "Utilisation côté client",
    usageBody: "Connecteur Claude : renseigner client_id / client_secret dans les champs OAuth. Client via en-tête : coller l'access token dans « Authorization: Bearer ».",
    existingTitle: "Identifiants existants",
    emptyList: "Aucun identifiant pour le moment.",
    createdAtLabel: "Créé le",
    lastUsedLabel: "Dernière utilisation",
    neverUsed: "Jamais utilisé",
    revoke: "Révoquer",
    confirmRevoke: "Confirmer la révocation",
    toastRevoked: "Identifiant révoqué",
    statusActive: "Actif",
    statusExpired: "Expiré",
    statusRevoked: "Révoqué",
    newSectionTitle: "Générer un nouvel identifiant",
  },
  validation: {
    nameRequired: "Le nom est requis",
    fullNameRequired: "Le nom complet est requis",
    firstNameRequired: "Le prenom est requis",
    lastNameRequired: "Le nom de famille est requis",
    emailRequired: "L'email est requis",
    emailInvalid: "Email invalide",
    phoneRequired: "Le telephone est requis",
    passwordRequired: "Le mot de passe est requis",
    passwordMinLength: "Le mot de passe doit contenir au moins 8 caracteres",
    passwordsDoNotMatch: "Les mots de passe ne correspondent pas",
    siretRequired: "Le SIRET est requis",
    addressRequired: "L'adresse est requise",
    cityRequired: "La ville est requise",
    postalCodeRequired: "Le code postal est requis",
    displayNameRequired: "Le nom d'affichage est requis",
    priceMustBePositive: "Le prix doit etre positif",
    frequencyRequired: "La frequence est requise",
    titleRequired: "Le titre est requis",
    titleMaxLength: "Le titre ne peut pas depasser 255 caracteres",
    numberplateRequired: "La plaque est requise",
    markRequired: "La marque est requise",
    modelRequired: "Le modele est requis",
    motorTypeRequired: "Le type moteur est requis",
    roleRequired: "Le role est requis",
    codeRequired: "Le code est requis",
    labelRequired: "Le libelle est requis",
    installMethodRequired: "La methode d'installation est requise",
    numberNonNegative: "La valeur ne peut pas etre negative",
    vatRateInvalid: "Le taux de TVA doit etre entre 0 et 100",
    referencePrefixRequired: "Le prefixe de reference est requis",
    minUnitsInvalid: "Le nombre minimum d'unites doit etre d'au moins 1",
    weightsMustTotal100: "La somme des pondérations doit être 100",
  },
  forms: {
    name: "Nom",
    firstName: "Prenom",
    lastName: "Nom",
    email: "Email",
    phone: "Telephone",
    password: "Mot de passe",
    newPassword: "Nouveau mot de passe",
    role: "Role",
    status: "Statut",
    company: "Entreprise",
    description: "Description",
  },
  notFound: {
    title: "Page introuvable",
    description: "La page que vous recherchez n'existe pas ou a ete deplacee.",
    backToDashboard: "Retour au tableau de bord",
  },
  dashboard: {
    periods: {
      "7d": "7 jours",
      "30d": "30 jours",
      "90d": "90 jours",
      "12m": "12 mois",
    },
    charts: {
      verified: "Verifiees",
      newF: "Nouvelles",
      newM: "Nouveaux",
      connected: "Connectes",
      active: "Actifs",
      trial: "Essai",
      expired: "Expires",
      companyGrowth: "Croissance des entreprises",
      companyGrowthDesc: "Evolution sur la periode",
      vehicleGrowth: "Croissance des vehicules",
      vehicleGrowthDesc: "Nouveaux et connectes",
      subscriptionTimeline: "Timeline des abonnements",
      subscriptionTimelineDesc: "Actifs, essai et expires",
      planDistribution: "Distribution des plans",
      planDistributionDesc: "Repartition par type de plan",
      motorTypes: "Types de motorisation",
      motorTypesDesc: "Repartition par type de moteur",
    },
    stats: {
      companies: "Entreprises",
      users: "Utilisateurs",
      vehicles: "Vehicules",
      subscriptions: "Abonnements",
      sites: "Sites",
      planDistribution: "Distribution Plans",
      plansSuffix: " plans",
      withVehicles: (n: number) => `${n} avec vehicules`,
      newCompanies: (n: number) => `${n} nouvelles`,
      connected: (n: number) => `${n} connectes`,
      onTrial: (n: number) => `${n} en essai`,
    },
    loadError: "Impossible de charger les statistiques",
  },
  companies: {
    toasts: {
      created: "Entreprise creee avec succes",
      updated: "Entreprise mise a jour",
      deleted: "Entreprise supprimee",
      restored: "Entreprise restauree",
      lookupSuccess: "Informations de l'entreprise recuperees",
      siretInvalid: "Le SIRET doit contenir exactement 14 chiffres",
      accessUpdating: "Mise a jour de l'acces...",
      accessEnabled: "Acces de l'entreprise active",
      accessDisabled: "Acces de l'entreprise desactive",
      testFlagged: "Marqué comme compte de test — exclu des statistiques Santé client",
      testUnflagged: "Marque de test retirée — inclus dans les statistiques Santé client",
      refacturationGranted: "Refacturation inter-entreprises activée pour ce groupe",
      refacturationRevoked: "Refacturation inter-entreprises désactivée pour ce groupe",
      aiAgentsEnabled: "Donna (agents IA) activée pour cette société",
      aiAgentsDisabled: "Donna (agents IA) désactivée pour cette société",
    },
    sort: {
      label: "Trier par",
      newest: "Plus recentes",
      oldest: "Plus anciennes",
      disabledFirst: "Desactivees d'abord",
      enabledFirst: "Activees d'abord",
    },
    actions: {
      enableAccess: "Activer l'acces",
      disableAccess: "Desactiver l'acces",
      markTest: "Marquer comme compte de test",
      unmarkTest: "Retirer la marque de test",
      grantRefacturation: "Activer la refacturation inter-entreprises",
      revokeRefacturation: "Désactiver la refacturation inter-entreprises",
      enableAiAgents: "Activer Donna (accès anticipé)",
      disableAiAgents: "Désactiver Donna",
    },
    testBadge: "TEST",
    refacturationBadge: "REFACT.",
    aiAgentsBadge: "DONNA",
    searchPlaceholder: "Rechercher une entreprise...",
    empty: "Aucune entreprise trouvee",
    stats: {
      total: "Total",
      withVehicles: "Avec vehicules",
      withSubscription: "Avec abonnement",
      new30d: "Nouvelles (30j)",
    },
    dialog: {
      titleEdit: "Modifier l'entreprise",
      titleCreate: "Nouvelle entreprise",
      siretPlaceholder: "14 chiffres",
      siretLookupTitle: "Rechercher l'entreprise par SIRET",
    },
    fields: {
      siret: "SIRET",
    },
    delete: {
      title: "Supprimer l'entreprise",
      description: (name: string | undefined) =>
        `Voulez-vous vraiment supprimer "${name}" ? Cette action est reversible.`,
    },
    countLabel: (n: number) => `${n} entreprise${n > 1 ? "s" : ""}`,
  },
  users: {
    toasts: {
      created: "Utilisateur cree",
      updated: "Utilisateur mis a jour",
      deleted: "Utilisateur supprime",
      statusChanged: "Statut modifie",
      emailVerified: "Email verifie",
      passwordReset: "Mot de passe reinitialise",
    },
    columns: {
      emailVerified: "Email verifie",
    },
    actions: {
      verifyEmail: "Verifier email",
      resetPassword: "Reset mot de passe",
    },
    stats: {
      total: "Total",
      active: "Actifs",
      disabled: "Desactives",
      emailVerified: "Email verifie",
    },
    statusFilter: {
      pending: "En attente",
      active: "Actif",
      disabled: "Desactive",
    },
    roles: {
      company: "Entreprise",
      driver: "Chauffeur",
      siteManager: "Gestionnaire",
      siteManagerLong: "Gestionnaire de site",
      companyClient: "Client",
      companyClientLong: "Client entreprise",
    },
    roleLabels: {
      admin: "Administrateur",
      manager: "Manager",
      user: "Utilisateur",
      technician: "Technicien",
      super_admin: "Super Admin",
    } as Record<string, string>,
    dialog: {
      titleEdit: "Modifier l'utilisateur",
      titleCreate: "Nouvel utilisateur",
      resetPasswordTitle: "Reinitialiser le mot de passe",
      resetPasswordSubmit: "Reinitialiser",
    },
    delete: {
      title: "Supprimer l'utilisateur",
      description: (firstName?: string, lastName?: string) =>
        `Voulez-vous vraiment supprimer "${firstName ?? ""} ${lastName ?? ""}" ?`,
    },
    toggleStatus: {
      title: "Changer le statut",
      description: (active: boolean) =>
        `Voulez-vous ${active ? "desactiver" : "activer"} cet utilisateur ?`,
    },
  },
  vehicles: {
    toasts: {
      updated: "Vehicule mis a jour",
      deleted: "Vehicule supprime",
      linkbycarConnected: "Vehicule connecte a LinkByCar avec succes",
      eligibilityChecked: "Vehicule eligible, vous pouvez le connecter",
      eligibilityChecking: "Verification de l'eligibilite...",
      linkbycarDisconnecting: "Déconnexion de LinkByCar...",
      linkbycarDisconnected: "Véhicule déconnecté de LinkByCar",
      linkbycarNotRegistered: "Ce véhicule n'était pas enregistré chez LinkByCar — son statut local a été corrigé",
    },
    columns: {
      numberplate: "Plaque",
      vin: "VIN",
      mark: "Marque",
      model: "Modele",
      motorType: "Moteur",
      connection: "Connexion",
      provider: "Fournisseur",
    },
    fields: {
      motorTypeLong: "Type moteur",
    },
    actions: {
      connectLinkbycar: "Connecter LinkByCar",
      testEligibility: "Tester l'eligibilite",
      disconnectLinkbycar: "Déconnecter de LinkByCar",
      disconnectCompany: "Déconnecter une société",
    },
    stats: {
      total: "Total",
      connected: "Connectes",
      notConnected: "Non connectes",
      new30d: "Nouveaux (30j)",
    },
    connectionFilter: {
      notConnected: "Non connecte",
      eligible: "Eligible",
      pending: "En attente",
      connected: "Connecte",
    },
    disconnect: {
      title: "Déconnecter de LinkByCar",
      description: (numberplate: string | undefined) =>
        `Le véhicule « ${numberplate} » sera retiré de LinkByCar : la collecte de données et l'abonnement associé s'arrêtent. Il pourra être reconnecté plus tard.`,
      confirm: "Déconnecter",
    },
    companyDisconnect: {
      title: "Déconnecter une société de LinkByCar",
      trigger: "Déconnecter une société",
      pickCompany: "Choisissez d'abord une société dans le filtre « Entreprise » ci-dessus.",
      loading: "Lecture de l'état LinkByCar...",
      warning:
        "Les véhicules seront retirés de LinkByCar : la collecte de données et les abonnements associés s'arrêtent immédiatement.",
      counts: {
        total: "Véhicules",
        connected: "Connectés",
        pending: "En attente",
        eligible: "Éligibles",
        notConnected: "Non connectés",
      },
      targetLinked: (n: number) =>
        `${n} véhicule${n !== 1 ? "s" : ""} connecté${n !== 1 ? "s" : ""} ou en attente ${n !== 1 ? "seront retirés" : "sera retiré"} de LinkByCar.`,
      includeAllLabel: "Rattrapage : traiter tous les véhicules ayant un VIN",
      includeAllHint: (n: number) =>
        `${n} véhicule${n !== 1 ? "s" : ""} ${n !== 1 ? "seront envoyés" : "sera envoyé"} à LinkByCar, y compris ceux que le statut local dit déjà déconnectés. Plus long, mais corrige les statuts périmés.`,
      nothing: "Aucun véhicule à déconnecter pour cette société.",
      confirm: "Lancer la déconnexion",
      queued: (n: number) => `Déconnexion lancée pour ${n} véhicule${n !== 1 ? "s" : ""}.`,
      progressTitle: "Déconnexion en cours",
      progressRemaining: (n: number) =>
        `${n} véhicule${n !== 1 ? "s" : ""} encore rattaché${n !== 1 ? "s" : ""} à LinkByCar.`,
      progressDone: "Terminé — plus aucun véhicule rattaché à LinkByCar.",
      progressCatchUp:
        "Le rattrapage se poursuit en arrière-plan sur les véhicules que le statut local disait déjà déconnectés.",
      progressStalled:
        "Le traitement continue en arrière-plan. Rouvrez cette fenêtre plus tard pour voir où il en est.",
      loadError: "Impossible de lire l'état LinkByCar de cette société.",
      close: "Fermer",
      verify: {
        trigger: "Vérifier chez LinkByCar",
        running: "Interrogation de LinkByCar...",
        error: "Impossible d'interroger LinkByCar. Réessayez dans un instant.",
        clean: "LinkByCar ne détient plus aucun véhicule de cette société.",
        remaining: (n: number) =>
          `LinkByCar détient encore ${n} véhicule${n !== 1 ? "s" : ""} de cette société.`,
        checked: (n: number, total: number) =>
          `${n} véhicule${n !== 1 ? "s" : ""} avec VIN recoupé${n !== 1 ? "s" : ""} avec les ${total} enregistrements du compte LinkByCar.`,
        staleHint: (n: number) =>
          `Dont ${n} que le statut local dit déjà déconnecté${n !== 1 ? "s" : ""} : seul le rattrapage les traitera.`,
        absentHint: (n: number) =>
          `${n} véhicule${n !== 1 ? "s" : ""} marqué${n !== 1 ? "s" : ""} connecté${n !== 1 ? "s" : ""} chez nous mais inconnu${n !== 1 ? "s" : ""} de LinkByCar.`,
        archived: "archivé",
        columns: { plate: "Véhicule", local: "Statut local", provider: "LinkByCar" },
      },
    },
    dialog: {
      titleEdit: "Modifier le vehicule",
    },
    delete: {
      title: "Supprimer le vehicule",
      description: (numberplate: string | undefined) =>
        `Voulez-vous vraiment supprimer le vehicule "${numberplate}" ?`,
    },
  },
  sites: {
    toasts: {
      updated: "Site mis a jour",
      deleted: "Site supprime",
    },
    columns: {
      address: "Adresse",
      city: "Ville",
      postalCode: "Code postal",
      capacity: "Capacite",
      manager: "Responsable",
    },
    stats: {
      total: "Total",
      withVehicles: "Avec vehicules",
      withoutVehicles: "Sans vehicules",
      new30d: "Nouveaux (30j)",
    },
    dialog: {
      titleEdit: "Modifier le site",
    },
    delete: {
      title: "Supprimer le site",
      description: (name: string | undefined) =>
        `Voulez-vous vraiment supprimer le site "${name}" ?`,
    },
  },
  subscriptions: {
    toasts: {
      planCreated: "Plan cree",
      planUpdated: "Plan mis a jour",
    },
    tabs: {
      subscriptions: "Abonnements",
      plans: "Plans",
      billing: "Facturation",
      products: "Produits facturés",
      signals: "Signaux commerciaux",
      donna: "Donna (IA)",
    },
    stats: {
      total: "Total",
      active: "Actifs",
      trial: "En essai",
      expiredTrial: "Essai expire",
    },
    columns: {
      id: "ID",
      plan: "Plan",
      trial: "Essai",
    },
    trialFilter: {
      label: "Essai",
      trial: "Essai",
      standard: "Standard",
    },
    plans: {
      newPlan: "Nouveau plan",
      popular: "Populaire",
      popularField: "Populaire",
      activeField: "Actif",
      unlimited: "Illimite",
      perMonth: "mois",
      perYear: "an",
      companiesCount: (n: number) => `${n} entreprises`,
    },
    dialog: {
      titleEdit: "Modifier le plan",
      titleCreate: "Nouveau plan",
      identifier: "Identifiant",
      displayName: "Nom d'affichage",
      originalPrice: "Prix original",
      discountedPrice: "Prix reduit",
      frequency: "Frequence",
      monthly: "Mensuel",
      yearly: "Annuel",
    },
  },
  donna: {
    intro: (markup: string, rate: string) =>
      `Donna = tout le produit IA (chat + agents en arrière-plan). Chaque appel est facturé au coût fournisseur × ${markup}. Cadeau mensuel : ${rate} de ce que le client paie pour la flotte. L'IA de la plateforme (OCR, analyses) est comptée à part et offerte.`,
    month: "Mois",
    searchPlaceholder: "Rechercher un client...",
    empty: "Aucun client dans la liste : ajoutez-en un pour lui offrir du crédit Donna",
    addClient: "Ajouter un client",
    remove: "Retirer",
    removeTitle: (name: string) => `Retirer ${name} de la liste ?`,
    removeDescription: "Le cadeau de ce mois est repris et Donna s'arrête pour ce client dès qu'il n'a plus de crédit, sauf s'il accepte de payer au-delà.",
    removed: "Client retiré",
    add: {
      title: "Ajouter un client",
      intro: "Le client reçoit du crédit Donna sans avoir à l'utiliser d'abord. Sans crédit, Donna ne fonctionne pas pour lui tant qu'il n'a pas accepté de payer au-delà.",
      change: "Changer",
      amount: "Cadeau de ce mois (€)",
      amountPlaceholder: "Calculé depuis le prix par véhicule",
      amountHint: "Laissez vide pour le cadeau automatique (nécessite un prix par véhicule).",
      note: "Note (facultatif)",
      none: "Aucune entreprise à ajouter",
      submit: "Ajouter",
      added: "Client ajouté",
    },
    giftOff: "Cadeau automatique désactivé (Paramètres)",
    stats: {
      gifts: "Cadeaux accordés",
      donnaUsed: "Consommation Donna (prix client)",
      donnaCost: "Coût Donna (fournisseur)",
      overage: "Dépassement à facturer",
      platformCost: "IA plateforme offerte (coût)",
      net: "Résultat IA du mois",
      netHint: "Dépassement facturé − tous les coûts IA",
      unassigned: (amount: string) => `dont ${amount} non rattaché à un client`,
    },
    columns: {
      client: "Client",
      pricePerVehicle: "Prix / véhicule",
      gift: "Cadeau",
      donna: "Donna utilisé",
      overage: "Dépassement",
      cost: "Coût réel",
      platform: "Plateforme (offert)",
      net: "Résultat",
    },
    noPrice: "à saisir",
    revoked: "retiré",
    custom: "personnalisé",
    grantAll: "Accorder les cadeaux du mois",
    grantedAll: (n: number, amount: string) => `${n} cadeau(x) accordé(s), ${amount} au total`,
    settings: {
      button: "Paramètres",
      title: "Paramètres Donna",
      intro: "Tout le tarif de Donna se règle ici. Un changement s'applique aux appels suivants ; ce qui est déjà compté garde son prix.",
      saved: "Paramètres enregistrés",
      cancel: "Annuler",
      markup: "Marge (coefficient)",
      markupHint: "Prix client = coût fournisseur × ce coefficient. 1,20 = +20 %.",
      usdToEur: "Taux USD → EUR",
      usdToEurHint: "Les fournisseurs facturent en dollars ; nos coûts sont en euros.",
      giftRate: "Cadeau mensuel (%)",
      giftRateHint: "Part de ce que le client paie pour sa flotte (véhicules facturables × prix par véhicule).",
      giftEnabled: "Cadeau automatique activé",
      giftEnabledHint: "Désactivé : plus aucun cadeau automatique. Les cadeaux déjà accordés et les cadeaux personnalisés restent.",
      prices: "Prix des modèles (USD par million de tokens)",
      pricesHint: "Prix publics des fournisseurs. Un modèle daté (gpt-4o-2024-08-06) prend le prix du nom qu'il commence.",
      model: "Modèle",
      input: "Entrée",
      output: "Sortie",
      cacheRead: "Cache lu",
      cacheWrite: "Cache écrit",
      otherModels: "Tout autre modèle",
      addModel: "Ajouter un modèle",
      ocrPage: "OCR (USD par page)",
      ocrPageHint: "Pages lues par Azure Vision.",
    },
    save: "Enregistrer",
    saved: "Prix enregistré",
    details: "Détail",
    detail: {
      title: (name: string, period: string) => `${name} — ${period}`,
      priceLabel: "Prix payé par véhicule / mois (temporaire)",
      priceHint: "Saisie manuelle en attendant le module de tarification.",
      giftEnabled: "Cadeau mensuel activé",
      quote: (amount: string, vehicles: number, price: string) => `Cadeau de ce mois s'il était accordé maintenant : ${amount} (${vehicles} véhicules × ${price} × taux du cadeau)`,
      noQuote: "Aucun cadeau possible : prix manquant, cadeau désactivé ou aucun véhicule facturable.",
      grant: "Accorder le cadeau du mois",
      granted: "Cadeau accordé",
      revoke: "Retirer le cadeau",
      revokedToast: "Cadeau retiré",
      restore: "Rétablir le cadeau",
      restoredToast: "Cadeau rétabli",
      customTitle: "Cadeau personnalisé",
      customHint: "Un montant de votre choix pour ce mois : geste commercial, client sans prix, ou correction du cadeau calculé. Il remplace le cadeau du mois.",
      customAmount: "Montant en €",
      customNote: "Motif (interne)",
      customGrant: "Offrir ce montant",
      customNoteShown: (note: string) => `Motif : ${note}`,
      gift: "Cadeau",
      used: "Utilisé",
      remaining: "Restant",
      overage: "Dépassement",
      ourCost: "Notre coût",
      donnaLines: "Donna — où est allée la consommation",
      workers: "Agents en arrière-plan",
      platformLines: "IA plateforme (offerte)",
      feature: "Poste",
      calls: "Appels",
      price: "Prix client",
      cost: "Coût",
      on: "Actif",
      off: "Désactivé",
      nothing: "Rien ce mois-ci",
    },
  },
  billing: {
    searchPlaceholder: "Rechercher un client, contact, email...",
    empty: "Aucun client",
    settingsButton: "Paramètres",
    manageButton: "Gérer",
    months: (n: number) => `${n} mois`,
    perMonth: (amount: string) => `${amount} / mois`,
    unpaidOf: (n: number, tol: number) => `${n} / ${tol}`,
    stats: {
      totalDue: "Montant dû total",
      withUnpaid: "Clients avec impayés",
      atRisk: "À risque de suspension",
      suspended: "Comptes suspendus",
    },
    columns: {
      client: "Client",
      plan: "Plan",
      vehicles: "Véhicules",
      status: "Statut",
      unpaid: "Impayés",
      amountDue: "Montant dû",
      nextDue: "Prochaine échéance",
      tolerance: "Tolérance",
      action: "Action",
    },
    settings: {
      title: "Paramètres de facturation",
      toleranceLabel: "Période de tolérance par défaut (mois)",
      toleranceHelp: "Appliquée aux nouveaux clients. Modifiable individuellement depuis la fiche de chaque client.",
      save: "Enregistrer",
      saved: "Paramètres enregistrés",
    },
    products: {
      intro:
        "Les produits facturés aux clients sous contrat, au prix catalogue HT par véhicule et par mois. Un nouveau prix s'applique dès la prochaine facture aux clients sans prix à eux ; les autres gardent leur prix, seule la remise affichée change. Les factures déjà émises ne bougent pas.",
      newProduct: "Nouveau produit",
      edit: "Modifier",
      columns: { product: "Produit", role: "Facturé sur", price: "Prix catalogue HT", pennylane: "Produit Pennylane", clients: "Clients", status: "Statut" },
      roles: {
        fleet: "Chaque véhicule de la flotte",
        telematics: "Chaque véhicule connecté",
        bundle: "Chaque véhicule équipé d'un boîtier",
      } as Record<string, string>,
      active: "Actif",
      inactive: "Désactivé",
      perVehicle: (price: string) => `${price} / véhicule / mois`,
      saved: "Produit enregistré",
      created: "Produit créé",
      dialog: {
        titleCreate: "Nouveau produit",
        titleEdit: "Modifier le produit",
        label: "Nom sur la facture",
        role: "Facturé sur",
        roleFixed: "Fixé à la création : il dit quels véhicules la ligne compte.",
        price: "Prix catalogue HT / véhicule / mois",
        description: "Texte sous la ligne de facture",
        pennylane: "ID produit Pennylane (facultatif)",
        pennylaneHint: "Pennylane remplit alors la ligne depuis son catalogue.",
        active: "Proposé dans les contrats",
        activeLocked: (n: number) => `Facturé à ${n} client${n > 1 ? "s" : ""} : changez d'abord leur contrat pour le désactiver.`,
        create: "Créer le produit",
        save: "Enregistrer",
      },
    },
    manage: {
      title: "Gestion de la facturation",
      contact: "Contact",
      paymentMode: "Mode de paiement",
      subscriptionStart: "Début abonnement",
      lastPayment: "Dernier paiement",
      statut: "Statut",
      unpaidMonths: "Mois impayés",
      amountDue: "Montant dû",
      autoLockTitle: "Verrouillage automatique du compte",
      autoLockHelp: "Suspend automatiquement le compte client après la période de tolérance d'impayés consécutifs.",
      toleranceTitle: "Période de tolérance (mois)",
      toleranceHelp: "Nombre de mois d'impayés tolérés avant verrouillage automatique.",
      useDefault: (n: number) => `Réinitialiser à la valeur par défaut (${n} mois)`,
      inheritsDefault: "Hérite de la valeur par défaut",
      warnDisabled: "Le verrouillage automatique est désactivé pour ce client. Aucune suspension ne sera appliquée en cas d'impayés.",
      warnWillLock: (unpaid: number, tol: number) =>
        `Avec ces paramètres, ce compte sera verrouillé immédiatement (${unpaid} mois impayés ≥ ${tol} mois de tolérance).`,
      accessTitle: "Accès du compte",
      lockState: "État actuel",
      suspend: "Suspendre maintenant",
      reactivate: "Réactiver",
      backToAuto: "Revenir à l'automatique",
      invoicesTitle: "Factures à réconcilier",
      markPaid: "Marquer payé",
      save: "Enregistrer",
      notFound: "Client introuvable",
      mandate: {
        title: "Prélèvement SEPA",
        phases: {
          none: "Aucun mandat",
          waiting: "En attente de signature",
          active: "Actif",
          inactive: "Inactif",
        },
        off: "Le prélèvement n'est pas encore ouvert (BILLING_SEPA_ENABLED).",
        none: "Pennylane envoie le mandat au client par e-mail ; il le signe en ligne.",
        waiting: (on: string, source: string) => `Mandat envoyé le ${on} (${source}), pas encore signé.`,
        active: (on: string) => `Mandat signé le ${on} : Pennylane prélève les factures.`,
        activeNoDate: "Mandat signé : Pennylane prélève les factures.",
        inactive: (status: string) => `Mandat ${status} : plus de prélèvement.`,
        // Pennylane's mandate statuses, in words (only "enabled" is documented).
        statuses: { revoked: "révoqué", canceled: "annulé", cancelled: "annulé", refused: "refusé", expired: "expiré", failed: "en échec" } as Record<string, string>,
        // Why the bank rejected a debit, in Pennylane's payment statuses.
        debitStatuses: { failed: "échec", charged_back: "contesté par le client", customer_approval_denied: "refusé par le client" } as Record<string, string>,
        sources: { client: "par le client", admin: "par l'admin", auto: "automatique", command: "envoi groupé" } as Record<string, string>,
        send: "Envoyer le mandat",
        resend: "Renvoyer le mandat",
        sent: "Mandat envoyé par Pennylane",
        email: "E-mail de l'entreprise",
        lastError: "Dernière erreur",
        rejects: "Prélèvements rejetés (12 mois)",
        reject: (number: string, amount: string, on: string) => `Facture ${number}, ${amount} TTC, rejet vu le ${on}`,
        settled: "réglée depuis",
        owed: "à régler",
      },
      contract: {
        title: "Contrat de facturation",
        active: "Facturé par la plateforme",
        activeHelp: "Le traitement mensuel ne facture que les clients actifs.",
        mode: "Règle",
        modes: {
          contract: "Contrat : le mois écoulé, compté au dernier jour",
          plan: "Offre : prix de l'offre sur chaque véhicule (Télématique : les connectés, les autres en Fleet Business), le mois à venir",
        } as Record<string, string>,
        roles: {
          fleet: "Flotte (chaque véhicule)",
          telematics: "Télématique (chaque véhicule connecté)",
          bundle: "Pack boîtier (chaque véhicule équipé)",
        } as Record<string, string>,
        notInvoiced: "Non facturé",
        clientPrice: "Prix client",
        priceHint: (list: string) => `Prix client HT / véhicule / mois. Vide : prix catalogue, ${list}.`,
        notes: "Conditions du contrat",
        save: "Enregistrer le contrat",
        saved: "Contrat enregistré",
        none: "Aucun contrat : ce client n'est pas facturé par la plateforme.",
        lastMonth: (month: string) => `Facture de ${month}`,
        thisMonth: (month: string) => `${month}, en cours (compté aujourd'hui)`,
        nextMonth: (month: string) => `Prochaine facture : ${month}, émise le 1er (comptée aujourd'hui)`,
        counts: (fleet: number, boxes: number, cars: number) => `${fleet} véhicules, ${boxes} boîtiers, ${cars} voitures connectées`,
        columns: { product: "Produit", quantity: "Qté", list: "Prix liste", discount: "Remise", total: "Total HT" },
        total: "Total HT",
        empty: "Rien à facturer",
      },
      vehiclePlans: {
        title: "Plans des véhicules",
        inUse: "Facturé par les plans de ses véhicules : seuls les véhicules qui ont un plan sont facturés, chacun au prix client de ses plans.",
        contractNotInUse: "Aucun plan pour l'instant : ce client est facturé selon son contrat. Dès le premier plan attribué, seuls les véhicules qui ont un plan sont facturés, au dernier jour du mois : attribuez les plans de toute la flotte d'un coup.",
        offerNotInUse: (plan: string, count: number) =>
          `Aucun plan choisi pour l'instant : l'offre ${plan} est facturée sur ${count} véhicule${count > 1 ? "s" : ""}. Au premier choix, ${count > 1 ? "ils la gardent" : "il la garde"}, puis chaque véhicule suit ses plans.`,
        notBilled: "Ce client n'est pas facturé par la plateforme : les plans ne changent rien tant que sa facturation n'est pas active.",
        columns: { plan: "Plan", list: "Prix liste", price: "Prix client HT", vehicles: "Véhicules", vehicle: "Véhicule" },
        offSale: "hors vente",
        priceHint: "Vide : prix liste. Le prix s'applique à la prochaine facture.",
        savePrices: "Enregistrer les prix",
        pricesSaved: "Prix enregistrés",
        search: "Immatriculation, marque, modèle",
        selectAll: "Tout cocher",
        selected: (n: number) => `${n} coché${n > 1 ? "s" : ""}`,
        choosePlan: "Plan",
        add: "Ajouter",
        remove: "Retirer",
        updated: "Plans des véhicules mis à jour",
        prorata: (amount: string) => `Prorata sur la prochaine facture : ${amount} HT`,
        connected: "connecté",
        byOffer: "par l'offre",
        none: "aucun plan",
        noVehicle: "Aucun véhicule dans la flotte.",
        totals: (withPlan: number, total: number, amount: string) =>
          `${withPlan} véhicule${withPlan > 1 ? "s" : ""} facturé${withPlan > 1 ? "s" : ""} sur ${total} · ${amount} HT / mois`,
      },
      pennylane: {
        title: "Client Pennylane",
        help: "Le client Pennylane qui reçoit les factures de cette entreprise.",
        off: "Pennylane est désactivé sur cette plateforme (PENNYLANE_ENABLED) : le lien n'est pas vérifié.",
        none: "Aucun lien : à la première facture, un nouveau client serait créé dans Pennylane.",
        linked: (name: string, id: string) => `${name} (n° ${id})`,
        unchecked: (id: string) => `Client n° ${id}`,
        sirenDiffers: (siren: string) => `SIREN différent de celui de l'entreprise (${siren}) : vérifiez que c'est bien l'entité facturée.`,
        alsoLinked: (names: string) => `Aussi lié à : ${names}`,
        search: "Nom ou SIREN / SIRET",
        searchButton: "Rechercher",
        noResult: "Aucun client Pennylane trouvé",
        link: "Lier",
        unlink: "Délier",
        linkedToast: "Client Pennylane lié",
        unlinkedToast: "Lien supprimé",
      },
    },
    suspendConfirm: {
      title: "Suspendre le compte",
      description: (name: string) =>
        `« ${name} » sera verrouillé : l'accès à l'application est bloqué quel que soit le niveau d'impayés. Cela ne retire pas les véhicules d'ANTAI.`,
    },
    toasts: {
      configSaved: "Configuration mise à jour",
      suspended: "Compte suspendu",
      reactivated: "Compte réactivé",
      backToAuto: "Politique automatique rétablie",
      invoicePaid: "Facture marquée comme payée",
    },
  },
  tickets: {
    toasts: {
      updated: "Ticket mis a jour",
      deleted: "Ticket supprime",
    },
    columns: {
      ticket: "Ticket",
      category: "Categorie",
      priority: "Priorite",
      createdBy: "Cree par",
    },
    actions: {
      viewDetails: "Voir les details",
    },
    searchPlaceholder: "Rechercher un ticket...",
    empty: "Aucun ticket trouve",
    stats: {
      total: "Total",
      open: "Ouverts",
      resolved: "Resolus",
      new30d: "Nouveaux (30j)",
      awaitingReply: "En attente de reponse",
    },
    filters: {
      allStatuses: "Tous les statuts",
      allPriorities: "Toutes les priorites",
      allCategories: "Toutes les categories",
      allAssignees: "Tous les assignes",
      unassigned: "Non assigne",
      assignee: "Assigne a",
      conversation: "Conversation",
      allConversations: "Toutes les conversations",
      awaitingReply: "Client en attente de reponse",
    },
    awaitingReplyBadge: "Reponse client",
    columnsExtra: {
      assignee: "Assigne a",
      lastClientMessage: "Dernier message client",
      lastDadycarReply: "Derniere reponse Dadycar",
    },
    delete: {
      title: "Supprimer le ticket",
      description: (title: string | undefined) =>
        `Voulez-vous vraiment supprimer "${title}" ? Cette action est reversible.`,
    },
  },
  ticketDetail: {
    notFound: "Ticket introuvable",
    ticketIdLabel: (id: number) => `Ticket #${id}`,
    editTitle: "Modifier le ticket",
    sections: {
      description: "Description",
      documents: (n: number) => `Documents (${n})`,
      info: "Informations",
      history: "Historique",
    },
    fields: {
      title: "Titre",
      noDescription: "Aucune description",
      createdAt: "Date de creation",
      updatedAt: "Derniere mise a jour",
      assignee: "Assigne a",
      lastClientMessage: "Dernier message client",
      lastDadycarReply: "Derniere reponse Dadycar",
    },
    assignee: {
      placeholder: "Selectionner un membre",
      search: "Rechercher un membre...",
      empty: "Aucun membre",
      unassign: "Desassigner",
      activeCount: (n: number) => `(${n})`,
    },
    communications: {
      tabs: {
        client: "Conversation Client",
        internal: "Communications Internes",
      },
      empty: "Aucun message pour le moment",
      composerPlaceholderClient: "Repondre au client...",
      composerPlaceholderInternal: "Note interne... (tapez @ pour mentionner)",
      sendClient: "Envoyer au client",
      sendInternal: "Publier la note",
      privateBadge: "Note privee - non visible par le client",
      clientFooter: (ticketId: number) =>
        `Envoye via support@dadycar.fr - Sujet: [Ticket #${ticketId}]`,
      mention: {
        header: "Mentionner un membre",
        empty: "Aucun resultat",
      },
      attachmentsHint: "Glissez-deposez des fichiers (max 10 fichiers, 10 Mo chacun)",
      fileTooLarge: (name: string) => `Fichier trop volumineux : "${name}" depasse 10 Mo`,
      tooManyFiles: "Maximum 10 fichiers par message",
      internalOnly: "Interne uniquement",
      edit: "Editer",
      delete: "Supprimer",
      editedAt: "(modifie)",
      clientImmutable: "Les conversations client ne peuvent etre modifiees.",
      toastMessageSent: "Message publie",
      toastMessageEdited: "Message mis a jour",
      toastMessageDeleted: "Message supprime",
      confirmDeleteTitle: "Supprimer la note",
      confirmDeleteDescription:
        "Voulez-vous vraiment supprimer cette note interne ? Cette action est irreversible.",
    },
    history: {
      readOnly: "Lecture seule - Interne",
      loadMore: "Charger plus",
      empty: "Aucune entree d'historique",
      labels: {
        create: "a cree le ticket",
        deleted: "a supprime le ticket",
        status_change: "a change le statut",
        priority_change: "a change la priorite",
        category_change: "a change la categorie",
        title_change: "a modifie le titre",
        description_change: "a modifie la description",
        assign: "a assigne le ticket",
        unassign: "a desassigne le ticket",
        message_client: "a repondu au client",
        message_from_client: "a ecrit a Dadycar",
        message_internal: "a ajoute une note interne",
        message_edited: "a modifie un message",
        message_deleted: "a supprime un message",
        attachment_added: "a ajoute une piece jointe",
        attachment_removed: "a retire une piece jointe",
      },
      unassigned: "Non assigne",
      system: "Systeme",
    },
  },
  rfid: {
    stats: {
      total: "Total des lots",
      processing: "En traitement",
      processed: "Traités",
      changesPending: "Changements en attente",
      companies: "Entreprises",
    },
    searchPlaceholder: "Rechercher une référence...",
    empty: "Aucun lot de cartes RFID",
    columns: {
      reference: "Référence",
      company: "Entreprise",
      status: "Statut",
      changes: "Changements",
      submittedBy: "Soumis par",
      submittedAt: "Soumis le",
    },
    filters: {
      status: "Statut",
      allStatuses: "Tous les statuts",
      company: "Entreprise",
      allCompanies: "Toutes les entreprises",
    },
    statuses: {
      processing: "En traitement",
      processed: "Traité",
    },
    actions: {
      viewDetails: "Voir le détail",
      process: "Traiter le lot",
    },
    toasts: {
      processed: "Lot traité",
    },
    detail: {
      notFound: "Lot introuvable",
      referenceLabel: (ref: string) => `Lot ${ref}`,
      sections: {
        info: "Informations",
        changes: (n: number) => `Changements (${n})`,
      },
      fields: {
        reference: "Référence",
        company: "Entreprise",
        status: "Statut",
        changesCount: "Changements",
        submittedBy: "Soumis par",
        submittedAt: "Soumis le",
        processedBy: "Traité par",
        processedAt: "Traité le",
        empty: "—",
      },
      change: {
        card: (num: string) => `Carte ${num}`,
        noCard: "Aucune carte",
        requestedBy: "Demandé par",
        empty: "Aucun changement dans ce lot",
      },
      changeTypes: {
        create: "Création",
        assign: "Attribution",
        vehicles: "Véhicules",
        activate: "Activation",
        deactivate: "Désactivation",
        archive: "Archivage",
      },
      process: {
        button: "Traiter le lot",
        confirmTitle: "Traiter ce lot ?",
        confirmDescription:
          "Cette action finalise les changements (activation/désactivation) et synchronise les badges conducteurs sur les appareils. Elle est irréversible.",
        alreadyProcessed: "Ce lot a déjà été traité.",
      },
    },
  },
  health: {
    periods: { month: "Ce mois-ci", week: "La semaine dernière", "3months": "3 derniers mois", custom: "Personnalisé" },
    tiers: { healthy: "En bonne santé", attention: "À surveiller", at_risk: "À risque" },
    watchlist: "Liste de surveillance",
    needsCompute: {
      title: "Analyses pas encore calculées",
      description: "Le calcul nocturne n'a pas encore été exécuté. Les métriques apparaîtront une fois les snapshots générés.",
    },
    exec: {
      portfolioScore: "Score du portefeuille",
      clients: "Clients",
      totalClients: "Total clients",
      activeThisMonth: "Actifs ce mois-ci",
      inactive: "Inactifs",
      newClients: "Nouveaux (30 jours)",
      churnRisk: "Risque de churn",
      users: "Utilisateurs",
      totalUsers: "Total utilisateurs",
      activeToday: "Actifs aujourd'hui",
      activeWeek: "Actifs cette semaine",
      activeMonth: "Actifs ce mois-ci",
      adoption: "Adoption",
      avgLoginFrequency: "Fréquence de connexion moy.",
      avgModules: "Modules moy. / client",
      avgSession: "Session moy.",
      avgFeatureAdoption: "Adoption fonctionnalités moy.",
      engagement: "Engagement du portefeuille",
      actionsPerWeek: "Total actions / semaine",
      vsPrev: "vs préc.",
      distribution: "Répartition de santé",
      clientsLower: "clients",
      bandHealthy: (n: number) => `En santé (${n}+)`,
      bandAttention: "À surveiller",
      bandAtRisk: (n: number) => `À risque (<${n})`,
      churnListTitle: "Risque de churn · à surveiller",
      noChurn: "Aucun client sous le seuil « à risque ».",
      viewAll: "Tout voir →",
      noLoginDays: (n: number) => `Aucune connexion depuis ${n} jours`,
      daysAgo: (n: number) => `il y a ${n}j`,
      moduleUtil: "Utilisation des modules · moy. portefeuille",
      perMonth: "/mois",
      minutes: (n: number) => `${n}m`,
    },
    list: {
      searchPlaceholder: "Rechercher un client…",
      new: "NOUV.",
      accounts: (n: number) => `${n} compte${n > 1 ? "s" : ""}`,
      columns: {
        company: "Entreprise", plan: "Offre", vehicles: "Véhicules", users: "Utilisateurs",
        active: "Actifs", modules: "Modules", trend: "Tendance", health: "Santé",
      },
      tabs: { all: "Tous", healthy: "En santé", attention: "À surveiller", at_risk: "À risque" },
    },
    profile: {
      back: "Retour à tous les clients",
      score: "/ 100",
      clientSince: (y: string) => `Client depuis ${y}`,
      tiles: { vehicles: "Véhicules", users: "Utilisateurs", active: "Actifs", mau: "MAU" },
      tabs: { overview: "Aperçu", activity: "Activité & Connexions", adoption: "Adoption", behavior: "Comportement", benchmark: "Comparaison" },
      breakdown: "Détail du score de santé",
      weight: (n: number) => `pondération ${n}%`,
      excluded: "Exclu (non applicable)",
      alerts: "Alertes d'adoption & engagement",
      noAlerts: "Aucune alerte active — le compte est en bonne santé.",
      engagementTrend: "Tendance d'engagement",
      thisMonth: "Ce mois-ci", lastMonth: "Mois dernier", actionsLower: "actions",
      fleetMaturity: "Maturité de la flotte",
      components: { activity: "Activité utilisateur", adoption: "Adoption des modules", frequency: "Fréquence des sessions", completeness: "Complétude des données", growth: "Tendance de croissance" },
      maturityItems: {
        vehicles_data: "Données véhicules saisies", employees: "Employés affectés", sites: "Sites créés",
        suppliers: "Fournisseurs enregistrés", finance_documents: "Documents financiers importés", fuel_energy: "Carburant & Énergie suivis",
      },
      dau: "Utilisateurs actifs / jour", wau: "Utilisateurs actifs / semaine", mau: "Utilisateurs actifs / mois",
      today: "aujourd'hui", last7: "7 derniers jours", last30: "30 derniers jours",
      loginAnalytics: "Analyse des connexions", logins30d: "Connexions · 30 derniers jours", avgLoginsUser: "Connexions moy. / utilisateur",
      mostActive: "Utilisateurs les plus actifs", inactiveUsers: "Utilisateurs inactifs",
      noLogin30: "Sans connexion depuis 30+ jours", noLogin60: "Sans connexion depuis 60+ jours", noLogin90: "Sans connexion depuis 90+ jours",
      byModule: "Adoption des fonctionnalités · par module", ranking: "Classement d'utilisation", discovery: "Chronologie de découverte",
      status: { active: "Actif", low: "Peu utilisé", unused: "Inutilisé", "n/a": "N/A" },
      threshold: (n: number) => `cible ${n}`,
      workflow: "Analyse des parcours · navigation principale", avgSession: "Session moy.",
      minutes: (n: number) => `${n} min`,
      heatmap: "Carte d'activité", byHour: "Par heure", byWeekday: "Par jour de la semaine",
      low: "Faible", high: "Élevée",
      annual: "Activité annuelle · 12 derniers mois", activeDays: (n: number) => `${n} jours actifs sur l'année`,
      less: "Moins", more: "Plus", lowActivity: "Faible activité — peu de parcours à afficher.",
      benchmarkTitle: "Comparaison avec tous les clients", benchmarkUnavailable: "La comparaison nécessite un jeu de snapshots calculé.",
      benchmarkAgainst: (n: number) => `Comparé à la moyenne du portefeuille sur les ${n} autres comptes.`,
      thisClient: "Ce client", peerAvg: "Moy. pairs", vsPeers: "vs pairs",
      benchmarkSummary: (n: number) => `Sous-utilisation sur ${n} des 5 métriques vs la moyenne du portefeuille.`,
      benchmarkOutperforms: "Surperforme les pairs sur toutes les métriques.",
    },
    config: {
      scoreWeights: "Pondérations du score", weightsHint: "Contribution de chaque composante au score 0–100. Doit totaliser 100.",
      total: "Total",
      weights: { activity: "Activité utilisateur", adoption: "Adoption des modules", frequency: "Fréquence des sessions", completeness: "Complétude des données", growth: "Tendance de croissance" },
      targets: "Cibles & calibrage",
      targetActions: "Actions cibles / utilisateur", targetLogins: "Connexions cibles / utilisateur", growthBand: "Bande de croissance",
      perMonth: "/mois", band: "±% mappé sur 0 et 100",
      moduleThresholds: "Seuils d'adoption par module",
      moduleThresholdsHint: "% d'utilisation (par véhicule) ou nombre minimum (compte/enregistrement) à partir duquel un module est adopté.",
      completenessItems: "Éléments de complétude véhicule",
      tierCutoffs: "Seuils des paliers de santé", tierHealthy: "En santé ≥", tierAtRisk: "À risque <",
      alertThresholds: "Seuils d'alerte",
      alerts: {
        inactivity_amber_days: "Inactivité — orange (jours ouvrés)", inactivity_red_days: "Inactivité — rouge (jours ouvrés)",
        weak_adoption_amber: "Faible adoption — orange (%)", weak_adoption_red: "Faible adoption — rouge (%)", tenure_gate_months: "Ancienneté minimale (mois)",
        weekly_drop_enabled: "Baisse hebdo d'utilisateurs actifs (1 = actif)", monthly_drop_enabled: "Baisse mensuelle d'utilisateurs actifs (1 = actif)",
      },
      defaultPeriod: "Période par défaut",
      save: "Enregistrer", reset: "Réinitialiser",
      resetTitle: "Réinitialiser aux valeurs par défaut ?", resetDescription: "Cela restaure tous les paramètres de scoring à leur valeur par défaut.",
      readOnly: "Vous avez un accès en lecture seule à cette configuration.",
      toasts: { saved: "Configuration enregistrée", reset: "Configuration réinitialisée" },
    },
    weekdays: ["Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim"],
  },
  activityLogs: {
    stats: {
      userActivity: "Activite utilisateurs",
      vehicleHistory: "Historique vehicules",
      statusChanges: "Changements de statut",
      siteChanges: "Changements de site",
      todayCount: (today: number, last30: number) => `${today} aujourd'hui, ${last30} ce mois`,
      last30Days: (n: number) => `${n} ces 30 derniers jours`,
    },
    tabs: {
      activity: "Activite",
      vehicles: "Vehicules",
      statuses: "Statuts",
      sites: "Sites",
    },
    columns: {
      action: "Action",
      method: "Methode",
      module: "Module",
      user: "Utilisateur",
      ip: "IP",
      description: "Description",
      vehicle: "Vehicule",
      oldStatus: "Ancien statut",
      newStatus: "Nouveau statut",
      oldSite: "Ancien site",
      newSite: "Nouveau site",
    },
    search: {
      userActivity: "Rechercher URL, module, IP, utilisateur...",
      vehicleHistory: "Rechercher description, action...",
    },
    filters: {
      modules: {
        vehicles: "Vehicules",
        drivers: "Conducteurs",
        sites: "Sites",
      },
      vehicleActions: {
        archived: "Archive",
        unarchived: "Desarchive",
      },
    },
  },
  telematics: {
    tabs: {
      orders: "Commandes",
      catalog: "Catalogue produits",
    },
    catalog: {
      subtitle:
        "Gerez les produits disponibles a la commande, leurs specifications, leurs besoins couverts et leurs prix.",
      addButton: "Nouveau produit",
      searchPlaceholder: "Rechercher par nom, SKU, besoin ou description...",
      empty: "Aucun produit",
      stats: {
        products: "Produits",
        active: "Actifs",
        outOfStock: "Rupture",
        stockValue: "Valeur stock",
      },
      filters: {
        category: "Categorie",
        allCategories: "Toutes les categories",
      },
      columns: {
        sku: "SKU",
        product: "Produit",
        category: "Categorie",
        needs: "Besoins couverts",
        price: "Prix HT",
        stock: "Stock",
        status: "Statut",
      },
      categories: {
        boitier: "Boitier",
        module: "Module",
        capteur: "Capteur",
        accessoire: "Accessoire",
      },
      dialog: {
        titleCreate: "Nouveau produit",
        titleEdit: "Modifier le produit",
        submitCreate: "Créer le produit",
        submitEdit: "Enregistrer",
      },
      fields: {
        sku: "SKU",
        skuPlaceholder: "TLT-FMC003",
        category: "Categorie",
        name: "Nom du produit",
        namePlaceholder: "Teltonika FMC003",
        description: "Description",
        priceHt: "Prix HT (€)",
        stock: "Stock",
        statusActive: "Produit actif",
        needsCovered: "Besoins couverts",
        needsHelp: "Sélectionnez les fonctionnalités proposées par ce produit.",
        addCustomNeed: "Ajouter un besoin personnalise...",
        addNeedButton: "Ajouter",
        specifications: "Specifications",
        addSpec: "Ajouter",
        specKeyPlaceholder: "Cle",
        specValuePlaceholder: "Valeur",
      },
      toasts: {
        created: "Produit cree",
        updated: "Produit mis a jour",
        deleted: "Produit supprime",
      },
      delete: {
        title: "Supprimer le produit",
        description: (name?: string) =>
          `Voulez-vous vraiment supprimer "${name ?? ""}" ?`,
      },
    },
    orders: {
      searchPlaceholder: "Rechercher par reference, organisation ou produit...",
      empty: "Aucune commande",
      stats: {
        total: "Total commandes",
        pending: "En attente",
        inProgress: "En cours",
        installed: "Installes",
      },
      filters: {
        status: "Statut",
        allStatuses: "Tous les statuts",
      },
      columns: {
        reference: "Reference",
        organization: "Organisation",
        products: "Boitiers",
        quantity: "Quantite",
        delivery: "Livraison",
        date: "Date",
        totalHt: "Total HT",
        status: "Statut",
      },
      actions: {
        accept: "Accepter",
        reject: "Rejeter",
        view: "Voir la commande",
      },
      lifecycle: {
        acceptTitle: "Accepter la commande",
        acceptDescription:
          "La commande passera au statut « En cours » et sera transmise au fournisseur.",
        acceptOrderDateLabel: "Date de commande",
        acceptNotePlaceholder: "Note interne (optionnel)",
        rejectTitle: "Rejeter la commande",
        rejectDescription:
          "La commande sera marquée comme « Rejetée » et le gestionnaire de flotte sera notifié.",
        rejectReasonPlaceholder: "Motif du rejet",
        confirm: "Confirmer",
      },
      toasts: {
        accepted: "Commande acceptee",
        rejected: "Commande rejetee",
      },
    },
    orderDetail: {
      notFound: "Commande introuvable",
      subtitle: (org: string, date: string) =>
        `${org} · soumise le ${date}`,
      sections: {
        delivery: (n: number) => `Livraison (${n} site${n > 1 ? "s" : ""})`,
        needs: "Besoins exprimes",
        totalCommande: "Total commande",
        ttc: "TTC",
        summary: "Recapitulatif",
        dates: "Dates",
        demandeur: "Demandeur",
      },
      fields: {
        units: (n: number) => `${n} unite${n > 1 ? "s" : ""}`,
        unitPrice: (qty: number, price: string) => `${qty} × ${price}`,
        lines: "Lignes",
        boxes: "Boitiers",
        sites: "Sites",
        orderDate: "Date de commande",
        receivedDate: "Date de réception",
        dateNotSet: "Non renseignée",
        installation: "Installation",
        totalHt: "Total HT",
        vat: (rate: number) => `TVA (${rate}%)`,
        totalTtc: "Total TTC",
        noNeeds: "Aucun besoin exprime",
      },
    },
    requestInstallation: {
      action: "Demander l'installation",
      title: "Lancer la demande d'installation",
      description:
        "Notifiez un ou plusieurs installateurs : chacun proposera ses créneaux, le client validera celui qui lui convient.",
      installerLabel: "Installateur",
      installerPlaceholder: "Choisir un installateur",
      vehiclesLabel: "Boîtiers",
      noInstallers: "Aucun installateur disponible.",
      missingInstaller: "Sélectionnez au moins un installateur.",
      confirm: "Lancer la demande",
      success: "Demande(s) d'installation lancée(s)",
      // Wizard
      step1Title: "Commande livrée",
      step1Lead: (ref: string) =>
        `Commande ${ref} — vient d'être livrée. Voulez-vous lancer la demande d'installation ?`,
      step1Heading: "Une commande a été livrée",
      step1Body: (boxes: number, location: string, vehicles: number) =>
        `${boxes} boîtier(s) télématique(s) à livrer à ${location}, pour installation sur ${vehicles} véhicule(s). Souhaitez-vous lancer la demande d'installation ?`,
      remindLater: "Me rappeler plus tard",
      launch: "Lancer la demande d'installation",
      step2Title: "Récapitulatif de la commande",
      step2Lead: (ref: string) =>
        `Commande ${ref} — vérifiez les informations avant de notifier les installateurs.`,
      summaryTitle: "Récapitulatif de la commande",
      boxesLabel: "Boîtiers télématiques",
      qtyLabel: "Qté",
      clientLabel: "Client",
      deliveryLabel: "Lieu de livraison",
      contactLabel: "Contact sur site",
      sitesTitle: "Sites de livraison",
      sitesCount: (n: number) => `${n} site${n > 1 ? "s" : ""}`,
      unitsLabel: (n: number) => `${n} boîtier${n > 1 ? "s" : ""}`,
      noContact: "Aucun contact renseigné",
      vehiclesTitle: "Véhicules",
      colPlate: "Immat.",
      colVehicle: "Véhicule",
      colYear: "Année",
      colVin: "VIN",
      colBox: "Boîtier",
      back: "Retour",
      next: "Continuer",
      step3Title: "Affecter les installateurs",
      step3Lead: (ref: string) =>
        `Commande ${ref} — sélectionnez les véhicules puis le ou les installateurs qui s'en chargeront.`,
      // Sélection des véhicules à affecter (relation many-to-many).
      selectVehiclesTitle: "Véhicules à affecter",
      vehiclesSelectedCount: (n: number) =>
        `${n} sélectionné${n !== 1 ? "s" : ""}`,
      selectAll: "Tout sélectionner",
      deselectAll: "Tout désélectionner",
      allAssigned: "Tous les véhicules sont déjà affectés à un installateur.",
      assignedTo: (name: string) => `Affecté à ${name}`,
      colAssignment: "Affectation",
      noVehicles: "Aucun véhicule à installer pour cette commande.",
      // Regroupement des véhicules par site de livraison.
      siteGroupNoSite: "Sans site",
      siteVehiclesCount: (n: number) => `${n} véhicule${n !== 1 ? "s" : ""}`,
      selectSiteAll: "Tout sélectionner",
      selectSiteNone: "Tout désélectionner",
      // Construction des groupes (véhicules → installateurs) avant soumission.
      assignSelected: (n: number) =>
        `Affecter ${n} véhicule${n !== 1 ? "s" : ""}`,
      pickInstallersTitle: "Choisir les installateurs",
      pickInstallersLead: (n: number) =>
        `Pour ${n} véhicule${n !== 1 ? "s" : ""} sélectionné${n !== 1 ? "s" : ""}.`,
      confirmGroup: "Valider le groupe",
      groupBadge: (index: number, names: string) => `Groupe ${index} · ${names}`,
      groupsTitle: "Groupes d'affectation",
      groupVehiclesCount: (n: number) => `${n} véhicule${n !== 1 ? "s" : ""}`,
      remainingToAssign: (n: number) =>
        `${n} véhicule${n !== 1 ? "s" : ""} restant${n !== 1 ? "s" : ""} à affecter`,
      allAssignedReady: "Tous les véhicules sont affectés.",
      submitGroups: (n: number) =>
        `Soumettre la demande (${n} groupe${n !== 1 ? "s" : ""})`,
      personnelTitle: "Personnel d'installation",
      selectedCount: (n: number) => `${n} sélectionné${n !== 1 ? "s" : ""}`,
      submit: (n: number) => `Soumettre la demande (${n})`,
      submitToast: (n: number) =>
        `Email envoyé à ${n} installateur${n !== 1 ? "s" : ""}`,
    },
    installerAvailabilities: {
      action: "Disponibilités des installateurs",
      title: "Disponibilités des installateurs",
      lead: (ref: string) =>
        `Commande ${ref} — réponses des installateurs notifiés.`,
      responsesTitle: "Réponses reçues",
      responsesCount: (responded: number, total: number) =>
        `${responded} / ${total}`,
      responded: "A répondu",
      awaiting: "En attente",
      scheduledBanner: (date: string) => `Installation planifiée le ${date}`,
      scheduledWith: (name: string) => `avec ${name}`,
      noResponses: "Aucun installateur notifié pour cette commande.",
      close: "Fermer",
      loadError: "Impossible de charger les disponibilités.",
    },
    markDelivered: {
      action: "Marquer comme livré",
      success: "Commande marquée comme livrée.",
      title: "Marquer la commande comme livrée",
      description:
        "La commande passera au statut « Livré ». Indiquez la date de réception.",
      receivedDateLabel: "Date de réception",
      confirm: "Confirmer",
    },
  },
  installers: {
    badge: "installateur",
    searchPlaceholder: "Rechercher un installateur...",
    noResults: "Aucun installateur ne correspond à votre recherche.",
    empty: "Aucun installateur",
    emptyHint: "Les membres de l'équipe d'installation apparaîtront ici.",
    archivedBadge: "archivé",
    archivedSince: (date: string) => `Archivé le ${date}`,
    archivedEmpty: "Aucun installateur archivé",
    archivedEmptyHint: "Les installateurs que vous archivez apparaîtront ici.",
    tabs: {
      active: "Actifs",
      archived: "Archivés",
    },
    details: "Voir les détails",
    since: (date: string) => `Depuis le ${date}`,
    recentTitle: "Dernières installations",
    noPlate: "Sans immat",
    deviceUnknown: "Boîtier inconnu",
    validatedCount: (n: number) => `${n} validée${n !== 1 ? "s" : ""}`,
    errorsCount: (n: number) => `${n} erreur${n !== 1 ? "s" : ""}`,
    stats: {
      installations: "Installations",
      okRate: "Taux OK",
      avgMin: "Min moy.",
    },
    manage: {
      add: "Ajouter un installateur",
      edit: "Modifier",
      delete: "Supprimer",
      createTitle: "Nouvel installateur",
      editTitle: "Modifier l'installateur",
      createLead: "Créez un compte installateur. Il s'en servira pour se connecter à l'application.",
      editLead: "Mettez à jour le nom et l'e-mail de l'installateur.",
      nameLabel: "Nom",
      namePlaceholder: "Nom complet",
      emailLabel: "E-mail",
      emailPlaceholder: "installateur@exemple.com",
      passwordLabel: "Mot de passe",
      passwordPlaceholder: "Au moins 8 caractères",
      passwordConfirmLabel: "Confirmer le mot de passe",
      cancel: "Annuler",
      save: "Enregistrer",
      create: "Créer",
      createSuccess: "Installateur créé.",
      updateSuccess: "Installateur mis à jour.",
      passwordMismatch: "Les mots de passe ne correspondent pas.",
      // Changement de mot de passe
      changePassword: "Modifier le mot de passe",
      passwordTitle: "Modifier le mot de passe",
      passwordLead: (name: string) =>
        `Définissez un nouveau mot de passe pour ${name}.`,
      newPasswordLabel: "Nouveau mot de passe",
      passwordSuccess: "Mot de passe mis à jour.",
      // Archivage (soft delete d'un installateur actif)
      archive: "Archiver",
      archiveTitle: "Archiver l'installateur",
      archiveConfirm: (name: string) =>
        `Voulez-vous vraiment archiver ${name} ? Vous pourrez le restaurer plus tard.`,
      archiveSuccess: "Installateur archivé.",
      // Restauration
      restore: "Restaurer",
      restoreSuccess: "Installateur restauré.",
      // Suppression définitive (irréversible)
      deleteForever: "Supprimer définitivement",
      deleteTitle: "Supprimer définitivement",
      deleteConfirm: (name: string) =>
        `Voulez-vous vraiment supprimer définitivement ${name} ? Cette action est irréversible.`,
      deleteSuccess: "Installateur supprimé définitivement.",
    },
  },
  installations: {
    searchPlaceholder: "Rechercher par immat, IMEI, modèle...",
    empty: "Aucune installation",
    emptyHint: "Les installations réalisées par l'équipe apparaîtront ici.",
    results: (n: number) => `${n} résultat${n !== 1 ? "s" : ""}`,
    stats: {
      total: "Total",
      validated: "Validées",
      toFix: "À corriger",
      pending: "En attente",
      avgMin: "Moy. min",
    },
    filters: {
      title: "Filtres",
      status: "Statut",
      allStatuses: "Tous les statuts",
      installer: "Installateur",
      allInstallers: "Tous les installateurs",
      dateFrom: "Du",
      dateTo: "Au",
      reset: "Réinitialiser",
    },
    statusLabels: {
      in_progress: "En cours",
      validated: "Validée",
      gps_error: "À corriger",
      pending: "En attente",
    } as Record<string, string>,
    card: {
      noPlate: "Sans immatriculation",
      deviceUnknown: "Boîtier inconnu",
      fleetVehicle: (id: number) => `Parc #${id}`,
      photos: (n: number) => `${n} photo${n !== 1 ? "s" : ""}`,
      minutes: (n: number) => `${n} min`,
    },
    edit: {
      title: "Modifier l'installation",
      backToList: "Retour à la liste",
      next: "Suivant",
      previous: "Précédent",
      save: "Enregistrer",
      saveAndValidate: "Enregistrer et valider",
      saving: "Enregistrement…",
      savedToast: "Installation enregistrée",
      saveError: "L'enregistrement a échoué.",
      steps: {
        vehicle: "Véhicule",
        device: "Boîtier",
        wiring: "Câblage & accessoires",
        summary: "Récapitulatif",
      },
      summaryHint:
        "Vérifiez les informations puis enregistrez. « Enregistrer et valider » applique les modifications et finalise l'installation.",
    },
    detail: {
      notFound: "Installation introuvable",
      actions: {
        edit: "Modifier",
        validate: "Valider l'installation",
        validating: "Validation…",
        save: "Enregistrer",
        saving: "Enregistrement…",
        cancel: "Annuler",
        editTitle: "Modifier l'installation",
        incomplete: "Installation incomplète :",
        actionError: "L'action a échoué. Réessayez.",
        addWiring: "Ajouter un fil",
        unlinkFleet: "Détacher du parc",
        fleetSearchPlaceholder: "Rechercher une plaque ou un VIN dans le parc…",
        fleetSearchEmpty: "Aucun véhicule trouvé",
      },
      sections: {
        intervention: "Intervention",
        vehicle: "Véhicule",
        device: "Boîtier",
        wiring: "Câblage",
        validation: "Validation GPS",
        accessories: "Accessoires",
        photos: "Photos",
        notes: "Commentaires",
      },
      fields: {
        installer: "Installateur",
        interventionDate: "Date d'intervention",
        location: "Emplacement",
        duration: "Durée",
        licensePlate: "Immatriculation",
        vin: "VIN",
        fleetVehicle: "Véhicule du parc",
        fleetLinked: (id: number) => `Rattaché — véhicule #${id}`,
        fleetNotLinked: "Non rattaché au parc",
        odometer: "Km compteur (saisie)",
        hourMeter: "Horamètre (saisie)",
        fuelLevel: "Niveau carburant (saisie)",
        odometerGps: "Km compteur (test GPS)",
        hourMeterGps: "Horamètre (test GPS)",
        fuelLevelGps: "Niveau carburant (test GPS)",
        model: "Modèle",
        productLine: "Gamme de produit",
        telematicsBox: "Boîtier (catalogue)",
        imei: "IMEI",
        stockOrigin: "Origine du stock",
        canModule: "Module CAN",
        canModuleType: "Type de module CAN",
        simIccid: "ICCID SIM",
        simOperator: "Opérateur SIM",
        simApn: "APN SIM",
        contactDetected: "Contact détecté",
        gpsDate: "Position GPS le",
        gpsAddress: "Adresse GPS",
        satellites: "Satellites",
        wire: "Fil",
        accessory: "Accessoire",
      },
      fuelLevels: {
        none: "Vide",
        quarter: "1/4",
        half: "1/2",
        three_quarters: "3/4",
        full: "Plein",
      } as Record<string, string>,
      stockOrigins: {
        client: "Stock client",
        installer: "Stock installateur",
        both: "Mixte",
      } as Record<string, string>,
      photoTypes: {
        vin: "VIN",
        before_install: "Avant installation",
        after_install: "Après installation",
        device_position: "Position du boîtier",
        incident: "Incident",
      } as Record<string, string>,
    },
  },
  antai: {
    searchPlaceholder: "Rechercher par entreprise, véhicule, plaque ou VIN...",
    empty: "Aucun véhicule",
    refresh: "Actualiser",
    queuedHint: "Le traitement est mis en file d'attente — actualisez pour voir le résultat.",
    stats: {
      total: "Total véhicules",
      visible: "Visibles ANTAI",
      hidden: "Masqués",
      exceptions: "Exceptions",
      openExceptions: (n: number) => `${n} ouverte${n !== 1 ? "s" : ""}`,
      archivedSuffix: (n: number) => `dont ${n} archivé${n !== 1 ? "s" : ""}`,
    },
    sort: {
      label: "Trier",
      recentSync: "Sync. récente",
      oldestSync: "Sync. ancienne",
      plateAsc: "Plaque A-Z",
      plateDesc: "Plaque Z-A",
      newest: "Plus récents",
      oldest: "Plus anciens",
    },
    filters: {
      title: "Filtres",
      company: "Entreprise",
      companyStatus: "Compte entreprise",
      vehicleStatus: "Statut véhicule",
      visibility: "Visibilité ANTAI",
      binding: "Liaison",
      archived: "Archivage",
      unbindingReason: "Motif de dissociation",
      exceptionType: "Type d'exception",
      exceptionStatus: "Statut d'exception",
      reset: "Réinitialiser",
      activeCount: (n: number) => `${n} actif${n !== 1 ? "s" : ""}`,
    },
    columns: {
      vehicle: "Véhicule",
      vin: "VIN",
      company: "Entreprise",
      vehicleStatus: "Statut",
      visibility: "Visibilité ANTAI",
      binding: "Liaison",
      archive: "Archivage",
      exception: "Exception",
      lastUpdate: "Dernière maj",
    },
    actions: {
      view: "Voir les détails",
      enable: "Activer la visibilité",
      disable: "Désactiver la visibilité",
      manageException: "Gérer l'exception",
    },
    enable: {
      title: "Activer la visibilité ANTAI",
      description: (name: string) => `Le véhicule « ${name} » sera ajouté à ANTAI (statut Visible).`,
    },
    disable: {
      title: "Désactiver la visibilité ANTAI",
      description: (name: string) => `Le véhicule « ${name} » sera retiré d'ANTAI (statut Masqué).`,
      reasonLabel: "Motif",
    },
    bulk: {
      selected: (n: number) => `${n} véhicule${n !== 1 ? "s" : ""} sélectionné${n !== 1 ? "s" : ""}`,
      enable: "Activer la visibilité",
      disable: "Désactiver la visibilité",
      clear: "Effacer la sélection",
      enableTitle: "Activer la visibilité (lot)",
      enableDescription: (n: number) =>
        `La visibilité ANTAI sera activée pour ${n} véhicule${n !== 1 ? "s" : ""}. Le traitement est mis en file d'attente.`,
      disableTitle: "Désactiver la visibilité (lot)",
      disableDescription: (n: number) =>
        `La visibilité ANTAI sera désactivée pour ${n} véhicule${n !== 1 ? "s" : ""}. Le traitement est mis en file d'attente.`,
      queued: (n: number) => `${n} véhicule${n !== 1 ? "s" : ""} mis en file d'attente`,
    },
    cascade: {
      action: "Désactiver tous les véhicules ANTAI",
      title: "Désactiver les véhicules de l'entreprise",
      description: (company: string) =>
        `Tous les véhicules non masqués de « ${company} » seront retirés d'ANTAI (motif : compte désactivé). Le traitement est mis en file d'attente.`,
      queued: (n: number) => `${n} véhicule${n !== 1 ? "s" : ""} mis en file d'attente`,
    },
    exception: {
      badge: (type: string, status: string) => `${type} · ${status}`,
      title: "Gérer l'exception",
      subtitle: "Suivi de la résolution. Ceci ne modifie pas l'état ANTAI réel — utilisez Activer/Désactiver pour cela.",
      statusLabel: "Statut de résolution",
      typeLabel: "Type d'exception",
      resolutionLabel: "Résolution",
      resolutionHelp: "L'incident peut-il être résolu en interne ou nécessite-t-il une intervention externe (ANTAI) ?",
      detailLabel: "Détail",
      detailPlaceholder: "Notes de suivi, référence du ticket ANTAI...",
      detailMaxLength: "Le détail ne peut pas dépasser 2000 caractères",
      none: "Aucune",
      submit: "Enregistrer",
      resolvedAt: (date: string) => `Résolue le ${date}`,
      updated: "Exception mise à jour",
    },
    toasts: {
      enabled: "Visibilité activée",
      disabled: "Visibilité désactivée",
    },
    detail: {
      notFound: "Véhicule introuvable",
      sections: {
        antaiStatus: "État ANTAI",
        vehicle: "Véhicule",
        company: "Entreprise",
        exception: "Exception",
      },
      fields: {
        plate: "Plaque",
        vin: "VIN",
        mark: "Marque",
        model: "Modèle",
        motorType: "Motorisation",
        vehicleStatus: "Statut véhicule",
        companyAccount: "Compte entreprise",
        visibility: "Visibilité ANTAI",
        binding: "Liaison",
        archive: "Archivage",
        unbindingReason: "Motif de dissociation",
        clientCode: "Code client ANTAI",
        lastUpdate: "Dernière synchronisation",
        createdAt: "Créé le",
        exceptionType: "Type",
        exceptionStatus: "Statut",
        exceptionResolution: "Résolution",
        exceptionDetail: "Détail",
        resolvedAt: "Résolue le",
      },
    },
    enums: {
      visibility: {
        visible: "Visible",
        hidden: "Masqué",
        exception: "Exception",
      },
      binding: {
        bound: "Lié",
        unbound: "Dissocié",
        exception: "Exception",
      },
      companyStatus: {
        active: "Actif",
        disabled: "Désactivé",
      },
      archived: {
        active: "Actif",
        archived: "Archivé",
      },
      unbindingReason: {
        manual: "Manuel",
        company_disabled: "Compte désactivé",
        external_removal: "Retrait externe",
        exception: "Exception",
      },
      exceptionType: {
        already_linked_other_client: "Déjà lié à un autre code client",
        removed_externally: "Retiré en externe",
        sync_failure: "Échec de synchronisation",
        antai_rejection: "Rejet ANTAI",
        other: "Autre",
      },
      exceptionStatus: {
        open: "Ouverte",
        in_progress: "En cours",
        resolved: "Résolue",
      },
      exceptionResolution: {
        internal: "Interne",
        external: "Externe",
      },
      disableReason: {
        manual: "Manuel",
        external_removal: "Retrait externe",
        company_disabled: "Compte désactivé",
      },
    },
  },
  internalUsers: {
    inviteButton: "Inviter un utilisateur",
    roleSettingsButton: "Paramètres des rôles",
    searchPlaceholder: "Rechercher par nom ou email...",
    empty: "Aucun utilisateur interne trouvé",
    noActivity: "—",
    stats: {
      total: "Total",
      active: "Actifs",
      invited: "Invitations",
      suspended: "Suspendus",
    },
    filters: {
      role: "Rôle",
      allRoles: "Tous les rôles",
      status: "Statut",
      allStatuses: "Tous les statuts",
    },
    columns: {
      user: "Utilisateur",
      role: "Rôle",
      status: "Statut",
      lastActivity: "Dernière activité",
      createdAt: "Créé le",
    },
    actions: {
      edit: "Éditer",
      permissions: "Permissions",
      resendInvitation: "Renvoyer l'invitation",
      delete: "Supprimer",
    },
    roleLabels: {
      super_admin: "Super Admin",
      admin: "Admin",
      support: "Support",
      commercial: "Commercial",
      read_only: "Lecture seule",
    } as Record<string, string>,
    statusLabels: {
      active: "Actif",
      invited: "Invité",
      suspended: "Suspendu",
    } as Record<string, string>,
    permissionLabels: {
      "tickets.manage": "Gérer les tickets",
      "tickets.view": "Consulter les tickets",
      "companies.manage": "Gérer les entreprises",
      "users.manage": "Gérer les utilisateurs clients",
      "internal.manage": "Gérer les utilisateurs internes",
      "telematic.manage": "Gérer les commandes télématique",
      "catalog.manage": "Gérer le catalogue produit",
      "subscriptions.manage": "Gérer les abonnements",
      "admin_vehicles.manage": "Gérer les véhicules",
      "logs.view": "Consulter les journaux",
      "rfid.manage": "Gérer les cartes RFID",
      "impersonate.use": "Se connecter en tant qu'utilisateur (impersonation)",
    } as Record<string, string>,
    invite: {
      title: "Inviter un utilisateur",
      subtitle: "Un email d'invitation sera envoyé.",
      submit: "Envoyer l'invitation",
    },
    edit: {
      title: "Éditer l'utilisateur",
      subtitle: "Mettre à jour les informations du membre.",
      submit: "Enregistrer",
    },
    form: {
      fullName: "Nom complet",
      email: "Email",
      role: "Rôle",
      status: "Statut",
    },
    roleHint: (role: string, count: number) =>
      `Le rôle ${role} inclut par défaut ${count} permission(s). Vous pourrez les ajuster depuis l'action « Permissions ».`,
    permissionsDialog: {
      title: (name: string) => `Permissions de ${name}`,
      baseRole: (role: string) => `Rôle de base : ${role}`,
      modified: "Modifié",
    },
    roleSettings: {
      title: "Paramètres des rôles",
      subtitle: "Définir les permissions par défaut pour chaque rôle.",
    },
    delete: {
      title: "Supprimer l'utilisateur",
      description: (name?: string) =>
        `Voulez-vous vraiment supprimer "${name ?? ""}" ?`,
    },
    toasts: {
      invited: "Invitation envoyée",
      updated: "Utilisateur mis à jour",
      deleted: "Utilisateur supprimé",
      invitationResent: "Invitation renvoyée",
      permissionsSaved: "Permissions enregistrées",
      roleUpdated: "Rôle mis à jour",
    },
  },
  dormantAccounts: {
    hint: "Comptes gratuits restés sans activité le temps fixé par leur offre (réglage « Fermeture après inactivité », 12 mois pour l'offre gratuite) : prévenus par e-mail 30 jours avant, puis fermés. Un compte fermé garde toutes ses données ; « Restaurer » rend l'accès à ses utilisateurs.",
    searchPlaceholder: "Rechercher une entreprise ou un e-mail...",
    empty: "Aucun compte dormant",
    status: { all: "Tous", notified: "Prévenus", closed: "Fermés", restored: "Restaurés" },
    badges: { notified: "Prévenu", closed: "Fermé", restored: "Restauré" },
    columns: { company: "Entreprise", lastActivity: "Dernière activité", status: "État", action: "" },
    notified: (on: string, closeOn: string) => `Prévenu le ${on} · fermeture le ${closeOn}`,
    closed: (date: string) => `Fermé le ${date}`,
    restored: (date: string, who?: string | null) => (who ? `Restauré le ${date} par ${who}` : `Restauré le ${date}`),
    restore: "Restaurer",
    confirm: {
      title: "Restaurer ce compte ?",
      description: (name?: string) =>
        `${name ?? "Ce compte"} retrouve son accès : ses utilisateurs peuvent de nouveau se connecter à Dadycar Fleet et à DadycarGo, avec toutes leurs données. Le décompte d'inactivité repart d'aujourd'hui.`,
    },
    toasts: { restored: "Compte restauré" },
  },
  upsellSignals: {
    hint: "Entreprises qui ont atteint une limite de leur offre : à appeler. Les nouveaux signaux partent aussi chaque matin par e-mail à l'équipe commerciale.",
    searchPlaceholder: "Rechercher une entreprise ou un e-mail...",
    empty: "Aucun signal",
    status: { open: "À traiter", handled: "Traités", all: "Tous" },
    allKinds: "Tous les signaux",
    columns: {
      company: "Entreprise",
      contact: "Contact",
      signal: "Signal",
      occurrences: "Fois",
      lastSeen: "Dernier",
      follow: "Suivi",
    },
    vehicles: (n: number) => `${n} véhicule${n > 1 ? "s" : ""}`,
    seenAgain: "de nouveau",
    handledBy: (who: string, date: string) => `Traité par ${who} le ${date}`,
    handledOn: (date: string) => `Traité le ${date}`,
    markHandled: "Marquer traité",
    reopen: "Rouvrir",
    toasts: { handled: "Signal marqué traité", reopened: "Signal rouvert" },
  },
  entitlements: {
    planButton: "Fonctionnalités",
    planTitle: (name: string) => `Fonctionnalités — ${name}`,
    planHint: "Ce que le plan inclut. Un module non listé suit le comportement par défaut du plan.",
    defaultLabel: "Comportement par défaut",
    states: { allow: "Inclus", preview: "Aperçu", deny: "Exclu" },
    capabilities: "Modules",
    quotas: "Limites",
    fromDefault: "par défaut",
    unlimited: "Illimité",
    periods: { lifetime: "À vie", month: "Par mois" },
    // How a limit without a period is counted: read from the data, or a plain setting.
    counters: { live: "Compté sur les données", setting: "Réglage" } as Record<string, string>,
    save: "Enregistrer",
    saved: "Fonctionnalités enregistrées",
    unlimitedPlanNotice: "Ce plan est illimité : il inclut tout, quelles que soient ces lignes.",
    search: "Rechercher…",
    companyMenu: "Offre et fonctionnalités",
    companyTitle: (name: string) => `Offre et fonctionnalités — ${name}`,
    companyHint: "Le plan de l'entreprise, et les exceptions qui ne valent que pour elle.",
    plan: "Plan",
    noPlan: "Aucun plan",
    planChanged: "Plan de l'entreprise mis à jour",
    planState: "Plan",
    effective: "Effectif",
    override: "Exception",
    setOverride: "Exception",
    removeOverride: "Retirer",
    overrideTitle: (label: string) => `Exception — ${label}`,
    overrideSaved: "Exception enregistrée",
    overrideRemoved: "Exception retirée",
    note: "Note",
    expiresAt: "Jusqu'au (facultatif)",
    expired: "expirée",
    used: "Utilisé",
    limit: "Plafond",
    planLimit: "Plafond du plan",
    resetUsage: "Remettre à zéro",
    usageReset: "Compteur remis à zéro",
    cancel: "Annuler",
  },
  // Plan changes during the month and cancellation (billing automation, part 2).
  subscriptionChanges: {
    title: "Abonnement",
    confirmPlanTitle: (name: string) => `Passer à l'offre ${name}`,
    appliesNow: "Le changement s'applique immédiatement. Les droits suivent l'offre dès la prochaine requête.",
    supplement: (amount: string, vehicles: number, days: number, month: number) =>
      `Ce mois-ci : +${amount} HT ajoutés à la prochaine facture (${vehicles} véhicules, ${days} jours sur ${month}).`,
    credit: (amount: string, vehicles: number, days: number, month: number) =>
      `Ce mois-ci : ${amount} HT déduits de la prochaine facture (${vehicles} véhicules, ${days} jours sur ${month}).`,
    // No prorata: month not invoiced yet, no vehicle invoiced, same price, or a contract client.
    noAdjustment: "Aucun ajustement sur le mois en cours.",
    nextMonth: (vehicles: number, amount: string) =>
      `Ensuite, chaque mois : ${vehicles} véhicule${vehicles > 1 ? "s" : ""} = ${amount} HT.`,
    // Billed by its vehicles' plans: the offer moves on the vehicles holding it, the other plans stay.
    nextMonthVehiclePlans: (vehicles: number, amount: string) =>
      `Ensuite, chaque mois : les plans de ${vehicles} véhicule${vehicles > 1 ? "s" : ""} = ${amount} HT.`,
    confirmChange: "Confirmer le changement",
    planChanged: "Offre modifiée",
    noCancellation: "Aucune résiliation en cours.",
    endsOn: (date: string, source: string) => `Résiliation prévue : fin le ${date} (demandée par ${source}).`,
    endedOn: (date: string) => `Abonnement terminé le ${date}.`,
    reason: "Motif",
    sources: { client: "le client", admin: "Dadycar" },
    cancel: "Résilier",
    cancelTitle: "Résilier l'abonnement",
    cancelHint: "L'accès reste ouvert jusqu'à la date de fin incluse ; aucune facture n'est émise pour les mois suivants. Par défaut : fin du mois en cours, déjà facturé.",
    endDate: "Date de fin",
    reasonPlaceholder: "Motif (facultatif)",
    confirmCancel: "Confirmer la résiliation",
    cancelled: "Résiliation enregistrée",
    undo: "Annuler la résiliation",
    undone: "Résiliation annulée",
    pending: "Sur la prochaine facture",
    history: "Historique",
    kinds: {
      vehicle_plans: "Plans des véhicules",
      plan_change: "Changement d'offre",
      cancellation: "Résiliation",
      cancellation_undone: "Résiliation annulée",
      trial_started: "Essai démarré",
      trial_stopped: "Essai arrêté par le client",
      trial_resumed: "Essai repris",
      trial_converted: "Fin de l'essai : offre payante",
      trial_ended: "Fin de l'essai : plan gratuit",
    },
    trialUntil: (date: string) => `jusqu'au ${date}`,
    trialEndsOn: (date: string) => `fin le ${date}`,
    trialRunning: (plan: string, date: string, how: string) => `Essai ${plan} jusqu'au ${date}, ${how} : facturé à partir du lendemain.`,
    trialStopped: (date: string) => `Essai arrêté par le client : retour au plan gratuit après le ${date}, rien n'est facturé.`,
    trialConverted: (from: string, to: string) => `Essai du ${from} au ${to}, puis offre payante.`,
    trialEnded: (from: string, to: string) => `Essai du ${from} au ${to}, puis retour au plan gratuit.`,
    trialCard: (brand: string, last: string) => `carte ${brand} •••• ${last}`,
    trialSepa: "prélèvement SEPA",
    date: "Date",
    event: "Événement",
    by: "Par",
    invoiced: "facturé",
    empty: "Aucun changement enregistré.",
    close: "Fermer",
    frequencies: { monthly: "mensuel", yearly: "annuel", quarterly: "trimestriel", half_yearly: "semestriel" },
  },
};
