@vielzeug/lingua 2.4.1 → 26.10.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 +9 -28
- package/dist/_bounded-cache.cjs +1 -1
- package/dist/_bounded-cache.cjs.map +1 -1
- package/dist/_bounded-cache.js +1 -9
- package/dist/_bounded-cache.js.map +1 -1
- package/dist/_catalog.cjs +1 -1
- package/dist/_catalog.cjs.map +1 -1
- package/dist/_catalog.js +1 -49
- package/dist/_catalog.js.map +1 -1
- package/dist/_dev.cjs +1 -1
- package/dist/_dev.cjs.map +1 -1
- package/dist/_dev.d.ts +1 -1
- package/dist/_dev.d.ts.map +1 -1
- package/dist/_dev.js +1 -6
- package/dist/_dev.js.map +1 -1
- package/dist/_locale.cjs +1 -1
- package/dist/_locale.cjs.map +1 -1
- package/dist/_locale.js +1 -25
- package/dist/_locale.js.map +1 -1
- package/dist/_resources.cjs +1 -1
- package/dist/_resources.cjs.map +1 -1
- package/dist/_resources.d.ts +9 -3
- package/dist/_resources.d.ts.map +1 -1
- package/dist/_resources.js +1 -50
- package/dist/_resources.js.map +1 -1
- package/dist/_template.cjs +1 -1
- package/dist/_template.cjs.map +1 -1
- package/dist/_template.d.ts +2 -1
- package/dist/_template.d.ts.map +1 -1
- package/dist/_template.js +1 -31
- package/dist/_template.js.map +1 -1
- package/dist/catalog.cjs +1 -1
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.ts +10 -10
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +1 -9
- package/dist/catalog.js.map +1 -1
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +4 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +1 -13
- package/dist/errors.js.map +1 -1
- package/dist/format.cjs +1 -1
- package/dist/format.cjs.map +1 -1
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +1 -84
- package/dist/format.js.map +1 -1
- package/dist/i18n.cjs +1 -1
- package/dist/i18n.cjs.map +1 -1
- package/dist/i18n.d.ts +11 -7
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +1 -90
- package/dist/i18n.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -5
- package/dist/lingua.cjs +1 -1
- package/dist/lingua.cjs.map +1 -1
- package/dist/lingua.iife.js +1 -1
- package/dist/lingua.iife.js.map +1 -1
- package/dist/lingua.js +1 -1
- package/dist/lingua.js.map +1 -1
- package/dist/ripple.cjs +2 -0
- package/dist/ripple.cjs.map +1 -0
- package/dist/ripple.d.ts +24 -0
- package/dist/ripple.d.ts.map +1 -0
- package/dist/ripple.js +2 -0
- package/dist/ripple.js.map +1 -0
- package/dist/translator.cjs +1 -1
- package/dist/translator.cjs.map +1 -1
- package/dist/translator.d.ts +15 -10
- package/dist/translator.d.ts.map +1 -1
- package/dist/translator.js +1 -67
- package/dist/translator.js.map +1 -1
- package/dist/types.d.ts +38 -14
- package/dist/types.d.ts.map +1 -1
- package/dist/validate.cjs +1 -1
- package/dist/validate.cjs.map +1 -1
- package/dist/validate.js +1 -45
- package/dist/validate.js.map +1 -1
- package/package.json +25 -8
package/README.md
CHANGED
|
@@ -1,56 +1,37 @@
|
|
|
1
1
|
# @vielzeug/lingua
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
|
|
5
|
-
`@vielzeug/lingua` provides immutable translators for fixed locales and a stateful i18n store for locale changes and optional lazy catalogs.
|
|
3
|
+
> Typed i18n with pluralization and lazy locale loading
|
|
6
4
|
|
|
7
5
|
## Installation
|
|
8
6
|
|
|
9
7
|
```sh
|
|
10
8
|
pnpm add @vielzeug/lingua
|
|
9
|
+
npm install @vielzeug/lingua
|
|
10
|
+
yarn add @vielzeug/lingua
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
## Quick Start
|
|
14
14
|
|
|
15
15
|
```ts
|
|
16
|
-
import {
|
|
16
|
+
import { createTranslator } from '@vielzeug/lingua';
|
|
17
17
|
|
|
18
|
-
const translator =
|
|
18
|
+
const translator = createTranslator({
|
|
19
19
|
greeting: 'Hello, {name}!',
|
|
20
20
|
inbox: { plural: { one: 'One message', other: '{count} messages' } },
|
|
21
|
-
});
|
|
21
|
+
}, { locale: 'en' });
|
|
22
22
|
|
|
23
23
|
translator.translate('greeting', { values: { name: 'Ada' } });
|
|
24
24
|
translator.translate('inbox', { count: 3 });
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
## Integration Patterns
|
|
28
|
-
|
|
29
|
-
Use `translate()` for string interpolation and `segments()` for UI values. Give UI values consumer-owned keys before passing them; Lingua returns same values without cloning or mutation.
|
|
30
|
-
|
|
31
|
-
```ts
|
|
32
|
-
const retry = { key: 'retry', href: '/retry' };
|
|
33
|
-
translator.segments('greeting', { values: { name: retry } });
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Use `createTranslationStore()` only when locale changes at runtime. Its stable `subscribe` and `getSnapshot` methods work directly with platform subscription APIs such as React `useSyncExternalStore`; hydrate client store from server `serialize()` state before first render. Missing keys return key, and absent interpolation values return `{name}` by default.
|
|
37
|
-
|
|
38
|
-
Keep arrays and application metadata outside catalogs. Store message keys with application definitions, then translate labels while building UI options.
|
|
39
|
-
|
|
40
|
-
## Exports
|
|
41
|
-
|
|
42
|
-
- `createCatalogTranslator` — immutable translator for one fixed-locale catalog.
|
|
43
|
-
- `createTranslator` — immutable translator for fixed locale-keyed catalogs.
|
|
44
|
-
- `createTranslationStore` / `hydrateTranslationStore` — mutable locale state, lazy catalog loading, and SSR state.
|
|
45
|
-
- `createFormatter` from `@vielzeug/lingua/format`.
|
|
46
|
-
- `validateCatalog` from `@vielzeug/lingua/validate`.
|
|
47
|
-
|
|
48
27
|
## Documentation
|
|
49
28
|
|
|
50
29
|
- [Overview](https://vielzeug.dev/lingua/)
|
|
51
30
|
- [Usage Guide](https://vielzeug.dev/lingua/usage)
|
|
52
31
|
- [API Reference](https://vielzeug.dev/lingua/api)
|
|
32
|
+
- [Examples](https://vielzeug.dev/lingua/examples)
|
|
33
|
+
- [Migration Guide](https://vielzeug.dev/lingua/migration)
|
|
53
34
|
|
|
54
35
|
## License
|
|
55
36
|
|
|
56
|
-
MIT © Helmuth Saatkamp
|
|
37
|
+
MIT © [Helmuth Saatkamp](https://github.com/helmuthdu) — part of the [Vielzeug](https://github.com/helmuthdu/vielzeug) monorepo.
|
package/dist/_bounded-cache.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function
|
|
1
|
+
function getOrCreate(e,t,n,r){if(e.has(t))return e.get(t);let i=r();return e.size>=n&&e.delete(e.keys().next().value),e.set(t,i),i}exports.getOrCreate=getOrCreate;
|
|
2
2
|
//# sourceMappingURL=_bounded-cache.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_bounded-cache.cjs","names":[],"sources":["../src/_bounded-cache.ts"],"sourcesContent":["// Internal — not part of the public API.\n// Minimal bounded cache: evicts the oldest entry (insertion order) once `maxSize` is exceeded.\n// Not LRU — no access-time reordering, only insertion order matters. These caches exist purely\n// to avoid rebuilding cheap-but-not-free values (compiled `Intl` formatters, scoped translator\n// objects) for a bounded number of frequently-reused keys, not to model real recency.\n\nexport function getOrCreate<K, V>(cache: Map<K, V>, key: K, maxSize: number, build: () => V): V {\n if (cache.has(key)) return cache.get(key)!;\n\n const value = build();\n\n if (cache.size >= maxSize) cache.delete(cache.keys().next().value as K);\n\n cache.set(key, value);\n\n return value;\n}\n"],"mappings":"AAMA,SAAgB,
|
|
1
|
+
{"version":3,"file":"_bounded-cache.cjs","names":[],"sources":["../src/_bounded-cache.ts"],"sourcesContent":["// Internal — not part of the public API.\n// Minimal bounded cache: evicts the oldest entry (insertion order) once `maxSize` is exceeded.\n// Not LRU — no access-time reordering, only insertion order matters. These caches exist purely\n// to avoid rebuilding cheap-but-not-free values (compiled `Intl` formatters, scoped translator\n// objects) for a bounded number of frequently-reused keys, not to model real recency.\n\nexport function getOrCreate<K, V>(cache: Map<K, V>, key: K, maxSize: number, build: () => V): V {\n if (cache.has(key)) return cache.get(key)!;\n\n const value = build();\n\n if (cache.size >= maxSize) cache.delete(cache.keys().next().value as K);\n\n cache.set(key, value);\n\n return value;\n}\n"],"mappings":"AAMA,SAAgB,YAAkB,EAAkB,EAAQ,EAAiB,EAAmB,CAC9F,GAAI,EAAM,IAAI,CAAG,EAAG,OAAO,EAAM,IAAI,CAAG,EAExC,IAAM,EAAQ,EAAM,EAMpB,OAJI,EAAM,MAAQ,GAAS,EAAM,OAAO,EAAM,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAU,EAEtE,EAAM,IAAI,EAAK,CAAK,EAEb,CACT"}
|
package/dist/_bounded-cache.js
CHANGED
|
@@ -1,10 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
function e(e, t, n, r) {
|
|
3
|
-
if (e.has(t)) return e.get(t);
|
|
4
|
-
let i = r();
|
|
5
|
-
return e.size >= n && e.delete(e.keys().next().value), e.set(t, i), i;
|
|
6
|
-
}
|
|
7
|
-
//#endregion
|
|
8
|
-
export { e as getOrCreate };
|
|
9
|
-
|
|
1
|
+
function getOrCreate(e,t,n,r){if(e.has(t))return e.get(t);let i=r();return e.size>=n&&e.delete(e.keys().next().value),e.set(t,i),i}export{getOrCreate};
|
|
10
2
|
//# sourceMappingURL=_bounded-cache.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_bounded-cache.js","names":[],"sources":["../src/_bounded-cache.ts"],"sourcesContent":["// Internal — not part of the public API.\n// Minimal bounded cache: evicts the oldest entry (insertion order) once `maxSize` is exceeded.\n// Not LRU — no access-time reordering, only insertion order matters. These caches exist purely\n// to avoid rebuilding cheap-but-not-free values (compiled `Intl` formatters, scoped translator\n// objects) for a bounded number of frequently-reused keys, not to model real recency.\n\nexport function getOrCreate<K, V>(cache: Map<K, V>, key: K, maxSize: number, build: () => V): V {\n if (cache.has(key)) return cache.get(key)!;\n\n const value = build();\n\n if (cache.size >= maxSize) cache.delete(cache.keys().next().value as K);\n\n cache.set(key, value);\n\n return value;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"_bounded-cache.js","names":[],"sources":["../src/_bounded-cache.ts"],"sourcesContent":["// Internal — not part of the public API.\n// Minimal bounded cache: evicts the oldest entry (insertion order) once `maxSize` is exceeded.\n// Not LRU — no access-time reordering, only insertion order matters. These caches exist purely\n// to avoid rebuilding cheap-but-not-free values (compiled `Intl` formatters, scoped translator\n// objects) for a bounded number of frequently-reused keys, not to model real recency.\n\nexport function getOrCreate<K, V>(cache: Map<K, V>, key: K, maxSize: number, build: () => V): V {\n if (cache.has(key)) return cache.get(key)!;\n\n const value = build();\n\n if (cache.size >= maxSize) cache.delete(cache.keys().next().value as K);\n\n cache.set(key, value);\n\n return value;\n}\n"],"mappings":"AAMA,SAAgB,YAAkB,EAAkB,EAAQ,EAAiB,EAAmB,CAC9F,GAAI,EAAM,IAAI,CAAG,EAAG,OAAO,EAAM,IAAI,CAAG,EAExC,IAAM,EAAQ,EAAM,EAMpB,OAJI,EAAM,MAAQ,GAAS,EAAM,OAAO,EAAM,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAU,EAEtE,EAAM,IAAI,EAAK,CAAK,EAEb,CACT"}
|
package/dist/_catalog.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("./_template.cjs"),t=require("./errors.cjs");var n=new Set([`__proto__`,`constructor`,`prototype`]);function
|
|
1
|
+
const e=require("./_template.cjs"),t=require("./errors.cjs");var n=new Set([`__proto__`,`constructor`,`prototype`]);function isPluralMessage(e){return typeof e==`object`&&!!e&&Object.hasOwn(e,`plural`)}function compileCatalog(r){let i=new Map,visit=(r,a)=>{if(typeof r==`string`){i.set(a,{kind:`text`,template:e.compileTemplate(r)});return}if(typeof r!=`object`||!r||Array.isArray(r))throw new t.LinguaInvalidCatalogError(`Catalog node "${a}" must be a string, plural message, or object.`);if(isPluralMessage(r)){if(Reflect.ownKeys(r).some(e=>e!==`plural`))throw new t.LinguaInvalidCatalogError(`Plural message "${a}" must contain only a "plural" property.`);if(typeof r.plural!=`object`||r.plural===null||Array.isArray(r.plural))throw new t.LinguaInvalidCatalogError(`Plural message "${a}" must provide an object of string forms.`);let n=new Map;for(let[i,o]of Object.entries(r.plural)){if(typeof o!=`string`)throw new t.LinguaInvalidCatalogError(`Plural form "${a}.${i}" must be a string.`);n.set(i,e.compileTemplate(o))}i.set(a,{forms:n,kind:`plural`});return}for(let[e,i]of Object.entries(r)){if(n.has(e))throw new t.LinguaInvalidCatalogError(`Catalog key "${e}" is reserved.`);visit(i,a?`${a}.${e}`:e)}};for(let[e,i]of Object.entries(r)){if(n.has(e))throw new t.LinguaInvalidCatalogError(`Catalog key "${e}" is reserved.`);visit(i,e)}return i}exports.compileCatalog=compileCatalog,exports.isPluralMessage=isPluralMessage;
|
|
2
2
|
//# sourceMappingURL=_catalog.cjs.map
|
package/dist/_catalog.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_catalog.cjs","names":[],"sources":["../src/_catalog.ts"],"sourcesContent":["import { compileTemplate, type Template } from './_template';\nimport { LinguaInvalidCatalogError } from './errors';\nimport type { Catalog, CatalogNode, PluralMessage } from './types';\n\nconst unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);\n\nexport type CompiledText = { readonly kind: 'text'; readonly template: Template };\nexport type CompiledPlural = { readonly forms: ReadonlyMap<string, Template>; readonly kind: 'plural' };\nexport type CompiledMessage = CompiledPlural | CompiledText;\nexport type CompiledCatalog = ReadonlyMap<string, CompiledMessage>;\n\nexport function isPluralMessage(node: CatalogNode): node is PluralMessage {\n return typeof node === 'object' && node !== null && Object.hasOwn(node, 'plural');\n}\n\n/** Compile explicit catalog nodes once. Nested objects only group keys; plural intent is never inferred. */\nexport function compileCatalog(catalog: Catalog): CompiledCatalog {\n const messages = new Map<string, CompiledMessage>();\n\n const visit = (node: CatalogNode, prefix: string): void => {\n if (typeof node === 'string') {\n messages.set(prefix, { kind: 'text', template: compileTemplate(node) });\n\n return;\n }\n\n if (typeof node !== 'object' || node === null || Array.isArray(node)) {\n throw new LinguaInvalidCatalogError(`Catalog node \"${prefix}\" must be a string, plural message, or object.`);\n }\n\n if (isPluralMessage(node)) {\n if (Reflect.ownKeys(node).some((key) => key !== 'plural')) {\n throw new LinguaInvalidCatalogError(`Plural message \"${prefix}\" must contain only a \"plural\" property.`);\n }\n\n if (typeof node.plural !== 'object' || node.plural === null || Array.isArray(node.plural)) {\n throw new LinguaInvalidCatalogError(`Plural message \"${prefix}\" must provide an object of string forms.`);\n }\n\n const forms = new Map<string, Template>();\n\n for (const [form, template] of Object.entries(node.plural)) {\n if (typeof template !== 'string') {\n throw new LinguaInvalidCatalogError(`Plural form \"${prefix}.${form}\" must be a string.`);\n }\n\n forms.set(form, compileTemplate(template));\n }\n\n messages.set(prefix, { forms, kind: 'plural' });\n\n return;\n }\n\n for (const [key, value] of Object.entries(node)) {\n if (unsafeKeys.has(key)) {\n throw new LinguaInvalidCatalogError(`Catalog key \"${key}\" is reserved.`);\n }\n\n visit(value, prefix ? `${prefix}.${key}` : key);\n }\n };\n\n for (const [key, value] of Object.entries(catalog)) {\n if (unsafeKeys.has(key)) throw new LinguaInvalidCatalogError(`Catalog key \"${key}\" is reserved.`);\n\n visit(value, key);\n }\n\n return messages;\n}\n"],"mappings":"6DAIA,IAAM,EAAa,IAAI,IAAI,CAAC,YAAa,cAAe,WAAW,CAAC,EAOpE,SAAgB,
|
|
1
|
+
{"version":3,"file":"_catalog.cjs","names":[],"sources":["../src/_catalog.ts"],"sourcesContent":["import { compileTemplate, type Template } from './_template';\nimport { LinguaInvalidCatalogError } from './errors';\nimport type { Catalog, CatalogNode, PluralMessage } from './types';\n\nconst unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);\n\nexport type CompiledText = { readonly kind: 'text'; readonly template: Template };\nexport type CompiledPlural = { readonly forms: ReadonlyMap<string, Template>; readonly kind: 'plural' };\nexport type CompiledMessage = CompiledPlural | CompiledText;\nexport type CompiledCatalog = ReadonlyMap<string, CompiledMessage>;\n\nexport function isPluralMessage(node: CatalogNode): node is PluralMessage {\n return typeof node === 'object' && node !== null && Object.hasOwn(node, 'plural');\n}\n\n/** Compile explicit catalog nodes once. Nested objects only group keys; plural intent is never inferred. */\nexport function compileCatalog(catalog: Catalog): CompiledCatalog {\n const messages = new Map<string, CompiledMessage>();\n\n const visit = (node: CatalogNode, prefix: string): void => {\n if (typeof node === 'string') {\n messages.set(prefix, { kind: 'text', template: compileTemplate(node) });\n\n return;\n }\n\n if (typeof node !== 'object' || node === null || Array.isArray(node)) {\n throw new LinguaInvalidCatalogError(`Catalog node \"${prefix}\" must be a string, plural message, or object.`);\n }\n\n if (isPluralMessage(node)) {\n if (Reflect.ownKeys(node).some((key) => key !== 'plural')) {\n throw new LinguaInvalidCatalogError(`Plural message \"${prefix}\" must contain only a \"plural\" property.`);\n }\n\n if (typeof node.plural !== 'object' || node.plural === null || Array.isArray(node.plural)) {\n throw new LinguaInvalidCatalogError(`Plural message \"${prefix}\" must provide an object of string forms.`);\n }\n\n const forms = new Map<string, Template>();\n\n for (const [form, template] of Object.entries(node.plural)) {\n if (typeof template !== 'string') {\n throw new LinguaInvalidCatalogError(`Plural form \"${prefix}.${form}\" must be a string.`);\n }\n\n forms.set(form, compileTemplate(template));\n }\n\n messages.set(prefix, { forms, kind: 'plural' });\n\n return;\n }\n\n for (const [key, value] of Object.entries(node)) {\n if (unsafeKeys.has(key)) {\n throw new LinguaInvalidCatalogError(`Catalog key \"${key}\" is reserved.`);\n }\n\n visit(value, prefix ? `${prefix}.${key}` : key);\n }\n };\n\n for (const [key, value] of Object.entries(catalog)) {\n if (unsafeKeys.has(key)) throw new LinguaInvalidCatalogError(`Catalog key \"${key}\" is reserved.`);\n\n visit(value, key);\n }\n\n return messages;\n}\n"],"mappings":"6DAIA,IAAM,EAAa,IAAI,IAAI,CAAC,YAAa,cAAe,WAAW,CAAC,EAOpE,SAAgB,gBAAgB,EAA0C,CACxE,OAAO,OAAO,GAAS,YAAY,GAAiB,OAAO,OAAO,EAAM,QAAQ,CAClF,CAGA,SAAgB,eAAe,EAAmC,CAChE,IAAM,EAAW,IAAI,IAEf,OAAS,EAAmB,IAAyB,CACzD,GAAI,OAAO,GAAS,SAAU,CAC5B,EAAS,IAAI,EAAQ,CAAE,KAAM,OAAQ,SAAU,EAAA,gBAAgB,CAAI,CAAE,CAAC,EAEtE,MACF,CAEA,GAAI,OAAO,GAAS,WAAY,GAAiB,MAAM,QAAQ,CAAI,EACjE,MAAM,IAAI,EAAA,0BAA0B,iBAAiB,EAAO,+CAA+C,EAG7G,GAAI,gBAAgB,CAAI,EAAG,CACzB,GAAI,QAAQ,QAAQ,CAAI,CAAC,CAAC,KAAM,GAAQ,IAAQ,QAAQ,EACtD,MAAM,IAAI,EAAA,0BAA0B,mBAAmB,EAAO,yCAAyC,EAGzG,GAAI,OAAO,EAAK,QAAW,UAAY,EAAK,SAAW,MAAQ,MAAM,QAAQ,EAAK,MAAM,EACtF,MAAM,IAAI,EAAA,0BAA0B,mBAAmB,EAAO,0CAA0C,EAG1G,IAAM,EAAQ,IAAI,IAElB,IAAK,GAAM,CAAC,EAAM,KAAa,OAAO,QAAQ,EAAK,MAAM,EAAG,CAC1D,GAAI,OAAO,GAAa,SACtB,MAAM,IAAI,EAAA,0BAA0B,gBAAgB,EAAO,GAAG,EAAK,oBAAoB,EAGzF,EAAM,IAAI,EAAM,EAAA,gBAAgB,CAAQ,CAAC,CAC3C,CAEA,EAAS,IAAI,EAAQ,CAAE,QAAO,KAAM,QAAS,CAAC,EAE9C,MACF,CAEA,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,CAAI,EAAG,CAC/C,GAAI,EAAW,IAAI,CAAG,EACpB,MAAM,IAAI,EAAA,0BAA0B,gBAAgB,EAAI,eAAe,EAGzE,MAAM,EAAO,EAAS,GAAG,EAAO,GAAG,IAAQ,CAAG,CAChD,CACF,EAEA,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,CAAO,EAAG,CAClD,GAAI,EAAW,IAAI,CAAG,EAAG,MAAM,IAAI,EAAA,0BAA0B,gBAAgB,EAAI,eAAe,EAEhG,MAAM,EAAO,CAAG,CAClB,CAEA,OAAO,CACT"}
|
package/dist/_catalog.js
CHANGED
|
@@ -1,50 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { LinguaInvalidCatalogError as t } from "./errors.js";
|
|
3
|
-
//#region src/_catalog.ts
|
|
4
|
-
var n = /* @__PURE__ */ new Set([
|
|
5
|
-
"__proto__",
|
|
6
|
-
"constructor",
|
|
7
|
-
"prototype"
|
|
8
|
-
]);
|
|
9
|
-
function r(e) {
|
|
10
|
-
return typeof e == "object" && !!e && Object.hasOwn(e, "plural");
|
|
11
|
-
}
|
|
12
|
-
function i(i) {
|
|
13
|
-
let a = /* @__PURE__ */ new Map(), o = (i, s) => {
|
|
14
|
-
if (typeof i == "string") {
|
|
15
|
-
a.set(s, {
|
|
16
|
-
kind: "text",
|
|
17
|
-
template: e(i)
|
|
18
|
-
});
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
if (typeof i != "object" || !i || Array.isArray(i)) throw new t(`Catalog node "${s}" must be a string, plural message, or object.`);
|
|
22
|
-
if (r(i)) {
|
|
23
|
-
if (Reflect.ownKeys(i).some((e) => e !== "plural")) throw new t(`Plural message "${s}" must contain only a "plural" property.`);
|
|
24
|
-
if (typeof i.plural != "object" || i.plural === null || Array.isArray(i.plural)) throw new t(`Plural message "${s}" must provide an object of string forms.`);
|
|
25
|
-
let n = /* @__PURE__ */ new Map();
|
|
26
|
-
for (let [r, a] of Object.entries(i.plural)) {
|
|
27
|
-
if (typeof a != "string") throw new t(`Plural form "${s}.${r}" must be a string.`);
|
|
28
|
-
n.set(r, e(a));
|
|
29
|
-
}
|
|
30
|
-
a.set(s, {
|
|
31
|
-
forms: n,
|
|
32
|
-
kind: "plural"
|
|
33
|
-
});
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
for (let [e, r] of Object.entries(i)) {
|
|
37
|
-
if (n.has(e)) throw new t(`Catalog key "${e}" is reserved.`);
|
|
38
|
-
o(r, s ? `${s}.${e}` : e);
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
for (let [e, r] of Object.entries(i)) {
|
|
42
|
-
if (n.has(e)) throw new t(`Catalog key "${e}" is reserved.`);
|
|
43
|
-
o(r, e);
|
|
44
|
-
}
|
|
45
|
-
return a;
|
|
46
|
-
}
|
|
47
|
-
//#endregion
|
|
48
|
-
export { i as compileCatalog, r as isPluralMessage };
|
|
49
|
-
|
|
1
|
+
import{compileTemplate as e}from"./_template.js";import{LinguaInvalidCatalogError as t}from"./errors.js";var n=new Set([`__proto__`,`constructor`,`prototype`]);function isPluralMessage(e){return typeof e==`object`&&!!e&&Object.hasOwn(e,`plural`)}function compileCatalog(r){let i=new Map,visit=(r,a)=>{if(typeof r==`string`){i.set(a,{kind:`text`,template:e(r)});return}if(typeof r!=`object`||!r||Array.isArray(r))throw new t(`Catalog node "${a}" must be a string, plural message, or object.`);if(isPluralMessage(r)){if(Reflect.ownKeys(r).some(e=>e!==`plural`))throw new t(`Plural message "${a}" must contain only a "plural" property.`);if(typeof r.plural!=`object`||r.plural===null||Array.isArray(r.plural))throw new t(`Plural message "${a}" must provide an object of string forms.`);let n=new Map;for(let[i,o]of Object.entries(r.plural)){if(typeof o!=`string`)throw new t(`Plural form "${a}.${i}" must be a string.`);n.set(i,e(o))}i.set(a,{forms:n,kind:`plural`});return}for(let[e,i]of Object.entries(r)){if(n.has(e))throw new t(`Catalog key "${e}" is reserved.`);visit(i,a?`${a}.${e}`:e)}};for(let[e,i]of Object.entries(r)){if(n.has(e))throw new t(`Catalog key "${e}" is reserved.`);visit(i,e)}return i}export{compileCatalog,isPluralMessage};
|
|
50
2
|
//# sourceMappingURL=_catalog.js.map
|
package/dist/_catalog.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_catalog.js","names":[],"sources":["../src/_catalog.ts"],"sourcesContent":["import { compileTemplate, type Template } from './_template';\nimport { LinguaInvalidCatalogError } from './errors';\nimport type { Catalog, CatalogNode, PluralMessage } from './types';\n\nconst unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);\n\nexport type CompiledText = { readonly kind: 'text'; readonly template: Template };\nexport type CompiledPlural = { readonly forms: ReadonlyMap<string, Template>; readonly kind: 'plural' };\nexport type CompiledMessage = CompiledPlural | CompiledText;\nexport type CompiledCatalog = ReadonlyMap<string, CompiledMessage>;\n\nexport function isPluralMessage(node: CatalogNode): node is PluralMessage {\n return typeof node === 'object' && node !== null && Object.hasOwn(node, 'plural');\n}\n\n/** Compile explicit catalog nodes once. Nested objects only group keys; plural intent is never inferred. */\nexport function compileCatalog(catalog: Catalog): CompiledCatalog {\n const messages = new Map<string, CompiledMessage>();\n\n const visit = (node: CatalogNode, prefix: string): void => {\n if (typeof node === 'string') {\n messages.set(prefix, { kind: 'text', template: compileTemplate(node) });\n\n return;\n }\n\n if (typeof node !== 'object' || node === null || Array.isArray(node)) {\n throw new LinguaInvalidCatalogError(`Catalog node \"${prefix}\" must be a string, plural message, or object.`);\n }\n\n if (isPluralMessage(node)) {\n if (Reflect.ownKeys(node).some((key) => key !== 'plural')) {\n throw new LinguaInvalidCatalogError(`Plural message \"${prefix}\" must contain only a \"plural\" property.`);\n }\n\n if (typeof node.plural !== 'object' || node.plural === null || Array.isArray(node.plural)) {\n throw new LinguaInvalidCatalogError(`Plural message \"${prefix}\" must provide an object of string forms.`);\n }\n\n const forms = new Map<string, Template>();\n\n for (const [form, template] of Object.entries(node.plural)) {\n if (typeof template !== 'string') {\n throw new LinguaInvalidCatalogError(`Plural form \"${prefix}.${form}\" must be a string.`);\n }\n\n forms.set(form, compileTemplate(template));\n }\n\n messages.set(prefix, { forms, kind: 'plural' });\n\n return;\n }\n\n for (const [key, value] of Object.entries(node)) {\n if (unsafeKeys.has(key)) {\n throw new LinguaInvalidCatalogError(`Catalog key \"${key}\" is reserved.`);\n }\n\n visit(value, prefix ? `${prefix}.${key}` : key);\n }\n };\n\n for (const [key, value] of Object.entries(catalog)) {\n if (unsafeKeys.has(key)) throw new LinguaInvalidCatalogError(`Catalog key \"${key}\" is reserved.`);\n\n visit(value, key);\n }\n\n return messages;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"_catalog.js","names":[],"sources":["../src/_catalog.ts"],"sourcesContent":["import { compileTemplate, type Template } from './_template';\nimport { LinguaInvalidCatalogError } from './errors';\nimport type { Catalog, CatalogNode, PluralMessage } from './types';\n\nconst unsafeKeys = new Set(['__proto__', 'constructor', 'prototype']);\n\nexport type CompiledText = { readonly kind: 'text'; readonly template: Template };\nexport type CompiledPlural = { readonly forms: ReadonlyMap<string, Template>; readonly kind: 'plural' };\nexport type CompiledMessage = CompiledPlural | CompiledText;\nexport type CompiledCatalog = ReadonlyMap<string, CompiledMessage>;\n\nexport function isPluralMessage(node: CatalogNode): node is PluralMessage {\n return typeof node === 'object' && node !== null && Object.hasOwn(node, 'plural');\n}\n\n/** Compile explicit catalog nodes once. Nested objects only group keys; plural intent is never inferred. */\nexport function compileCatalog(catalog: Catalog): CompiledCatalog {\n const messages = new Map<string, CompiledMessage>();\n\n const visit = (node: CatalogNode, prefix: string): void => {\n if (typeof node === 'string') {\n messages.set(prefix, { kind: 'text', template: compileTemplate(node) });\n\n return;\n }\n\n if (typeof node !== 'object' || node === null || Array.isArray(node)) {\n throw new LinguaInvalidCatalogError(`Catalog node \"${prefix}\" must be a string, plural message, or object.`);\n }\n\n if (isPluralMessage(node)) {\n if (Reflect.ownKeys(node).some((key) => key !== 'plural')) {\n throw new LinguaInvalidCatalogError(`Plural message \"${prefix}\" must contain only a \"plural\" property.`);\n }\n\n if (typeof node.plural !== 'object' || node.plural === null || Array.isArray(node.plural)) {\n throw new LinguaInvalidCatalogError(`Plural message \"${prefix}\" must provide an object of string forms.`);\n }\n\n const forms = new Map<string, Template>();\n\n for (const [form, template] of Object.entries(node.plural)) {\n if (typeof template !== 'string') {\n throw new LinguaInvalidCatalogError(`Plural form \"${prefix}.${form}\" must be a string.`);\n }\n\n forms.set(form, compileTemplate(template));\n }\n\n messages.set(prefix, { forms, kind: 'plural' });\n\n return;\n }\n\n for (const [key, value] of Object.entries(node)) {\n if (unsafeKeys.has(key)) {\n throw new LinguaInvalidCatalogError(`Catalog key \"${key}\" is reserved.`);\n }\n\n visit(value, prefix ? `${prefix}.${key}` : key);\n }\n };\n\n for (const [key, value] of Object.entries(catalog)) {\n if (unsafeKeys.has(key)) throw new LinguaInvalidCatalogError(`Catalog key \"${key}\" is reserved.`);\n\n visit(value, key);\n }\n\n return messages;\n}\n"],"mappings":"yGAIA,IAAM,EAAa,IAAI,IAAI,CAAC,YAAa,cAAe,WAAW,CAAC,EAOpE,SAAgB,gBAAgB,EAA0C,CACxE,OAAO,OAAO,GAAS,YAAY,GAAiB,OAAO,OAAO,EAAM,QAAQ,CAClF,CAGA,SAAgB,eAAe,EAAmC,CAChE,IAAM,EAAW,IAAI,IAEf,OAAS,EAAmB,IAAyB,CACzD,GAAI,OAAO,GAAS,SAAU,CAC5B,EAAS,IAAI,EAAQ,CAAE,KAAM,OAAQ,SAAU,EAAgB,CAAI,CAAE,CAAC,EAEtE,MACF,CAEA,GAAI,OAAO,GAAS,WAAY,GAAiB,MAAM,QAAQ,CAAI,EACjE,MAAM,IAAI,EAA0B,iBAAiB,EAAO,+CAA+C,EAG7G,GAAI,gBAAgB,CAAI,EAAG,CACzB,GAAI,QAAQ,QAAQ,CAAI,CAAC,CAAC,KAAM,GAAQ,IAAQ,QAAQ,EACtD,MAAM,IAAI,EAA0B,mBAAmB,EAAO,yCAAyC,EAGzG,GAAI,OAAO,EAAK,QAAW,UAAY,EAAK,SAAW,MAAQ,MAAM,QAAQ,EAAK,MAAM,EACtF,MAAM,IAAI,EAA0B,mBAAmB,EAAO,0CAA0C,EAG1G,IAAM,EAAQ,IAAI,IAElB,IAAK,GAAM,CAAC,EAAM,KAAa,OAAO,QAAQ,EAAK,MAAM,EAAG,CAC1D,GAAI,OAAO,GAAa,SACtB,MAAM,IAAI,EAA0B,gBAAgB,EAAO,GAAG,EAAK,oBAAoB,EAGzF,EAAM,IAAI,EAAM,EAAgB,CAAQ,CAAC,CAC3C,CAEA,EAAS,IAAI,EAAQ,CAAE,QAAO,KAAM,QAAS,CAAC,EAE9C,MACF,CAEA,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,CAAI,EAAG,CAC/C,GAAI,EAAW,IAAI,CAAG,EACpB,MAAM,IAAI,EAA0B,gBAAgB,EAAI,eAAe,EAGzE,MAAM,EAAO,EAAS,GAAG,EAAO,GAAG,IAAQ,CAAG,CAChD,CACF,EAEA,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,CAAO,EAAG,CAClD,GAAI,EAAW,IAAI,CAAG,EAAG,MAAM,IAAI,EAA0B,gBAAgB,EAAI,eAAe,EAEhG,MAAM,EAAO,CAAG,CAClB,CAEA,OAAO,CACT"}
|
package/dist/_dev.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function
|
|
1
|
+
function warn(e){}function error(e,...t){}exports.error=error,exports.warn=warn;
|
|
2
2
|
//# sourceMappingURL=_dev.cjs.map
|
package/dist/_dev.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_dev.cjs","names":[],"sources":["../src/_dev.ts"],"sourcesContent":["const isDev = !(globalThis as { __LINGUA_PROD__?: boolean }).__LINGUA_PROD__;\n\n/** @internal @security Messages may include user-supplied data. */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/lingua] ${msg}`);\n}\n\n/** @internal */\nexport function error(msg: string, ...args: unknown[]): void {\n if (isDev) console.error(`[@vielzeug/lingua] ${msg}`, ...args);\n}\n"],"mappings":"AAGA,SAAgB,
|
|
1
|
+
{"version":3,"file":"_dev.cjs","names":[],"sources":["../src/_dev.ts"],"sourcesContent":["export const isDev = !(globalThis as { __LINGUA_PROD__?: boolean }).__LINGUA_PROD__;\n\n/** @internal @security Messages may include user-supplied data. */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/lingua] ${msg}`);\n}\n\n/** @internal */\nexport function error(msg: string, ...args: unknown[]): void {\n if (isDev) console.error(`[@vielzeug/lingua] ${msg}`, ...args);\n}\n"],"mappings":"AAGA,SAAgB,KAAK,EAAmB,CAExC,CAGA,SAAgB,MAAM,EAAa,GAAG,EAAuB,CAE7D"}
|
package/dist/_dev.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare const isDev: boolean;
|
|
2
2
|
//# sourceMappingURL=_dev.d.ts.map
|
package/dist/_dev.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_dev.d.ts","sourceRoot":"","sources":["../src/_dev.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"_dev.d.ts","sourceRoot":"","sources":["../src/_dev.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,SAAiE,CAAC"}
|
package/dist/_dev.js
CHANGED
package/dist/_dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_dev.js","names":[],"sources":["../src/_dev.ts"],"sourcesContent":["const isDev = !(globalThis as { __LINGUA_PROD__?: boolean }).__LINGUA_PROD__;\n\n/** @internal @security Messages may include user-supplied data. */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/lingua] ${msg}`);\n}\n\n/** @internal */\nexport function error(msg: string, ...args: unknown[]): void {\n if (isDev) console.error(`[@vielzeug/lingua] ${msg}`, ...args);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"_dev.js","names":[],"sources":["../src/_dev.ts"],"sourcesContent":["export const isDev = !(globalThis as { __LINGUA_PROD__?: boolean }).__LINGUA_PROD__;\n\n/** @internal @security Messages may include user-supplied data. */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/lingua] ${msg}`);\n}\n\n/** @internal */\nexport function error(msg: string, ...args: unknown[]): void {\n if (isDev) console.error(`[@vielzeug/lingua] ${msg}`, ...args);\n}\n"],"mappings":"AAGA,SAAgB,KAAK,EAAmB,CAExC,CAGA,SAAgB,MAAM,EAAa,GAAG,EAAuB,CAE7D"}
|
package/dist/_locale.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("./errors.cjs");var t=new Map;function
|
|
1
|
+
const e=require("./errors.cjs");var t=new Map;function canonicalLocale(t){try{let[e]=Intl.getCanonicalLocales(t);if(e)return e}catch{}throw new e.LinguaInvalidLocaleError(`Invalid BCP 47 locale tag: "${t}".`)}function localeChain(e,t){let n=new Set;for(let r of[e,...t]){let e=r.split(`-`);for(let t=e.length;t>0;t--)n.add(e.slice(0,t).join(`-`))}return[...n]}function pluralCategory(e,n,r){let i=`${e}:${r?`ordinal`:`cardinal`}`,a=t.get(i);return a||(a=new Intl.PluralRules(e,{type:r?`ordinal`:`cardinal`}),t.set(i,a)),a.select(n)}exports.canonicalLocale=canonicalLocale,exports.localeChain=localeChain,exports.pluralCategory=pluralCategory;
|
|
2
2
|
//# sourceMappingURL=_locale.cjs.map
|
package/dist/_locale.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_locale.cjs","names":[],"sources":["../src/_locale.ts"],"sourcesContent":["import { LinguaInvalidLocaleError } from './errors';\nimport type { Locale } from './types';\n\nconst pluralRules = new Map<string, Intl.PluralRules>();\n\nexport function canonicalLocale(locale: string): Locale {\n try {\n const [canonical] = Intl.getCanonicalLocales(locale);\n\n if (canonical) return canonical;\n } catch {\n // Error below names the failed public input.\n }\n\n throw new LinguaInvalidLocaleError(`Invalid BCP 47 locale tag: \"${locale}\".`);\n}\n\nexport function localeChain(locale: Locale, fallback: readonly Locale[]): readonly Locale[] {\n const chain = new Set<Locale>();\n\n for (const candidate of [locale, ...fallback]) {\n const parts = candidate.split('-');\n\n for (let length = parts.length; length > 0; length--) {\n chain.add(parts.slice(0, length).join('-'));\n }\n }\n\n return [...chain];\n}\n\nexport function pluralCategory(locale: Locale, count: number, ordinal: boolean): Intl.LDMLPluralRule {\n const key = `${locale}:${ordinal ? 'ordinal' : 'cardinal'}`;\n let rules = pluralRules.get(key);\n\n if (!rules) {\n rules = new Intl.PluralRules(locale, { type: ordinal ? 'ordinal' : 'cardinal' });\n pluralRules.set(key, rules);\n }\n\n return rules.select(count);\n}\n"],"mappings":"gCAGA,IAAM,EAAc,IAAI,IAExB,SAAgB,
|
|
1
|
+
{"version":3,"file":"_locale.cjs","names":[],"sources":["../src/_locale.ts"],"sourcesContent":["import { LinguaInvalidLocaleError } from './errors';\nimport type { Locale } from './types';\n\nconst pluralRules = new Map<string, Intl.PluralRules>();\n\nexport function canonicalLocale(locale: string): Locale {\n try {\n const [canonical] = Intl.getCanonicalLocales(locale);\n\n if (canonical) return canonical;\n } catch {\n // Error below names the failed public input.\n }\n\n throw new LinguaInvalidLocaleError(`Invalid BCP 47 locale tag: \"${locale}\".`);\n}\n\nexport function localeChain(locale: Locale, fallback: readonly Locale[]): readonly Locale[] {\n const chain = new Set<Locale>();\n\n for (const candidate of [locale, ...fallback]) {\n const parts = candidate.split('-');\n\n for (let length = parts.length; length > 0; length--) {\n chain.add(parts.slice(0, length).join('-'));\n }\n }\n\n return [...chain];\n}\n\nexport function pluralCategory(locale: Locale, count: number, ordinal: boolean): Intl.LDMLPluralRule {\n const key = `${locale}:${ordinal ? 'ordinal' : 'cardinal'}`;\n let rules = pluralRules.get(key);\n\n if (!rules) {\n rules = new Intl.PluralRules(locale, { type: ordinal ? 'ordinal' : 'cardinal' });\n pluralRules.set(key, rules);\n }\n\n return rules.select(count);\n}\n"],"mappings":"gCAGA,IAAM,EAAc,IAAI,IAExB,SAAgB,gBAAgB,EAAwB,CACtD,GAAI,CACF,GAAM,CAAC,GAAa,KAAK,oBAAoB,CAAM,EAEnD,GAAI,EAAW,OAAO,CACxB,MAAQ,CAER,CAEA,MAAM,IAAI,EAAA,yBAAyB,+BAA+B,EAAO,GAAG,CAC9E,CAEA,SAAgB,YAAY,EAAgB,EAAgD,CAC1F,IAAM,EAAQ,IAAI,IAElB,IAAK,IAAM,IAAa,CAAC,EAAQ,GAAG,CAAQ,EAAG,CAC7C,IAAM,EAAQ,EAAU,MAAM,GAAG,EAEjC,IAAK,IAAI,EAAS,EAAM,OAAQ,EAAS,EAAG,IAC1C,EAAM,IAAI,EAAM,MAAM,EAAG,CAAM,CAAC,CAAC,KAAK,GAAG,CAAC,CAE9C,CAEA,MAAO,CAAC,GAAG,CAAK,CAClB,CAEA,SAAgB,eAAe,EAAgB,EAAe,EAAuC,CACnG,IAAM,EAAM,GAAG,EAAO,GAAG,EAAU,UAAY,aAC3C,EAAQ,EAAY,IAAI,CAAG,EAO/B,OALK,IACH,EAAQ,IAAI,KAAK,YAAY,EAAQ,CAAE,KAAM,EAAU,UAAY,UAAW,CAAC,EAC/E,EAAY,IAAI,EAAK,CAAK,GAGrB,EAAM,OAAO,CAAK,CAC3B"}
|
package/dist/_locale.js
CHANGED
|
@@ -1,26 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
//#region src/_locale.ts
|
|
3
|
-
var t = /* @__PURE__ */ new Map();
|
|
4
|
-
function n(t) {
|
|
5
|
-
try {
|
|
6
|
-
let [e] = Intl.getCanonicalLocales(t);
|
|
7
|
-
if (e) return e;
|
|
8
|
-
} catch {}
|
|
9
|
-
throw new e(`Invalid BCP 47 locale tag: "${t}".`);
|
|
10
|
-
}
|
|
11
|
-
function r(e, t) {
|
|
12
|
-
let n = /* @__PURE__ */ new Set();
|
|
13
|
-
for (let r of [e, ...t]) {
|
|
14
|
-
let e = r.split("-");
|
|
15
|
-
for (let t = e.length; t > 0; t--) n.add(e.slice(0, t).join("-"));
|
|
16
|
-
}
|
|
17
|
-
return [...n];
|
|
18
|
-
}
|
|
19
|
-
function i(e, n, r) {
|
|
20
|
-
let i = `${e}:${r ? "ordinal" : "cardinal"}`, a = t.get(i);
|
|
21
|
-
return a || (a = new Intl.PluralRules(e, { type: r ? "ordinal" : "cardinal" }), t.set(i, a)), a.select(n);
|
|
22
|
-
}
|
|
23
|
-
//#endregion
|
|
24
|
-
export { n as canonicalLocale, r as localeChain, i as pluralCategory };
|
|
25
|
-
|
|
1
|
+
import{LinguaInvalidLocaleError as e}from"./errors.js";var t=new Map;function canonicalLocale(t){try{let[e]=Intl.getCanonicalLocales(t);if(e)return e}catch{}throw new e(`Invalid BCP 47 locale tag: "${t}".`)}function localeChain(e,t){let n=new Set;for(let r of[e,...t]){let e=r.split(`-`);for(let t=e.length;t>0;t--)n.add(e.slice(0,t).join(`-`))}return[...n]}function pluralCategory(e,n,r){let i=`${e}:${r?`ordinal`:`cardinal`}`,a=t.get(i);return a||(a=new Intl.PluralRules(e,{type:r?`ordinal`:`cardinal`}),t.set(i,a)),a.select(n)}export{canonicalLocale,localeChain,pluralCategory};
|
|
26
2
|
//# sourceMappingURL=_locale.js.map
|
package/dist/_locale.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_locale.js","names":[],"sources":["../src/_locale.ts"],"sourcesContent":["import { LinguaInvalidLocaleError } from './errors';\nimport type { Locale } from './types';\n\nconst pluralRules = new Map<string, Intl.PluralRules>();\n\nexport function canonicalLocale(locale: string): Locale {\n try {\n const [canonical] = Intl.getCanonicalLocales(locale);\n\n if (canonical) return canonical;\n } catch {\n // Error below names the failed public input.\n }\n\n throw new LinguaInvalidLocaleError(`Invalid BCP 47 locale tag: \"${locale}\".`);\n}\n\nexport function localeChain(locale: Locale, fallback: readonly Locale[]): readonly Locale[] {\n const chain = new Set<Locale>();\n\n for (const candidate of [locale, ...fallback]) {\n const parts = candidate.split('-');\n\n for (let length = parts.length; length > 0; length--) {\n chain.add(parts.slice(0, length).join('-'));\n }\n }\n\n return [...chain];\n}\n\nexport function pluralCategory(locale: Locale, count: number, ordinal: boolean): Intl.LDMLPluralRule {\n const key = `${locale}:${ordinal ? 'ordinal' : 'cardinal'}`;\n let rules = pluralRules.get(key);\n\n if (!rules) {\n rules = new Intl.PluralRules(locale, { type: ordinal ? 'ordinal' : 'cardinal' });\n pluralRules.set(key, rules);\n }\n\n return rules.select(count);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"_locale.js","names":[],"sources":["../src/_locale.ts"],"sourcesContent":["import { LinguaInvalidLocaleError } from './errors';\nimport type { Locale } from './types';\n\nconst pluralRules = new Map<string, Intl.PluralRules>();\n\nexport function canonicalLocale(locale: string): Locale {\n try {\n const [canonical] = Intl.getCanonicalLocales(locale);\n\n if (canonical) return canonical;\n } catch {\n // Error below names the failed public input.\n }\n\n throw new LinguaInvalidLocaleError(`Invalid BCP 47 locale tag: \"${locale}\".`);\n}\n\nexport function localeChain(locale: Locale, fallback: readonly Locale[]): readonly Locale[] {\n const chain = new Set<Locale>();\n\n for (const candidate of [locale, ...fallback]) {\n const parts = candidate.split('-');\n\n for (let length = parts.length; length > 0; length--) {\n chain.add(parts.slice(0, length).join('-'));\n }\n }\n\n return [...chain];\n}\n\nexport function pluralCategory(locale: Locale, count: number, ordinal: boolean): Intl.LDMLPluralRule {\n const key = `${locale}:${ordinal ? 'ordinal' : 'cardinal'}`;\n let rules = pluralRules.get(key);\n\n if (!rules) {\n rules = new Intl.PluralRules(locale, { type: ordinal ? 'ordinal' : 'cardinal' });\n pluralRules.set(key, rules);\n }\n\n return rules.select(count);\n}\n"],"mappings":"uDAGA,IAAM,EAAc,IAAI,IAExB,SAAgB,gBAAgB,EAAwB,CACtD,GAAI,CACF,GAAM,CAAC,GAAa,KAAK,oBAAoB,CAAM,EAEnD,GAAI,EAAW,OAAO,CACxB,MAAQ,CAER,CAEA,MAAM,IAAI,EAAyB,+BAA+B,EAAO,GAAG,CAC9E,CAEA,SAAgB,YAAY,EAAgB,EAAgD,CAC1F,IAAM,EAAQ,IAAI,IAElB,IAAK,IAAM,IAAa,CAAC,EAAQ,GAAG,CAAQ,EAAG,CAC7C,IAAM,EAAQ,EAAU,MAAM,GAAG,EAEjC,IAAK,IAAI,EAAS,EAAM,OAAQ,EAAS,EAAG,IAC1C,EAAM,IAAI,EAAM,MAAM,EAAG,CAAM,CAAC,CAAC,KAAK,GAAG,CAAC,CAE9C,CAEA,MAAO,CAAC,GAAG,CAAK,CAClB,CAEA,SAAgB,eAAe,EAAgB,EAAe,EAAuC,CACnG,IAAM,EAAM,GAAG,EAAO,GAAG,EAAU,UAAY,aAC3C,EAAQ,EAAY,IAAI,CAAG,EAO/B,OALK,IACH,EAAQ,IAAI,KAAK,YAAY,EAAQ,CAAE,KAAM,EAAU,UAAY,UAAW,CAAC,EAC/E,EAAY,IAAI,EAAK,CAAK,GAGrB,EAAM,OAAO,CAAK,CAC3B"}
|
package/dist/_resources.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("./errors.cjs"),t=require("./_catalog.cjs"),n=require("./_locale.cjs");function
|
|
1
|
+
const e=require("./errors.cjs"),t=require("./_catalog.cjs"),n=require("./_locale.cjs");function createCatalogStore(r){let i=new Map,a=new Map,hydrate=(e,r)=>{i.set(n.canonicalLocale(e),{catalog:r,compiled:t.compileCatalog(r)})};for(let[e,t]of Object.entries(r.catalogs??{}))hydrate(e,t);let load=async t=>{let o=n.canonicalLocale(t);if(i.has(o))return!1;let s=a.get(o);if(s)return await s,!1;if(!r.loadCatalog)throw new e.LinguaMissingCatalogError(`No catalog source provided for locale "${o}".`);let c=Promise.resolve(r.loadCatalog(o)).then(e=>{hydrate(o,e),a.delete(o)},e=>{throw a.delete(o),e});return a.set(o,c),await c,!0};return{catalogMap(){return new Map([...i].map(([e,{compiled:t}])=>[e,t]))},hydrate,isLoaded(e){return i.has(n.canonicalLocale(e))},load,state(e){let t={};for(let[e,{catalog:n}]of i)t[e]=n;return{catalogs:t,locale:e,version:1}}}}exports.createCatalogStore=createCatalogStore;
|
|
2
2
|
//# sourceMappingURL=_resources.cjs.map
|
package/dist/_resources.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_resources.cjs","names":[],"sources":["../src/_resources.ts"],"sourcesContent":["import { type CompiledCatalog, compileCatalog } from './_catalog';\nimport { canonicalLocale } from './_locale';\nimport { LinguaMissingCatalogError } from './errors';\nimport type { Catalog,
|
|
1
|
+
{"version":3,"file":"_resources.cjs","names":[],"sources":["../src/_resources.ts"],"sourcesContent":["import { type CompiledCatalog, compileCatalog } from './_catalog';\nimport { canonicalLocale } from './_locale';\nimport { LinguaMissingCatalogError } from './errors';\nimport type { Catalog, Catalogs, Locale, TranslationState } from './types';\n\ntype CatalogStoreOptions<C extends Catalog> = {\n readonly catalogs?: Catalogs<C>;\n readonly loadCatalog?: (locale: Locale) => Promise<C> | C;\n};\n\n/** One catalog state machine owns loaded catalogs and in-flight loading work. */\nexport function createCatalogStore<C extends Catalog>(options: CatalogStoreOptions<C>) {\n const loaded = new Map<Locale, { readonly catalog: C; readonly compiled: CompiledCatalog }>();\n const tasks = new Map<Locale, Promise<void>>();\n\n const hydrate = (locale: Locale, catalog: C): void => {\n loaded.set(canonicalLocale(locale), { catalog, compiled: compileCatalog(catalog) });\n };\n\n for (const [locale, catalog] of Object.entries(options.catalogs ?? {})) hydrate(locale, catalog);\n\n const load = async (requestedLocale: Locale): Promise<boolean> => {\n const locale = canonicalLocale(requestedLocale);\n\n if (loaded.has(locale)) return false;\n\n const existing = tasks.get(locale);\n\n if (existing) {\n await existing;\n\n return false;\n }\n\n if (!options.loadCatalog) {\n throw new LinguaMissingCatalogError(`No catalog source provided for locale \"${locale}\".`);\n }\n\n const task = Promise.resolve(options.loadCatalog(locale)).then(\n (catalog) => {\n hydrate(locale, catalog);\n tasks.delete(locale);\n },\n (error: unknown) => {\n tasks.delete(locale);\n throw error;\n },\n );\n\n tasks.set(locale, task);\n await task;\n\n return true;\n };\n\n return {\n catalogMap(): ReadonlyMap<Locale, CompiledCatalog> {\n return new Map([...loaded].map(([locale, { compiled }]) => [locale, compiled]));\n },\n hydrate,\n isLoaded(locale: Locale): boolean {\n return loaded.has(canonicalLocale(locale));\n },\n load,\n state(locale: Locale): TranslationState<C> {\n const catalogs: Catalogs<C> = {};\n\n for (const [loadedLocale, { catalog }] of loaded) catalogs[loadedLocale] = catalog;\n\n return { catalogs, locale, version: 1 };\n },\n };\n}\n"],"mappings":"uFAWA,SAAgB,mBAAsC,EAAiC,CACrF,IAAM,EAAS,IAAI,IACb,EAAQ,IAAI,IAEZ,SAAW,EAAgB,IAAqB,CACpD,EAAO,IAAI,EAAA,gBAAgB,CAAM,EAAG,CAAE,UAAS,SAAU,EAAA,eAAe,CAAO,CAAE,CAAC,CACpF,EAEA,IAAK,GAAM,CAAC,EAAQ,KAAY,OAAO,QAAQ,EAAQ,UAAY,CAAC,CAAC,EAAG,QAAQ,EAAQ,CAAO,EAE/F,IAAM,KAAO,KAAO,IAA8C,CAChE,IAAM,EAAS,EAAA,gBAAgB,CAAe,EAE9C,GAAI,EAAO,IAAI,CAAM,EAAG,MAAO,GAE/B,IAAM,EAAW,EAAM,IAAI,CAAM,EAEjC,GAAI,EAGF,OAFA,MAAM,EAEC,GAGT,GAAI,CAAC,EAAQ,YACX,MAAM,IAAI,EAAA,0BAA0B,0CAA0C,EAAO,GAAG,EAG1F,IAAM,EAAO,QAAQ,QAAQ,EAAQ,YAAY,CAAM,CAAC,CAAC,CAAC,KACvD,GAAY,CACX,QAAQ,EAAQ,CAAO,EACvB,EAAM,OAAO,CAAM,CACrB,EACC,GAAmB,CAElB,MADA,EAAM,OAAO,CAAM,EACb,CACR,CACF,EAKA,OAHA,EAAM,IAAI,EAAQ,CAAI,EACtB,MAAM,EAEC,EACT,EAEA,MAAO,CACL,YAAmD,CACjD,OAAO,IAAI,IAAI,CAAC,GAAG,CAAM,CAAC,CAAC,KAAK,CAAC,EAAQ,CAAE,eAAgB,CAAC,EAAQ,CAAQ,CAAC,CAAC,CAChF,EACA,QACA,SAAS,EAAyB,CAChC,OAAO,EAAO,IAAI,EAAA,gBAAgB,CAAM,CAAC,CAC3C,EACA,KACA,MAAM,EAAqC,CACzC,IAAM,EAAwB,CAAC,EAE/B,IAAK,GAAM,CAAC,EAAc,CAAE,cAAc,EAAQ,EAAS,GAAgB,EAE3E,MAAO,CAAE,WAAU,SAAQ,QAAS,CAAE,CACxC,CACF,CACF"}
|
package/dist/_resources.d.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { type CompiledCatalog } from './_catalog';
|
|
2
|
-
import type { Catalog,
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import type { Catalog, Catalogs, Locale, TranslationState } from './types';
|
|
3
|
+
type CatalogStoreOptions<C extends Catalog> = {
|
|
4
|
+
readonly catalogs?: Catalogs<C>;
|
|
5
|
+
readonly loadCatalog?: (locale: Locale) => Promise<C> | C;
|
|
6
|
+
};
|
|
7
|
+
/** One catalog state machine owns loaded catalogs and in-flight loading work. */
|
|
8
|
+
export declare function createCatalogStore<C extends Catalog>(options: CatalogStoreOptions<C>): {
|
|
5
9
|
catalogMap(): ReadonlyMap<Locale, CompiledCatalog>;
|
|
10
|
+
hydrate: (locale: Locale, catalog: C) => void;
|
|
6
11
|
isLoaded(locale: Locale): boolean;
|
|
7
12
|
load: (requestedLocale: Locale) => Promise<boolean>;
|
|
8
13
|
state(locale: Locale): TranslationState<C>;
|
|
9
14
|
};
|
|
15
|
+
export {};
|
|
10
16
|
//# sourceMappingURL=_resources.d.ts.map
|
package/dist/_resources.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_resources.d.ts","sourceRoot":"","sources":["../src/_resources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAkB,MAAM,YAAY,CAAC;AAGlE,OAAO,KAAK,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"_resources.d.ts","sourceRoot":"","sources":["../src/_resources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAkB,MAAM,YAAY,CAAC;AAGlE,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE3E,KAAK,mBAAmB,CAAC,CAAC,SAAS,OAAO,IAAI;IAC5C,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;CAC3D,CAAC;AAEF,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,OAAO,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC;kBA6CnE,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC;sBAzC3B,MAAM,WAAW,CAAC,KAAG,IAAI;qBA6C/B,MAAM,GAAG,OAAO;4BAvCE,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;kBA2C9C,MAAM,GAAG,gBAAgB,CAAC,CAAC,CAAC;EAQ7C"}
|
package/dist/_resources.js
CHANGED
|
@@ -1,51 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { compileCatalog as t } from "./_catalog.js";
|
|
3
|
-
import { canonicalLocale as n } from "./_locale.js";
|
|
4
|
-
//#region src/_resources.ts
|
|
5
|
-
function r(r) {
|
|
6
|
-
let i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map();
|
|
7
|
-
for (let [e, t] of Object.entries(r)) i.set(n(e), t);
|
|
8
|
-
let s = (e, n) => {
|
|
9
|
-
a.set(e, {
|
|
10
|
-
catalog: n,
|
|
11
|
-
compiled: t(n)
|
|
12
|
-
});
|
|
13
|
-
};
|
|
14
|
-
for (let [e, t] of i) typeof t != "function" && s(e, t);
|
|
15
|
-
return {
|
|
16
|
-
catalogMap() {
|
|
17
|
-
return new Map([...a].map(([e, { compiled: t }]) => [e, t]));
|
|
18
|
-
},
|
|
19
|
-
isLoaded(e) {
|
|
20
|
-
return a.has(n(e));
|
|
21
|
-
},
|
|
22
|
-
load: async (t) => {
|
|
23
|
-
let r = n(t);
|
|
24
|
-
if (a.has(r)) return !1;
|
|
25
|
-
let c = i.get(r);
|
|
26
|
-
if (!c) throw new e(`Catalog has no source for locale "${r}".`);
|
|
27
|
-
if (typeof c != "function") return s(r, c), !0;
|
|
28
|
-
let l = o.get(r);
|
|
29
|
-
if (l) return await l, !1;
|
|
30
|
-
let u = c().then((e) => {
|
|
31
|
-
s(r, e), o.delete(r);
|
|
32
|
-
}, (e) => {
|
|
33
|
-
throw o.delete(r), e;
|
|
34
|
-
});
|
|
35
|
-
return o.set(r, u), await u, !0;
|
|
36
|
-
},
|
|
37
|
-
state(e) {
|
|
38
|
-
let t = {};
|
|
39
|
-
for (let [e, { catalog: n }] of a) t[e] = n;
|
|
40
|
-
return {
|
|
41
|
-
catalogs: t,
|
|
42
|
-
locale: e,
|
|
43
|
-
version: 3
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
//#endregion
|
|
49
|
-
export { r as createCatalogStore };
|
|
50
|
-
|
|
1
|
+
import{LinguaMissingCatalogError as e}from"./errors.js";import{compileCatalog as t}from"./_catalog.js";import{canonicalLocale as n}from"./_locale.js";function createCatalogStore(r){let i=new Map,a=new Map,hydrate=(e,r)=>{i.set(n(e),{catalog:r,compiled:t(r)})};for(let[e,t]of Object.entries(r.catalogs??{}))hydrate(e,t);let load=async t=>{let o=n(t);if(i.has(o))return!1;let s=a.get(o);if(s)return await s,!1;if(!r.loadCatalog)throw new e(`No catalog source provided for locale "${o}".`);let c=Promise.resolve(r.loadCatalog(o)).then(e=>{hydrate(o,e),a.delete(o)},e=>{throw a.delete(o),e});return a.set(o,c),await c,!0};return{catalogMap(){return new Map([...i].map(([e,{compiled:t}])=>[e,t]))},hydrate,isLoaded(e){return i.has(n(e))},load,state(e){let t={};for(let[e,{catalog:n}]of i)t[e]=n;return{catalogs:t,locale:e,version:1}}}}export{createCatalogStore};
|
|
51
2
|
//# sourceMappingURL=_resources.js.map
|
package/dist/_resources.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_resources.js","names":[],"sources":["../src/_resources.ts"],"sourcesContent":["import { type CompiledCatalog, compileCatalog } from './_catalog';\nimport { canonicalLocale } from './_locale';\nimport { LinguaMissingCatalogError } from './errors';\nimport type { Catalog,
|
|
1
|
+
{"version":3,"file":"_resources.js","names":[],"sources":["../src/_resources.ts"],"sourcesContent":["import { type CompiledCatalog, compileCatalog } from './_catalog';\nimport { canonicalLocale } from './_locale';\nimport { LinguaMissingCatalogError } from './errors';\nimport type { Catalog, Catalogs, Locale, TranslationState } from './types';\n\ntype CatalogStoreOptions<C extends Catalog> = {\n readonly catalogs?: Catalogs<C>;\n readonly loadCatalog?: (locale: Locale) => Promise<C> | C;\n};\n\n/** One catalog state machine owns loaded catalogs and in-flight loading work. */\nexport function createCatalogStore<C extends Catalog>(options: CatalogStoreOptions<C>) {\n const loaded = new Map<Locale, { readonly catalog: C; readonly compiled: CompiledCatalog }>();\n const tasks = new Map<Locale, Promise<void>>();\n\n const hydrate = (locale: Locale, catalog: C): void => {\n loaded.set(canonicalLocale(locale), { catalog, compiled: compileCatalog(catalog) });\n };\n\n for (const [locale, catalog] of Object.entries(options.catalogs ?? {})) hydrate(locale, catalog);\n\n const load = async (requestedLocale: Locale): Promise<boolean> => {\n const locale = canonicalLocale(requestedLocale);\n\n if (loaded.has(locale)) return false;\n\n const existing = tasks.get(locale);\n\n if (existing) {\n await existing;\n\n return false;\n }\n\n if (!options.loadCatalog) {\n throw new LinguaMissingCatalogError(`No catalog source provided for locale \"${locale}\".`);\n }\n\n const task = Promise.resolve(options.loadCatalog(locale)).then(\n (catalog) => {\n hydrate(locale, catalog);\n tasks.delete(locale);\n },\n (error: unknown) => {\n tasks.delete(locale);\n throw error;\n },\n );\n\n tasks.set(locale, task);\n await task;\n\n return true;\n };\n\n return {\n catalogMap(): ReadonlyMap<Locale, CompiledCatalog> {\n return new Map([...loaded].map(([locale, { compiled }]) => [locale, compiled]));\n },\n hydrate,\n isLoaded(locale: Locale): boolean {\n return loaded.has(canonicalLocale(locale));\n },\n load,\n state(locale: Locale): TranslationState<C> {\n const catalogs: Catalogs<C> = {};\n\n for (const [loadedLocale, { catalog }] of loaded) catalogs[loadedLocale] = catalog;\n\n return { catalogs, locale, version: 1 };\n },\n };\n}\n"],"mappings":"sJAWA,SAAgB,mBAAsC,EAAiC,CACrF,IAAM,EAAS,IAAI,IACb,EAAQ,IAAI,IAEZ,SAAW,EAAgB,IAAqB,CACpD,EAAO,IAAI,EAAgB,CAAM,EAAG,CAAE,UAAS,SAAU,EAAe,CAAO,CAAE,CAAC,CACpF,EAEA,IAAK,GAAM,CAAC,EAAQ,KAAY,OAAO,QAAQ,EAAQ,UAAY,CAAC,CAAC,EAAG,QAAQ,EAAQ,CAAO,EAE/F,IAAM,KAAO,KAAO,IAA8C,CAChE,IAAM,EAAS,EAAgB,CAAe,EAE9C,GAAI,EAAO,IAAI,CAAM,EAAG,MAAO,GAE/B,IAAM,EAAW,EAAM,IAAI,CAAM,EAEjC,GAAI,EAGF,OAFA,MAAM,EAEC,GAGT,GAAI,CAAC,EAAQ,YACX,MAAM,IAAI,EAA0B,0CAA0C,EAAO,GAAG,EAG1F,IAAM,EAAO,QAAQ,QAAQ,EAAQ,YAAY,CAAM,CAAC,CAAC,CAAC,KACvD,GAAY,CACX,QAAQ,EAAQ,CAAO,EACvB,EAAM,OAAO,CAAM,CACrB,EACC,GAAmB,CAElB,MADA,EAAM,OAAO,CAAM,EACb,CACR,CACF,EAKA,OAHA,EAAM,IAAI,EAAQ,CAAI,EACtB,MAAM,EAEC,EACT,EAEA,MAAO,CACL,YAAmD,CACjD,OAAO,IAAI,IAAI,CAAC,GAAG,CAAM,CAAC,CAAC,KAAK,CAAC,EAAQ,CAAE,eAAgB,CAAC,EAAQ,CAAQ,CAAC,CAAC,CAChF,EACA,QACA,SAAS,EAAyB,CAChC,OAAO,EAAO,IAAI,EAAgB,CAAM,CAAC,CAC3C,EACA,KACA,MAAM,EAAqC,CACzC,IAAM,EAAwB,CAAC,EAE/B,IAAK,GAAM,CAAC,EAAc,CAAE,cAAc,EAAQ,EAAS,GAAgB,EAE3E,MAAO,CAAE,WAAU,SAAQ,QAAS,CAAE,CACxC,CACF,CACF"}
|
package/dist/_template.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e=/\{([\p{ID_Continue}-]+)\}/gu;function
|
|
1
|
+
var e=/\{([\p{ID_Continue}-]+)\}/gu;function compileTemplate(t){let n=[],r=0;for(let i of t.matchAll(e)){let e=i.index??0;e>r&&n.push(t.slice(r,e)),n.push({value:i[1]}),r=e+i[0].length}return r<t.length&&n.push(t.slice(r)),n}function renderText(e,t,n){return e.map(e=>{if(typeof e==`string`)return e;let r=Object.hasOwn(t,e.value)?t[e.value]:void 0;return r==null?n(e.value):String(r)}).join(``)}function renderParts(e,t,n){let r=[];for(let i of e){if(typeof i==`string`){i!==``&&r.push({type:`text`,value:i});continue}Object.hasOwn(t,i.value)?r.push({type:`value`,value:t[i.value]}):r.push({type:`text`,value:n(i.value)})}return r}exports.compileTemplate=compileTemplate,exports.renderParts=renderParts,exports.renderText=renderText;
|
|
2
2
|
//# sourceMappingURL=_template.cjs.map
|
package/dist/_template.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_template.cjs","names":[],"sources":["../src/_template.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"_template.cjs","names":[],"sources":["../src/_template.ts"],"sourcesContent":["import type { Part } from './types';\n\nexport type TemplatePart = string | { readonly value: string };\nexport type Template = readonly TemplatePart[];\n\nconst interpolation = /\\{([\\p{ID_Continue}-]+)\\}/gu;\n\nexport function compileTemplate(value: string): Template {\n const parts: TemplatePart[] = [];\n let offset = 0;\n\n for (const match of value.matchAll(interpolation)) {\n const index = match.index ?? 0;\n\n if (index > offset) parts.push(value.slice(offset, index));\n\n parts.push({ value: match[1] });\n offset = index + match[0].length;\n }\n\n if (offset < value.length) parts.push(value.slice(offset));\n\n return parts;\n}\n\nexport function renderText(\n parts: Template,\n values: Record<string, unknown>,\n missing: (name: string) => string,\n): string {\n return parts\n .map((part) => {\n if (typeof part === 'string') return part;\n\n const value = Object.hasOwn(values, part.value) ? values[part.value] : undefined;\n\n return value == null ? missing(part.value) : String(value);\n })\n .join('');\n}\n\nexport function renderParts<V>(\n parts: Template,\n values: Record<string, V | number>,\n missing: (name: string) => string,\n): Array<Part<V | number>> {\n const result: Array<Part<V | number>> = [];\n\n for (const part of parts) {\n if (typeof part === 'string') {\n if (part !== '') result.push({ type: 'text', value: part });\n\n continue;\n }\n\n if (Object.hasOwn(values, part.value)) {\n result.push({ type: 'value', value: values[part.value]! as V | number });\n } else {\n result.push({ type: 'text', value: missing(part.value) });\n }\n }\n\n return result;\n}\n"],"mappings":"AAKA,IAAM,EAAgB,8BAEtB,SAAgB,gBAAgB,EAAyB,CACvD,IAAM,EAAwB,CAAC,EAC3B,EAAS,EAEb,IAAK,IAAM,KAAS,EAAM,SAAS,CAAa,EAAG,CACjD,IAAM,EAAQ,EAAM,OAAS,EAEzB,EAAQ,GAAQ,EAAM,KAAK,EAAM,MAAM,EAAQ,CAAK,CAAC,EAEzD,EAAM,KAAK,CAAE,MAAO,EAAM,EAAG,CAAC,EAC9B,EAAS,EAAQ,EAAM,EAAE,CAAC,MAC5B,CAIA,OAFI,EAAS,EAAM,QAAQ,EAAM,KAAK,EAAM,MAAM,CAAM,CAAC,EAElD,CACT,CAEA,SAAgB,WACd,EACA,EACA,EACQ,CACR,OAAO,EACJ,IAAK,GAAS,CACb,GAAI,OAAO,GAAS,SAAU,OAAO,EAErC,IAAM,EAAQ,OAAO,OAAO,EAAQ,EAAK,KAAK,EAAI,EAAO,EAAK,OAAS,IAAA,GAEvE,OAAO,GAAS,KAAO,EAAQ,EAAK,KAAK,EAAI,OAAO,CAAK,CAC3D,CAAC,CAAC,CACD,KAAK,EAAE,CACZ,CAEA,SAAgB,YACd,EACA,EACA,EACyB,CACzB,IAAM,EAAkC,CAAC,EAEzC,IAAK,IAAM,KAAQ,EAAO,CACxB,GAAI,OAAO,GAAS,SAAU,CACxB,IAAS,IAAI,EAAO,KAAK,CAAE,KAAM,OAAQ,MAAO,CAAK,CAAC,EAE1D,QACF,CAEI,OAAO,OAAO,EAAQ,EAAK,KAAK,EAClC,EAAO,KAAK,CAAE,KAAM,QAAS,MAAO,EAAO,EAAK,MAAsB,CAAC,EAEvE,EAAO,KAAK,CAAE,KAAM,OAAQ,MAAO,EAAQ,EAAK,KAAK,CAAE,CAAC,CAE5D,CAEA,OAAO,CACT"}
|
package/dist/_template.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import type { Part } from './types';
|
|
1
2
|
export type TemplatePart = string | {
|
|
2
3
|
readonly value: string;
|
|
3
4
|
};
|
|
4
5
|
export type Template = readonly TemplatePart[];
|
|
5
6
|
export declare function compileTemplate(value: string): Template;
|
|
6
7
|
export declare function renderText(parts: Template, values: Record<string, unknown>, missing: (name: string) => string): string;
|
|
7
|
-
export declare function
|
|
8
|
+
export declare function renderParts<V>(parts: Template, values: Record<string, V | number>, missing: (name: string) => string): Array<Part<V | number>>;
|
|
8
9
|
//# sourceMappingURL=_template.d.ts.map
|
package/dist/_template.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_template.d.ts","sourceRoot":"","sources":["../src/_template.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAC/D,MAAM,MAAM,QAAQ,GAAG,SAAS,YAAY,EAAE,CAAC;AAI/C,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAgBvD;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,QAAQ,EACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAChC,MAAM,CAUR;AAED,wBAAgB,
|
|
1
|
+
{"version":3,"file":"_template.d.ts","sourceRoot":"","sources":["../src/_template.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAEpC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAC/D,MAAM,MAAM,QAAQ,GAAG,SAAS,YAAY,EAAE,CAAC;AAI/C,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAgBvD;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,QAAQ,EACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAChC,MAAM,CAUR;AAED,wBAAgB,WAAW,CAAC,CAAC,EAC3B,KAAK,EAAE,QAAQ,EACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,EAClC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAChC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAkBzB"}
|
package/dist/_template.js
CHANGED
|
@@ -1,32 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
var e = /\{([\p{ID_Continue}-]+)\}/gu;
|
|
3
|
-
function t(t) {
|
|
4
|
-
let n = [], r = 0;
|
|
5
|
-
for (let i of t.matchAll(e)) {
|
|
6
|
-
let e = i.index ?? 0;
|
|
7
|
-
e > r && n.push(t.slice(r, e)), n.push({ value: i[1] }), r = e + i[0].length;
|
|
8
|
-
}
|
|
9
|
-
return r < t.length && n.push(t.slice(r)), n;
|
|
10
|
-
}
|
|
11
|
-
function n(e, t, n) {
|
|
12
|
-
return e.map((e) => {
|
|
13
|
-
if (typeof e == "string") return e;
|
|
14
|
-
let r = Object.hasOwn(t, e.value) ? t[e.value] : void 0;
|
|
15
|
-
return r == null ? n(e.value) : String(r);
|
|
16
|
-
}).join("");
|
|
17
|
-
}
|
|
18
|
-
function r(e, t, n) {
|
|
19
|
-
let r = [];
|
|
20
|
-
for (let i of e) {
|
|
21
|
-
if (typeof i == "string") {
|
|
22
|
-
i !== "" && r.push(i);
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
r.push(Object.hasOwn(t, i.value) ? t[i.value] : n(i.value));
|
|
26
|
-
}
|
|
27
|
-
return r;
|
|
28
|
-
}
|
|
29
|
-
//#endregion
|
|
30
|
-
export { t as compileTemplate, r as renderSegments, n as renderText };
|
|
31
|
-
|
|
1
|
+
var e=/\{([\p{ID_Continue}-]+)\}/gu;function compileTemplate(t){let n=[],r=0;for(let i of t.matchAll(e)){let e=i.index??0;e>r&&n.push(t.slice(r,e)),n.push({value:i[1]}),r=e+i[0].length}return r<t.length&&n.push(t.slice(r)),n}function renderText(e,t,n){return e.map(e=>{if(typeof e==`string`)return e;let r=Object.hasOwn(t,e.value)?t[e.value]:void 0;return r==null?n(e.value):String(r)}).join(``)}function renderParts(e,t,n){let r=[];for(let i of e){if(typeof i==`string`){i!==``&&r.push({type:`text`,value:i});continue}Object.hasOwn(t,i.value)?r.push({type:`value`,value:t[i.value]}):r.push({type:`text`,value:n(i.value)})}return r}export{compileTemplate,renderParts,renderText};
|
|
32
2
|
//# sourceMappingURL=_template.js.map
|
package/dist/_template.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_template.js","names":[],"sources":["../src/_template.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"_template.js","names":[],"sources":["../src/_template.ts"],"sourcesContent":["import type { Part } from './types';\n\nexport type TemplatePart = string | { readonly value: string };\nexport type Template = readonly TemplatePart[];\n\nconst interpolation = /\\{([\\p{ID_Continue}-]+)\\}/gu;\n\nexport function compileTemplate(value: string): Template {\n const parts: TemplatePart[] = [];\n let offset = 0;\n\n for (const match of value.matchAll(interpolation)) {\n const index = match.index ?? 0;\n\n if (index > offset) parts.push(value.slice(offset, index));\n\n parts.push({ value: match[1] });\n offset = index + match[0].length;\n }\n\n if (offset < value.length) parts.push(value.slice(offset));\n\n return parts;\n}\n\nexport function renderText(\n parts: Template,\n values: Record<string, unknown>,\n missing: (name: string) => string,\n): string {\n return parts\n .map((part) => {\n if (typeof part === 'string') return part;\n\n const value = Object.hasOwn(values, part.value) ? values[part.value] : undefined;\n\n return value == null ? missing(part.value) : String(value);\n })\n .join('');\n}\n\nexport function renderParts<V>(\n parts: Template,\n values: Record<string, V | number>,\n missing: (name: string) => string,\n): Array<Part<V | number>> {\n const result: Array<Part<V | number>> = [];\n\n for (const part of parts) {\n if (typeof part === 'string') {\n if (part !== '') result.push({ type: 'text', value: part });\n\n continue;\n }\n\n if (Object.hasOwn(values, part.value)) {\n result.push({ type: 'value', value: values[part.value]! as V | number });\n } else {\n result.push({ type: 'text', value: missing(part.value) });\n }\n }\n\n return result;\n}\n"],"mappings":"AAKA,IAAM,EAAgB,8BAEtB,SAAgB,gBAAgB,EAAyB,CACvD,IAAM,EAAwB,CAAC,EAC3B,EAAS,EAEb,IAAK,IAAM,KAAS,EAAM,SAAS,CAAa,EAAG,CACjD,IAAM,EAAQ,EAAM,OAAS,EAEzB,EAAQ,GAAQ,EAAM,KAAK,EAAM,MAAM,EAAQ,CAAK,CAAC,EAEzD,EAAM,KAAK,CAAE,MAAO,EAAM,EAAG,CAAC,EAC9B,EAAS,EAAQ,EAAM,EAAE,CAAC,MAC5B,CAIA,OAFI,EAAS,EAAM,QAAQ,EAAM,KAAK,EAAM,MAAM,CAAM,CAAC,EAElD,CACT,CAEA,SAAgB,WACd,EACA,EACA,EACQ,CACR,OAAO,EACJ,IAAK,GAAS,CACb,GAAI,OAAO,GAAS,SAAU,OAAO,EAErC,IAAM,EAAQ,OAAO,OAAO,EAAQ,EAAK,KAAK,EAAI,EAAO,EAAK,OAAS,IAAA,GAEvE,OAAO,GAAS,KAAO,EAAQ,EAAK,KAAK,EAAI,OAAO,CAAK,CAC3D,CAAC,CAAC,CACD,KAAK,EAAE,CACZ,CAEA,SAAgB,YACd,EACA,EACA,EACyB,CACzB,IAAM,EAAkC,CAAC,EAEzC,IAAK,IAAM,KAAQ,EAAO,CACxB,GAAI,OAAO,GAAS,SAAU,CACxB,IAAS,IAAI,EAAO,KAAK,CAAE,KAAM,OAAQ,MAAO,CAAK,CAAC,EAE1D,QACF,CAEI,OAAO,OAAO,EAAQ,EAAK,KAAK,EAClC,EAAO,KAAK,CAAE,KAAM,QAAS,MAAO,EAAO,EAAK,MAAsB,CAAC,EAEvE,EAAO,KAAK,CAAE,KAAM,OAAQ,MAAO,EAAQ,EAAK,KAAK,CAAE,CAAC,CAE5D,CAEA,OAAO,CACT"}
|
package/dist/catalog.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("./_catalog.cjs");function
|
|
1
|
+
const e=require("./_catalog.cjs");function catalogKeys(t){return[...e.compileCatalog(t).keys()]}exports.catalogKeys=catalogKeys;
|
|
2
2
|
//# sourceMappingURL=catalog.cjs.map
|
package/dist/catalog.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.cjs","names":[],"sources":["../src/catalog.ts"],"sourcesContent":["import { compileCatalog } from './_catalog';\nimport type {
|
|
1
|
+
{"version":3,"file":"catalog.cjs","names":[],"sources":["../src/catalog.ts"],"sourcesContent":["import { compileCatalog } from './_catalog';\nimport type { Catalog, MessageKey } from './types';\n\n/** Enumerate every message key in a catalog as a dotted path.\n *\n * Traverses nested grouping objects and explicit `{ plural: ... }` messages,\n * producing the same dotted paths that `MessageKey<C>` represents at the type\n * level. Use this to derive key arrays from the catalog itself instead of\n * maintaining a parallel list that can go stale.\n *\n * Pass any catalog subtree to enumerate group-scoped keys. For an `I18n`\n * instance, pass its current locale catalog explicitly.\n *\n * @example\n * ```ts\n * const messages = {\n * nav: { home: '...', settings: '...' },\n * };\n * const keys = catalogKeys(messages); // ['nav.home', 'nav.settings']\n * const navKeys = catalogKeys(messages.nav); // ['home', 'settings']\n *\n * // From an i18n instance — read the current locale's catalog first\n * const i18n = createI18n({ catalogs: { en: messages }, locale: 'en' });\n * const state = i18n.serialize();\n * const allKeys = catalogKeys(state.catalogs[state.locale]);\n * ```\n */\nexport function catalogKeys<C extends Catalog>(catalog: C): ReadonlyArray<MessageKey<C>> {\n return [...compileCatalog(catalog).keys()] as unknown as ReadonlyArray<MessageKey<C>>;\n}\n"],"mappings":"kCA2BA,SAAgB,YAA+B,EAA0C,CACvF,MAAO,CAAC,GAAG,EAAA,eAAe,CAAO,CAAC,CAAC,KAAK,CAAC,CAC3C"}
|