@cosmicdrift/kumiko-locale-fr 0.378.0 → 0.380.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-locale-fr",
3
- "version": "0.378.0",
3
+ "version": "0.380.0",
4
4
  "description": "French UI and mail copy for Kumiko framework screens. Opt in by mounting localeFr() + localeFrClient().",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -28,7 +28,7 @@
28
28
  }
29
29
  },
30
30
  "dependencies": {
31
- "@cosmicdrift/kumiko-framework": "0.378.0"
31
+ "@cosmicdrift/kumiko-framework": "0.380.0"
32
32
  },
33
33
  "publishConfig": {
34
34
  "registry": "https://registry.npmjs.org",
package/src/strings.ts CHANGED
@@ -47,15 +47,20 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
47
47
  "audit.log.col.actor": "Acteur",
48
48
  "audit.log.col.aggregateId": "ID d'agrégat",
49
49
  "audit.log.col.aggregateType": "Type d'agrégat",
50
+ "audit.log.col.tenant": "Locataire",
50
51
  "audit.log.col.type": "Événement",
51
52
  "audit.log.col.when": "Date",
52
53
  "audit.log.detail.field.id": "ID de l'événement",
53
54
  "audit.log.detail.metadata": "Métadonnées",
54
55
  "audit.log.detail.payload": "Payload de l'événement",
56
+ "audit.log.description": "Tous les événements de ce locataire. Une ligne ouvre les détails.",
57
+ "audit.log.allTenants.description":
58
+ "Tous les événements de tous les locataires. Une ligne ouvre les détails.",
55
59
  "audit.log.detail.subtitle":
56
- "Vue détaillée en lecture seule d'un événement d'audit avec l'acteur, l'horodatage, l'agrégat ainsi que le payload et les métadonnées bruts de l'événement ; accessible depuis une ligne du journal d'audit.",
60
+ "Un événement avec son acteur, son horodatage et ses données enregistrées.",
57
61
  "audit.log.details": "Détails",
58
62
  "audit:nav.auditLog": "Journal d'audit",
63
+ "audit:nav.auditLogAllTenants": "Journal d'audit (tous les locataires)",
59
64
  "auth-mfa:entity:__action-form__:field:code": "Code de votre application d'authentification",
60
65
  "auth.errors.accountLocked": "Compte temporairement verrouillé.",
61
66
  "auth.errors.accountLockedRetry": "Compte verrouillé. Réessayez dans {minutes} minutes.",
@@ -537,10 +542,17 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
537
542
  "errors.unconfigured": "Cette fonctionnalité n'est pas encore configurée.",
538
543
  "errors.uniqueViolation": "Cette entrée existe déjà.",
539
544
  "errors.unprocessable": "La requête n'a pas pu être traitée.",
545
+ "errors.file.violatesBindTarget": "Ce fichier ne respecte pas les exigences du champ cible.",
540
546
  "errors.validation.custom": "Valeur invalide.",
541
547
  "errors.validation.failed": "Échec de la validation.",
542
548
  "errors.validation.invalid_element": "Entrée invalide.",
543
549
  "errors.validation.invalid_format": "Format invalide.",
550
+ "errors.validation.invalid_format.email": "Adresse e-mail invalide, p. ex. nom@exemple.fr.",
551
+ "errors.validation.invalid_format.url": "Adresse web invalide, p. ex. https://exemple.fr.",
552
+ "errors.validation.invalid_format.date": "Date invalide, p. ex. 20/10/2026.",
553
+ "errors.validation.invalid_format.datetime": "Date et heure invalides, p. ex. 20/10/2026 14:30.",
554
+ "errors.validation.invalid_format.uuid":
555
+ "Identifiant invalide, p. ex. 123e4567-e89b-12d3-a456-426614174000.",
544
556
  "errors.validation.invalid_key": "Clé invalide.",
545
557
  "errors.validation.invalid_option": "Choix invalide.",
546
558
  "errors.validation.invalid_type": "Valeur invalide.",
@@ -557,6 +569,8 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
557
569
  "kumiko.validation.number.min": "Doit être au moins {minimum}.",
558
570
  "kumiko.validation.number.max": "Doit être {maximum} ou moins.",
559
571
  "errors.validation.too_small": "Trop petit ou trop court (minimum : {minimum}).",
572
+ "errors.validation.list_min_rows.one": "Au moins 1 ligne est requise.",
573
+ "errors.validation.list_min_rows.other": "Au moins {minimum} lignes sont requises.",
560
574
  "errors.validation.unexpected_field": "Champ inconnu.",
561
575
  "errors.validation.unrecognized_keys": "Champs inconnus.",
562
576
  "errors.versionConflict": "L'enregistrement a été modifié entre-temps. Rechargez et réessayez.",
@@ -754,18 +768,24 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
754
768
  "kumiko.field.embedded-list.empty-cta": "Ajouter la première ligne",
755
769
  "kumiko.field.embedded-list.move-down": "Descendre",
756
770
  "kumiko.field.embedded-list.move-up": "Monter",
757
- "kumiko.field.embedded-list.paste-cells-unmatched":
758
- "{count} cellule(s) sans option correspondante ont été laissées inchangées.",
759
- "kumiko.field.embedded-list.paste-rows-truncated":
760
- "{count} ligne(s) collée(s) ont été ignorées (nombre maximal de lignes atteint).",
771
+ "kumiko.field.embedded-list.paste-cells-unmatched.one":
772
+ "1 cellule sans option correspondante a été laissée inchangée.",
773
+ "kumiko.field.embedded-list.paste-cells-unmatched.other":
774
+ "{count} cellules sans option correspondante ont été laissées inchangées.",
775
+ "kumiko.field.embedded-list.paste-rows-truncated.one":
776
+ "1 ligne collée a été ignorée (nombre maximal de lignes atteint).",
777
+ "kumiko.field.embedded-list.paste-rows-truncated.other":
778
+ "{count} lignes collées ont été ignorées (nombre maximal de lignes atteint).",
761
779
  "kumiko.field.embedded-list.remove-row": "Supprimer la ligne",
762
780
  "kumiko.field.file-list.add": "Ajouter un fichier",
763
781
  "kumiko.field.file-list.empty": "Aucun fichier pour l'instant.",
782
+ "kumiko.field.dropzone.limit-count": "jusqu'à {count} fichiers",
783
+ "kumiko.field.dropzone.limit-size": "jusqu'à {size} par fichier",
784
+ "kumiko.field.dropzone.title": "Déposez des fichiers ici ou cliquez pour choisir",
764
785
  "kumiko.field.file-list.move-down": "Descendre le fichier",
765
786
  "kumiko.field.file-list.move-up": "Monter le fichier",
766
787
  "kumiko.field.file-upload.attached": "Fichier joint",
767
788
  "kumiko.field.file-upload.change": "Modifier",
768
- "kumiko.field.file-upload.failed": "Échec du téléversement",
769
789
  "kumiko.field.file-upload.remove": "Supprimer",
770
790
  "kumiko.field.file-upload.upload": "Téléverser",
771
791
  "kumiko.field.fillAction.failed": "Impossible de récupérer une suggestion.",
@@ -815,6 +835,9 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
815
835
  "kumiko.list.count.other": "{count} entrées",
816
836
  "kumiko.list.empty.filtered":
817
837
  "Aucune entrée ne correspond à la recherche ou aux filtres actuels.",
838
+ "kumiko.list.empty.defaultFiltered":
839
+ "Aucune entrée ne correspond au filtre par défaut. Affichez tout pour inclure les entrées hors filtre.",
840
+ "kumiko.list.empty.showAll": "Tout afficher",
818
841
  "kumiko.list.empty.hint": "Créez la première pour commencer.",
819
842
  "kumiko.list.empty.title": "Aucune entrée pour l'instant.",
820
843
  "kumiko.list.end-of-list": "— Fin de la liste —",
@@ -854,6 +877,7 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
854
877
  "kumiko.planCard.priceUnavailable": "Prix non disponible",
855
878
  "kumiko.reference.system-tenant": "Système",
856
879
  "kumiko.reference.system-user": "Système",
880
+ "kumiko.reference.unknown-user": "Inconnu",
857
881
  "kumiko.rowAction.failed": "Échec de l'action",
858
882
  "kumiko.clientAction.success": "Terminé.",
859
883
  "kumiko.clientAction.unregistered": "Cette action n'est pas disponible dans cette application.",
@@ -890,6 +914,10 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
890
914
  "kumiko.widget.upload.done": "Téléversé",
891
915
  "kumiko.widget.upload.error": "Échec",
892
916
  "kumiko.widget.upload.rejected-type": "Type de fichier non autorisé",
917
+ "kumiko.widget.upload.invalid-type": "Type ou contenu de fichier non autorisé",
918
+ "kumiko.widget.upload.max-count": "{count} fichiers au maximum",
919
+ "kumiko.widget.upload.remove": "Retirer le fichier",
920
+ "kumiko.widget.upload.too-large": "Le fichier est trop volumineux",
893
921
  "kumiko.widget.upload.uploading": "Téléversement en cours…",
894
922
  "kumiko.wizard.next-with-title": "Suivant : {title}",
895
923
  "kumiko.wizard.save-and-close": "Enregistrer et fermer",
@@ -1015,6 +1043,8 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
1015
1043
  "secrets.errors.invalidValue": "Cette valeur n'est pas valide pour ce secret.",
1016
1044
  "screen:api-token-create.title": "Créer un nouveau jeton",
1017
1045
  "screen:api-tokens.title": "Jetons d'accès personnels",
1046
+ "screen:audit-log-all-tenants-detail.title": "Événement",
1047
+ "screen:audit-log-all-tenants.title": "Journal d'audit (tous les locataires)",
1018
1048
  "screen:audit-log-detail.title": "Événement",
1019
1049
  "screen:audit-log.title": "Journal d'audit",
1020
1050
  "screen:auth-mfa-disable.title": "Désactiver l'authentification à deux facteurs",
@@ -1099,7 +1129,9 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
1099
1129
  "tags.manage.cancel": "Annuler",
1100
1130
  "tags.manage.create": "Créer une étiquette",
1101
1131
  "tags.manage.delete": "Supprimer",
1102
- "tags.manage.deleteConfirmDesc": "La supprime de {count} objets. Cette action est irréversible.",
1132
+ "tags.manage.deleteConfirmDesc.one": "La retire d'1 objet. Cette action est irréversible.",
1133
+ "tags.manage.deleteConfirmDesc.other":
1134
+ "La retire de {count} objets. Cette action est irréversible.",
1103
1135
  "tags.manage.deleteConfirmTitle": "Supprimer l'étiquette « {name} » ?",
1104
1136
  "tags.manage.edit": "Modifier",
1105
1137
  "tags.manage.namePlaceholder": "Nom de l'étiquette",
@@ -1120,6 +1152,24 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
1120
1152
  "tags:entity:tag:field:color": "Couleur",
1121
1153
  "tags:entity:tag:field:name": "Nom",
1122
1154
  "tags:entity:tag:field:scope": "Portée",
1155
+ "template-resolver:write:upsert-system:title": "Enregistrer le modèle système",
1156
+ "template-resolver:write:upsert-tenant:title": "Enregistrer le modèle",
1157
+ "template-resolver:write:publish:title": "Publier le modèle",
1158
+ "template-resolver:write:archive:title": "Archiver le modèle",
1159
+ "template-resolver:write:publish-system:title": "Publier le modèle système",
1160
+ "template-resolver:write:archive-system:title": "Archiver le modèle système",
1161
+ "template-resolver:write:discard-draft:title": "Supprimer le brouillon",
1162
+ "template-resolver:write:discard-draft-system:title": "Supprimer le brouillon du modèle système",
1163
+ "template-resolver:write:reset-to-system:title": "Rétablir le modèle système",
1164
+ "template-resolver:write:set:title": "Enregistrer le texte",
1165
+ "template-resolver:write:import-bundle:title": "Importer le modèle",
1166
+ "template-resolver:write:import-bundle-system:title": "Importer un modèle système",
1167
+ "template-resolver:write:copy-locale:title": "Copier le modèle dans une autre langue",
1168
+ "template-resolver:write:resource-upload:title": "Téléverser une image ou une pièce jointe",
1169
+ "template-resolver:write:resource-remove:title": "Retirer l'image ou la pièce jointe",
1170
+ "template-resolver:write:resource-link-pdf:title": "Joindre un modèle PDF",
1171
+ "template-resolver:write:send-test:title": "Envoyer un e-mail de test",
1172
+ "template-resolver:write:patch-draft:title": "Modifier le brouillon du modèle",
1123
1173
  "template-resolver.documentEditor.button": "Bouton",
1124
1174
  "template-resolver.documentEditor.buttonDefaultText": "Confirmer",
1125
1175
  "template-resolver.documentEditor.buttonTarget": "Cible du bouton",
@@ -1217,6 +1267,8 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
1217
1267
  "Seule la plateforme gère ce modèle ; il ne peut pas être remplacé par organisation.",
1218
1268
  "templateResolver.errors.templateNotTenantEditable":
1219
1269
  "Seule la plateforme peut modifier ce modèle.",
1270
+ "templateResolver.overview.lockedOverride":
1271
+ "Version propre enregistrée mais non diffusée : le modèle n’est pas activé pour les organisations.",
1220
1272
  "templateResolver.errors.template.targetExists":
1221
1273
  "Un modèle existe déjà pour la langue « {detail} » ; écrasez-le explicitement pour le remplacer.",
1222
1274
  "templateResolver.warnings.resourceNotUploaded": "Image non téléversée : {detail}",
@@ -1527,6 +1579,11 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
1527
1579
  "Modifiez la mise en page des e-mails ou le papier à en-tête PDF.",
1528
1580
  "documentDesigner.search": "Rechercher des modèles",
1529
1581
  "documentDesigner.action.edit": "Modifier",
1582
+ "documentDesigner.status.lockedOverride": "Non livrée",
1583
+ "documentDesigner.action.resetLockedOverride": "Retirer la version propre",
1584
+ "documentDesigner.action.resetLockedOverride.confirm":
1585
+ "La version propre enregistrée d'une langue (l'allemand en premier) est archivée et la version de la plateforme reste utilisée. Si le modèle compte plusieurs langues, l'opération est à répéter pour chacune.",
1586
+ "documentDesigner.action.resetLockedOverride.confirmLabel": "Retirer",
1530
1587
  "documentDesigner.col.template": "Modèle",
1531
1588
  "documentDesigner.col.kind": "Type",
1532
1589
  "documentDesigner.col.origin": "Origine",
@@ -1554,7 +1611,8 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
1554
1611
  "documentDesigner.status.draftVersion": "Brouillon v{version}",
1555
1612
  "documentDesigner.usedBy.allMails": "tous les e-mails",
1556
1613
  "documentDesigner.usedBy.allPdfs": "tous les PDF",
1557
- "documentDesigner.usedBy.templates": "{count} modèles",
1614
+ "documentDesigner.usedBy.templates.one": "1 modèle",
1615
+ "documentDesigner.usedBy.templates.other": "{count} modèles",
1558
1616
  "documentDesigner.usedBy.title": "Utilisé par",
1559
1617
  "documentDesigner.usedBy.none": "Aucun modèle n'utilise encore cette mise en page.",
1560
1618
  "documentDesigner.overriddenBy.tenants": "{active} organisations",
@@ -1620,9 +1678,13 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
1620
1678
  "documentDesigner.editor.origin.none": "Il n'existe pas encore de mise en page.",
1621
1679
  "documentDesigner.editor.origin.system":
1622
1680
  "Vous consultez la mise en page système. L'enregistrer crée une personnalisation pour votre organisation.",
1623
- "documentDesigner.editor.origin.tenant.mails":
1681
+ "documentDesigner.editor.origin.tenant.mails.one":
1682
+ "Remplace la mise en page système v{version}. S'applique à 1 modèle d'e-mail de cette organisation.",
1683
+ "documentDesigner.editor.origin.tenant.mails.other":
1624
1684
  "Remplace la mise en page système v{version}. S'applique à {count} modèles d'e-mail de cette organisation.",
1625
- "documentDesigner.editor.origin.tenant.pdfs":
1685
+ "documentDesigner.editor.origin.tenant.pdfs.one":
1686
+ "Remplace le papier à en-tête système v{version}. S'applique à 1 modèle PDF de cette organisation.",
1687
+ "documentDesigner.editor.origin.tenant.pdfs.other":
1626
1688
  "Remplace le papier à en-tête système v{version}. S'applique à {count} modèles PDF de cette organisation.",
1627
1689
  "documentDesigner.editor.origin.platformPlain": "Mise en page système v{version}",
1628
1690
  "documentDesigner.editor.origin.platformCount":
@@ -1648,9 +1710,13 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
1648
1710
  "Le contenu de chaque modèle d'e-mail est inséré ici. L'objet et le texte d'aperçu proviennent du modèle.",
1649
1711
  "documentDesigner.editor.slot.pdf": "Le contenu de chaque modèle PDF est inséré ici.",
1650
1712
  "documentDesigner.editor.footer.checking": "Vérification de la mise en page …",
1651
- "documentDesigner.editor.footer.okMail":
1713
+ "documentDesigner.editor.footer.okMail.one":
1714
+ "Espace réservé du contenu présent. Après la publication, la modification s'applique à 1 modèle.",
1715
+ "documentDesigner.editor.footer.okMail.other":
1652
1716
  "Espace réservé du contenu présent. Après la publication, la modification s'applique à {count} modèles.",
1653
- "documentDesigner.editor.footer.okPdf":
1717
+ "documentDesigner.editor.footer.okPdf.one":
1718
+ "Espace réservé du contenu présent. Après la publication, la modification s'applique à 1 modèle.",
1719
+ "documentDesigner.editor.footer.okPdf.other":
1654
1720
  "Espace réservé du contenu présent. Après la publication, la modification s'applique à {count} modèles.",
1655
1721
  "documentDesigner.editor.discard": "Abandonner les modifications",
1656
1722
  "documentDesigner.editor.save": "Enregistrer",
@@ -1760,7 +1826,7 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
1760
1826
  "Les e-mails transactionnels n'ont pas besoin de lien de désabonnement. Avec « Marketing », la mise en page doit en fournir un.",
1761
1827
  "documentDesigner.mail.chrome.title": "En-tête et pied de page",
1762
1828
  "documentDesigner.mail.chrome.headerChip": "Libellé dans l'en-tête",
1763
- "documentDesigner.mail.chrome.headerChipPlaceholder": "p. ex. Nouvel incident",
1829
+ "documentDesigner.mail.chrome.headerChipPlaceholder": "p. ex. Rappel",
1764
1830
  "documentDesigner.mail.chrome.tone": "Tonalité",
1765
1831
  "documentDesigner.mail.chrome.toneAccent": "Couleur d'accentuation (par défaut)",
1766
1832
  "documentDesigner.mail.chrome.toneInfo": "Info (gris bleuté)",
@@ -1829,7 +1895,8 @@ export const localeFrBundle: Readonly<Record<string, string>> = {
1829
1895
  "documentDesigner.mail.preview.samplesHint":
1830
1896
  "Les montants et les dates sont mis en forme selon les paramètres de l'organisation.",
1831
1897
  "documentDesigner.mail.preview.missingInContent": "absent du contenu",
1832
- "documentDesigner.mail.preview.entries": "{count} entrées",
1898
+ "documentDesigner.mail.preview.entries.one": "1 entrée",
1899
+ "documentDesigner.mail.preview.entries.other": "{count} entrées",
1833
1900
  "documentDesigner.mail.preview.checks": "Vérifications",
1834
1901
  "documentDesigner.mail.preview.checksHint":
1835
1902
  "Ce que le serveur a constaté lors du rendu de cet e-mail.",
@@ -1,37 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
- import { localeFrBundle } from "../strings";
3
- import { frameworkEnCatalog } from "./en-catalog";
4
-
5
- function placeholders(s: string): string[] {
6
- return [...s.matchAll(/\{(\w+)\}/g)].map((m) => m[1] ?? "").sort();
7
- }
8
-
9
- describe("locale-fr completeness", () => {
10
- test("has every English framework key", () => {
11
- const missing = Object.keys(frameworkEnCatalog).filter((k) => localeFrBundle[k] === undefined);
12
- expect(missing).toEqual([]);
13
- });
14
-
15
- test("has no stale extra keys", () => {
16
- const extra = Object.keys(localeFrBundle).filter((k) => frameworkEnCatalog[k] === undefined);
17
- expect(extra).toEqual([]);
18
- });
19
-
20
- test("interpolation placeholders match English", () => {
21
- for (const key of Object.keys(frameworkEnCatalog)) {
22
- expect(placeholders(localeFrBundle[key] ?? "")).toEqual(
23
- placeholders(frameworkEnCatalog[key] ?? ""),
24
- );
25
- }
26
- });
27
-
28
- test("uses localized tenant wording, not raw English tenant labels", () => {
29
- const roleAllowlist = new Set(["TenantAdmin", "SystemAdmin"]);
30
- const offenders: string[] = [];
31
- for (const [key, value] of Object.entries(localeFrBundle)) {
32
- if (roleAllowlist.has(value)) continue;
33
- if (/\btenants?\b/i.test(value)) offenders.push(key);
34
- }
35
- expect(offenders).toEqual([]);
36
- });
37
- });