@jarenjs/locales 0.34.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/LICENSE +21 -0
- package/README.md +119 -0
- package/dist/types/ar.d.ts +7 -0
- package/dist/types/de.d.ts +7 -0
- package/dist/types/es.d.ts +7 -0
- package/dist/types/fr.d.ts +7 -0
- package/dist/types/helpers.d.ts +41 -0
- package/dist/types/index.d.ts +23 -0
- package/dist/types/ja.d.ts +7 -0
- package/dist/types/ko.d.ts +7 -0
- package/dist/types/nl.d.ts +7 -0
- package/dist/types/pt.d.ts +7 -0
- package/dist/types/ru.d.ts +7 -0
- package/dist/types/tr.d.ts +7 -0
- package/dist/types/zh-tw.d.ts +7 -0
- package/package.json +95 -0
- package/src/ar.js +159 -0
- package/src/de.js +131 -0
- package/src/es.js +131 -0
- package/src/fr.js +131 -0
- package/src/helpers.js +59 -0
- package/src/index.js +26 -0
- package/src/ja.js +126 -0
- package/src/ko.js +129 -0
- package/src/nl.js +130 -0
- package/src/pt.js +131 -0
- package/src/ru.js +141 -0
- package/src/tr.js +128 -0
- package/src/zh-tw.js +129 -0
package/src/de.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
//@ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* German (de) message catalog for @jarenjs/validate and @jarenjs/forms.
|
|
5
|
+
*
|
|
6
|
+
* A catalog is a plain flat object `{ [key]: closure | template string }`;
|
|
7
|
+
* compile it with `compileMessageCatalog` from either consumer package
|
|
8
|
+
* and hand it to `localizeErrors` (validate) or the `catalog` parameters
|
|
9
|
+
* of `validateField` / `evaluateFormRules` (forms). A pack imports only
|
|
10
|
+
* the shared rendering helpers; key parity with the built-in English
|
|
11
|
+
* catalogs is enforced by tests in the repo, not by imports.
|
|
12
|
+
*
|
|
13
|
+
* Globalization mechanics (the pack-authoring pattern - see
|
|
14
|
+
* packages/validate/docs/ERROR-MESSAGES.md):
|
|
15
|
+
* - `Intl.PluralRules` picks plural categories ("1 Eigenschaft" /
|
|
16
|
+
* "2 Eigenschaften"; "Zeichen" is invariant and needs none),
|
|
17
|
+
* - `Intl.NumberFormat` renders numeric limits the German way,
|
|
18
|
+
* - `Intl.ListFormat` renders enum alternatives ("a, b oder c"),
|
|
19
|
+
* all held as module-level singletons (allocation discipline).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
formatMessageValue,
|
|
24
|
+
makeNumberRenderer,
|
|
25
|
+
makePluralPicker,
|
|
26
|
+
makeTypeNamer,
|
|
27
|
+
} from './helpers.js';
|
|
28
|
+
|
|
29
|
+
//#region Intl singletons
|
|
30
|
+
|
|
31
|
+
const pluralRules = new Intl.PluralRules('de');
|
|
32
|
+
const numberFormat = new Intl.NumberFormat('de-DE');
|
|
33
|
+
const listFormat = new Intl.ListFormat('de', { style: 'long', type: 'disjunction' });
|
|
34
|
+
|
|
35
|
+
/** Pick the German singular or plural noun form for a count. */
|
|
36
|
+
const plural = makePluralPicker(pluralRules);
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Render a numeric limit through the German number format; non-numbers
|
|
40
|
+
* (e.g. an unresolved $data pointer) render as-is.
|
|
41
|
+
*/
|
|
42
|
+
const num = makeNumberRenderer(numberFormat);
|
|
43
|
+
|
|
44
|
+
/** German names (with article) for the JSON Schema type keyword values. */
|
|
45
|
+
const TYPE_NAMES = {
|
|
46
|
+
string: 'eine Zeichenkette (string)',
|
|
47
|
+
number: 'eine Zahl',
|
|
48
|
+
integer: 'eine ganze Zahl',
|
|
49
|
+
boolean: 'ein boolescher Wert',
|
|
50
|
+
array: 'eine Liste (array)',
|
|
51
|
+
object: 'ein Objekt',
|
|
52
|
+
null: 'null',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/** Type keyword values under their German display name, article included. */
|
|
56
|
+
const typeName = makeTypeNamer(TYPE_NAMES);
|
|
57
|
+
|
|
58
|
+
//#endregion
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The German catalog. Covers every key of validate's `messagesEn`, every
|
|
62
|
+
* `form/*` key of forms' `formsMessagesEn`, `x-form/assert`, and the
|
|
63
|
+
* `JQ2xxx` codes reachable through `$query`.
|
|
64
|
+
* @type {Record<string, string | ((params: any, error?: object) => string)>}
|
|
65
|
+
*/
|
|
66
|
+
export const de = {
|
|
67
|
+
//#region @jarenjs/validate (document voice)
|
|
68
|
+
type: (p) => p.types
|
|
69
|
+
? `muss einer der folgenden Typen sein: ${p.types.join(', ')}`
|
|
70
|
+
: `muss ${typeName(p.type)} sein`,
|
|
71
|
+
required: (p) => p.missingProperty
|
|
72
|
+
? `muss die Pflichteigenschaft '${p.missingProperty}' enthalten`
|
|
73
|
+
: 'muss die Pflichteigenschaften enthalten',
|
|
74
|
+
minimum: (p) => `muss ${p.comparison} ${num(p.limit)} sein`,
|
|
75
|
+
maximum: (p) => `muss ${p.comparison} ${num(p.limit)} sein`,
|
|
76
|
+
exclusiveMinimum: (p) => `muss ${p.comparison} ${num(p.limit)} sein`,
|
|
77
|
+
exclusiveMaximum: (p) => `muss ${p.comparison} ${num(p.limit)} sein`,
|
|
78
|
+
multipleOf: (p) => `muss ein Vielfaches von ${num(p.multipleOf)} sein`,
|
|
79
|
+
minLength: (p) => `darf nicht weniger als ${num(p.limit)} Zeichen enthalten`,
|
|
80
|
+
maxLength: (p) => `darf nicht mehr als ${num(p.limit)} Zeichen enthalten`,
|
|
81
|
+
pattern: 'muss dem Muster "{pattern}" entsprechen',
|
|
82
|
+
additionalProperties: (p) => p.additionalProperty
|
|
83
|
+
? `darf die zusätzliche Eigenschaft '${p.additionalProperty}' nicht enthalten`
|
|
84
|
+
: 'darf keine zusätzlichen Eigenschaften enthalten',
|
|
85
|
+
minProperties: (p) => `darf nicht weniger als ${num(p.limit)} ${plural(p.limit, 'Eigenschaft', 'Eigenschaften')} enthalten`,
|
|
86
|
+
maxProperties: (p) => `darf nicht mehr als ${num(p.limit)} ${plural(p.limit, 'Eigenschaft', 'Eigenschaften')} enthalten`,
|
|
87
|
+
minItems: (p) => `darf nicht weniger als ${num(p.limit)} ${plural(p.limit, 'Element', 'Elemente')} enthalten`,
|
|
88
|
+
maxItems: (p) => `darf nicht mehr als ${num(p.limit)} ${plural(p.limit, 'Element', 'Elemente')} enthalten`,
|
|
89
|
+
uniqueItems: 'darf keine doppelten Elemente enthalten',
|
|
90
|
+
contains: 'muss mindestens ein gültiges Element enthalten',
|
|
91
|
+
items: 'die Elemente der Liste sind ungültig',
|
|
92
|
+
allOf: 'muss allen Teilschemata entsprechen',
|
|
93
|
+
anyOf: 'muss einem Teilschema in anyOf entsprechen',
|
|
94
|
+
oneOf: 'muss genau einem Teilschema in oneOf entsprechen',
|
|
95
|
+
not: 'darf dem Teilschema NICHT entsprechen',
|
|
96
|
+
format: 'muss dem Format "{format}" entsprechen',
|
|
97
|
+
if: 'muss dem "if"-Schema entsprechen',
|
|
98
|
+
then: 'muss dem "then"-Schema entsprechen',
|
|
99
|
+
else: 'muss dem "else"-Schema entsprechen',
|
|
100
|
+
'false schema': 'das boolesche Schema false ist immer ungültig',
|
|
101
|
+
$query: (p) => p.code
|
|
102
|
+
? `die '$query'-Assertion meldete ${p.code} bei '${p.docPath}'`
|
|
103
|
+
: "muss die '$query'-Assertion erfüllen",
|
|
104
|
+
JQ2001: (p) => `die '$query'-Assertion konnte nicht ausgewertet werden (${p.code} bei '${p.docPath}')`,
|
|
105
|
+
JQ2003: (p) => `die '$query'-Assertion lieferte mehrere Ergebnisse (${p.code} bei '${p.docPath}')`,
|
|
106
|
+
//#endregion
|
|
107
|
+
|
|
108
|
+
//#region @jarenjs/forms (second-person field voice)
|
|
109
|
+
'form/required': 'Dieses Feld ist erforderlich',
|
|
110
|
+
'form/type': (p) => `Muss ${typeName(p.type)} sein`,
|
|
111
|
+
'form/const': (p) => `Muss ${formatMessageValue(p.constValue)} sein`,
|
|
112
|
+
'form/enum': (p) => `Muss ${Array.isArray(p.enumValues) ? listFormat.format(p.enumValues.map(formatMessageValue)) : formatMessageValue(p.enumValues)} sein`,
|
|
113
|
+
'form/minLength': (p) => `Muss mindestens ${num(p.limit)} Zeichen enthalten (derzeit ${num(p.len)})`,
|
|
114
|
+
'form/maxLength': (p) => `Darf höchstens ${num(p.limit)} Zeichen enthalten (derzeit ${num(p.len)})`,
|
|
115
|
+
'form/pattern': 'Muss dem Muster {pattern} entsprechen',
|
|
116
|
+
'form/format': (p) => `Muss dem Format ${p.format} entsprechen`,
|
|
117
|
+
'form/minimum': (p) => `Muss mindestens ${num(p.limit)} sein`,
|
|
118
|
+
'form/maximum': (p) => `Darf höchstens ${num(p.limit)} sein`,
|
|
119
|
+
'form/exclusiveMinimum': (p) => `Muss größer als ${num(p.limit)} sein`,
|
|
120
|
+
'form/exclusiveMaximum': (p) => `Muss kleiner als ${num(p.limit)} sein`,
|
|
121
|
+
'form/multipleOf': (p) => `Muss ein Vielfaches von ${num(p.multipleOf)} sein`,
|
|
122
|
+
'form/minItems': (p) => `Muss mindestens ${num(p.limit)} ${plural(p.limit, 'Element', 'Elemente')} enthalten`,
|
|
123
|
+
'form/maxItems': (p) => `Darf höchstens ${num(p.limit)} ${plural(p.limit, 'Element', 'Elemente')} enthalten`,
|
|
124
|
+
'form/uniqueItems': 'Die Elemente müssen eindeutig sein',
|
|
125
|
+
'form/minProperties': (p) => `Muss mindestens ${num(p.limit)} ${plural(p.limit, 'Eigenschaft', 'Eigenschaften')} enthalten`,
|
|
126
|
+
'form/maxProperties': (p) => `Darf höchstens ${num(p.limit)} ${plural(p.limit, 'Eigenschaft', 'Eigenschaften')} enthalten`,
|
|
127
|
+
'x-form/assert': 'Ungültiger Wert',
|
|
128
|
+
'form/addItem': 'Element hinzufügen',
|
|
129
|
+
'form/removeItem': 'Element entfernen',
|
|
130
|
+
//#endregion
|
|
131
|
+
};
|
package/src/es.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
//@ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Spanish (es) message catalog for @jarenjs/validate and @jarenjs/forms.
|
|
5
|
+
*
|
|
6
|
+
* A catalog is a plain flat object `{ [key]: closure | template string }`;
|
|
7
|
+
* compile it with `compileMessageCatalog` from either consumer package
|
|
8
|
+
* and hand it to `localizeErrors` (validate) or the `catalog` parameters
|
|
9
|
+
* of `validateField` / `evaluateFormRules` (forms). A pack imports only
|
|
10
|
+
* the shared rendering helpers; key parity with the built-in English
|
|
11
|
+
* catalogs is enforced by tests in the repo, not by imports.
|
|
12
|
+
*
|
|
13
|
+
* Globalization mechanics (the pack-authoring pattern - see
|
|
14
|
+
* packages/validate/docs/ERROR-MESSAGES.md):
|
|
15
|
+
* - `Intl.PluralRules` picks plural categories, and the singular of
|
|
16
|
+
* "caracteres" shifts its accent ("1 carácter" / "2 caracteres"),
|
|
17
|
+
* - `Intl.NumberFormat` renders numeric limits the Spanish way,
|
|
18
|
+
* - `Intl.ListFormat` renders enum alternatives ("a, b o c"),
|
|
19
|
+
* all held as module-level singletons (allocation discipline).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
formatMessageValue,
|
|
24
|
+
makeNumberRenderer,
|
|
25
|
+
makePluralPicker,
|
|
26
|
+
makeTypeNamer,
|
|
27
|
+
} from './helpers.js';
|
|
28
|
+
|
|
29
|
+
//#region Intl singletons
|
|
30
|
+
|
|
31
|
+
const pluralRules = new Intl.PluralRules('es');
|
|
32
|
+
const numberFormat = new Intl.NumberFormat('es-ES');
|
|
33
|
+
const listFormat = new Intl.ListFormat('es', { style: 'long', type: 'disjunction' });
|
|
34
|
+
|
|
35
|
+
/** Pick the Spanish singular or plural noun form for a count. */
|
|
36
|
+
const plural = makePluralPicker(pluralRules);
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Render a numeric limit through the Spanish number format; non-numbers
|
|
40
|
+
* (e.g. an unresolved $data pointer) render as-is.
|
|
41
|
+
*/
|
|
42
|
+
const num = makeNumberRenderer(numberFormat);
|
|
43
|
+
|
|
44
|
+
/** Spanish names (with article) for the JSON Schema type keyword values. */
|
|
45
|
+
const TYPE_NAMES = {
|
|
46
|
+
string: 'una cadena (string)',
|
|
47
|
+
number: 'un número',
|
|
48
|
+
integer: 'un número entero',
|
|
49
|
+
boolean: 'un booleano',
|
|
50
|
+
array: 'una lista (array)',
|
|
51
|
+
object: 'un objeto',
|
|
52
|
+
null: 'null',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/** Type keyword values under their Spanish display name, article included. */
|
|
56
|
+
const typeName = makeTypeNamer(TYPE_NAMES);
|
|
57
|
+
|
|
58
|
+
//#endregion
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The Spanish catalog. Covers every key of validate's `messagesEn`, every
|
|
62
|
+
* `form/*` key of forms' `formsMessagesEn`, `x-form/assert`, and the
|
|
63
|
+
* `JQ2xxx` codes reachable through `$query`.
|
|
64
|
+
* @type {Record<string, string | ((params: any, error?: object) => string)>}
|
|
65
|
+
*/
|
|
66
|
+
export const es = {
|
|
67
|
+
//#region @jarenjs/validate (document voice)
|
|
68
|
+
type: (p) => p.types
|
|
69
|
+
? `debe ser uno de los siguientes tipos: ${p.types.join(', ')}`
|
|
70
|
+
: `debe ser ${typeName(p.type)}`,
|
|
71
|
+
required: (p) => p.missingProperty
|
|
72
|
+
? `debe tener la propiedad obligatoria '${p.missingProperty}'`
|
|
73
|
+
: 'debe tener las propiedades obligatorias',
|
|
74
|
+
minimum: (p) => `debe ser ${p.comparison} ${num(p.limit)}`,
|
|
75
|
+
maximum: (p) => `debe ser ${p.comparison} ${num(p.limit)}`,
|
|
76
|
+
exclusiveMinimum: (p) => `debe ser ${p.comparison} ${num(p.limit)}`,
|
|
77
|
+
exclusiveMaximum: (p) => `debe ser ${p.comparison} ${num(p.limit)}`,
|
|
78
|
+
multipleOf: (p) => `debe ser un múltiplo de ${num(p.multipleOf)}`,
|
|
79
|
+
minLength: (p) => `no debe tener menos de ${num(p.limit)} ${plural(p.limit, 'carácter', 'caracteres')}`,
|
|
80
|
+
maxLength: (p) => `no debe tener más de ${num(p.limit)} ${plural(p.limit, 'carácter', 'caracteres')}`,
|
|
81
|
+
pattern: 'debe coincidir con el patrón "{pattern}"',
|
|
82
|
+
additionalProperties: (p) => p.additionalProperty
|
|
83
|
+
? `no debe tener la propiedad adicional '${p.additionalProperty}'`
|
|
84
|
+
: 'no debe tener propiedades adicionales',
|
|
85
|
+
minProperties: (p) => `no debe tener menos de ${num(p.limit)} ${plural(p.limit, 'propiedad', 'propiedades')}`,
|
|
86
|
+
maxProperties: (p) => `no debe tener más de ${num(p.limit)} ${plural(p.limit, 'propiedad', 'propiedades')}`,
|
|
87
|
+
minItems: (p) => `no debe tener menos de ${num(p.limit)} ${plural(p.limit, 'elemento', 'elementos')}`,
|
|
88
|
+
maxItems: (p) => `no debe tener más de ${num(p.limit)} ${plural(p.limit, 'elemento', 'elementos')}`,
|
|
89
|
+
uniqueItems: 'no debe tener elementos duplicados',
|
|
90
|
+
contains: 'debe contener al menos un elemento válido',
|
|
91
|
+
items: 'los elementos de la lista no son válidos',
|
|
92
|
+
allOf: 'debe cumplir todos los subesquemas',
|
|
93
|
+
anyOf: 'debe cumplir un subesquema de anyOf',
|
|
94
|
+
oneOf: 'debe cumplir exactamente un subesquema de oneOf',
|
|
95
|
+
not: 'NO debe cumplir el subesquema',
|
|
96
|
+
format: 'debe coincidir con el formato "{format}"',
|
|
97
|
+
if: 'debe cumplir el esquema "if"',
|
|
98
|
+
then: 'debe cumplir el esquema "then"',
|
|
99
|
+
else: 'debe cumplir el esquema "else"',
|
|
100
|
+
'false schema': 'el esquema booleano false siempre es inválido',
|
|
101
|
+
$query: (p) => p.code
|
|
102
|
+
? `la aserción '$query' produjo ${p.code} en '${p.docPath}'`
|
|
103
|
+
: "debe cumplir la aserción '$query'",
|
|
104
|
+
JQ2001: (p) => `la aserción '$query' no se pudo evaluar (${p.code} en '${p.docPath}')`,
|
|
105
|
+
JQ2003: (p) => `la aserción '$query' produjo varios resultados (${p.code} en '${p.docPath}')`,
|
|
106
|
+
//#endregion
|
|
107
|
+
|
|
108
|
+
//#region @jarenjs/forms (second-person field voice)
|
|
109
|
+
'form/required': 'Este campo es obligatorio',
|
|
110
|
+
'form/type': (p) => `Debe ser ${typeName(p.type)}`,
|
|
111
|
+
'form/const': (p) => `Debe ser ${formatMessageValue(p.constValue)}`,
|
|
112
|
+
'form/enum': (p) => `Debe ser ${Array.isArray(p.enumValues) ? listFormat.format(p.enumValues.map(formatMessageValue)) : formatMessageValue(p.enumValues)}`,
|
|
113
|
+
'form/minLength': (p) => `Debe tener al menos ${num(p.limit)} ${plural(p.limit, 'carácter', 'caracteres')} (actualmente ${num(p.len)})`,
|
|
114
|
+
'form/maxLength': (p) => `Debe tener como máximo ${num(p.limit)} ${plural(p.limit, 'carácter', 'caracteres')} (actualmente ${num(p.len)})`,
|
|
115
|
+
'form/pattern': 'Debe coincidir con el patrón {pattern}',
|
|
116
|
+
'form/format': (p) => `Debe cumplir el formato ${p.format}`,
|
|
117
|
+
'form/minimum': (p) => `Debe ser al menos ${num(p.limit)}`,
|
|
118
|
+
'form/maximum': (p) => `Debe ser como máximo ${num(p.limit)}`,
|
|
119
|
+
'form/exclusiveMinimum': (p) => `Debe ser mayor que ${num(p.limit)}`,
|
|
120
|
+
'form/exclusiveMaximum': (p) => `Debe ser menor que ${num(p.limit)}`,
|
|
121
|
+
'form/multipleOf': (p) => `Debe ser un múltiplo de ${num(p.multipleOf)}`,
|
|
122
|
+
'form/minItems': (p) => `Debe tener al menos ${num(p.limit)} ${plural(p.limit, 'elemento', 'elementos')}`,
|
|
123
|
+
'form/maxItems': (p) => `Debe tener como máximo ${num(p.limit)} ${plural(p.limit, 'elemento', 'elementos')}`,
|
|
124
|
+
'form/uniqueItems': 'Los elementos deben ser únicos',
|
|
125
|
+
'form/minProperties': (p) => `Debe tener al menos ${num(p.limit)} ${plural(p.limit, 'propiedad', 'propiedades')}`,
|
|
126
|
+
'form/maxProperties': (p) => `Debe tener como máximo ${num(p.limit)} ${plural(p.limit, 'propiedad', 'propiedades')}`,
|
|
127
|
+
'x-form/assert': 'Valor no válido',
|
|
128
|
+
'form/addItem': 'Añadir elemento',
|
|
129
|
+
'form/removeItem': 'Eliminar elemento',
|
|
130
|
+
//#endregion
|
|
131
|
+
};
|
package/src/fr.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
//@ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* French (fr) message catalog for @jarenjs/validate and @jarenjs/forms.
|
|
5
|
+
*
|
|
6
|
+
* A catalog is a plain flat object `{ [key]: closure | template string }`;
|
|
7
|
+
* compile it with `compileMessageCatalog` from either consumer package
|
|
8
|
+
* and hand it to `localizeErrors` (validate) or the `catalog` parameters
|
|
9
|
+
* of `validateField` / `evaluateFormRules` (forms). A pack imports only
|
|
10
|
+
* the shared rendering helpers; key parity with the built-in English
|
|
11
|
+
* catalogs is enforced by tests in the repo, not by imports.
|
|
12
|
+
*
|
|
13
|
+
* Globalization mechanics (the pack-authoring pattern - see
|
|
14
|
+
* packages/validate/docs/ERROR-MESSAGES.md):
|
|
15
|
+
* - `Intl.PluralRules` picks plural categories (French counts 0 and 1
|
|
16
|
+
* as singular: "0 caractère" / "2 caractères"),
|
|
17
|
+
* - `Intl.NumberFormat` renders numeric limits the French way,
|
|
18
|
+
* - `Intl.ListFormat` renders enum alternatives ("a, b ou c"),
|
|
19
|
+
* all held as module-level singletons (allocation discipline).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
formatMessageValue,
|
|
24
|
+
makeNumberRenderer,
|
|
25
|
+
makePluralPicker,
|
|
26
|
+
makeTypeNamer,
|
|
27
|
+
} from './helpers.js';
|
|
28
|
+
|
|
29
|
+
//#region Intl singletons
|
|
30
|
+
|
|
31
|
+
const pluralRules = new Intl.PluralRules('fr');
|
|
32
|
+
const numberFormat = new Intl.NumberFormat('fr-FR');
|
|
33
|
+
const listFormat = new Intl.ListFormat('fr', { style: 'long', type: 'disjunction' });
|
|
34
|
+
|
|
35
|
+
/** Pick the French singular or plural noun form for a count. */
|
|
36
|
+
const plural = makePluralPicker(pluralRules);
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Render a numeric limit through the French number format; non-numbers
|
|
40
|
+
* (e.g. an unresolved $data pointer) render as-is.
|
|
41
|
+
*/
|
|
42
|
+
const num = makeNumberRenderer(numberFormat);
|
|
43
|
+
|
|
44
|
+
/** French names (with article) for the JSON Schema type keyword values. */
|
|
45
|
+
const TYPE_NAMES = {
|
|
46
|
+
string: 'une chaîne (string)',
|
|
47
|
+
number: 'un nombre',
|
|
48
|
+
integer: 'un nombre entier',
|
|
49
|
+
boolean: 'un booléen',
|
|
50
|
+
array: 'une liste (array)',
|
|
51
|
+
object: 'un objet',
|
|
52
|
+
null: 'null',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/** Type keyword values under their French display name, article included. */
|
|
56
|
+
const typeName = makeTypeNamer(TYPE_NAMES);
|
|
57
|
+
|
|
58
|
+
//#endregion
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The French catalog. Covers every key of validate's `messagesEn`, every
|
|
62
|
+
* `form/*` key of forms' `formsMessagesEn`, `x-form/assert`, and the
|
|
63
|
+
* `JQ2xxx` codes reachable through `$query`.
|
|
64
|
+
* @type {Record<string, string | ((params: any, error?: object) => string)>}
|
|
65
|
+
*/
|
|
66
|
+
export const fr = {
|
|
67
|
+
//#region @jarenjs/validate (document voice)
|
|
68
|
+
type: (p) => p.types
|
|
69
|
+
? `doit être l'un des types suivants : ${p.types.join(', ')}`
|
|
70
|
+
: `doit être ${typeName(p.type)}`,
|
|
71
|
+
required: (p) => p.missingProperty
|
|
72
|
+
? `doit contenir la propriété obligatoire '${p.missingProperty}'`
|
|
73
|
+
: 'doit contenir les propriétés obligatoires',
|
|
74
|
+
minimum: (p) => `doit être ${p.comparison} ${num(p.limit)}`,
|
|
75
|
+
maximum: (p) => `doit être ${p.comparison} ${num(p.limit)}`,
|
|
76
|
+
exclusiveMinimum: (p) => `doit être ${p.comparison} ${num(p.limit)}`,
|
|
77
|
+
exclusiveMaximum: (p) => `doit être ${p.comparison} ${num(p.limit)}`,
|
|
78
|
+
multipleOf: (p) => `doit être un multiple de ${num(p.multipleOf)}`,
|
|
79
|
+
minLength: (p) => `ne doit pas contenir moins de ${num(p.limit)} ${plural(p.limit, 'caractère', 'caractères')}`,
|
|
80
|
+
maxLength: (p) => `ne doit pas contenir plus de ${num(p.limit)} ${plural(p.limit, 'caractère', 'caractères')}`,
|
|
81
|
+
pattern: 'doit correspondre au motif "{pattern}"',
|
|
82
|
+
additionalProperties: (p) => p.additionalProperty
|
|
83
|
+
? `ne doit pas contenir la propriété supplémentaire '${p.additionalProperty}'`
|
|
84
|
+
: 'ne doit pas contenir de propriétés supplémentaires',
|
|
85
|
+
minProperties: (p) => `ne doit pas contenir moins de ${num(p.limit)} ${plural(p.limit, 'propriété', 'propriétés')}`,
|
|
86
|
+
maxProperties: (p) => `ne doit pas contenir plus de ${num(p.limit)} ${plural(p.limit, 'propriété', 'propriétés')}`,
|
|
87
|
+
minItems: (p) => `ne doit pas contenir moins de ${num(p.limit)} ${plural(p.limit, 'élément', 'éléments')}`,
|
|
88
|
+
maxItems: (p) => `ne doit pas contenir plus de ${num(p.limit)} ${plural(p.limit, 'élément', 'éléments')}`,
|
|
89
|
+
uniqueItems: "ne doit pas contenir d'éléments en double",
|
|
90
|
+
contains: 'doit contenir au moins un élément valide',
|
|
91
|
+
items: 'les éléments de la liste sont invalides',
|
|
92
|
+
allOf: 'doit satisfaire tous les sous-schémas',
|
|
93
|
+
anyOf: 'doit satisfaire un sous-schéma de anyOf',
|
|
94
|
+
oneOf: 'doit satisfaire exactement un sous-schéma de oneOf',
|
|
95
|
+
not: 'ne doit PAS satisfaire le sous-schéma',
|
|
96
|
+
format: 'doit correspondre au format "{format}"',
|
|
97
|
+
if: 'doit satisfaire le schéma "if"',
|
|
98
|
+
then: 'doit satisfaire le schéma "then"',
|
|
99
|
+
else: 'doit satisfaire le schéma "else"',
|
|
100
|
+
'false schema': 'le schéma booléen false est toujours invalide',
|
|
101
|
+
$query: (p) => p.code
|
|
102
|
+
? `l'assertion '$query' a levé ${p.code} à '${p.docPath}'`
|
|
103
|
+
: "doit satisfaire l'assertion '$query'",
|
|
104
|
+
JQ2001: (p) => `l'assertion '$query' n'a pas pu être évaluée (${p.code} à '${p.docPath}')`,
|
|
105
|
+
JQ2003: (p) => `l'assertion '$query' a produit plusieurs résultats (${p.code} à '${p.docPath}')`,
|
|
106
|
+
//#endregion
|
|
107
|
+
|
|
108
|
+
//#region @jarenjs/forms (second-person field voice)
|
|
109
|
+
'form/required': 'Ce champ est obligatoire',
|
|
110
|
+
'form/type': (p) => `Doit être ${typeName(p.type)}`,
|
|
111
|
+
'form/const': (p) => `Doit être ${formatMessageValue(p.constValue)}`,
|
|
112
|
+
'form/enum': (p) => `Doit être ${Array.isArray(p.enumValues) ? listFormat.format(p.enumValues.map(formatMessageValue)) : formatMessageValue(p.enumValues)}`,
|
|
113
|
+
'form/minLength': (p) => `Doit contenir au moins ${num(p.limit)} ${plural(p.limit, 'caractère', 'caractères')} (actuellement ${num(p.len)})`,
|
|
114
|
+
'form/maxLength': (p) => `Doit contenir au plus ${num(p.limit)} ${plural(p.limit, 'caractère', 'caractères')} (actuellement ${num(p.len)})`,
|
|
115
|
+
'form/pattern': 'Doit correspondre au motif {pattern}',
|
|
116
|
+
'form/format': (p) => `Doit respecter le format ${p.format}`,
|
|
117
|
+
'form/minimum': (p) => `Doit être au moins ${num(p.limit)}`,
|
|
118
|
+
'form/maximum': (p) => `Doit être au plus ${num(p.limit)}`,
|
|
119
|
+
'form/exclusiveMinimum': (p) => `Doit être supérieur à ${num(p.limit)}`,
|
|
120
|
+
'form/exclusiveMaximum': (p) => `Doit être inférieur à ${num(p.limit)}`,
|
|
121
|
+
'form/multipleOf': (p) => `Doit être un multiple de ${num(p.multipleOf)}`,
|
|
122
|
+
'form/minItems': (p) => `Doit contenir au moins ${num(p.limit)} ${plural(p.limit, 'élément', 'éléments')}`,
|
|
123
|
+
'form/maxItems': (p) => `Doit contenir au plus ${num(p.limit)} ${plural(p.limit, 'élément', 'éléments')}`,
|
|
124
|
+
'form/uniqueItems': 'Les éléments doivent être uniques',
|
|
125
|
+
'form/minProperties': (p) => `Doit contenir au moins ${num(p.limit)} ${plural(p.limit, 'propriété', 'propriétés')}`,
|
|
126
|
+
'form/maxProperties': (p) => `Doit contenir au plus ${num(p.limit)} ${plural(p.limit, 'propriété', 'propriétés')}`,
|
|
127
|
+
'x-form/assert': 'Valeur invalide',
|
|
128
|
+
'form/addItem': 'Ajouter un élément',
|
|
129
|
+
"form/removeItem": "Supprimer l'élément",
|
|
130
|
+
//#endregion
|
|
131
|
+
};
|
package/src/helpers.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
//@ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The pack-authoring toolkit: the rendering steps every locale pack
|
|
5
|
+
* performs identically, parameterised by the one thing that is actually
|
|
6
|
+
* per-language.
|
|
7
|
+
*
|
|
8
|
+
* Each factory takes a pack's own `Intl` singleton or translated table
|
|
9
|
+
* and returns the render closure the catalog entries call. Building the
|
|
10
|
+
* closure once at module load keeps the packs' allocation discipline:
|
|
11
|
+
* nothing is constructed per message. This module is internal to
|
|
12
|
+
* `@jarenjs/locales` - packs import it, consumers never see it.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export { formatMessageValue } from '@jarenjs/core/message';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Build a numeric-limit renderer over a pack's number format. Values
|
|
19
|
+
* that are not numbers (e.g. an unresolved $data pointer) render as-is,
|
|
20
|
+
* so a limit is always readable even when it never resolved.
|
|
21
|
+
*
|
|
22
|
+
* @param {Intl.NumberFormat} numberFormat - The pack's number format
|
|
23
|
+
* @returns {(value: unknown) => string} The limit renderer
|
|
24
|
+
*/
|
|
25
|
+
export function makeNumberRenderer(numberFormat) {
|
|
26
|
+
return function renderNumber(value) {
|
|
27
|
+
return typeof value === 'number' ? numberFormat.format(value) : String(value);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Build a two-form noun picker over a pack's plural rules: the count's
|
|
33
|
+
* CLDR category selects the `one` form, everything else the `other`
|
|
34
|
+
* form. Only for languages whose counted messages need exactly two
|
|
35
|
+
* forms - a pack that needs more categories, or that avoids agreement
|
|
36
|
+
* altogether by phrasing around a fixed noun, does not use this.
|
|
37
|
+
*
|
|
38
|
+
* @param {Intl.PluralRules} pluralRules - The pack's plural rules
|
|
39
|
+
* @returns {(count: number, one: string, other: string) => string} The form picker
|
|
40
|
+
*/
|
|
41
|
+
export function makePluralPicker(pluralRules) {
|
|
42
|
+
return function pickPluralForm(count, one, other) {
|
|
43
|
+
return pluralRules.select(count) === 'one' ? one : other;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Build a type-name renderer over a pack's translated table. An
|
|
49
|
+
* unlisted type (a custom or future keyword value) renders under its
|
|
50
|
+
* JSON Schema name rather than disappearing.
|
|
51
|
+
*
|
|
52
|
+
* @param {Record<string, string>} typeNames - The pack's translated type names
|
|
53
|
+
* @returns {(type: string) => string} The type-name renderer
|
|
54
|
+
*/
|
|
55
|
+
export function makeTypeNamer(typeNames) {
|
|
56
|
+
return function renderTypeName(type) {
|
|
57
|
+
return typeNames[type] ?? type;
|
|
58
|
+
};
|
|
59
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//@ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @jarenjs/locales - locale packs (message catalogs) for the error
|
|
5
|
+
* messages of @jarenjs/validate and @jarenjs/forms.
|
|
6
|
+
*
|
|
7
|
+
* Each pack is a plain flat object of message-key -> closure/template
|
|
8
|
+
* entries (the catalog contract of
|
|
9
|
+
* packages/validate/docs/ERROR-MESSAGES.md); compile them with
|
|
10
|
+
* `compileMessageCatalog` from the consuming package. A pack holds its
|
|
11
|
+
* own translations and `Intl` singletons, and imports nothing but the
|
|
12
|
+
* rendering helpers of `./helpers.js` - never a consumer package, so
|
|
13
|
+
* either consumer can serve any pack.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export { ar } from './ar.js';
|
|
17
|
+
export { de } from './de.js';
|
|
18
|
+
export { es } from './es.js';
|
|
19
|
+
export { fr } from './fr.js';
|
|
20
|
+
export { ja } from './ja.js';
|
|
21
|
+
export { ko } from './ko.js';
|
|
22
|
+
export { nl } from './nl.js';
|
|
23
|
+
export { pt } from './pt.js';
|
|
24
|
+
export { ru } from './ru.js';
|
|
25
|
+
export { tr } from './tr.js';
|
|
26
|
+
export { zhTW } from './zh-tw.js';
|
package/src/ja.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
//@ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Japanese (ja) message catalog for @jarenjs/validate and @jarenjs/forms.
|
|
5
|
+
*
|
|
6
|
+
* A catalog is a plain flat object `{ [key]: closure | template string }`;
|
|
7
|
+
* compile it with `compileMessageCatalog` from either consumer package
|
|
8
|
+
* and hand it to `localizeErrors` (validate) or the `catalog` parameters
|
|
9
|
+
* of `validateField` / `evaluateFormRules` (forms). A pack imports only
|
|
10
|
+
* the shared rendering helpers; key parity with the built-in English
|
|
11
|
+
* catalogs is enforced by tests in the repo, not by imports.
|
|
12
|
+
*
|
|
13
|
+
* Globalization mechanics (the pack-authoring pattern - see
|
|
14
|
+
* packages/validate/docs/ERROR-MESSAGES.md):
|
|
15
|
+
* - Japanese has no grammatical plural, so there is no plural helper
|
|
16
|
+
* here; counts read through counters ("2 文字", "3 個"),
|
|
17
|
+
* - `Intl.NumberFormat` renders numeric limits the Japanese way,
|
|
18
|
+
* - `Intl.ListFormat` renders enum alternatives ("a、b、または c"),
|
|
19
|
+
* all held as module-level singletons (allocation discipline).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
formatMessageValue,
|
|
24
|
+
makeNumberRenderer,
|
|
25
|
+
makeTypeNamer,
|
|
26
|
+
} from './helpers.js';
|
|
27
|
+
|
|
28
|
+
//#region Intl singletons
|
|
29
|
+
|
|
30
|
+
const numberFormat = new Intl.NumberFormat('ja-JP');
|
|
31
|
+
const listFormat = new Intl.ListFormat('ja', { style: 'long', type: 'disjunction' });
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Render a numeric limit through the Japanese number format; non-numbers
|
|
35
|
+
* (e.g. an unresolved $data pointer) render as-is.
|
|
36
|
+
*/
|
|
37
|
+
const num = makeNumberRenderer(numberFormat);
|
|
38
|
+
|
|
39
|
+
/** Japanese names for the JSON Schema type keyword values. */
|
|
40
|
+
const TYPE_NAMES = {
|
|
41
|
+
string: '文字列 (string)',
|
|
42
|
+
number: '数値',
|
|
43
|
+
integer: '整数',
|
|
44
|
+
boolean: '真偽値',
|
|
45
|
+
array: '配列 (array)',
|
|
46
|
+
object: 'オブジェクト',
|
|
47
|
+
null: 'null',
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/** Type keyword values under their Japanese display name. */
|
|
51
|
+
const typeName = makeTypeNamer(TYPE_NAMES);
|
|
52
|
+
|
|
53
|
+
//#endregion
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The Japanese catalog. Covers every key of validate's `messagesEn`,
|
|
57
|
+
* every `form/*` key of forms' `formsMessagesEn`, `x-form/assert`, and
|
|
58
|
+
* the `JQ2xxx` codes reachable through `$query`.
|
|
59
|
+
* @type {Record<string, string | ((params: any, error?: object) => string)>}
|
|
60
|
+
*/
|
|
61
|
+
export const ja = {
|
|
62
|
+
//#region @jarenjs/validate (document voice)
|
|
63
|
+
type: (p) => p.types
|
|
64
|
+
? `次のいずれかの型でなければなりません: ${p.types.join(', ')}`
|
|
65
|
+
: `${typeName(p.type)}でなければなりません`,
|
|
66
|
+
required: (p) => p.missingProperty
|
|
67
|
+
? `必須プロパティ '${p.missingProperty}' が必要です`
|
|
68
|
+
: '必須プロパティが必要です',
|
|
69
|
+
minimum: (p) => `${p.comparison} ${num(p.limit)} でなければなりません`,
|
|
70
|
+
maximum: (p) => `${p.comparison} ${num(p.limit)} でなければなりません`,
|
|
71
|
+
exclusiveMinimum: (p) => `${p.comparison} ${num(p.limit)} でなければなりません`,
|
|
72
|
+
exclusiveMaximum: (p) => `${p.comparison} ${num(p.limit)} でなければなりません`,
|
|
73
|
+
multipleOf: (p) => `${num(p.multipleOf)} の倍数でなければなりません`,
|
|
74
|
+
minLength: (p) => `${num(p.limit)} 文字以上でなければなりません`,
|
|
75
|
+
maxLength: (p) => `${num(p.limit)} 文字以下でなければなりません`,
|
|
76
|
+
pattern: 'パターン "{pattern}" に一致しなければなりません',
|
|
77
|
+
additionalProperties: (p) => p.additionalProperty
|
|
78
|
+
? `追加のプロパティ '${p.additionalProperty}' は使用できません`
|
|
79
|
+
: '追加のプロパティは使用できません',
|
|
80
|
+
minProperties: (p) => `プロパティは ${num(p.limit)} 個以上でなければなりません`,
|
|
81
|
+
maxProperties: (p) => `プロパティは ${num(p.limit)} 個以下でなければなりません`,
|
|
82
|
+
minItems: (p) => `項目は ${num(p.limit)} 個以上でなければなりません`,
|
|
83
|
+
maxItems: (p) => `項目は ${num(p.limit)} 個以下でなければなりません`,
|
|
84
|
+
uniqueItems: '重複する項目は使用できません',
|
|
85
|
+
contains: '有効な項目を少なくとも 1 つ含まなければなりません',
|
|
86
|
+
items: '配列の項目が無効です',
|
|
87
|
+
allOf: 'すべてのサブスキーマに一致しなければなりません',
|
|
88
|
+
anyOf: 'anyOf のいずれかのサブスキーマに一致しなければなりません',
|
|
89
|
+
oneOf: 'oneOf のちょうど 1 つのサブスキーマに一致しなければなりません',
|
|
90
|
+
not: 'サブスキーマに一致してはいけません',
|
|
91
|
+
format: '形式 "{format}" に一致しなければなりません',
|
|
92
|
+
if: '"if" スキーマに一致しなければなりません',
|
|
93
|
+
then: '"then" スキーマに一致しなければなりません',
|
|
94
|
+
else: '"else" スキーマに一致しなければなりません',
|
|
95
|
+
'false schema': 'ブールスキーマ false は常に無効です',
|
|
96
|
+
$query: (p) => p.code
|
|
97
|
+
? `'$query' アサーションが '${p.docPath}' で ${p.code} を発生させました`
|
|
98
|
+
: "'$query' アサーションを満たさなければなりません",
|
|
99
|
+
JQ2001: (p) => `'$query' アサーションを評価できませんでした('${p.docPath}' で ${p.code})`,
|
|
100
|
+
JQ2003: (p) => `'$query' アサーションが複数の結果を返しました('${p.docPath}' で ${p.code})`,
|
|
101
|
+
//#endregion
|
|
102
|
+
|
|
103
|
+
//#region @jarenjs/forms (second-person field voice)
|
|
104
|
+
'form/required': 'この項目は必須です',
|
|
105
|
+
'form/type': (p) => `${typeName(p.type)}でなければなりません`,
|
|
106
|
+
'form/const': (p) => `${formatMessageValue(p.constValue)} でなければなりません`,
|
|
107
|
+
'form/enum': (p) => `${Array.isArray(p.enumValues) ? listFormat.format(p.enumValues.map(formatMessageValue)) : formatMessageValue(p.enumValues)} のいずれかでなければなりません`,
|
|
108
|
+
'form/minLength': (p) => `${num(p.limit)} 文字以上で入力してください(現在 ${num(p.len)} 文字)`,
|
|
109
|
+
'form/maxLength': (p) => `${num(p.limit)} 文字以下で入力してください(現在 ${num(p.len)} 文字)`,
|
|
110
|
+
'form/pattern': 'パターン {pattern} に一致しなければなりません',
|
|
111
|
+
'form/format': (p) => `有効な ${p.format} 形式で入力してください`,
|
|
112
|
+
'form/minimum': (p) => `${num(p.limit)} 以上でなければなりません`,
|
|
113
|
+
'form/maximum': (p) => `${num(p.limit)} 以下でなければなりません`,
|
|
114
|
+
'form/exclusiveMinimum': (p) => `${num(p.limit)} より大きくなければなりません`,
|
|
115
|
+
'form/exclusiveMaximum': (p) => `${num(p.limit)} より小さくなければなりません`,
|
|
116
|
+
'form/multipleOf': (p) => `${num(p.multipleOf)} の倍数でなければなりません`,
|
|
117
|
+
'form/minItems': (p) => `項目は ${num(p.limit)} 個以上必要です`,
|
|
118
|
+
'form/maxItems': (p) => `項目は ${num(p.limit)} 個以下にしてください`,
|
|
119
|
+
'form/uniqueItems': '項目は一意でなければなりません',
|
|
120
|
+
'form/minProperties': (p) => `プロパティは ${num(p.limit)} 個以上必要です`,
|
|
121
|
+
'form/maxProperties': (p) => `プロパティは ${num(p.limit)} 個以下にしてください`,
|
|
122
|
+
'x-form/assert': '無効な値です',
|
|
123
|
+
'form/addItem': '項目を追加',
|
|
124
|
+
'form/removeItem': '項目を削除',
|
|
125
|
+
//#endregion
|
|
126
|
+
};
|