@nxgt/i18n 3.0.0 → 3.1.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/README.md +48 -0
- package/dist/catalogues.d.ts +11 -2
- package/dist/catalogues.d.ts.map +1 -1
- package/dist/chunks/{index-wabmsewh.js → index-g7dn8z2a.js} +88 -12
- package/dist/chunks/{index-wabmsewh.js.map → index-g7dn8z2a.js.map} +6 -5
- package/dist/index.browser.d.ts +1 -0
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +7 -3
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/parse.d.ts +48 -0
- package/dist/parse.d.ts.map +1 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -69,6 +69,12 @@ setFallbackLanguage('fr');
|
|
|
69
69
|
`SUPPORTED_LANGUAGES`, `getLanguage()` accepts it from a source or
|
|
70
70
|
`localStorage`, and `translate` answers in it. Registering the same language
|
|
71
71
|
again merges again; nothing is removed.
|
|
72
|
+
- `registerCatalogue(language, catalogue, { replace: true })` drops what was
|
|
73
|
+
registered for that language before, then registers `catalogue`. A reload
|
|
74
|
+
from a database uses it, so a key retired since the last load disappears.
|
|
75
|
+
It drops every earlier registration for that language, whichever module
|
|
76
|
+
made it. The package's own messages stay underneath either way. The options
|
|
77
|
+
are typed `RegisterCatalogueOptions`.
|
|
72
78
|
- `setFallbackLanguage(language)` changes what `getLanguage()` answers when
|
|
73
79
|
nothing names a language (`'en'` until then). The language must have a
|
|
74
80
|
catalogue; otherwise it throws a `RangeError`, so register a new language
|
|
@@ -105,6 +111,48 @@ skipped, so an override never erases a message. The inputs are not changed,
|
|
|
105
111
|
and a `__proto__` key is ignored. The result is typed as `base`; keys an
|
|
106
112
|
override adds are not in that type.
|
|
107
113
|
|
|
114
|
+
### Checking a message: `parseMessage`
|
|
115
|
+
|
|
116
|
+
`parseMessage(message)` parses an ICU message the way `translate` formats it,
|
|
117
|
+
and answers the arguments it uses, with their kinds:
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
import { MessageSyntaxError, parseMessage } from '@nxgt/i18n';
|
|
121
|
+
|
|
122
|
+
parseMessage('{n, plural, one {# file by {who}} other {# files}}');
|
|
123
|
+
// [{ name: 'n', kind: 'plural' }, { name: 'who', kind: 'argument' }]
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
parseMessage('Hello {name');
|
|
127
|
+
} catch (error) {
|
|
128
|
+
if (error instanceof MessageSyntaxError) {
|
|
129
|
+
error.code; // 'EXPECT_ARGUMENT_CLOSING_BRACE'
|
|
130
|
+
error.line; error.column; // 1, 7
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
- Each `{ name, kind }` pair is listed once, in the order it first appears,
|
|
136
|
+
including inside plural and select branches and tags. A name used two ways,
|
|
137
|
+
such as `{n}` and `{n, number}`, appears twice, which is how a check finds it.
|
|
138
|
+
The result is a `MessageArgument[]`, and `kind` is an `ArgumentKind`.
|
|
139
|
+
- The kinds are `argument`, `number`, `date`, `time`, `select`, `plural`,
|
|
140
|
+
`selectordinal` and `tag`. A tag such as `<b>…</b>` is formatted by a
|
|
141
|
+
function the caller passes under that name.
|
|
142
|
+
- A message that does not parse throws a `MessageSyntaxError`, a
|
|
143
|
+
`SyntaxError` carrying the parser's `code`, the `source`, and the `offset`,
|
|
144
|
+
`line` and `column` where parsing failed. A plural or select without an
|
|
145
|
+
`other` branch is refused, as the formatter refuses it. A skeleton the
|
|
146
|
+
parser locates keeps its own code (`INVALID_NUMBER_SKELETON`,
|
|
147
|
+
`EXPECT_DATE_TIME_SKELETON`). One it refuses without saying where, such as
|
|
148
|
+
`{d, date, ::YYYY}`, has the code `INVALID_SKELETON` and no position. `cause`
|
|
149
|
+
is the parser's own error.
|
|
150
|
+
|
|
151
|
+
Use it to check a catalogue loaded from a database, at load time or in a spec:
|
|
152
|
+
every message parses, keeps to the ICU subset the app allows, and uses each
|
|
153
|
+
argument with the same kind in every language. `translate` itself never
|
|
154
|
+
throws: a message that does not parse is logged and returned as it is.
|
|
155
|
+
|
|
108
156
|
## Where the language comes from
|
|
109
157
|
|
|
110
158
|
`getLanguage()` asks, most specific first:
|
package/dist/catalogues.d.ts
CHANGED
|
@@ -11,14 +11,23 @@ export declare function registeredCatalogues(): Readonly<ByLanguage>;
|
|
|
11
11
|
* one `SUPPORTED_LANGUAGES` is.
|
|
12
12
|
*/
|
|
13
13
|
export declare function supportedLanguages(): readonly Language[];
|
|
14
|
+
export type RegisterCatalogueOptions = {
|
|
15
|
+
/**
|
|
16
|
+
* Replace what was registered for the language instead of merging over
|
|
17
|
+
* it: a reload drops the keys it no longer has. The package's own
|
|
18
|
+
* catalogue stays underneath either way.
|
|
19
|
+
*/
|
|
20
|
+
replace?: boolean;
|
|
21
|
+
};
|
|
14
22
|
/**
|
|
15
23
|
* Registers `catalogue` for `language`, merged deeply over what that language
|
|
16
24
|
* already has (`mergeCatalogues`): a key it names wins, a key it leaves out
|
|
17
25
|
* keeps the package's message. A language with no catalogue yet becomes
|
|
18
26
|
* supported — `getLanguage()` accepts it from a source or `localStorage`, and
|
|
19
|
-
* `translate` answers in it.
|
|
27
|
+
* `translate` answers in it. With `{ replace: true }`, earlier registrations
|
|
28
|
+
* for the language are dropped first.
|
|
20
29
|
*/
|
|
21
|
-
export declare function registerCatalogue(language: Language, catalogue: Catalogue): void;
|
|
30
|
+
export declare function registerCatalogue(language: Language, catalogue: Catalogue, { replace }?: RegisterCatalogueOptions): void;
|
|
22
31
|
/** The language `getLanguage()` answers when nothing else names one. */
|
|
23
32
|
export declare function getFallbackLanguage(): Language;
|
|
24
33
|
/**
|
package/dist/catalogues.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalogues.d.ts","sourceRoot":"","sources":["../src/catalogues.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnD,KAAK,UAAU,GAAG,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AA8D9C;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,QAAQ,CAAC,UAAU,CAAC,CAE3D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,SAAS,QAAQ,EAAE,CAExD;AAED
|
|
1
|
+
{"version":3,"file":"catalogues.d.ts","sourceRoot":"","sources":["../src/catalogues.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnD,KAAK,UAAU,GAAG,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AA8D9C;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,QAAQ,CAAC,UAAU,CAAC,CAE3D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,SAAS,QAAQ,EAAE,CAExD;AAED,MAAM,MAAM,wBAAwB,GAAG;IACtC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAChC,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,SAAS,EACpB,EAAE,OAAe,EAAE,GAAE,wBAA6B,GAChD,IAAI,CAgBN;AAED,wEAAwE;AACxE,wBAAgB,mBAAmB,IAAI,QAAQ,CAE9C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAO5D"}
|
|
@@ -141,12 +141,12 @@ var validation_default = {
|
|
|
141
141
|
size: "The length of the field ''{path}'' must be between {min} and {max}.",
|
|
142
142
|
past: "The value for the field ''{path}'' must be a valid date before {limit}.",
|
|
143
143
|
future: "The value for the field ''{path}'' must be a valid date after {limit}.",
|
|
144
|
-
email: "The value for the field ''{path}'' must be {numberOfDomains, plural, =0 {a valid email address} =1 {an email address within the domain ''{domains}''} other {an email address within one of the following domains: [{domains}]}.",
|
|
144
|
+
email: "The value for the field ''{path}'' must be {numberOfDomains, plural, =0 {a valid email address} =1 {an email address within the domain ''{domains}''} other {an email address within one of the following domains: [{domains}]}}.",
|
|
145
145
|
ip: "The value for the field ''{path}'' must be a valid IP address.",
|
|
146
146
|
ipv4: "The value for the field ''{path}'' must be a valid IPv4 address.",
|
|
147
147
|
ipv6: "The value for the field ''{path}'' must be a valid IPv6 address.",
|
|
148
148
|
mac: "The value for the field ''{path}'' must be a valid MAC address.",
|
|
149
|
-
url: "The value for the field ''{path}'' must be {numberOfDomains, plural, =0 {a valid URL} =1 {a URL within the domain ''{domains}''} other {a URL within one of the following domains: [{domains}]}.",
|
|
149
|
+
url: "The value for the field ''{path}'' must be {numberOfDomains, plural, =0 {a valid URL} =1 {a URL within the domain ''{domains}''} other {a URL within one of the following domains: [{domains}]}}.",
|
|
150
150
|
uuid: "The value for the field ''{path}'' must be a valid UUID.",
|
|
151
151
|
guid: "The value for the field ''{path}'' must be a valid GUID.",
|
|
152
152
|
ssn: "The value for the field ''{path}'' must be a valid social security number(SSN).",
|
|
@@ -160,7 +160,7 @@ var validation_default = {
|
|
|
160
160
|
positive: "The value for the field ''{path}'' must be a positive number.",
|
|
161
161
|
negative: "The value for the field ''{path}'' must be a negative number.",
|
|
162
162
|
"no-scalars": "Invalid type: ''{type}'' is not a scalar type.",
|
|
163
|
-
"not-null": "The value for {length, plural, =0 {the field} other {each item of the field} ''{path}'' should not be null.",
|
|
163
|
+
"not-null": "The value for {length, plural, =0 {the field} other {each item of the field}} ''{path}'' should not be null.",
|
|
164
164
|
required: "The value for the field ''{path}'' is required.",
|
|
165
165
|
time: "The value for the field ''{path}'' must be a valid time in the format HH:mm."
|
|
166
166
|
}
|
|
@@ -366,12 +366,12 @@ var validation_default2 = {
|
|
|
366
366
|
size: "La longueur du champ ''{path}'' doit être comprise entre {min} et {max}.",
|
|
367
367
|
past: "La valeur pour le champ ''{path}'' doit être une date valide antérieure à {limit}.",
|
|
368
368
|
future: "La valeur pour le champ ''{path}'' doit être une date valide postérieure à {limit}.",
|
|
369
|
-
email: "La valeur pour le champ ''{path}'' doit être {numberOfDomains, plural, =0 {une adresse électronique valide} =1 {une adresse électronique dans le domaine ''{domains}'' } other {une adresse électronique dans l'un des domaines suivants : [{domains}]}.",
|
|
369
|
+
email: "La valeur pour le champ ''{path}'' doit être {numberOfDomains, plural, =0 {une adresse électronique valide} =1 {une adresse électronique dans le domaine ''{domains}'' } other {une adresse électronique dans l'un des domaines suivants : [{domains}]}}.",
|
|
370
370
|
ip: "La valeur pour le champ ''{path}'' doit être une adresse IP valide.",
|
|
371
371
|
ipv4: "La valeur pour le champ ''{path}'' doit être une adresse IPv4 valide.",
|
|
372
372
|
ipv6: "La valeur pour le champ ''{path}'' doit être une adresse IPv6 valide.",
|
|
373
373
|
mac: "La valeur pour le champ ''{path}'' doit être une adresse MAC valide.",
|
|
374
|
-
url: "La valeur pour le champ ''{path}'' doit être {numberOfDomains, plural, =0 {une URL valide} =1 {une URL dans le domaine ''{domains}'' } other {une URL dans l'un des domaines suivants : [{domains}]}.",
|
|
374
|
+
url: "La valeur pour le champ ''{path}'' doit être {numberOfDomains, plural, =0 {une URL valide} =1 {une URL dans le domaine ''{domains}'' } other {une URL dans l'un des domaines suivants : [{domains}]}}.",
|
|
375
375
|
uuid: "La valeur pour le champ ''{path}'' doit être un UUID valide.",
|
|
376
376
|
guid: "La valeur pour le champ ''{path}'' doit être un GUID valide.",
|
|
377
377
|
ssn: "La valeur pour le champ ''{path}'' doit être un numéro de sécurité social valide.",
|
|
@@ -380,8 +380,8 @@ var validation_default2 = {
|
|
|
380
380
|
"zip-code": "La valeur pour le champ ''{path}'' doit être un code postal valide.",
|
|
381
381
|
"object-id": "La valeur pour le champ ''{path}'' doit être une chaîne hexadécimale de 24 caractères.",
|
|
382
382
|
pattern: "Valeur invalide pour le champ ''{path}'' . La valeur doit correspondre au motif : ''{pattern}'' .",
|
|
383
|
-
"not-blank": "
|
|
384
|
-
"not-empty": "
|
|
383
|
+
"not-blank": "Le champ ''{path}'' ne doit pas être vide.",
|
|
384
|
+
"not-empty": "Le champ ''{path}'' ne doit pas être vide.",
|
|
385
385
|
positive: "La valeur pour le champ ''{path}'' doit être un nombre positif.",
|
|
386
386
|
negative: "La valeur pour le champ ''{path}'' doit être un nombre négatif.",
|
|
387
387
|
"no-scalars": "Type invalide : ''{type}'' n'est pas un type scalaire.",
|
|
@@ -517,12 +517,12 @@ function registeredCatalogues2() {
|
|
|
517
517
|
function supportedLanguages2() {
|
|
518
518
|
return state().languages;
|
|
519
519
|
}
|
|
520
|
-
function registerCatalogue2(language, catalogue) {
|
|
520
|
+
function registerCatalogue2(language, catalogue, { replace = false } = {}) {
|
|
521
521
|
if (typeof language !== "string" || language === "" || language === "__proto__") {
|
|
522
522
|
throw new TypeError(`@nxgt/i18n: registerCatalogue needs a language name, got ${JSON.stringify(language)}`);
|
|
523
523
|
}
|
|
524
524
|
const shared = state();
|
|
525
|
-
shared.registered[language] = mergeCatalogues2(shared.registered[language] ?? {}, catalogue);
|
|
525
|
+
shared.registered[language] = mergeCatalogues2(replace ? {} : shared.registered[language] ?? {}, catalogue);
|
|
526
526
|
refresh(shared, language);
|
|
527
527
|
}
|
|
528
528
|
function getFallbackLanguage2() {
|
|
@@ -611,7 +611,83 @@ function createTranslator2(resources = {}, localeProvider = getLanguage2) {
|
|
|
611
611
|
};
|
|
612
612
|
}
|
|
613
613
|
var translate2 = createTranslator2(registeredCatalogues2());
|
|
614
|
-
export { mergeCatalogues2, resources2, registeredCatalogues2, supportedLanguages2, registerCatalogue2, getFallbackLanguage2, setFallbackLanguage2, LANGUAGE_KEY2, SUPPORTED_LANGUAGES2, registerLanguageSource2, languageFromSources2, getLanguage2, createTranslator2, translate2 };
|
|
615
614
|
|
|
616
|
-
|
|
617
|
-
|
|
615
|
+
// src/parse.ts
|
|
616
|
+
import {
|
|
617
|
+
parse,
|
|
618
|
+
TYPE
|
|
619
|
+
} from "@formatjs/icu-messageformat-parser";
|
|
620
|
+
|
|
621
|
+
class MessageSyntaxError2 extends SyntaxError {
|
|
622
|
+
code;
|
|
623
|
+
source;
|
|
624
|
+
name = "MessageSyntaxError";
|
|
625
|
+
offset;
|
|
626
|
+
line;
|
|
627
|
+
column;
|
|
628
|
+
constructor(code, source, position, cause) {
|
|
629
|
+
const where = position ? ` at ${position.line}:${position.column}` : "";
|
|
630
|
+
super(`@nxgt/i18n: ${code}${where} in ${JSON.stringify(source)}`, {
|
|
631
|
+
cause
|
|
632
|
+
});
|
|
633
|
+
this.code = code;
|
|
634
|
+
this.source = source;
|
|
635
|
+
this.offset = position?.offset;
|
|
636
|
+
this.line = position?.line;
|
|
637
|
+
this.column = position?.column;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
function kindOf(element) {
|
|
641
|
+
switch (element.type) {
|
|
642
|
+
case TYPE.argument:
|
|
643
|
+
return "argument";
|
|
644
|
+
case TYPE.number:
|
|
645
|
+
return "number";
|
|
646
|
+
case TYPE.date:
|
|
647
|
+
return "date";
|
|
648
|
+
case TYPE.time:
|
|
649
|
+
return "time";
|
|
650
|
+
case TYPE.select:
|
|
651
|
+
return "select";
|
|
652
|
+
case TYPE.plural:
|
|
653
|
+
return element.pluralType === "ordinal" ? "selectordinal" : "plural";
|
|
654
|
+
case TYPE.tag:
|
|
655
|
+
return "tag";
|
|
656
|
+
default:
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
function collect(elements, found) {
|
|
661
|
+
for (const element of elements) {
|
|
662
|
+
const kind = kindOf(element);
|
|
663
|
+
if (kind !== undefined && "value" in element) {
|
|
664
|
+
const name = element.value;
|
|
665
|
+
if (!found.some((seen) => seen.name === name && seen.kind === kind)) {
|
|
666
|
+
found.push({ name, kind });
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
if (element.type === TYPE.select || element.type === TYPE.plural) {
|
|
670
|
+
for (const option of Object.values(element.options)) {
|
|
671
|
+
collect(option.value, found);
|
|
672
|
+
}
|
|
673
|
+
} else if (element.type === TYPE.tag) {
|
|
674
|
+
collect(element.children, found);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
function parseMessage2(message) {
|
|
679
|
+
let elements;
|
|
680
|
+
try {
|
|
681
|
+
elements = parse(message);
|
|
682
|
+
} catch (error) {
|
|
683
|
+
const { location } = error;
|
|
684
|
+
throw location ? new MessageSyntaxError2(error.message, message, location.start, error) : new MessageSyntaxError2("INVALID_SKELETON", message, undefined, error);
|
|
685
|
+
}
|
|
686
|
+
const found = [];
|
|
687
|
+
collect(elements, found);
|
|
688
|
+
return found;
|
|
689
|
+
}
|
|
690
|
+
export { mergeCatalogues2, resources2, registeredCatalogues2, supportedLanguages2, registerCatalogue2, getFallbackLanguage2, setFallbackLanguage2, LANGUAGE_KEY2, SUPPORTED_LANGUAGES2, registerLanguageSource2, languageFromSources2, getLanguage2, createTranslator2, translate2, MessageSyntaxError2, parseMessage2 };
|
|
691
|
+
|
|
692
|
+
//# debugId=08677851F59036F664756E2164756E21
|
|
693
|
+
//# sourceMappingURL=index-g7dn8z2a.js.map
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/merge.ts", "../src/resources/en/index.ts", "../src/resources/fr/index.ts", "../src/resources/index.ts", "../src/catalogues.ts", "../src/consts.ts", "../src/sources.ts", "../src/i18n.ts"],
|
|
3
|
+
"sources": ["../src/merge.ts", "../src/resources/en/index.ts", "../src/resources/fr/index.ts", "../src/resources/index.ts", "../src/catalogues.ts", "../src/consts.ts", "../src/sources.ts", "../src/i18n.ts", "../src/parse.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import type { Catalogue } from './types';\n\ntype Branch = Record<string, unknown>;\n\nfunction isBranch(value: unknown): value is Branch {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Copies `source` into `target`, which is always an object this module made,\n * never one of the caller's: a branch in `source` is merged into a fresh\n * object, so the result shares nothing with its inputs.\n */\nfunction mergeInto(target: Branch, source: Branch): Branch {\n\tfor (const key of Object.keys(source)) {\n\t\t// A catalogue read from a database is data: `__proto__` must not\n\t\t// reach the result's prototype.\n\t\tif (key === '__proto__') continue;\n\t\tconst value = source[key];\n\t\tif (value === undefined || value === null) continue;\n\t\tif (isBranch(value)) {\n\t\t\tconst current = Object.hasOwn(target, key) ? target[key] : undefined;\n\t\t\ttarget[key] = mergeInto(isBranch(current) ? current : {}, value);\n\t\t} else {\n\t\t\ttarget[key] = value;\n\t\t}\n\t}\n\treturn target;\n}\n\n/**\n * Merges catalogues deeply, the last one winning leaf by leaf:\n * `mergeCatalogues(packageDefaults, appOverrides, databaseOverrides)`.\n *\n * A spread replaces whole branches — `{ ...resources.en, validation }` drops\n * every package key under `validation` the app did not repeat. Here a branch\n * is merged key by key; a leaf (a message) replaces what was there, branch\n * included. `undefined` and `null` are skipped, so an override never erases\n * a message. The inputs are not changed.\n *\n * The result is typed as `base`: an override can add keys, which the type\n * does not list.\n */\nexport function mergeCatalogues<B extends Catalogue>(\n\tbase: B,\n\t...overrides: readonly Catalogue[]\n): B {\n\tconst result: Branch = {};\n\tfor (const catalogue of [base, ...overrides]) {\n\t\tif (!isBranch(catalogue)) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`@nxgt/i18n: mergeCatalogues takes catalogue objects, got ${catalogue === null ? 'null' : typeof catalogue}`,\n\t\t\t);\n\t\t}\n\t\tmergeInto(result, catalogue);\n\t}\n\treturn result as B;\n}\n",
|
|
6
6
|
"import common from './common.json';\nimport errors from './errors.json';\nimport validation from './validation.json';\nimport zod from './zod.json';\n\nexport const en = {\n\t...common,\n\terrors,\n\tvalidation,\n\tzod,\n};\n",
|
|
7
7
|
"import common from './common.json';\nimport errors from './errors.json';\nimport validation from './validation.json';\nimport zod from './zod.json';\n\nexport const fr = {\n\t...common,\n\terrors,\n\tvalidation,\n\tzod,\n};\n",
|
|
8
8
|
"import { en } from './en';\nimport { fr } from './fr';\n\nexport const resources = {\n\ten,\n\tfr,\n};\n",
|
|
9
|
-
"import { mergeCatalogues } from './merge';\nimport { resources } from './resources';\nimport type { Catalogue, Language } from './types';\n\ntype ByLanguage = Record<Language, Catalogue>;\n\n/**\n * The shape every 3.x copy of this package agrees on. It is a contract\n * between versions: a field added here needs a new symbol name.\n */\ntype State = {\n\t/** Each copy's built-in catalogues, merged: a newer copy's keys join. */\n\tbase: ByLanguage;\n\t/** What the app registered, merged per language. */\n\tregistered: ByLanguage;\n\t/** `base` under `registered`, what `translate` reads. */\n\tcatalogues: ByLanguage;\n\tlanguages: Language[];\n\tfallback: Language;\n};\n\n/**\n * One state for the process, on `globalThis`, as the language sources are:\n * an app can hold two copies of this package — one a dependency of\n * `@nxgt/shared-hono`, one its own — and a catalogue registered through\n * either must translate through both. A 2.x copy has no such state and sees\n * none of it.\n */\nconst STATE = Symbol.for('@nxgt/i18n/catalogues@3');\n\n/** No prototype: a language is a key, and `constructor` is a fine name. */\nconst byLanguage = (): ByLanguage => Object.create(null);\n\nfunction refresh(state: State, language: Language): void {\n\tstate.catalogues[language] = mergeCatalogues(\n\t\tstate.base[language] ?? {},\n\t\tstate.registered[language] ?? {},\n\t);\n\tif (!state.languages.includes(language)) state.languages.push(language);\n}\n\nfunction state(): State {\n\tconst global = globalThis as { [STATE]?: State };\n\tglobal[STATE] ??= {\n\t\tbase: byLanguage(),\n\t\tregistered: byLanguage(),\n\t\tcatalogues: byLanguage(),\n\t\tlanguages: [],\n\t\tfallback: 'en',\n\t};\n\treturn global[STATE];\n}\n\n// Each copy adds its built-in catalogues when it loads: keys a newer copy\n// ships reach every copy, and a key both ship keeps the first one's message.\n{\n\tconst shared = state();\n\tfor (const [language, catalogue] of Object.entries(resources)) {\n\t\tshared.base[language] = mergeCatalogues(\n\t\t\tcatalogue,\n\t\t\tshared.base[language] ?? {},\n\t\t);\n\t\trefresh(shared, language);\n\t}\n}\n\n/**\n * The catalogues `translate` reads, by language: this package's `en` and `fr`\n * and whatever was registered on top. The object is live — a registration\n * shows in it — and is read-only to callers.\n */\nexport function registeredCatalogues(): Readonly<ByLanguage> {\n\treturn state().catalogues;\n}\n\n/**\n * The languages a catalogue is registered for. The array is live, the same\n * one `SUPPORTED_LANGUAGES` is.\n */\nexport function supportedLanguages(): readonly Language[] {\n\treturn state().languages;\n}\n\n/**\n * Registers `catalogue` for `language`, merged deeply over what that language\n * already has (`mergeCatalogues`): a key it names wins, a key it leaves out\n * keeps the package's message. A language with no catalogue yet becomes\n * supported — `getLanguage()` accepts it from a source or `localStorage`, and\n * `translate` answers in it.\n */\nexport function registerCatalogue(\n\tlanguage: Language,\n\tcatalogue: Catalogue,\n): void {\n\tif (\n\t\ttypeof language !== 'string' ||\n\t\tlanguage === '' ||\n\t\tlanguage === '__proto__'\n\t) {\n\t\tthrow new TypeError(\n\t\t\t`@nxgt/i18n: registerCatalogue needs a language name, got ${JSON.stringify(language)}`,\n\t\t);\n\t}\n\tconst shared = state();\n\tshared.registered[language] = mergeCatalogues(\n\t\
|
|
9
|
+
"import { mergeCatalogues } from './merge';\nimport { resources } from './resources';\nimport type { Catalogue, Language } from './types';\n\ntype ByLanguage = Record<Language, Catalogue>;\n\n/**\n * The shape every 3.x copy of this package agrees on. It is a contract\n * between versions: a field added here needs a new symbol name.\n */\ntype State = {\n\t/** Each copy's built-in catalogues, merged: a newer copy's keys join. */\n\tbase: ByLanguage;\n\t/** What the app registered, merged per language. */\n\tregistered: ByLanguage;\n\t/** `base` under `registered`, what `translate` reads. */\n\tcatalogues: ByLanguage;\n\tlanguages: Language[];\n\tfallback: Language;\n};\n\n/**\n * One state for the process, on `globalThis`, as the language sources are:\n * an app can hold two copies of this package — one a dependency of\n * `@nxgt/shared-hono`, one its own — and a catalogue registered through\n * either must translate through both. A 2.x copy has no such state and sees\n * none of it.\n */\nconst STATE = Symbol.for('@nxgt/i18n/catalogues@3');\n\n/** No prototype: a language is a key, and `constructor` is a fine name. */\nconst byLanguage = (): ByLanguage => Object.create(null);\n\nfunction refresh(state: State, language: Language): void {\n\tstate.catalogues[language] = mergeCatalogues(\n\t\tstate.base[language] ?? {},\n\t\tstate.registered[language] ?? {},\n\t);\n\tif (!state.languages.includes(language)) state.languages.push(language);\n}\n\nfunction state(): State {\n\tconst global = globalThis as { [STATE]?: State };\n\tglobal[STATE] ??= {\n\t\tbase: byLanguage(),\n\t\tregistered: byLanguage(),\n\t\tcatalogues: byLanguage(),\n\t\tlanguages: [],\n\t\tfallback: 'en',\n\t};\n\treturn global[STATE];\n}\n\n// Each copy adds its built-in catalogues when it loads: keys a newer copy\n// ships reach every copy, and a key both ship keeps the first one's message.\n{\n\tconst shared = state();\n\tfor (const [language, catalogue] of Object.entries(resources)) {\n\t\tshared.base[language] = mergeCatalogues(\n\t\t\tcatalogue,\n\t\t\tshared.base[language] ?? {},\n\t\t);\n\t\trefresh(shared, language);\n\t}\n}\n\n/**\n * The catalogues `translate` reads, by language: this package's `en` and `fr`\n * and whatever was registered on top. The object is live — a registration\n * shows in it — and is read-only to callers.\n */\nexport function registeredCatalogues(): Readonly<ByLanguage> {\n\treturn state().catalogues;\n}\n\n/**\n * The languages a catalogue is registered for. The array is live, the same\n * one `SUPPORTED_LANGUAGES` is.\n */\nexport function supportedLanguages(): readonly Language[] {\n\treturn state().languages;\n}\n\nexport type RegisterCatalogueOptions = {\n\t/**\n\t * Replace what was registered for the language instead of merging over\n\t * it: a reload drops the keys it no longer has. The package's own\n\t * catalogue stays underneath either way.\n\t */\n\treplace?: boolean;\n};\n\n/**\n * Registers `catalogue` for `language`, merged deeply over what that language\n * already has (`mergeCatalogues`): a key it names wins, a key it leaves out\n * keeps the package's message. A language with no catalogue yet becomes\n * supported — `getLanguage()` accepts it from a source or `localStorage`, and\n * `translate` answers in it. With `{ replace: true }`, earlier registrations\n * for the language are dropped first.\n */\nexport function registerCatalogue(\n\tlanguage: Language,\n\tcatalogue: Catalogue,\n\t{ replace = false }: RegisterCatalogueOptions = {},\n): void {\n\tif (\n\t\ttypeof language !== 'string' ||\n\t\tlanguage === '' ||\n\t\tlanguage === '__proto__'\n\t) {\n\t\tthrow new TypeError(\n\t\t\t`@nxgt/i18n: registerCatalogue needs a language name, got ${JSON.stringify(language)}`,\n\t\t);\n\t}\n\tconst shared = state();\n\tshared.registered[language] = mergeCatalogues(\n\t\treplace ? {} : (shared.registered[language] ?? {}),\n\t\tcatalogue,\n\t);\n\trefresh(shared, language);\n}\n\n/** The language `getLanguage()` answers when nothing else names one. */\nexport function getFallbackLanguage(): Language {\n\treturn state().fallback;\n}\n\n/**\n * Changes the fallback language, `'en'` until then. It must have a catalogue:\n * register one first for a language this package does not ship.\n */\nexport function setFallbackLanguage(language: Language): void {\n\tif (!state().languages.includes(language)) {\n\t\tthrow new RangeError(\n\t\t\t`@nxgt/i18n: no catalogue is registered for \"${language}\"; call registerCatalogue(\"${language}\", …) first`,\n\t\t);\n\t}\n\tstate().fallback = language;\n}\n",
|
|
10
10
|
"import { supportedLanguages } from './catalogues';\n\nexport const LANGUAGE_KEY = 'language';\n\n/**\n * The languages a catalogue is registered for: `en` and `fr`, then each one\n * `registerCatalogue()` adds. Live — a registration shows in it.\n */\nexport const SUPPORTED_LANGUAGES: readonly string[] = supportedLanguages();\n",
|
|
11
11
|
"import { SUPPORTED_LANGUAGES } from './consts';\nimport type { Language } from './types';\n\n/**\n * Where a language may come from: a server's request context, a framework's\n * state. It answers the request's language, or nothing — `undefined`, `null`,\n * a language no catalogue has — and the next source is asked.\n */\nexport type LanguageSource = () => string | null | undefined;\n\n/**\n * One registry for the process, on `globalThis`: an app can hold two copies\n * of this package — one a dependency of `@nxgt/shared-hono`, one its own —\n * and a source registered through either must answer both.\n */\nconst REGISTRY = Symbol.for('@nxgt/i18n/language-sources');\n\nfunction registry(): LanguageSource[] {\n\tconst global = globalThis as { [REGISTRY]?: LanguageSource[] };\n\tglobal[REGISTRY] ??= [];\n\treturn global[REGISTRY];\n}\n\n/**\n * Adds a source `getLanguage()` asks, after those registered before it.\n * Registering one twice keeps one. Answers the function that removes it.\n *\n * This package knows no server: `@nxgt/shared-hono` registers the Hono\n * request context's `language`, `@alxia/i18n` the alxia request's.\n */\nexport function registerLanguageSource(source: LanguageSource): () => void {\n\tconst sources = registry();\n\tif (!sources.includes(source)) sources.push(source);\n\treturn () => {\n\t\tconst index = sources.indexOf(source);\n\t\tif (index !== -1) sources.splice(index, 1);\n\t};\n}\n\n/**\n * The first supported language a registered source answers. A source that\n * throws is skipped: a language is never worth a failed request.\n */\nexport function languageFromSources(): Language | undefined {\n\tfor (const source of registry()) {\n\t\tlet answer: string | null | undefined;\n\t\ttry {\n\t\t\tanswer = source();\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof answer === 'string' && SUPPORTED_LANGUAGES.includes(answer)) {\n\t\t\treturn answer;\n\t\t}\n\t}\n\treturn undefined;\n}\n",
|
|
12
|
-
"import { IntlMessageFormat } from 'intl-messageformat';\nimport _ from 'lodash';\nimport { getFallbackLanguage, registeredCatalogues } from './catalogues';\nimport { LANGUAGE_KEY, SUPPORTED_LANGUAGES } from './consts';\nimport { languageFromSources } from './sources';\nimport type {\n\tLanguage,\n\tLanguageProvider,\n\tLocaleKey,\n\tTranslationContext,\n} from './types';\n\n/**\n * Where the language comes from when the caller does not say, most specific\n * first:\n *\n * 1. a registered source — `registerLanguageSource()`: a server's request\n * context, which `@nxgt/shared-hono` registers for Hono and\n * `@alxia/i18n` for alxia;\n * 2. `localStorage`, when that object exists;\n * 3. the fallback language — `'en'`, or what `setFallbackLanguage()` set.\n *\n * Until 2.0 this read Hono's request context itself, through\n * `hono/context-storage`, which tied every consumer — a browser bundle, an\n * alxia server — to Hono. The Hono part lives in `@nxgt/shared-hono` now.\n *\n * `createTranslator` still takes a provider, so a caller that wants one source\n * and not the others passes it.\n */\nexport function getLanguage(): Language {\n\tconst fromSource = languageFromSources();\n\tif (fromSource !== undefined) return fromSource;\n\tif (typeof localStorage !== 'undefined') {\n\t\tconst stored = localStorage.getItem(LANGUAGE_KEY);\n\t\tif (stored !== null && SUPPORTED_LANGUAGES.includes(stored)) return stored;\n\t}\n\treturn getFallbackLanguage();\n}\n\n/**\n * The message under `key` in `language`'s catalogue, if that language has one\n * of its own (not `constructor` through the prototype) and the key leads to a\n * message, not a branch.\n */\nfunction messageIn(\n\tresources: Record<string, any>,\n\tlanguage: string,\n\tkey: string,\n): string | undefined {\n\tif (!Object.hasOwn(resources, language)) return undefined;\n\tconst message = _.get(resources[language], key);\n\treturn typeof message === 'string' ? message : undefined;\n}\n\n/**\n * A translator over `resources`. A key the language lacks — or a language\n * with no catalogue at all — is looked up in the fallback language\n * (`getFallbackLanguage()`), and only then answered as the key itself.\n */\nexport function createTranslator<K extends string = LocaleKey>(\n\tresources: Record<string, any> = {},\n\tlocaleProvider: LanguageProvider = getLanguage,\n) {\n\treturn (\n\t\tkey: K,\n\t\tcontext: TranslationContext = undefined,\n\t\tprovideLanguage: LanguageProvider = localeProvider,\n\t): string => {\n\t\tconst language =\n\t\t\ttypeof provideLanguage === 'function'\n\t\t\t\t? provideLanguage()\n\t\t\t\t: provideLanguage;\n\t\tlet locale = language;\n\t\tlet found = messageIn(resources, language, key);\n\t\tconst fallback = getFallbackLanguage();\n\t\tif (found === undefined && fallback !== language) {\n\t\t\tfound = messageIn(resources, fallback, key);\n\t\t\tlocale = fallback;\n\t\t}\n\t\tlet message = found ?? key;\n\t\ttry {\n\t\t\tmessage = new IntlMessageFormat(message, locale).format(context);\n\t\t} catch (e) {\n\t\t\tconsole.error(e);\n\t\t}\n\n\t\treturn message;\n\t};\n}\n\n/**\n * Translates with this package's catalogues and every one registered on top\n * (`registerCatalogue`), in `getLanguage()`'s language.\n */\nexport const translate = createTranslator(registeredCatalogues());\n"
|
|
12
|
+
"import { IntlMessageFormat } from 'intl-messageformat';\nimport _ from 'lodash';\nimport { getFallbackLanguage, registeredCatalogues } from './catalogues';\nimport { LANGUAGE_KEY, SUPPORTED_LANGUAGES } from './consts';\nimport { languageFromSources } from './sources';\nimport type {\n\tLanguage,\n\tLanguageProvider,\n\tLocaleKey,\n\tTranslationContext,\n} from './types';\n\n/**\n * Where the language comes from when the caller does not say, most specific\n * first:\n *\n * 1. a registered source — `registerLanguageSource()`: a server's request\n * context, which `@nxgt/shared-hono` registers for Hono and\n * `@alxia/i18n` for alxia;\n * 2. `localStorage`, when that object exists;\n * 3. the fallback language — `'en'`, or what `setFallbackLanguage()` set.\n *\n * Until 2.0 this read Hono's request context itself, through\n * `hono/context-storage`, which tied every consumer — a browser bundle, an\n * alxia server — to Hono. The Hono part lives in `@nxgt/shared-hono` now.\n *\n * `createTranslator` still takes a provider, so a caller that wants one source\n * and not the others passes it.\n */\nexport function getLanguage(): Language {\n\tconst fromSource = languageFromSources();\n\tif (fromSource !== undefined) return fromSource;\n\tif (typeof localStorage !== 'undefined') {\n\t\tconst stored = localStorage.getItem(LANGUAGE_KEY);\n\t\tif (stored !== null && SUPPORTED_LANGUAGES.includes(stored)) return stored;\n\t}\n\treturn getFallbackLanguage();\n}\n\n/**\n * The message under `key` in `language`'s catalogue, if that language has one\n * of its own (not `constructor` through the prototype) and the key leads to a\n * message, not a branch.\n */\nfunction messageIn(\n\tresources: Record<string, any>,\n\tlanguage: string,\n\tkey: string,\n): string | undefined {\n\tif (!Object.hasOwn(resources, language)) return undefined;\n\tconst message = _.get(resources[language], key);\n\treturn typeof message === 'string' ? message : undefined;\n}\n\n/**\n * A translator over `resources`. A key the language lacks — or a language\n * with no catalogue at all — is looked up in the fallback language\n * (`getFallbackLanguage()`), and only then answered as the key itself.\n */\nexport function createTranslator<K extends string = LocaleKey>(\n\tresources: Record<string, any> = {},\n\tlocaleProvider: LanguageProvider = getLanguage,\n) {\n\treturn (\n\t\tkey: K,\n\t\tcontext: TranslationContext = undefined,\n\t\tprovideLanguage: LanguageProvider = localeProvider,\n\t): string => {\n\t\tconst language =\n\t\t\ttypeof provideLanguage === 'function'\n\t\t\t\t? provideLanguage()\n\t\t\t\t: provideLanguage;\n\t\tlet locale = language;\n\t\tlet found = messageIn(resources, language, key);\n\t\tconst fallback = getFallbackLanguage();\n\t\tif (found === undefined && fallback !== language) {\n\t\t\tfound = messageIn(resources, fallback, key);\n\t\t\tlocale = fallback;\n\t\t}\n\t\tlet message = found ?? key;\n\t\ttry {\n\t\t\tmessage = new IntlMessageFormat(message, locale).format(context);\n\t\t} catch (e) {\n\t\t\tconsole.error(e);\n\t\t}\n\n\t\treturn message;\n\t};\n}\n\n/**\n * Translates with this package's catalogues and every one registered on top\n * (`registerCatalogue`), in `getLanguage()`'s language.\n */\nexport const translate = createTranslator(registeredCatalogues());\n",
|
|
13
|
+
"import {\n\ttype MessageFormatElement,\n\tparse,\n\tTYPE,\n} from '@formatjs/icu-messageformat-parser';\n\n/**\n * How a message uses an argument, as the ICU syntax names it: `{name}` is an\n * `argument`, `{n, number}` a `number`, `{n, plural, …}` a `plural`,\n * `{n, selectordinal, …}` a `selectordinal`, `<b>…</b>` a `tag` (formatted\n * by a function the caller passes under that name).\n */\nexport type ArgumentKind =\n\t| 'argument'\n\t| 'number'\n\t| 'date'\n\t| 'time'\n\t| 'select'\n\t| 'plural'\n\t| 'selectordinal'\n\t| 'tag';\n\n/** One argument a message uses, and how. */\nexport type MessageArgument = { name: string; kind: ArgumentKind };\n\ntype Position = { offset: number; line: number; column: number };\n\n/**\n * A message that is not valid ICU. `code` is the parser's\n * (`EXPECT_ARGUMENT_CLOSING_BRACE`, …), and `offset`, `line` and `column`\n * point at where it went wrong in `source`. A skeleton the parser locates\n * keeps its own code (`INVALID_NUMBER_SKELETON`, `EXPECT_DATE_TIME_SKELETON`);\n * one it refuses without saying where (`{d, date, ::YYYY}`) has the code\n * `INVALID_SKELETON` and no position. `cause` is the parser's own error.\n */\nexport class MessageSyntaxError extends SyntaxError {\n\toverride readonly name = 'MessageSyntaxError';\n\treadonly offset: number | undefined;\n\treadonly line: number | undefined;\n\treadonly column: number | undefined;\n\n\tconstructor(\n\t\treadonly code: string,\n\t\treadonly source: string,\n\t\tposition: Position | undefined,\n\t\tcause: unknown,\n\t) {\n\t\tconst where = position ? ` at ${position.line}:${position.column}` : '';\n\t\tsuper(`@nxgt/i18n: ${code}${where} in ${JSON.stringify(source)}`, {\n\t\t\tcause,\n\t\t});\n\t\tthis.offset = position?.offset;\n\t\tthis.line = position?.line;\n\t\tthis.column = position?.column;\n\t}\n}\n\nfunction kindOf(element: MessageFormatElement): ArgumentKind | undefined {\n\tswitch (element.type) {\n\t\tcase TYPE.argument:\n\t\t\treturn 'argument';\n\t\tcase TYPE.number:\n\t\t\treturn 'number';\n\t\tcase TYPE.date:\n\t\t\treturn 'date';\n\t\tcase TYPE.time:\n\t\t\treturn 'time';\n\t\tcase TYPE.select:\n\t\t\treturn 'select';\n\t\tcase TYPE.plural:\n\t\t\treturn element.pluralType === 'ordinal' ? 'selectordinal' : 'plural';\n\t\tcase TYPE.tag:\n\t\t\treturn 'tag';\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nfunction collect(\n\telements: MessageFormatElement[],\n\tfound: MessageArgument[],\n): void {\n\tfor (const element of elements) {\n\t\tconst kind = kindOf(element);\n\t\tif (kind !== undefined && 'value' in element) {\n\t\t\tconst name = element.value;\n\t\t\tif (!found.some((seen) => seen.name === name && seen.kind === kind)) {\n\t\t\t\tfound.push({ name, kind });\n\t\t\t}\n\t\t}\n\t\tif (element.type === TYPE.select || element.type === TYPE.plural) {\n\t\t\tfor (const option of Object.values(element.options)) {\n\t\t\t\tcollect(option.value, found);\n\t\t\t}\n\t\t} else if (element.type === TYPE.tag) {\n\t\t\tcollect(element.children, found);\n\t\t}\n\t}\n}\n\n/**\n * Parses an ICU message the way `translate` formats it, and answers the\n * arguments it uses, each `{ name, kind }` pair once, in the order they first\n * appear — inside plural and select branches and tags too. A name used two\n * ways appears twice, which is how a check finds it. Throws a\n * `MessageSyntaxError` for a message that does not parse.\n *\n * For a catalogue loaded from a database: check every message at load time\n * or in a spec, keep to the ICU subset the app allows, and compare the kinds\n * of one key across languages.\n */\nexport function parseMessage(message: string): MessageArgument[] {\n\tlet elements: MessageFormatElement[];\n\ttry {\n\t\telements = parse(message);\n\t} catch (error) {\n\t\t// A syntax error carries its location; a refused skeleton is a plain\n\t\t// RangeError with a sentence for a message and no location.\n\t\tconst { location } = error as { location?: { start: Position } };\n\t\tthrow location\n\t\t\t? new MessageSyntaxError(\n\t\t\t\t\t(error as Error).message,\n\t\t\t\t\tmessage,\n\t\t\t\t\tlocation.start,\n\t\t\t\t\terror,\n\t\t\t\t)\n\t\t\t: new MessageSyntaxError('INVALID_SKELETON', message, undefined, error);\n\t}\n\tconst found: MessageArgument[] = [];\n\tcollect(elements, found);\n\treturn found;\n}\n"
|
|
13
14
|
],
|
|
14
|
-
"mappings": "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
|
|
15
|
-
"debugId": "
|
|
15
|
+
"mappings": "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",
|
|
16
|
+
"debugId": "08677851F59036F664756E2164756E21",
|
|
16
17
|
"names": []
|
|
17
18
|
}
|
package/dist/index.browser.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
|
package/dist/index.browser.js
CHANGED
|
@@ -12,16 +12,20 @@ import {
|
|
|
12
12
|
languageFromSources2,
|
|
13
13
|
getLanguage2,
|
|
14
14
|
createTranslator2,
|
|
15
|
-
translate2
|
|
16
|
-
|
|
15
|
+
translate2,
|
|
16
|
+
MessageSyntaxError2,
|
|
17
|
+
parseMessage2
|
|
18
|
+
} from "./chunks/index-g7dn8z2a.js";
|
|
17
19
|
export {
|
|
18
20
|
LANGUAGE_KEY2 as LANGUAGE_KEY,
|
|
21
|
+
MessageSyntaxError2 as MessageSyntaxError,
|
|
19
22
|
SUPPORTED_LANGUAGES2 as SUPPORTED_LANGUAGES,
|
|
20
23
|
createTranslator2 as createTranslator,
|
|
21
24
|
getFallbackLanguage2 as getFallbackLanguage,
|
|
22
25
|
getLanguage2 as getLanguage,
|
|
23
26
|
languageFromSources2 as languageFromSources,
|
|
24
27
|
mergeCatalogues2 as mergeCatalogues,
|
|
28
|
+
parseMessage2 as parseMessage,
|
|
25
29
|
registerCatalogue2 as registerCatalogue,
|
|
26
30
|
registerLanguageSource2 as registerLanguageSource,
|
|
27
31
|
registeredCatalogues2 as registeredCatalogues,
|
|
@@ -31,5 +35,5 @@ export {
|
|
|
31
35
|
translate2 as translate
|
|
32
36
|
};
|
|
33
37
|
|
|
34
|
-
//# debugId=
|
|
38
|
+
//# debugId=640BCA462E74B52664756E2164756E21
|
|
35
39
|
//# sourceMappingURL=index.browser.js.map
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -12,16 +12,20 @@ import {
|
|
|
12
12
|
languageFromSources2,
|
|
13
13
|
getLanguage2,
|
|
14
14
|
createTranslator2,
|
|
15
|
-
translate2
|
|
16
|
-
|
|
15
|
+
translate2,
|
|
16
|
+
MessageSyntaxError2,
|
|
17
|
+
parseMessage2
|
|
18
|
+
} from "./chunks/index-g7dn8z2a.js";
|
|
17
19
|
export {
|
|
18
20
|
LANGUAGE_KEY2 as LANGUAGE_KEY,
|
|
21
|
+
MessageSyntaxError2 as MessageSyntaxError,
|
|
19
22
|
SUPPORTED_LANGUAGES2 as SUPPORTED_LANGUAGES,
|
|
20
23
|
createTranslator2 as createTranslator,
|
|
21
24
|
getFallbackLanguage2 as getFallbackLanguage,
|
|
22
25
|
getLanguage2 as getLanguage,
|
|
23
26
|
languageFromSources2 as languageFromSources,
|
|
24
27
|
mergeCatalogues2 as mergeCatalogues,
|
|
28
|
+
parseMessage2 as parseMessage,
|
|
25
29
|
registerCatalogue2 as registerCatalogue,
|
|
26
30
|
registerLanguageSource2 as registerLanguageSource,
|
|
27
31
|
registeredCatalogues2 as registeredCatalogues,
|
|
@@ -31,5 +35,5 @@ export {
|
|
|
31
35
|
translate2 as translate
|
|
32
36
|
};
|
|
33
37
|
|
|
34
|
-
//# debugId=
|
|
38
|
+
//# debugId=F6F4B5663EA2D86364756E2164756E21
|
|
35
39
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
package/dist/parse.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a message uses an argument, as the ICU syntax names it: `{name}` is an
|
|
3
|
+
* `argument`, `{n, number}` a `number`, `{n, plural, …}` a `plural`,
|
|
4
|
+
* `{n, selectordinal, …}` a `selectordinal`, `<b>…</b>` a `tag` (formatted
|
|
5
|
+
* by a function the caller passes under that name).
|
|
6
|
+
*/
|
|
7
|
+
export type ArgumentKind = 'argument' | 'number' | 'date' | 'time' | 'select' | 'plural' | 'selectordinal' | 'tag';
|
|
8
|
+
/** One argument a message uses, and how. */
|
|
9
|
+
export type MessageArgument = {
|
|
10
|
+
name: string;
|
|
11
|
+
kind: ArgumentKind;
|
|
12
|
+
};
|
|
13
|
+
type Position = {
|
|
14
|
+
offset: number;
|
|
15
|
+
line: number;
|
|
16
|
+
column: number;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* A message that is not valid ICU. `code` is the parser's
|
|
20
|
+
* (`EXPECT_ARGUMENT_CLOSING_BRACE`, …), and `offset`, `line` and `column`
|
|
21
|
+
* point at where it went wrong in `source`. A skeleton the parser locates
|
|
22
|
+
* keeps its own code (`INVALID_NUMBER_SKELETON`, `EXPECT_DATE_TIME_SKELETON`);
|
|
23
|
+
* one it refuses without saying where (`{d, date, ::YYYY}`) has the code
|
|
24
|
+
* `INVALID_SKELETON` and no position. `cause` is the parser's own error.
|
|
25
|
+
*/
|
|
26
|
+
export declare class MessageSyntaxError extends SyntaxError {
|
|
27
|
+
readonly code: string;
|
|
28
|
+
readonly source: string;
|
|
29
|
+
readonly name = "MessageSyntaxError";
|
|
30
|
+
readonly offset: number | undefined;
|
|
31
|
+
readonly line: number | undefined;
|
|
32
|
+
readonly column: number | undefined;
|
|
33
|
+
constructor(code: string, source: string, position: Position | undefined, cause: unknown);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Parses an ICU message the way `translate` formats it, and answers the
|
|
37
|
+
* arguments it uses, each `{ name, kind }` pair once, in the order they first
|
|
38
|
+
* appear — inside plural and select branches and tags too. A name used two
|
|
39
|
+
* ways appears twice, which is how a check finds it. Throws a
|
|
40
|
+
* `MessageSyntaxError` for a message that does not parse.
|
|
41
|
+
*
|
|
42
|
+
* For a catalogue loaded from a database: check every message at load time
|
|
43
|
+
* or in a spec, keep to the ICU subset the app allows, and compare the kinds
|
|
44
|
+
* of one key across languages.
|
|
45
|
+
*/
|
|
46
|
+
export declare function parseMessage(message: string): MessageArgument[];
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAMA;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GACrB,UAAU,GACV,QAAQ,GACR,MAAM,GACN,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,eAAe,GACf,KAAK,CAAC;AAET,4CAA4C;AAC5C,MAAM,MAAM,eAAe,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,CAAC;AAEnE,KAAK,QAAQ,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjE;;;;;;;GAOG;AACH,qBAAa,kBAAmB,SAAQ,WAAW;IAOjD,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;IAPxB,SAAkB,IAAI,wBAAwB;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;gBAG1B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACvB,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAC9B,KAAK,EAAE,OAAO;CAUf;AA6CD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,EAAE,CAoB/D"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxgt/i18n",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
]
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
+
"@formatjs/icu-messageformat-parser": "^3.5.20",
|
|
44
45
|
"intl-messageformat": "^12.1.2",
|
|
45
46
|
"lodash": "^4.18.1"
|
|
46
47
|
},
|