@jarenjs/forms 0.46.5 → 0.49.2

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/README.md CHANGED
@@ -259,6 +259,29 @@ const errors = validateAllFields(model, data, catalog);
259
259
  // errors['/name'][0].message === 'Dit veld is verplicht'
260
260
  ```
261
261
 
262
+ ### A format's name, in the reader's language
263
+
264
+ A format's name is its wire name — `date-time`, `iso-time` — which is
265
+ English by construction and reads as gibberish inside a translated
266
+ sentence (*"Moet een geldige date-time zijn"*). A catalog that carries
267
+ `format/name/<format>` says how that format is called in its own
268
+ language, and `renderFormsMessage` swaps it in before `form/format`
269
+ renders. The error's own `params.format` stays the raw wire name, so the
270
+ same error re-rendered through a second catalog answers in *that*
271
+ language rather than repeating the first one's noun:
272
+
273
+ ```javascript
274
+ const error = validateField(whenField, 'nope', catalog)[0];
275
+ error.message; // 'Moet een geldige datum en tijd zijn'
276
+ error.params.format; // 'date-time'
277
+ formatDisplayName(catalog, 'email'); // 'email' — already a word
278
+ ```
279
+
280
+ `@jarenjs/locales` carries the six date and time names in every pack; a
281
+ format the catalog cannot name keeps its own, which is the readable
282
+ answer for the names that are already words and the only possible one for
283
+ a format nobody has heard of.
284
+
262
285
  ### MessageSpec in `x-form.message`
263
286
 
264
287
  A rule's `message` may be a plain string (backward compatible — an inline
@@ -15,7 +15,7 @@
15
15
  export { buildFormModel, resolveSchema, getFieldKind, humanizeKey, escapePointerKey, } from './model.js';
16
16
  export { compileFormRules, evaluateFormRules, formRulesToQueryAssertions, pruneHiddenValues, createRuleMemo, } from './rules.js';
17
17
  export { validateField, validateAllFields, } from './validate.js';
18
- export { formsMessagesEn, formChromeLabels, compileMessageTemplate, compileMessageCatalog, } from './messages.js';
18
+ export { formsMessagesEn, formChromeLabels, formatDisplayName, compileMessageTemplate, compileMessageCatalog, } from './messages.js';
19
19
  export { createInitialData, createItemValue, parseFieldInput, parsePointer, getValueAtPointer, setValueAtPointer, appendItem, removeItemAt, } from './data.js';
20
20
  export { FORM_FORMATS, getFormatInfo, } from './formats.js';
21
21
  export { buildFormViewModel, } from './viewmodel.js';
@@ -8,9 +8,37 @@ export { compileMessageTemplate, compileMessageCatalog, } from '@jarenjs/core/me
8
8
  export declare const formsMessagesEn: Record<string, string | ((params: object, error?: object) => string)>;
9
9
  /** The compiled built-in English catalog (module-level singleton). */
10
10
  export declare const formsMessages: Readonly<Record<string, (params: object, error?: object) => string>>;
11
+ /**
12
+ * The display name of a format, as the catalog in hand spells it.
13
+ *
14
+ * A format's name is its wire name - `date-time`, `iso-time` - which is
15
+ * English by construction and reads as gibberish inside a translated
16
+ * sentence ("Moet een geldige date-time zijn"). A catalog that carries
17
+ * `format/name/<format>` says how that format is called in its own
18
+ * language; the date catalog of `@jarenjs/locales` carries the six date
19
+ * and time ones. A format the catalog has no name for keeps its own,
20
+ * which is the readable answer for the format names that are already
21
+ * words ("email", "hostname") and the only possible one for a format
22
+ * this repository has never heard of.
23
+ *
24
+ * @param {Readonly<Record<string, (params: object, error?: object) => string>>|undefined} catalog - A compiled catalog, or undefined for English
25
+ * @param {string} format - The format name
26
+ * @returns {string} The display name, or the format name itself
27
+ * @example
28
+ * formatDisplayName(dutch, 'date-time'); // 'datum en tijd'
29
+ * formatDisplayName(dutch, 'email'); // 'email'
30
+ */
31
+ export declare function formatDisplayName(catalog: Readonly<Record<string, (params: object, error?: object) => string>> | undefined, format: string): string;
11
32
  /**
12
33
  * Resolve a message key through a caller catalog with built-in English
13
34
  * fallback and render it.
35
+ *
36
+ * A format failure is the one message whose params are prepared here
37
+ * rather than at the call site: the error's own `params.format` stays
38
+ * the raw wire name, so re-rendering the same error through a second
39
+ * catalog answers in that catalog's language instead of repeating the
40
+ * first one's noun.
41
+ *
14
42
  * @param {Readonly<Record<string, (params: object, error?: object) => string>>|undefined} catalog - A compiled catalog, or undefined for English
15
43
  * @param {string} msgid - The message key
16
44
  * @param {object} params - The structured params
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jarenjs/forms",
3
3
  "private": false,
4
- "version": "0.46.5",
4
+ "version": "0.49.2",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
7
7
  "types": "./dist/types/index.d.ts",
@@ -47,9 +47,9 @@
47
47
  "prepack": "npm run build:types"
48
48
  },
49
49
  "dependencies": {
50
- "@jarenjs/core": "^0.46.5",
51
- "@jarenjs/formats": "^0.46.5",
52
- "@jarenjs/json": "^0.46.5",
53
- "@jarenjs/validate": "^0.46.5"
50
+ "@jarenjs/core": "^0.49.2",
51
+ "@jarenjs/formats": "^0.49.2",
52
+ "@jarenjs/json": "^0.49.2",
53
+ "@jarenjs/validate": "^0.49.2"
54
54
  }
55
55
  }
package/src/index.js CHANGED
@@ -39,6 +39,7 @@ export {
39
39
  export {
40
40
  formsMessagesEn,
41
41
  formChromeLabels,
42
+ formatDisplayName,
42
43
  compileMessageTemplate,
43
44
  compileMessageCatalog,
44
45
  } from './messages.js';
package/src/messages.js CHANGED
@@ -68,9 +68,47 @@ export const formsMessagesEn = {
68
68
  /** The compiled built-in English catalog (module-level singleton). */
69
69
  export const formsMessages = compileMessageCatalog(formsMessagesEn);
70
70
 
71
+ /** Shared empty params for the entries that interpolate nothing. */
72
+ const NO_PARAMS = Object.freeze({});
73
+
74
+ /**
75
+ * The display name of a format, as the catalog in hand spells it.
76
+ *
77
+ * A format's name is its wire name - `date-time`, `iso-time` - which is
78
+ * English by construction and reads as gibberish inside a translated
79
+ * sentence ("Moet een geldige date-time zijn"). A catalog that carries
80
+ * `format/name/<format>` says how that format is called in its own
81
+ * language; the date catalog of `@jarenjs/locales` carries the six date
82
+ * and time ones. A format the catalog has no name for keeps its own,
83
+ * which is the readable answer for the format names that are already
84
+ * words ("email", "hostname") and the only possible one for a format
85
+ * this repository has never heard of.
86
+ *
87
+ * @param {Readonly<Record<string, (params: object, error?: object) => string>>|undefined} catalog - A compiled catalog, or undefined for English
88
+ * @param {string} format - The format name
89
+ * @returns {string} The display name, or the format name itself
90
+ * @example
91
+ * formatDisplayName(dutch, 'date-time'); // 'datum en tijd'
92
+ * formatDisplayName(dutch, 'email'); // 'email'
93
+ */
94
+ export function formatDisplayName(catalog, format) {
95
+ if (typeof format !== 'string' || catalog === undefined) return format;
96
+ const render = catalog[`format/name/${format}`];
97
+ if (render === undefined) return format;
98
+ const name = render(NO_PARAMS);
99
+ return typeof name === 'string' && name !== '' ? name : format;
100
+ }
101
+
71
102
  /**
72
103
  * Resolve a message key through a caller catalog with built-in English
73
104
  * fallback and render it.
105
+ *
106
+ * A format failure is the one message whose params are prepared here
107
+ * rather than at the call site: the error's own `params.format` stays
108
+ * the raw wire name, so re-rendering the same error through a second
109
+ * catalog answers in that catalog's language instead of repeating the
110
+ * first one's noun.
111
+ *
74
112
  * @param {Readonly<Record<string, (params: object, error?: object) => string>>|undefined} catalog - A compiled catalog, or undefined for English
75
113
  * @param {string} msgid - The message key
76
114
  * @param {object} params - The structured params
@@ -80,6 +118,10 @@ export function renderFormsMessage(catalog, msgid, params) {
80
118
  let render = catalog !== undefined ? catalog[msgid] : undefined;
81
119
  if (render === undefined) render = formsMessages[msgid];
82
120
  if (render === undefined) return msgid;
121
+ if (msgid === 'form/format') {
122
+ const format = formatDisplayName(catalog, /** @type {any} */ (params).format);
123
+ return render({ ...params, format });
124
+ }
83
125
  return render(params);
84
126
  }
85
127