import { formatFileSize } from "../kit-labels";
import type { UiKitLabels } from "../kit-labels";

/**
 * The kit's words in French: every namespace of {@link UiKitLabels}, for
 * `<UiKitProvider labels={UI_KIT_LABELS_FR}>`.
 *
 * Self-contained on purpose — nothing but the kit's own `formatFileSize` — so it works
 * as a starting point to copy and adjust. Counts and sizes are formatted with
 * `fr-FR` digits; {@link uiKitLabelsFr} takes another number locale
 * (e.g. `"de-CH"` for 1’234) without touching the words.
 */
export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
  const num = new Intl.NumberFormat(numberLocale);
  const n = (value: number) => num.format(value);
  const plural = (count: number, one: string, many: string) => (count < 2 ? one : many);

  return {
    feedbackAttachment: {
      attachmentAdd: "Joindre une image",
      attachmentCapture: "Capturer l’écran",
      attachmentPaste: "…ou collez une capture d’écran depuis le presse-papiers.",
      attachmentRemove: "Retirer la pièce jointe",
    },
    feedbackDialog: {
      title: "Envoyer un retour",
      category: "Catégorie",
      subject: "Objet",
      body: "Que s’est-il passé\u202f?",
      bodyOptional: "Que s’est-il passé\u202f? (facultatif)",
      attachment: "Capture d’écran",
      submitHint: "Ctrl/⌘ + Entrée pour envoyer",
      cancel: "Annuler",
      save: "Envoyer",
    },
    feedbackThread: {
      thread: "Commentaires",
      empty: "Aucun commentaire pour l’instant",
      loading: "Chargement des commentaires…",
      you: "Vous",
      staff: "Équipe",
      attachments: "Pièces jointes",
    },
    feedbackComposer: {
      field: "Écrire un commentaire",
      placeholder: "Écrire un commentaire…",
      send: "Envoyer",
      sendHint: (modifier) => `${modifier} + Entrée pour envoyer`,
      sendHintEnter: "Entrée pour envoyer, Maj + Entrée pour aller à la ligne",
    },
    accountSettings: {
      profile: {
        title: "Profil",
        email: "E-mail",
        role: "Rôle",
        memberSince: "Membre depuis",
        displayName: "Nom affiché",
        save: "Enregistrer",
      },
      password: {
        title: "Changer le mot de passe",
        current: "Mot de passe actuel",
        next: "Nouveau mot de passe",
        confirm: "Confirmer le nouveau mot de passe",
        submit: "Changer le mot de passe",
        tooShort: "Le nouveau mot de passe est trop court.",
        mismatch: "Les mots de passe ne correspondent pas.",
      },
      twoFactor: {
        status: "Authentification à deux facteurs",
        enabledText: "Activée",
        disabledText: "Désactivée",
        enable: "Configurer l’authentification à deux facteurs",
        scanHint:
          "Scannez ce code avec votre application d’authentification, puis saisissez le code affiché.",
        codeLabel: "Code de vérification",
        verify: "Vérifier et activer",
        disableSection: "Désactiver l’authentification à deux facteurs",
        password: "Mot de passe actuel",
        disable: "Désactiver",
        qrAlt: "Code QR pour votre application d’authentification",
        secretHint: "Impossible de le scanner\u202f? Saisissez plutôt cette clé dans l’application\u00a0:",
        copySecret: "Copier la clé",
      },
      passkeys: {
        title: "Clés d’accès",
        description:
          "Connectez-vous avec votre empreinte, votre visage ou le code PIN de l’appareil plutôt qu’avec un mot de passe.",
        empty: "Aucune clé d’accès pour l’instant",
        loading: "Chargement des clés d’accès…",
        list: "Vos clés d’accès",
        nameLabel: "Nom (facultatif)",
        namePlaceholder: "p. ex. Portable, Téléphone",
        add: "Ajouter une clé d’accès",
        adding: "En attente de l’appareil…",
        rename: "Renommer",
        renameItem: (name) => `Renommer ${name}`,
        renameField: (name) => `Nouveau nom pour ${name}`,
        save: "Enregistrer",
        cancel: "Annuler",
        delete: "Supprimer",
        deleteItem: (name) => `Supprimer ${name}`,
        deleteConfirm: (name) =>
          `Supprimer «\u202f${name}\u202f»\u202f? Elle ne permettra plus de se connecter.`,
        confirmDelete: "Supprimer la clé d’accès",
        created: (date) => `Ajoutée le ${date}`,
        lastUsed: (date) => `Dernière utilisation le ${date}`,
        neverUsed: "Jamais utilisée",
      },
    },
    measuredGrid: {
      view: "Vue du tableau",
      cellsView: "Cellules",
      textView: "Texte",
      addRow: "Ajouter une ligne",
      removeRow: (row) => `Supprimer la ligne ${row}`,
      clear: "Vider le tableau",
      pasteHint: "Collez un bloc copié d\u2019un tableur dans n\u2019importe quelle cellule",
      cell: (column, row) => `${column}, ligne ${row}`,
      rowNumber: "Ligne",
      rowActions: "Actions de ligne",
      keyboardHint:
        "Les flèches passent d\u2019une cellule à l\u2019autre. Tapez pour remplacer une cellule, F2 pour la modifier, Échap pour annuler la modification. Entrée descend et ajoute une ligne à la fin.",
      lineError: (line) => `La ligne ${line} n\u2019a pas pu être lue`,
      points: (count) => (count < 2 ? `${count} point` : `${count} points`),
      problems: (count) =>
        count < 2
          ? `${count} cellule n\u2019est pas un nombre`
          : `${count} cellules ne sont pas des nombres`,
    },
    pageContents: { title: "Sur cette page" },
    common: {
      dismiss: "Fermer",
      close: "Fermer",
      clear: "Effacer",
      search: "Rechercher",
      done: "Terminé",
      cancel: "Annuler",
      save: "Enregistrer",
      back: "Retour",
      next: "Suivant",
      remove: "Supprimer",
      loading: "Chargement…",
      noResults: "Aucun résultat",
      // No-break space before the colon, per French typography.
      fieldValue: (field, value) => `${field}\u00a0: ${value}`,
      opensInNewTab: "s’ouvre dans un nouvel onglet",
    },
    dataTable: {
      columns: "Colonnes",
      selectAllRows: "Sélectionner toutes les lignes",
      sortHint: "Cliquer pour trier · Maj+clic pour ajouter un tri",
      filter: "Filtrer",
      close: "Fermer",
      selectRow: "Sélectionner la ligne",
      autoSize: "Ajuster la largeur des colonnes",
      loading: "Chargement…",
      filters: "Filtres",
      clearAll: "Tout effacer",
      done: "Terminé",
      pageSize: "Lignes par page",
      pageSizeAll: "Toutes",
      prevPage: "Page précédente",
      nextPage: "Page suivante",
      clearFilter: "Effacer le filtre",
      filterPlaceholder: "Filtrer…",
      selectFilter: "Sélectionner",
      selectAll: "Tout",
      selectNone: "Aucun",
      dateFrom: "Du",
      dateTo: "Au",
      numberMin: "Min.",
      numberMax: "Max.",
      numberAbs: "Valeur absolue",
      presets: {
        today: "Aujourd’hui",
        yesterday: "Hier",
        this_week: "Cette semaine",
        last_week: "Semaine dernière",
        last_7_days: "7 derniers jours",
        last_30_days: "30 derniers jours",
        this_month: "Ce mois-ci",
        last_month: "Mois dernier",
        last_3_months: "3 derniers mois",
        ytd: "Depuis le début de l’année",
        last_year: "Année dernière",
      },
      table: "Tableau de données",
      filterResults: (shown, total) =>
        `${n(shown)} ${plural(shown, "ligne", "lignes")} sur ${n(total)}`,
      sortedAscending: (column) => `Trié par ${column}, ordre croissant`,
      sortedDescending: (column) => `Trié par ${column}, ordre décroissant`,
      sortCleared: (column) => `Tri retiré sur ${column}`,
      pageChanged: (page, totalPages) => `Page ${n(page)} sur ${n(totalPages)}`,
      pageRange: (from, to, total) => `${n(from)}–${n(to)} / ${n(total)}`,
      rowCount: (total) => n(total),
      columnsCount: (visible, total) => `Colonnes (${n(visible)}/${n(total)})`,
      empty: "Aucune entrée",
      actions: "Actions",
      edit: "Modifier",
      delete: "Supprimer",
      booleanTrue: "Oui",
      booleanFalse: "Non",
      booleanUnset: "Non défini",
    },
    miniCalendar: {
      previousMonth: "Mois précédent",
      nextMonth: "Mois suivant",
      // Already formatted in the provider's locale ("lundi 14 septembre 2026").
      day: (date) => date,
      chooseStart: "Choisissez une date de début",
      chooseEnd: "Choisissez une date de fin",
      // "Date" is feminine and the formatted day is not a noun French can agree with,
      // so the date is set after a label rather than made the subject.
      startSelected: (date) => `Date de début\u00a0: ${date}. Choisissez une date de fin.`,
      rangeSelected: (from, to) =>
        `Période du ${from} au ${to} sélectionnée. Choisissez une date de début pour recommencer.`,
    },
    calendarHeatmap: {
      grid: "Valeurs quotidiennes",
      day: (date, value) => `${date} : ${value}`,
      less: "Moins",
      more: "Plus",
      truncated: (count) =>
        `Affichage des jours les plus récents ; ${n(count)} ${count === 1 ? "jour antérieur n’est pas affiché" : "jours antérieurs ne sont pas affichés"}.`,
    },
    datePicker: {
      apply: "Appliquer",
      cancel: "Annuler",
      presets: "Plages rapides",
      panel: "Choisir une date",
      rangePanel: "Choisir une période",
      clear: "Effacer",
      previousDay: "Jour précédent",
      nextDay: "Jour suivant",
      today: "Aujourd’hui",
    },
    monthPicker: {
      previousYear: "Année précédente",
      nextYear: "Année suivante",
      panel: "Choisir un mois",
      month: (monthYear) => monthYear,
      previousMonth: "Mois précédent",
      nextMonth: "Mois suivant",
      today: "Aujourd’hui",
    },
    popover: {
      panel: "Fenêtre contextuelle",
    },
    combobox: {
      search: "Rechercher",
      noResults: "Aucun résultat",
      clear: "Effacer",
      loading: "Chargement…",
      create: (query) => `Créer «\u202f${query}\u202f»`,
      selectedCount: (count) => `${n(count)} ${plural(count, "sélectionné", "sélectionnés")}`,
      loadError: "Impossible de charger les résultats",
      resultCount: (count) => `${n(count)} ${plural(count, "résultat", "résultats")}`,
      minChars: (count) =>
        `Saisissez au moins ${n(count)} ${plural(count, "caractère", "caractères")}`,
    },
    multiSelect: {
      search: "Rechercher",
      selectAll: "Tout sélectionner",
      clear: "Effacer",
      all: "Tous",
      // The bare count, as in English: the trigger has always shown just the number.
      selectedCount: (count) => n(count),
    },
    calculator: {
      open: "Ouvrir la calculatrice",
      panel: "Calculatrice",
      calculation: "Calcul",
      backspace: "Retour arrière",
      clear: "Effacer",
      equals: "Égal",
      done: "Terminé",
      plus: "Plus",
      minus: "Moins",
      times: "Multiplié par",
      divide: "Divisé par",
      decimal: "Séparateur décimal",
    },
    currency: {
      currency: "Devise",
      search: "Rechercher une devise",
    },
    chipInput: {
      // The quoted value is a citation; the participle agrees with the implied
      // "élément" whatever the chip says.
      added: (value) => `«\u202f${value}\u202f» ajouté`,
      removed: (value) => `«\u202f${value}\u202f» supprimé`,
      remove: "Supprimer",
      atLimit: (max) => `Limite de ${n(max)} ${plural(max, "élément", "éléments")} atteinte`,
      duplicate: (value) => `«\u202f${value}\u202f» figure déjà dans la liste`,
    },
    swatchPicker: {
      none: "Aucune couleur",
      mixed: "Mixte\u00a0: les éléments sélectionnés ont des couleurs différentes",
    },
    iconPicker: {
      none: "Aucune icône",
      mixed: "Mixte\u00a0: les éléments sélectionnés ont des icônes différentes",
      search: "Rechercher des icônes",
      noResults: "Aucune icône ne correspond",
      resultCount: (count) => `${n(count)} ${plural(count, "icône", "icônes")}`,
    },
    fieldSync: {
      synced: "Enregistré",
      edited: "Modifications non enregistrées",
      pending: "Enregistrement…",
      error: "Échec de l’enregistrement",
      retry: "Réessayer",
    },
    passwordReveal: {
      show: "Afficher le mot de passe",
      hide: "Masquer le mot de passe",
    },
    dangerConfirm: {
      arm: "Supprimer…",
      confirm: "Supprimer",
      cancel: "Annuler",
      prompt: "Cette action est irréversible.",
      password: "Mot de passe",
      phrase: (phrase) => `Saisissez «\u202f${phrase}\u202f» pour confirmer`,
    },
    tabs: {
      add: "Ajouter un onglet",
      remove: (tab) => `Supprimer ${tab}`,
    },
    appShell: {
      collapse: "Réduire la barre latérale",
      expand: "Développer la barre latérale",
      toggleGroup: (groupLabel) => `${groupLabel}\u00a0: pages`,
    },
    topBar: {
      theme: "Changer de thème",
      palette: "Préréglage d’apparence",
      language: "Langue",
      switchRole: "Changer de rôle",
      role: (value) => `Rôle\u00a0: ${value}`,
    },
    pickerSheet: {
      close: "Fermer",
    },
    dialogFrame: {
      close: "Fermer",
    },
    bulkActionBar: {
      selected: (count) => `${n(count)} ${count === 1 ? "sélectionné" : "sélectionnés"}`,
      clear: "Effacer la sélection",
      cleared: "Sélection effacée",
    },
    swipeableRow: {
      actions: "Actions de la ligne",
    },
    file: {
      // The kit's own `Intl` unit formatting, pinned to this locale ("3,4 Mo").
      size: (bytes) => formatFileSize(bytes, numberLocale),
    },
    filePicker: {
      dropzone: "Envoi de fichier",
      browse: "Parcourir",
      empty: "Déposez un fichier ici",
      emptyMultiple: "Déposez des fichiers ici",
      hint: (accept) => (accept ? `Acceptés\u00a0: ${accept}` : "Tout type de fichier"),
      busy: "Envoi en cours…",
      rejectedPick: (count) =>
        count < 2
          ? "Le fichier n\u2019a pas été ajouté"
          : `Aucun des ${count} fichiers n\u2019a été ajouté`,
      rejectedType: (name) => `Le type du fichier «\u202f${name}\u202f» n’est pas pris en charge`,
      rejectedTypeOnly: (accept) => `Uniquement des fichiers ${accept}`,
      rejectedSize: (name, maxSize) => `«\u202f${name}\u202f» dépasse ${maxSize}`,
      rejectedCount: (name, maxFiles) =>
        `«\u202f${name}\u202f» n’a pas été ajouté\u00a0: ${n(maxFiles)} ${plural(maxFiles, "fichier", "fichiers")} au maximum`,
      rejectedInvalid: (name) => `«\u202f${name}\u202f» ne peut pas être utilisé ici`,
      rejectedMany: (count) =>
        count < 2
          ? `${n(count)} fichier n’a pas été ajouté`
          : `${n(count)} fichiers n’ont pas été ajoutés`,
      // The name branch is for exactly one file, as in English; 0 falls to the count.
      selected: (count, firstName) =>
        count === 1
          ? `«\u202f${firstName}\u202f» sélectionné`
          : `${n(count)} ${plural(count, "fichier sélectionné", "fichiers sélectionnés")}`,
      remove: (name) => `Supprimer «\u202f${name}\u202f»`,
      clearAll: "Supprimer tous les fichiers",
      removed: (name) => `«\u202f${name}\u202f» supprimé`,
      cleared: "Tous les fichiers ont été supprimés",
    },
    wizard: {
      done: "Terminé",
      cancel: "Annuler",
      back: "Retour",
      next: "Suivant",
      skip: "Passer",
      finish: "Terminer",
      submitting: "Création…",
      steps: "Étapes",
      step: (current, total) => `Étape ${n(current)} sur ${n(total)}`,
      cancelTitle: "Abandonner ce formulaire\u202f?",
      confirmCancel: "Vos saisies seront perdues.",
      cancelConfirmLabel: "Abandonner",
      cancelDismissLabel: "Continuer la saisie",
      reviewTitle: "Vérification",
      edit: "Modifier",
      missingRequired: "Veuillez remplir tous les champs obligatoires.",
      genericError: "Une erreur est survenue",
    },
    tour: {
      next: "Suivant",
      back: "Retour",
      skip: "Passer",
      done: "Terminé",
      awaitClickHint: "Cliquez sur l’élément mis en évidence pour continuer",
      step: (current, total) => `${n(current)} / ${n(total)}`,
    },
    commandPalette: {
      clear: "Effacer la recherche",
      submit: "Rechercher",
      close: "Fermer",
      placeholder: "Rechercher…",
      empty: "Aucun résultat",
      loading: "Recherche…",
      dialog: "Recherche",
      error: "La recherche a échoué. Réessayez.",
    },
    globalSearch: {
      trigger: "Rechercher",
      placeholder: "Rechercher ou aller à…",
      shortcut: (keys) => `Rechercher (${keys})`,
      suggestions: "Essayez",
      results: "Résultats",
    },
    sparkline: {
      // "En hausse de 12 à 40" would read as "up BY 12", hence the colon.
      rising: (first, last) => `En hausse\u00a0: de ${first} à ${last}`,
      falling: (first, last) => `En baisse\u00a0: de ${first} à ${last}`,
      flat: (value) => `Stable à ${value}`,
      single: (value) => `Une seule valeur\u00a0: ${value}`,
      noData: "Aucune donnée",
      named: (name, summary) => `${name}\u00a0: ${summary}`,
    },
    statTile: {
      increase: (amount) => `En hausse de ${amount}`,
      decrease: (amount) => `En baisse de ${amount}`,
      unchanged: "Sans changement",
      better: (change) => `${change} (favorable)`,
      worse: (change) => `${change} (défavorable)`,
      noValue: "Aucune donnée",
      loading: "Chargement…",
    },
    signaturePad: {
      label: "Signature",
      instructions: "Signez dans le cadre avec une souris, votre doigt ou un stylet.",
      typedFallbackHint: "Si vous ne pouvez pas dessiner, saisissez plutôt votre nom.",
      empty: "Aucun tracé pour l’instant",
      signed: "Signature tracée",
      undo: "Annuler le dernier trait",
      clear: "Effacer",
      save: "Enregistrer la signature",
      useTyped: "Saisir le nom à la place",
      useDrawn: "Dessiner à la place",
      typedName: "Nom complet",
      cleared: "Signature effacée",
      undone: "Dernier trait supprimé",
      viewEmpty: "Non signé",
      viewDrawn: "Signature manuscrite",
      viewTyped: (name) => `Signé avec le nom saisi ${name}`,
    },
    passwordStrength: {
      // Agrees with "mot de passe" (masculine).
      tooShort: "Trop court",
      weak: "Faible",
      fair: "Moyen",
      good: "Bon",
      strong: "Fort",
      announcement: (level) => `Robustesse du mot de passe\u00a0: ${level}`,
      // Unformatted, as in the English default.
      ruleLength: (minLength) =>
        `Au moins ${minLength} ${plural(minLength, "caractère", "caractères")}`,
      ruleCase: "Majuscules et minuscules",
      ruleDigit: "Un chiffre",
      ruleSymbol: "Un caractère spécial",
      optional: (rule) => `${rule} (facultatif)`,
      met: "Respecté\u00a0:",
      notMet: "Non respecté\u00a0:",
      tooLong: (maxBytes) =>
        `Au plus ${maxBytes} ${plural(maxBytes, "caractère", "caractères")} (les lettres accentuées et les emoji comptent pour plus d’un).`,
    },
    seriesChart: {
      resetZoom: "Réinitialiser le zoom",
      zoomHint:
        "Faites glisser pour zoomer\u00a0: une sélection à peu près carrée zoome sur les deux axes, une sélection longue et étroite sur son seul axe. Double-cliquez pour réinitialiser.",
      empty: "Aucune donnée",
      legend: "Séries",
      points: "Valeurs du graphique",
    },
    pieChart: {
      slices: "Secteurs du graphique",
      slice: (label, value, percent) => `${label}\u00a0: ${value} (${percent})`,
      total: "Total",
      empty: "Aucune donnée",
      legend: "Catégories",
    },
    confirmDialog: {
      confirm: "Confirmer",
      cancel: "Annuler",
    },
    floatingPanel: {
      close: "Fermer",
      badge: (count) => `${n(count)} ${plural(count, "nouveau", "nouveaux")}`,
    },
    copyButton: {
      copy: "Copier",
      copied: "Copié",
      failed: "Échec de la copie",
      copiedAnnouncement: "Copié dans le presse-papiers",
      failedAnnouncement: "Impossible de copier dans le presse-papiers",
    },
    list: {
      unread: "Non lu",
      opensInNewTab: "s’ouvre dans un nouvel onglet",
    },
    breadcrumbs: {
      label: "Fil d’Ariane",
      showAll: "Afficher le chemin complet",
    },
    toast: {
      close: "Fermer la notification",
      notifications: "Notifications",
      undo: "Annuler",
      redo: "Rétablir",
    },
    form: {
      save: "Enregistrer",
      cancel: "Annuler",
    },
    descriptionList: {
      empty: "—",
    },
    lineItems: {
      add: "Ajouter une ligne",
      remove: (row) => `Supprimer la ligne ${row}`,
      confirmRemove: (row) => `Supprimer la ligne ${row}\u202f? Appuyez de nouveau pour confirmer`,
      row: (row) => `Ligne ${row}`,
      cell: (column, row) => `${column}, ligne ${row}`,
      totals: "Total",
    },
    progressBar: {
      unlimited: "Illimité",
      overLimit: (amount) => `${amount} au-delà de la limite`,
    },
    signedAmount: {
      positive: (amount) => `plus ${amount}`,
      negative: (amount) => `moins ${amount}`,
    },
    errorBoundary: {
      title: "Une erreur s’est produite",
      message: "Cette partie de la page n’a pas pu s’afficher. Réessayez ou rechargez la page.",
      retry: "Réessayer",
      details: "Détails de l’erreur",
      reload: "Recharger",
      updateTitle: "Une nouvelle version est disponible",
      updateMessage: "Une partie de l’application a changé depuis le chargement de cette page. Rechargez-la pour obtenir la nouvelle version.",
      offlineTitle: "Vous êtes hors ligne",
      offlineMessage: "Cette page n’a pas pu être chargée sans connexion. Reconnectez-vous, puis rechargez la page.",
      copyReport: "Copier le rapport d’erreur",
      reported: "L’erreur a été signalée automatiquement.",
      reportedAs: (reference) => `Signalée sous la référence ${reference}`,
    },
    authedImage: {
      loading: "Chargement de l’image…",
      loadError: "Impossible de charger l’image",
      failedImage: (alt) => `${alt} : impossible de charger l’image`,
    },
    imageGrid: {
      list: "Images",
      item: (index, count) => `Image ${n(index)} sur ${n(count)}`,
      actions: (name) => `Actions pour ${name}`,
    },
    lightbox: {
      dialog: "Visionneuse d’images",
      close: "Fermer",
      previous: "Image précédente",
      next: "Image suivante",
      counter: (index, count) => `${n(index)} / ${n(count)}`,
      position: (index, count) => `Image ${n(index)} sur ${n(count)}`,
      download: "Télécharger",
      zoom: "Agrandir",
      noPreview: "Aucun aperçu disponible pour ce fichier",
      openInNewTab: "Ouvrir dans un nouvel onglet",
    },
  };
}

export const UI_KIT_LABELS_FR: UiKitLabels = uiKitLabelsFr();
