@vielzeug/lingua 1.1.4 → 2.0.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 +15 -54
- package/dist/_catalog.cjs +1 -1
- package/dist/_catalog.cjs.map +1 -1
- package/dist/_catalog.d.ts +13 -16
- package/dist/_catalog.d.ts.map +1 -1
- package/dist/_catalog.js +43 -36
- package/dist/_catalog.js.map +1 -1
- package/dist/_dev.cjs +1 -1
- package/dist/_dev.cjs.map +1 -1
- package/dist/_dev.js +3 -11
- package/dist/_dev.js.map +1 -1
- package/dist/_locale.cjs +2 -0
- package/dist/_locale.cjs.map +1 -0
- package/dist/_locale.d.ts +5 -0
- package/dist/_locale.d.ts.map +1 -0
- package/dist/_locale.js +26 -0
- package/dist/_locale.js.map +1 -0
- package/dist/_resources.cjs +2 -0
- package/dist/_resources.cjs.map +1 -0
- package/dist/_resources.d.ts +10 -0
- package/dist/_resources.d.ts.map +1 -0
- package/dist/_resources.js +51 -0
- package/dist/_resources.js.map +1 -0
- package/dist/_template.cjs +2 -0
- package/dist/_template.cjs.map +1 -0
- package/dist/_template.d.ts +8 -0
- package/dist/_template.d.ts.map +1 -0
- package/dist/_template.js +32 -0
- package/dist/_template.js.map +1 -0
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +6 -18
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +3 -9
- 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 +0 -9
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +10 -12
- 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 +25 -11
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +66 -183
- package/dist/i18n.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +4 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- 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/translator.cjs +2 -0
- package/dist/translator.cjs.map +1 -0
- package/dist/translator.d.ts +20 -0
- package/dist/translator.d.ts.map +1 -0
- package/dist/translator.js +61 -0
- package/dist/translator.js.map +1 -0
- package/dist/types.d.ts +53 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/validate.cjs +1 -1
- package/dist/validate.cjs.map +1 -1
- package/dist/validate.d.ts +5 -37
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +21 -52
- package/dist/validate.js.map +1 -1
- package/package.json +4 -4
- package/dist/_catalog-store.cjs +0 -2
- package/dist/_catalog-store.cjs.map +0 -1
- package/dist/_catalog-store.d.ts +0 -34
- package/dist/_catalog-store.d.ts.map +0 -1
- package/dist/_catalog-store.js +0 -81
- package/dist/_catalog-store.js.map +0 -1
- package/dist/_chain.cjs +0 -2
- package/dist/_chain.cjs.map +0 -1
- package/dist/_chain.d.ts +0 -21
- package/dist/_chain.d.ts.map +0 -1
- package/dist/_chain.js +0 -45
- package/dist/_chain.js.map +0 -1
- package/dist/_constants.cjs +0 -2
- package/dist/_constants.cjs.map +0 -1
- package/dist/_constants.d.ts +0 -3
- package/dist/_constants.d.ts.map +0 -1
- package/dist/_constants.js +0 -17
- package/dist/_constants.js.map +0 -1
- package/dist/_namespace-store.cjs +0 -2
- package/dist/_namespace-store.cjs.map +0 -1
- package/dist/_namespace-store.d.ts +0 -31
- package/dist/_namespace-store.d.ts.map +0 -1
- package/dist/_namespace-store.js +0 -54
- package/dist/_namespace-store.js.map +0 -1
- package/dist/_translate.cjs +0 -2
- package/dist/_translate.cjs.map +0 -1
- package/dist/_translate.d.ts +0 -21
- package/dist/_translate.d.ts.map +0 -1
- package/dist/_translate.js +0 -54
- package/dist/_translate.js.map +0 -1
- package/dist/i18n-types.d.ts +0 -261
- package/dist/i18n-types.d.ts.map +0 -1
- package/dist/template-BZRFdmaQ.cjs +0 -2
- package/dist/template-BZRFdmaQ.cjs.map +0 -1
- package/dist/template-BihTfBYb.js +0 -2
- package/dist/template-BihTfBYb.js.map +0 -1
- package/dist/template.cjs +0 -2
- package/dist/template.cjs.map +0 -1
- package/dist/template.d.ts +0 -15
- package/dist/template.d.ts.map +0 -1
- package/dist/template.js +0 -49
- package/dist/template.js.map +0 -1
- package/dist/validate-D1U8TTeT.js +0 -2
- package/dist/validate-D1U8TTeT.js.map +0 -1
- package/dist/validate-x7lFFyV2.cjs +0 -2
- package/dist/validate-x7lFFyV2.cjs.map +0 -1
package/dist/validate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","names":[],"sources":["../src/validate.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"validate.js","names":[],"sources":["../src/validate.ts"],"sourcesContent":["import type { Catalog, CatalogNode, Locale, PluralMessage } from './types';\n\nimport { compileCatalog } from './_catalog';\nimport { canonicalLocale } from './_locale';\n\nexport type ValidationIssue = {\n key: string;\n locale: Locale;\n missing: Intl.LDMLPluralRule;\n};\n\nfunction isPluralMessage(node: CatalogNode): node is PluralMessage {\n return typeof node === 'object' && node !== null && Object.hasOwn(node, 'plural');\n}\n\n/** Explicit tooling API. Runtime never loads validation code or emits asynchronous catalog warnings. */\nexport function validateCatalog(catalog: Catalog, locale: Locale): ValidationIssue[] {\n compileCatalog(catalog);\n\n const canonical = canonicalLocale(locale);\n const categories = new Intl.PluralRules(canonical).resolvedOptions().pluralCategories;\n const issues: ValidationIssue[] = [];\n\n const visit = (node: CatalogNode, key: string): void => {\n if (typeof node === 'string') return;\n\n if (isPluralMessage(node)) {\n for (const missing of categories) {\n if (!Object.hasOwn(node.plural, missing)) issues.push({ key, locale: canonical, missing });\n }\n\n return;\n }\n\n for (const [childKey, child] of Object.entries(node)) visit(child, key ? `${key}.${childKey}` : childKey);\n };\n\n for (const [key, node] of Object.entries(catalog)) visit(node, key);\n\n return issues;\n}\n"],"mappings":";;;AAWA,SAAS,EAAgB,GAA0C;CACjE,OAAO,OAAO,KAAS,cAAY,KAAiB,OAAO,OAAO,GAAM,QAAQ;AAClF;AAGA,SAAgB,EAAgB,GAAkB,GAAmC;CACnF,EAAe,CAAO;CAEtB,IAAM,IAAY,EAAgB,CAAM,GAClC,IAAa,IAAI,KAAK,YAAY,CAAS,CAAC,CAAC,gBAAgB,CAAC,CAAC,kBAC/D,IAA4B,CAAC,GAE7B,KAAS,GAAmB,MAAsB;EAClD,WAAO,KAAS,UAEpB;OAAI,EAAgB,CAAI,GAAG;IACzB,KAAK,IAAM,KAAW,GACpB,AAAK,OAAO,OAAO,EAAK,QAAQ,CAAO,KAAG,EAAO,KAAK;KAAE;KAAK,QAAQ;KAAW;IAAQ,CAAC;IAG3F;GACF;GAEA,KAAK,IAAM,CAAC,GAAU,MAAU,OAAO,QAAQ,CAAI,GAAG,EAAM,GAAO,IAAM,GAAG,EAAI,GAAG,MAAa,CAAQ;EAFxG;CAGF;CAEA,KAAK,IAAM,CAAC,GAAK,MAAS,OAAO,QAAQ,CAAO,GAAG,EAAM,GAAM,CAAG;CAElE,OAAO;AACT"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vielzeug/lingua",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Explicit typed localization with pluralization, lazy locale catalogs, and SSR hydration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist"
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
"node": ">=22"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@types/node": "^26.1.
|
|
51
|
+
"@types/node": "^26.1.2",
|
|
52
52
|
"typescript": "^6.0.3",
|
|
53
|
-
"vite": "^8.
|
|
53
|
+
"vite": "^8.2.0",
|
|
54
54
|
"vitest": "^4.1.10"
|
|
55
55
|
}
|
|
56
56
|
}
|
package/dist/_catalog-store.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("./_dev.cjs"),t=require("./_catalog.cjs"),n=require("./errors.cjs");function r(t,n){e.devOnly(()=>{Promise.resolve().then(()=>require("./validate.cjs")).then(({validateCatalog:r})=>{for(let i of r(n,t))e.warn(`catalog('${t}'): missing plural form '${i.form}' for key '${i.key}'.`)})})}function i(i){let a=new Map,o=new Map,s=new Map,c=new Set,l,u=(e,n)=>{let r=a.get(e);r||(r=new t.CatalogEntry,a.set(e,r)),r.setAll(n)},d=e=>{let c=n.checkDisposedAsync(i());if(c)return c;if(a.has(e))return Promise.resolve();let d=o.get(e);if(!d)return Promise.reject(new n.LinguaMissingLocaleError(`Missing locale source for "${e}".`));let f=s.get(e);if(f)return f;let p=d().then(n=>{o.get(e)===d&&(o.delete(e),u(e,t.flattenStrings(n)),r(e,n),s.delete(e),l?.(e))},t=>{throw o.get(e)===d&&s.delete(e),t});return s.set(e,p),p};return{dispose(){a.clear(),o.clear(),s.clear(),c.clear(),l=void 0},isLoaded(e){return a.has(e)},isRegistered(e){return c.has(e)},knownLocales(){return[...c]},get onChange(){return l},set onChange(e){l=e},patch(e,r){return n.checkDisposedAsync(i())||(o.has(e)?d(e).then(()=>{i()||(u(e,t.flattenStrings(r)),c.add(e),l?.(e))}):(u(e,t.flattenStrings(r)),c.add(e),l?.(e),Promise.resolve()))},preload:d,register(f,p,m){n.checkDisposed(i()),s.delete(f),c.add(f);let h=m.clearLocale(f);h.length>0&&e.warn(`register('${f}') cleared loaded namespace markers for: ${h.map(e=>`'${e}'`).join(`, `)}. Call loadNamespace() again to reload.`);let g;return typeof p==`function`?(o.set(f,p),a.delete(f),g=d(f)):(o.delete(f),a.delete(f),u(f,t.flattenStrings(p)),r(f,p),g=Promise.resolve(),l?.(f)),g},resolve(e){return a.get(e)},seedFrom(e,t){for(let[t,n]of e)a.set(t,n.clone()),c.add(t);for(let[e,n]of t)o.set(e,n),c.add(e)},snapshotCatalogs(){return a},snapshotLoaders(){return o}}}exports.createCatalogStore=i,exports.validateCatalogInDev=r;
|
|
2
|
-
//# sourceMappingURL=_catalog-store.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_catalog-store.cjs","names":[],"sources":["../src/_catalog-store.ts"],"sourcesContent":["// Internal — not part of the public API.\n// Owns all locale → CatalogEntry state, loaders, and in-flight loading tasks.\n\nimport type { NamespaceStore } from './_namespace-store';\n\nimport { CatalogEntry, type Messages, flattenStrings } from './_catalog';\nimport { devOnly, warn } from './_dev';\nimport { LinguaMissingLocaleError, checkDisposed, checkDisposedAsync } from './errors';\n\nexport type Locale = string;\nexport type Loader<M extends Messages = Messages> = () => Promise<M>;\nexport type LocaleSource<M extends Messages = Messages> = M | Loader<M>;\n\n// Dev-only feedback for the same catalog-authoring mistakes `validateCatalog()` (the CI/build\n// tool at `@vielzeug/lingua/validate`) already catches — most projects never wire that up, so\n// this gives the same signal for free, in the console the author is already watching, the\n// moment a full catalog becomes available: at `createI18n({ catalogs })` construction, via\n// `register()`, or once an async loader resolves. Not run for `patch()` — a namespace overlay is\n// expected to add only a handful of keys, not a complete plural set.\n//\n// Dynamic import, not a static one: `validate.ts`'s own docs promise it stays out of production\n// bundles. A static `import { validateCatalog } from './validate'` here would pull it into every\n// consumer's main bundle regardless of `devOnly()`'s runtime check — bundlers only eliminate\n// that dead branch if the consumer's own build defines `__LINGUA_PROD__` as a literal. The\n// dynamic import keeps validate.ts a genuinely separate, lazily-fetched chunk that's never\n// requested at all when `isDev` is false, no consumer bundler config required.\nexport function validateCatalogInDev(loc: Locale, messages: Messages): void {\n devOnly(() => {\n void import('./validate').then(({ validateCatalog }) => {\n for (const w of validateCatalog(messages, loc)) {\n warn(`catalog('${loc}'): missing plural form '${w.form}' for key '${w.key}'.`);\n }\n });\n });\n}\n\nexport type CatalogStore<M extends Messages = Messages> = {\n dispose(): void;\n isLoaded(loc: Locale): boolean;\n isRegistered(loc: Locale): boolean;\n /** All registered locale keys in insertion order. */\n knownLocales(): readonly Locale[];\n /** Callback invoked whenever a catalog changes (drives bump/notify). */\n onChange: ((loc: Locale) => void) | undefined;\n /** Patch a locale catalog with additional flat messages (used by loadNamespace). */\n patch(loc: Locale, messages: Messages): Promise<void>;\n /** Pre-load a locale catalog without switching. */\n preload(loc: Locale): Promise<void>;\n /** Register (or replace) a locale's source. Returns a Promise that resolves when the catalog is loaded. */\n register(loc: Locale, source: LocaleSource<M>, nsStore: NamespaceStore): Promise<void>;\n /** Resolve a compiled CatalogEntry for a locale (undefined if not loaded). */\n resolve(loc: Locale): CatalogEntry | undefined;\n /**\n * Seed the store with pre-compiled entries from a parent fork.\n * Called during fork() — compiled templates are shared by reference.\n */\n seedFrom(entries: ReadonlyMap<Locale, CatalogEntry>, loaderMap: ReadonlyMap<Locale, Loader<M>>): void;\n /** Snapshot of the raw catalogs map — used for SSR serialization (`getState()`) and fork seeding. */\n snapshotCatalogs(): ReadonlyMap<Locale, CatalogEntry>;\n /** Snapshot of the pending (not-yet-resolved) loaders map — used for fork seeding. */\n snapshotLoaders(): ReadonlyMap<Locale, Loader<M>>;\n};\n\nexport function createCatalogStore<M extends Messages = Messages>(disposed: () => boolean): CatalogStore<M> {\n const catalogs = new Map<Locale, CatalogEntry>();\n const loaders = new Map<Locale, Loader<M>>();\n const loadingTasks = new Map<Locale, Promise<void>>();\n const known = new Set<Locale>();\n\n let onChange: ((loc: Locale) => void) | undefined;\n\n const registerRaw = (normalized: Locale, flat: Map<string, string>): void => {\n let entry = catalogs.get(normalized);\n\n if (!entry) {\n entry = new CatalogEntry();\n catalogs.set(normalized, entry);\n }\n\n entry.setAll(flat);\n };\n\n const preload = (loc: Locale): Promise<void> => {\n const early = checkDisposedAsync(disposed());\n\n if (early) return early;\n\n if (catalogs.has(loc)) return Promise.resolve();\n\n const loader = loaders.get(loc);\n\n if (!loader) return Promise.reject(new LinguaMissingLocaleError(`Missing locale source for \"${loc}\".`));\n\n const existing = loadingTasks.get(loc);\n\n if (existing) return existing;\n\n const task = loader().then(\n (messages) => {\n if (loaders.get(loc) !== loader) return;\n\n loaders.delete(loc);\n registerRaw(loc, flattenStrings(messages));\n validateCatalogInDev(loc, messages);\n loadingTasks.delete(loc);\n onChange?.(loc);\n },\n (error: unknown) => {\n if (loaders.get(loc) === loader) loadingTasks.delete(loc);\n\n throw error;\n },\n );\n\n loadingTasks.set(loc, task);\n\n return task;\n };\n\n return {\n dispose() {\n catalogs.clear();\n loaders.clear();\n loadingTasks.clear();\n known.clear();\n onChange = undefined;\n },\n\n isLoaded(loc) {\n return catalogs.has(loc);\n },\n\n isRegistered(loc) {\n return known.has(loc);\n },\n\n knownLocales() {\n return [...known];\n },\n\n get onChange() {\n return onChange;\n },\n\n set onChange(fn: ((loc: Locale) => void) | undefined) {\n onChange = fn;\n },\n\n patch(loc, messages) {\n const early = checkDisposedAsync(disposed());\n\n if (early) return early;\n\n if (loaders.has(loc)) {\n return preload(loc).then(() => {\n if (disposed()) return;\n\n registerRaw(loc, flattenStrings(messages));\n known.add(loc);\n onChange?.(loc);\n });\n }\n\n registerRaw(loc, flattenStrings(messages));\n known.add(loc);\n onChange?.(loc);\n\n return Promise.resolve();\n },\n\n preload,\n\n register(loc, source, nsStore) {\n checkDisposed(disposed());\n\n loadingTasks.delete(loc);\n known.add(loc);\n\n // Clear namespace loaded-markers for this locale so namespaces can be re-applied\n // after catalog replacement.\n const clearedNs = nsStore.clearLocale(loc);\n\n if (clearedNs.length > 0) {\n warn(\n `register('${loc}') cleared loaded namespace markers for: ${clearedNs.map((ns) => `'${ns}'`).join(', ')}. Call loadNamespace() again to reload.`,\n );\n }\n\n let loadPromise: Promise<void>;\n\n if (typeof source === 'function') {\n loaders.set(loc, source as Loader<M>);\n catalogs.delete(loc);\n loadPromise = preload(loc);\n } else {\n loaders.delete(loc);\n catalogs.delete(loc);\n registerRaw(loc, flattenStrings(source as M));\n validateCatalogInDev(loc, source as M);\n loadPromise = Promise.resolve();\n onChange?.(loc);\n }\n\n return loadPromise;\n },\n\n resolve(loc) {\n return catalogs.get(loc);\n },\n\n seedFrom(entries, loaderMap) {\n for (const [loc, entry] of entries) {\n catalogs.set(loc, entry.clone());\n known.add(loc);\n }\n\n for (const [loc, loader] of loaderMap) {\n loaders.set(loc, loader);\n known.add(loc);\n }\n },\n\n snapshotCatalogs() {\n return catalogs as ReadonlyMap<Locale, CatalogEntry>;\n },\n\n snapshotLoaders() {\n return loaders as ReadonlyMap<Locale, Loader<M>>;\n },\n };\n}\n"],"mappings":"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"}
|
package/dist/_catalog-store.d.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { NamespaceStore } from './_namespace-store';
|
|
2
|
-
import { CatalogEntry, type Messages } from './_catalog';
|
|
3
|
-
export type Locale = string;
|
|
4
|
-
export type Loader<M extends Messages = Messages> = () => Promise<M>;
|
|
5
|
-
export type LocaleSource<M extends Messages = Messages> = M | Loader<M>;
|
|
6
|
-
export declare function validateCatalogInDev(loc: Locale, messages: Messages): void;
|
|
7
|
-
export type CatalogStore<M extends Messages = Messages> = {
|
|
8
|
-
dispose(): void;
|
|
9
|
-
isLoaded(loc: Locale): boolean;
|
|
10
|
-
isRegistered(loc: Locale): boolean;
|
|
11
|
-
/** All registered locale keys in insertion order. */
|
|
12
|
-
knownLocales(): readonly Locale[];
|
|
13
|
-
/** Callback invoked whenever a catalog changes (drives bump/notify). */
|
|
14
|
-
onChange: ((loc: Locale) => void) | undefined;
|
|
15
|
-
/** Patch a locale catalog with additional flat messages (used by loadNamespace). */
|
|
16
|
-
patch(loc: Locale, messages: Messages): Promise<void>;
|
|
17
|
-
/** Pre-load a locale catalog without switching. */
|
|
18
|
-
preload(loc: Locale): Promise<void>;
|
|
19
|
-
/** Register (or replace) a locale's source. Returns a Promise that resolves when the catalog is loaded. */
|
|
20
|
-
register(loc: Locale, source: LocaleSource<M>, nsStore: NamespaceStore): Promise<void>;
|
|
21
|
-
/** Resolve a compiled CatalogEntry for a locale (undefined if not loaded). */
|
|
22
|
-
resolve(loc: Locale): CatalogEntry | undefined;
|
|
23
|
-
/**
|
|
24
|
-
* Seed the store with pre-compiled entries from a parent fork.
|
|
25
|
-
* Called during fork() — compiled templates are shared by reference.
|
|
26
|
-
*/
|
|
27
|
-
seedFrom(entries: ReadonlyMap<Locale, CatalogEntry>, loaderMap: ReadonlyMap<Locale, Loader<M>>): void;
|
|
28
|
-
/** Snapshot of the raw catalogs map — used for SSR serialization (`getState()`) and fork seeding. */
|
|
29
|
-
snapshotCatalogs(): ReadonlyMap<Locale, CatalogEntry>;
|
|
30
|
-
/** Snapshot of the pending (not-yet-resolved) loaders map — used for fork seeding. */
|
|
31
|
-
snapshotLoaders(): ReadonlyMap<Locale, Loader<M>>;
|
|
32
|
-
};
|
|
33
|
-
export declare function createCatalogStore<M extends Messages = Messages>(disposed: () => boolean): CatalogStore<M>;
|
|
34
|
-
//# sourceMappingURL=_catalog-store.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_catalog-store.d.ts","sourceRoot":"","sources":["../src/_catalog-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,KAAK,QAAQ,EAAkB,MAAM,YAAY,CAAC;AAIzE,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAC5B,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;AACrE,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AAexE,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAQ1E;AAED,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI;IACxD,OAAO,IAAI,IAAI,CAAC;IAChB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACnC,qDAAqD;IACrD,YAAY,IAAI,SAAS,MAAM,EAAE,CAAC;IAClC,wEAAwE;IACxE,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC9C,oFAAoF;IACpF,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,mDAAmD;IACnD,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,2GAA2G;IAC3G,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvF,8EAA8E;IAC9E,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;IAC/C;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IACtG,qGAAqG;IACrG,gBAAgB,IAAI,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACtD,sFAAsF;IACtF,eAAe,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;CACnD,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,EAAE,QAAQ,EAAE,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,CAuK1G"}
|
package/dist/_catalog-store.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { devOnly as e, warn as t } from "./_dev.js";
|
|
2
|
-
import { CatalogEntry as n, flattenStrings as r } from "./_catalog.js";
|
|
3
|
-
import { LinguaMissingLocaleError as i, checkDisposed as a, checkDisposedAsync as o } from "./errors.js";
|
|
4
|
-
//#region src/_catalog-store.ts
|
|
5
|
-
function s(n, r) {
|
|
6
|
-
e(() => {
|
|
7
|
-
import("./validate.js").then(({ validateCatalog: e }) => {
|
|
8
|
-
for (let i of e(r, n)) t(`catalog('${n}'): missing plural form '${i.form}' for key '${i.key}'.`);
|
|
9
|
-
});
|
|
10
|
-
});
|
|
11
|
-
}
|
|
12
|
-
function c(e) {
|
|
13
|
-
let c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Set(), f, p = (e, t) => {
|
|
14
|
-
let r = c.get(e);
|
|
15
|
-
r || (r = new n(), c.set(e, r)), r.setAll(t);
|
|
16
|
-
}, m = (t) => {
|
|
17
|
-
let n = o(e());
|
|
18
|
-
if (n) return n;
|
|
19
|
-
if (c.has(t)) return Promise.resolve();
|
|
20
|
-
let a = l.get(t);
|
|
21
|
-
if (!a) return Promise.reject(new i(`Missing locale source for "${t}".`));
|
|
22
|
-
let d = u.get(t);
|
|
23
|
-
if (d) return d;
|
|
24
|
-
let m = a().then((e) => {
|
|
25
|
-
l.get(t) === a && (l.delete(t), p(t, r(e)), s(t, e), u.delete(t), f?.(t));
|
|
26
|
-
}, (e) => {
|
|
27
|
-
throw l.get(t) === a && u.delete(t), e;
|
|
28
|
-
});
|
|
29
|
-
return u.set(t, m), m;
|
|
30
|
-
};
|
|
31
|
-
return {
|
|
32
|
-
dispose() {
|
|
33
|
-
c.clear(), l.clear(), u.clear(), d.clear(), f = void 0;
|
|
34
|
-
},
|
|
35
|
-
isLoaded(e) {
|
|
36
|
-
return c.has(e);
|
|
37
|
-
},
|
|
38
|
-
isRegistered(e) {
|
|
39
|
-
return d.has(e);
|
|
40
|
-
},
|
|
41
|
-
knownLocales() {
|
|
42
|
-
return [...d];
|
|
43
|
-
},
|
|
44
|
-
get onChange() {
|
|
45
|
-
return f;
|
|
46
|
-
},
|
|
47
|
-
set onChange(e) {
|
|
48
|
-
f = e;
|
|
49
|
-
},
|
|
50
|
-
patch(t, n) {
|
|
51
|
-
return o(e()) || (l.has(t) ? m(t).then(() => {
|
|
52
|
-
e() || (p(t, r(n)), d.add(t), f?.(t));
|
|
53
|
-
}) : (p(t, r(n)), d.add(t), f?.(t), Promise.resolve()));
|
|
54
|
-
},
|
|
55
|
-
preload: m,
|
|
56
|
-
register(n, i, o) {
|
|
57
|
-
a(e()), u.delete(n), d.add(n);
|
|
58
|
-
let h = o.clearLocale(n);
|
|
59
|
-
h.length > 0 && t(`register('${n}') cleared loaded namespace markers for: ${h.map((e) => `'${e}'`).join(", ")}. Call loadNamespace() again to reload.`);
|
|
60
|
-
let g;
|
|
61
|
-
return typeof i == "function" ? (l.set(n, i), c.delete(n), g = m(n)) : (l.delete(n), c.delete(n), p(n, r(i)), s(n, i), g = Promise.resolve(), f?.(n)), g;
|
|
62
|
-
},
|
|
63
|
-
resolve(e) {
|
|
64
|
-
return c.get(e);
|
|
65
|
-
},
|
|
66
|
-
seedFrom(e, t) {
|
|
67
|
-
for (let [t, n] of e) c.set(t, n.clone()), d.add(t);
|
|
68
|
-
for (let [e, n] of t) l.set(e, n), d.add(e);
|
|
69
|
-
},
|
|
70
|
-
snapshotCatalogs() {
|
|
71
|
-
return c;
|
|
72
|
-
},
|
|
73
|
-
snapshotLoaders() {
|
|
74
|
-
return l;
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
//#endregion
|
|
79
|
-
export { c as createCatalogStore, s as validateCatalogInDev };
|
|
80
|
-
|
|
81
|
-
//# sourceMappingURL=_catalog-store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_catalog-store.js","names":[],"sources":["../src/_catalog-store.ts"],"sourcesContent":["// Internal — not part of the public API.\n// Owns all locale → CatalogEntry state, loaders, and in-flight loading tasks.\n\nimport type { NamespaceStore } from './_namespace-store';\n\nimport { CatalogEntry, type Messages, flattenStrings } from './_catalog';\nimport { devOnly, warn } from './_dev';\nimport { LinguaMissingLocaleError, checkDisposed, checkDisposedAsync } from './errors';\n\nexport type Locale = string;\nexport type Loader<M extends Messages = Messages> = () => Promise<M>;\nexport type LocaleSource<M extends Messages = Messages> = M | Loader<M>;\n\n// Dev-only feedback for the same catalog-authoring mistakes `validateCatalog()` (the CI/build\n// tool at `@vielzeug/lingua/validate`) already catches — most projects never wire that up, so\n// this gives the same signal for free, in the console the author is already watching, the\n// moment a full catalog becomes available: at `createI18n({ catalogs })` construction, via\n// `register()`, or once an async loader resolves. Not run for `patch()` — a namespace overlay is\n// expected to add only a handful of keys, not a complete plural set.\n//\n// Dynamic import, not a static one: `validate.ts`'s own docs promise it stays out of production\n// bundles. A static `import { validateCatalog } from './validate'` here would pull it into every\n// consumer's main bundle regardless of `devOnly()`'s runtime check — bundlers only eliminate\n// that dead branch if the consumer's own build defines `__LINGUA_PROD__` as a literal. The\n// dynamic import keeps validate.ts a genuinely separate, lazily-fetched chunk that's never\n// requested at all when `isDev` is false, no consumer bundler config required.\nexport function validateCatalogInDev(loc: Locale, messages: Messages): void {\n devOnly(() => {\n void import('./validate').then(({ validateCatalog }) => {\n for (const w of validateCatalog(messages, loc)) {\n warn(`catalog('${loc}'): missing plural form '${w.form}' for key '${w.key}'.`);\n }\n });\n });\n}\n\nexport type CatalogStore<M extends Messages = Messages> = {\n dispose(): void;\n isLoaded(loc: Locale): boolean;\n isRegistered(loc: Locale): boolean;\n /** All registered locale keys in insertion order. */\n knownLocales(): readonly Locale[];\n /** Callback invoked whenever a catalog changes (drives bump/notify). */\n onChange: ((loc: Locale) => void) | undefined;\n /** Patch a locale catalog with additional flat messages (used by loadNamespace). */\n patch(loc: Locale, messages: Messages): Promise<void>;\n /** Pre-load a locale catalog without switching. */\n preload(loc: Locale): Promise<void>;\n /** Register (or replace) a locale's source. Returns a Promise that resolves when the catalog is loaded. */\n register(loc: Locale, source: LocaleSource<M>, nsStore: NamespaceStore): Promise<void>;\n /** Resolve a compiled CatalogEntry for a locale (undefined if not loaded). */\n resolve(loc: Locale): CatalogEntry | undefined;\n /**\n * Seed the store with pre-compiled entries from a parent fork.\n * Called during fork() — compiled templates are shared by reference.\n */\n seedFrom(entries: ReadonlyMap<Locale, CatalogEntry>, loaderMap: ReadonlyMap<Locale, Loader<M>>): void;\n /** Snapshot of the raw catalogs map — used for SSR serialization (`getState()`) and fork seeding. */\n snapshotCatalogs(): ReadonlyMap<Locale, CatalogEntry>;\n /** Snapshot of the pending (not-yet-resolved) loaders map — used for fork seeding. */\n snapshotLoaders(): ReadonlyMap<Locale, Loader<M>>;\n};\n\nexport function createCatalogStore<M extends Messages = Messages>(disposed: () => boolean): CatalogStore<M> {\n const catalogs = new Map<Locale, CatalogEntry>();\n const loaders = new Map<Locale, Loader<M>>();\n const loadingTasks = new Map<Locale, Promise<void>>();\n const known = new Set<Locale>();\n\n let onChange: ((loc: Locale) => void) | undefined;\n\n const registerRaw = (normalized: Locale, flat: Map<string, string>): void => {\n let entry = catalogs.get(normalized);\n\n if (!entry) {\n entry = new CatalogEntry();\n catalogs.set(normalized, entry);\n }\n\n entry.setAll(flat);\n };\n\n const preload = (loc: Locale): Promise<void> => {\n const early = checkDisposedAsync(disposed());\n\n if (early) return early;\n\n if (catalogs.has(loc)) return Promise.resolve();\n\n const loader = loaders.get(loc);\n\n if (!loader) return Promise.reject(new LinguaMissingLocaleError(`Missing locale source for \"${loc}\".`));\n\n const existing = loadingTasks.get(loc);\n\n if (existing) return existing;\n\n const task = loader().then(\n (messages) => {\n if (loaders.get(loc) !== loader) return;\n\n loaders.delete(loc);\n registerRaw(loc, flattenStrings(messages));\n validateCatalogInDev(loc, messages);\n loadingTasks.delete(loc);\n onChange?.(loc);\n },\n (error: unknown) => {\n if (loaders.get(loc) === loader) loadingTasks.delete(loc);\n\n throw error;\n },\n );\n\n loadingTasks.set(loc, task);\n\n return task;\n };\n\n return {\n dispose() {\n catalogs.clear();\n loaders.clear();\n loadingTasks.clear();\n known.clear();\n onChange = undefined;\n },\n\n isLoaded(loc) {\n return catalogs.has(loc);\n },\n\n isRegistered(loc) {\n return known.has(loc);\n },\n\n knownLocales() {\n return [...known];\n },\n\n get onChange() {\n return onChange;\n },\n\n set onChange(fn: ((loc: Locale) => void) | undefined) {\n onChange = fn;\n },\n\n patch(loc, messages) {\n const early = checkDisposedAsync(disposed());\n\n if (early) return early;\n\n if (loaders.has(loc)) {\n return preload(loc).then(() => {\n if (disposed()) return;\n\n registerRaw(loc, flattenStrings(messages));\n known.add(loc);\n onChange?.(loc);\n });\n }\n\n registerRaw(loc, flattenStrings(messages));\n known.add(loc);\n onChange?.(loc);\n\n return Promise.resolve();\n },\n\n preload,\n\n register(loc, source, nsStore) {\n checkDisposed(disposed());\n\n loadingTasks.delete(loc);\n known.add(loc);\n\n // Clear namespace loaded-markers for this locale so namespaces can be re-applied\n // after catalog replacement.\n const clearedNs = nsStore.clearLocale(loc);\n\n if (clearedNs.length > 0) {\n warn(\n `register('${loc}') cleared loaded namespace markers for: ${clearedNs.map((ns) => `'${ns}'`).join(', ')}. Call loadNamespace() again to reload.`,\n );\n }\n\n let loadPromise: Promise<void>;\n\n if (typeof source === 'function') {\n loaders.set(loc, source as Loader<M>);\n catalogs.delete(loc);\n loadPromise = preload(loc);\n } else {\n loaders.delete(loc);\n catalogs.delete(loc);\n registerRaw(loc, flattenStrings(source as M));\n validateCatalogInDev(loc, source as M);\n loadPromise = Promise.resolve();\n onChange?.(loc);\n }\n\n return loadPromise;\n },\n\n resolve(loc) {\n return catalogs.get(loc);\n },\n\n seedFrom(entries, loaderMap) {\n for (const [loc, entry] of entries) {\n catalogs.set(loc, entry.clone());\n known.add(loc);\n }\n\n for (const [loc, loader] of loaderMap) {\n loaders.set(loc, loader);\n known.add(loc);\n }\n },\n\n snapshotCatalogs() {\n return catalogs as ReadonlyMap<Locale, CatalogEntry>;\n },\n\n snapshotLoaders() {\n return loaders as ReadonlyMap<Locale, Loader<M>>;\n },\n };\n}\n"],"mappings":"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"}
|
package/dist/_chain.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("./errors.cjs");function t(){return{canon:new Map,chain:new Map,plural:new Map}}function n(t,n){let r=n.canon.get(t);if(r!==void 0)return r;let i;try{[i]=Intl.getCanonicalLocales(t)}catch{}if(!i)throw new e.LinguaInvalidLocaleError(`Invalid BCP 47 locale tag: "${t}".`);return n.canon.set(t,i),i}function r(e,t,n,r){let i=`${e}:${n?`ordinal`:`cardinal`}`,a=r.plural.get(i);return a||(a=new Intl.PluralRules(e,{type:n?`ordinal`:`cardinal`}),r.plural.set(i,a)),a.select(t)}function i(e,t){let n=new Set;for(let r of[e,...t]){n.add(r);let e=r.split(`-`);for(let t=e.length-1;t>0;t--)n.add(e.slice(0,t).join(`-`))}return{chain:[...n],set:n}}function a(e,t,n){let r=t.length===0?e:`${e}|${t.join(`,`)}`,a=n.chain.get(r);if(a)return a;let o=i(e,t);return n.chain.set(r,o),o}exports.buildLocaleChain=a,exports.canon=n,exports.createLocaleCaches=t,exports.selectPluralForm=r;
|
|
2
|
-
//# sourceMappingURL=_chain.cjs.map
|
package/dist/_chain.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_chain.cjs","names":[],"sources":["../src/_chain.ts"],"sourcesContent":["// Internal — not part of the public API.\n// Locale chain building, canonicalization, and plural-rules selection.\n// All caches are per-instance — no shared module-level state.\n\nimport { LinguaInvalidLocaleError } from './errors';\n\nexport type Locale = string;\n\n// ─── Per-instance caches ──────────────────────────────────────────────────────\n\nexport type LocaleCaches = {\n canon: Map<string, string>;\n chain: Map<string, { chain: Locale[]; set: Set<Locale> }>;\n plural: Map<string, Intl.PluralRules>;\n};\n\nexport function createLocaleCaches(): LocaleCaches {\n return { canon: new Map(), chain: new Map(), plural: new Map() };\n}\n\n// ─── Canon ────────────────────────────────────────────────────────────────────\n\nexport function canon(locale: string, cache: LocaleCaches): string {\n const cached = cache.canon.get(locale);\n\n if (cached !== undefined) return cached;\n\n let canonical: string | undefined;\n\n try {\n [canonical] = Intl.getCanonicalLocales(locale);\n } catch {\n // Invalid BCP 47 tag — canonical stays undefined, guard below throws.\n }\n\n if (!canonical) throw new LinguaInvalidLocaleError(`Invalid BCP 47 locale tag: \"${locale}\".`);\n\n cache.canon.set(locale, canonical);\n\n return canonical;\n}\n\n// ─── Plural form selection ────────────────────────────────────────────────────\n\nexport function selectPluralForm(locale: Locale, count: number, ordinal: boolean, cache: LocaleCaches): string {\n const key = `${locale}:${ordinal ? 'ordinal' : 'cardinal'}`;\n let rules = cache.plural.get(key);\n\n if (!rules) {\n rules = new Intl.PluralRules(locale, { type: ordinal ? 'ordinal' : 'cardinal' });\n cache.plural.set(key, rules);\n }\n\n return rules.select(count);\n}\n\n// ─── Locale chain ─────────────────────────────────────────────────────────────\n\nfunction buildLocaleChainRaw(locale: Locale, fallback: Locale[]): { chain: Locale[]; set: Set<Locale> } {\n const set = new Set<Locale>();\n\n for (const value of [locale, ...fallback]) {\n set.add(value);\n\n const parts = value.split('-');\n\n for (let i = parts.length - 1; i > 0; i--) {\n set.add(parts.slice(0, i).join('-'));\n }\n }\n\n return { chain: [...set], set };\n}\n\n/**\n * Build a locale fallback chain, memoized per `(locale, fallback)` key using a provided cache.\n * The cache is per-instance (lives on LocaleCaches) — no shared module-level state.\n */\nexport function buildLocaleChain(\n locale: Locale,\n fallback: Locale[],\n cache: LocaleCaches,\n): { chain: Locale[]; set: Set<Locale> } {\n const key = fallback.length === 0 ? locale : `${locale}|${fallback.join(',')}`;\n const cached = cache.chain.get(key);\n\n if (cached) return cached;\n\n const result = buildLocaleChainRaw(locale, fallback);\n\n cache.chain.set(key, result);\n\n return result;\n}\n"],"mappings":"gCAgBA,SAAgB,GAAmC,CACjD,MAAO,CAAE,MAAO,IAAI,IAAO,MAAO,IAAI,IAAO,OAAQ,IAAI,GAAM,CACjE,CAIA,SAAgB,EAAM,EAAgB,EAA6B,CACjE,IAAM,EAAS,EAAM,MAAM,IAAI,CAAM,EAErC,GAAI,IAAW,IAAA,GAAW,OAAO,EAEjC,IAAI,EAEJ,GAAI,CACF,CAAC,GAAa,KAAK,oBAAoB,CAAM,CAC/C,MAAQ,CAER,CAEA,GAAI,CAAC,EAAW,MAAM,IAAI,EAAA,yBAAyB,+BAA+B,EAAO,GAAG,EAI5F,OAFA,EAAM,MAAM,IAAI,EAAQ,CAAS,EAE1B,CACT,CAIA,SAAgB,EAAiB,EAAgB,EAAe,EAAkB,EAA6B,CAC7G,IAAM,EAAM,GAAG,EAAO,GAAG,EAAU,UAAY,aAC3C,EAAQ,EAAM,OAAO,IAAI,CAAG,EAOhC,OALK,IACH,EAAQ,IAAI,KAAK,YAAY,EAAQ,CAAE,KAAM,EAAU,UAAY,UAAW,CAAC,EAC/E,EAAM,OAAO,IAAI,EAAK,CAAK,GAGtB,EAAM,OAAO,CAAK,CAC3B,CAIA,SAAS,EAAoB,EAAgB,EAA2D,CACtG,IAAM,EAAM,IAAI,IAEhB,IAAK,IAAM,IAAS,CAAC,EAAQ,GAAG,CAAQ,EAAG,CACzC,EAAI,IAAI,CAAK,EAEb,IAAM,EAAQ,EAAM,MAAM,GAAG,EAE7B,IAAK,IAAI,EAAI,EAAM,OAAS,EAAG,EAAI,EAAG,IACpC,EAAI,IAAI,EAAM,MAAM,EAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAEvC,CAEA,MAAO,CAAE,MAAO,CAAC,GAAG,CAAG,EAAG,KAAI,CAChC,CAMA,SAAgB,EACd,EACA,EACA,EACuC,CACvC,IAAM,EAAM,EAAS,SAAW,EAAI,EAAS,GAAG,EAAO,GAAG,EAAS,KAAK,GAAG,IACrE,EAAS,EAAM,MAAM,IAAI,CAAG,EAElC,GAAI,EAAQ,OAAO,EAEnB,IAAM,EAAS,EAAoB,EAAQ,CAAQ,EAInD,OAFA,EAAM,MAAM,IAAI,EAAK,CAAM,EAEpB,CACT"}
|
package/dist/_chain.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export type Locale = string;
|
|
2
|
-
export type LocaleCaches = {
|
|
3
|
-
canon: Map<string, string>;
|
|
4
|
-
chain: Map<string, {
|
|
5
|
-
chain: Locale[];
|
|
6
|
-
set: Set<Locale>;
|
|
7
|
-
}>;
|
|
8
|
-
plural: Map<string, Intl.PluralRules>;
|
|
9
|
-
};
|
|
10
|
-
export declare function createLocaleCaches(): LocaleCaches;
|
|
11
|
-
export declare function canon(locale: string, cache: LocaleCaches): string;
|
|
12
|
-
export declare function selectPluralForm(locale: Locale, count: number, ordinal: boolean, cache: LocaleCaches): string;
|
|
13
|
-
/**
|
|
14
|
-
* Build a locale fallback chain, memoized per `(locale, fallback)` key using a provided cache.
|
|
15
|
-
* The cache is per-instance (lives on LocaleCaches) — no shared module-level state.
|
|
16
|
-
*/
|
|
17
|
-
export declare function buildLocaleChain(locale: Locale, fallback: Locale[], cache: LocaleCaches): {
|
|
18
|
-
chain: Locale[];
|
|
19
|
-
set: Set<Locale>;
|
|
20
|
-
};
|
|
21
|
-
//# sourceMappingURL=_chain.d.ts.map
|
package/dist/_chain.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_chain.d.ts","sourceRoot":"","sources":["../src/_chain.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAI5B,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;KAAE,CAAC,CAAC;IAC1D,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;CACvC,CAAC;AAEF,wBAAgB,kBAAkB,IAAI,YAAY,CAEjD;AAID,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,MAAM,CAkBjE;AAID,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,GAAG,MAAM,CAU7G;AAoBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAAE,EAClB,KAAK,EAAE,YAAY,GAClB;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAAE,CAWvC"}
|
package/dist/_chain.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { LinguaInvalidLocaleError as e } from "./errors.js";
|
|
2
|
-
//#region src/_chain.ts
|
|
3
|
-
function t() {
|
|
4
|
-
return {
|
|
5
|
-
canon: /* @__PURE__ */ new Map(),
|
|
6
|
-
chain: /* @__PURE__ */ new Map(),
|
|
7
|
-
plural: /* @__PURE__ */ new Map()
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
function n(t, n) {
|
|
11
|
-
let r = n.canon.get(t);
|
|
12
|
-
if (r !== void 0) return r;
|
|
13
|
-
let i;
|
|
14
|
-
try {
|
|
15
|
-
[i] = Intl.getCanonicalLocales(t);
|
|
16
|
-
} catch {}
|
|
17
|
-
if (!i) throw new e(`Invalid BCP 47 locale tag: "${t}".`);
|
|
18
|
-
return n.canon.set(t, i), i;
|
|
19
|
-
}
|
|
20
|
-
function r(e, t, n, r) {
|
|
21
|
-
let i = `${e}:${n ? "ordinal" : "cardinal"}`, a = r.plural.get(i);
|
|
22
|
-
return a || (a = new Intl.PluralRules(e, { type: n ? "ordinal" : "cardinal" }), r.plural.set(i, a)), a.select(t);
|
|
23
|
-
}
|
|
24
|
-
function i(e, t) {
|
|
25
|
-
let n = /* @__PURE__ */ new Set();
|
|
26
|
-
for (let r of [e, ...t]) {
|
|
27
|
-
n.add(r);
|
|
28
|
-
let e = r.split("-");
|
|
29
|
-
for (let t = e.length - 1; t > 0; t--) n.add(e.slice(0, t).join("-"));
|
|
30
|
-
}
|
|
31
|
-
return {
|
|
32
|
-
chain: [...n],
|
|
33
|
-
set: n
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
function a(e, t, n) {
|
|
37
|
-
let r = t.length === 0 ? e : `${e}|${t.join(",")}`, a = n.chain.get(r);
|
|
38
|
-
if (a) return a;
|
|
39
|
-
let o = i(e, t);
|
|
40
|
-
return n.chain.set(r, o), o;
|
|
41
|
-
}
|
|
42
|
-
//#endregion
|
|
43
|
-
export { a as buildLocaleChain, n as canon, t as createLocaleCaches, r as selectPluralForm };
|
|
44
|
-
|
|
45
|
-
//# sourceMappingURL=_chain.js.map
|
package/dist/_chain.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_chain.js","names":[],"sources":["../src/_chain.ts"],"sourcesContent":["// Internal — not part of the public API.\n// Locale chain building, canonicalization, and plural-rules selection.\n// All caches are per-instance — no shared module-level state.\n\nimport { LinguaInvalidLocaleError } from './errors';\n\nexport type Locale = string;\n\n// ─── Per-instance caches ──────────────────────────────────────────────────────\n\nexport type LocaleCaches = {\n canon: Map<string, string>;\n chain: Map<string, { chain: Locale[]; set: Set<Locale> }>;\n plural: Map<string, Intl.PluralRules>;\n};\n\nexport function createLocaleCaches(): LocaleCaches {\n return { canon: new Map(), chain: new Map(), plural: new Map() };\n}\n\n// ─── Canon ────────────────────────────────────────────────────────────────────\n\nexport function canon(locale: string, cache: LocaleCaches): string {\n const cached = cache.canon.get(locale);\n\n if (cached !== undefined) return cached;\n\n let canonical: string | undefined;\n\n try {\n [canonical] = Intl.getCanonicalLocales(locale);\n } catch {\n // Invalid BCP 47 tag — canonical stays undefined, guard below throws.\n }\n\n if (!canonical) throw new LinguaInvalidLocaleError(`Invalid BCP 47 locale tag: \"${locale}\".`);\n\n cache.canon.set(locale, canonical);\n\n return canonical;\n}\n\n// ─── Plural form selection ────────────────────────────────────────────────────\n\nexport function selectPluralForm(locale: Locale, count: number, ordinal: boolean, cache: LocaleCaches): string {\n const key = `${locale}:${ordinal ? 'ordinal' : 'cardinal'}`;\n let rules = cache.plural.get(key);\n\n if (!rules) {\n rules = new Intl.PluralRules(locale, { type: ordinal ? 'ordinal' : 'cardinal' });\n cache.plural.set(key, rules);\n }\n\n return rules.select(count);\n}\n\n// ─── Locale chain ─────────────────────────────────────────────────────────────\n\nfunction buildLocaleChainRaw(locale: Locale, fallback: Locale[]): { chain: Locale[]; set: Set<Locale> } {\n const set = new Set<Locale>();\n\n for (const value of [locale, ...fallback]) {\n set.add(value);\n\n const parts = value.split('-');\n\n for (let i = parts.length - 1; i > 0; i--) {\n set.add(parts.slice(0, i).join('-'));\n }\n }\n\n return { chain: [...set], set };\n}\n\n/**\n * Build a locale fallback chain, memoized per `(locale, fallback)` key using a provided cache.\n * The cache is per-instance (lives on LocaleCaches) — no shared module-level state.\n */\nexport function buildLocaleChain(\n locale: Locale,\n fallback: Locale[],\n cache: LocaleCaches,\n): { chain: Locale[]; set: Set<Locale> } {\n const key = fallback.length === 0 ? locale : `${locale}|${fallback.join(',')}`;\n const cached = cache.chain.get(key);\n\n if (cached) return cached;\n\n const result = buildLocaleChainRaw(locale, fallback);\n\n cache.chain.set(key, result);\n\n return result;\n}\n"],"mappings":";;AAgBA,SAAgB,IAAmC;CACjD,OAAO;EAAE,uBAAO,IAAI,IAAI;EAAG,uBAAO,IAAI,IAAI;EAAG,wBAAQ,IAAI,IAAI;CAAE;AACjE;AAIA,SAAgB,EAAM,GAAgB,GAA6B;CACjE,IAAM,IAAS,EAAM,MAAM,IAAI,CAAM;CAErC,IAAI,MAAW,KAAA,GAAW,OAAO;CAEjC,IAAI;CAEJ,IAAI;EACF,CAAC,KAAa,KAAK,oBAAoB,CAAM;CAC/C,QAAQ,CAER;CAEA,IAAI,CAAC,GAAW,MAAM,IAAI,EAAyB,+BAA+B,EAAO,GAAG;CAI5F,OAFA,EAAM,MAAM,IAAI,GAAQ,CAAS,GAE1B;AACT;AAIA,SAAgB,EAAiB,GAAgB,GAAe,GAAkB,GAA6B;CAC7G,IAAM,IAAM,GAAG,EAAO,GAAG,IAAU,YAAY,cAC3C,IAAQ,EAAM,OAAO,IAAI,CAAG;CAOhC,OALK,MACH,IAAQ,IAAI,KAAK,YAAY,GAAQ,EAAE,MAAM,IAAU,YAAY,WAAW,CAAC,GAC/E,EAAM,OAAO,IAAI,GAAK,CAAK,IAGtB,EAAM,OAAO,CAAK;AAC3B;AAIA,SAAS,EAAoB,GAAgB,GAA2D;CACtG,IAAM,oBAAM,IAAI,IAAY;CAE5B,KAAK,IAAM,KAAS,CAAC,GAAQ,GAAG,CAAQ,GAAG;EACzC,EAAI,IAAI,CAAK;EAEb,IAAM,IAAQ,EAAM,MAAM,GAAG;EAE7B,KAAK,IAAI,IAAI,EAAM,SAAS,GAAG,IAAI,GAAG,KACpC,EAAI,IAAI,EAAM,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;CAEvC;CAEA,OAAO;EAAE,OAAO,CAAC,GAAG,CAAG;EAAG;CAAI;AAChC;AAMA,SAAgB,EACd,GACA,GACA,GACuC;CACvC,IAAM,IAAM,EAAS,WAAW,IAAI,IAAS,GAAG,EAAO,GAAG,EAAS,KAAK,GAAG,KACrE,IAAS,EAAM,MAAM,IAAI,CAAG;CAElC,IAAI,GAAQ,OAAO;CAEnB,IAAM,IAAS,EAAoB,GAAQ,CAAQ;CAInD,OAFA,EAAM,MAAM,IAAI,GAAK,CAAM,GAEpB;AACT"}
|
package/dist/_constants.cjs
DELETED
package/dist/_constants.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_constants.cjs","names":[],"sources":["../src/_constants.ts"],"sourcesContent":["// Shared constants used by both i18n.ts and validate.ts.\n// Not part of the public API — internal module only.\n\nexport const UNSAFE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\nexport const CLDR_FORMS = new Set(['zero', 'one', 'two', 'few', 'many', 'other']);\n"],"mappings":"AAGA,IAAa,EAAc,IAAI,IAAI,CAAC,YAAa,cAAe,WAAW,CAAC,EAE/D,EAAa,IAAI,IAAI,CAAC,OAAQ,MAAO,MAAO,MAAO,OAAQ,OAAO,CAAC"}
|
package/dist/_constants.d.ts
DELETED
package/dist/_constants.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_constants.d.ts","sourceRoot":"","sources":["../src/_constants.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW,aAAqD,CAAC;AAE9E,eAAO,MAAM,UAAU,aAA0D,CAAC"}
|
package/dist/_constants.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
//#region src/_constants.ts
|
|
2
|
-
var e = /* @__PURE__ */ new Set([
|
|
3
|
-
"__proto__",
|
|
4
|
-
"constructor",
|
|
5
|
-
"prototype"
|
|
6
|
-
]), t = /* @__PURE__ */ new Set([
|
|
7
|
-
"zero",
|
|
8
|
-
"one",
|
|
9
|
-
"two",
|
|
10
|
-
"few",
|
|
11
|
-
"many",
|
|
12
|
-
"other"
|
|
13
|
-
]);
|
|
14
|
-
//#endregion
|
|
15
|
-
export { t as CLDR_FORMS, e as UNSAFE_KEYS };
|
|
16
|
-
|
|
17
|
-
//# sourceMappingURL=_constants.js.map
|
package/dist/_constants.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_constants.js","names":[],"sources":["../src/_constants.ts"],"sourcesContent":["// Shared constants used by both i18n.ts and validate.ts.\n// Not part of the public API — internal module only.\n\nexport const UNSAFE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\nexport const CLDR_FORMS = new Set(['zero', 'one', 'two', 'few', 'many', 'other']);\n"],"mappings":";AAGA,IAAa,oBAAc,IAAI,IAAI;CAAC;CAAa;CAAe;AAAW,CAAC,GAE/D,oBAAa,IAAI,IAAI;CAAC;CAAQ;CAAO;CAAO;CAAO;CAAQ;AAAO,CAAC"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("./errors.cjs");function t(t){let n=new Map,r=new Map,i=new Map;return{clearLocale(e){let t=[];for(let[n,i]of r.entries())i.delete(e)&&t.push(n);return t},dispose(){n.clear(),r.clear(),i.clear()},isLoaded(e,t){return r.get(e)?.has(t)??!1},isRegistered(e){return n.has(e)},loadNamespace(a,o,s){let c=e.checkDisposedAsync(t());if(c)return c;let l=n.get(a);if(!l)return Promise.reject(new e.LinguaNamespaceMissingError(`Namespace '${a}' is not registered. Call registerNamespace() first.`));if(r.get(a)?.has(o))return Promise.resolve();let u=i.get(a)?.get(o);if(u)return u;let d=l(o).then(e=>s(o,e)).then(()=>{let e=r.get(a);e||(e=new Set,r.set(a,e)),e.add(o),i.get(a)?.delete(o)},e=>{throw i.get(a)?.delete(o),e});return i.has(a)||i.set(a,new Map),i.get(a).set(o,d),d},registerNamespace(r,i){e.checkDisposed(t()),n.set(r,i)},seedFrom(e){for(let[t,r]of e.snapshotRegistry())n.set(t,r);for(let[t,n]of e.snapshotLoaded())r.set(t,new Set(n))},snapshotLoaded(){return r},snapshotRegistry(){return n}}}exports.createNamespaceStore=t;
|
|
2
|
-
//# sourceMappingURL=_namespace-store.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_namespace-store.cjs","names":[],"sources":["../src/_namespace-store.ts"],"sourcesContent":["// Internal — not part of the public API.\n// Owns namespace factory registry, per-locale loaded markers, and in-flight namespace tasks.\n\nimport type { Messages } from './_catalog';\n\nimport { LinguaNamespaceMissingError, checkDisposed, checkDisposedAsync } from './errors';\n\nexport type Locale = string;\nexport type NamespaceFactory<M extends Messages = Messages> = (locale: Locale) => Promise<M>;\n\nexport type NamespaceStore<M extends Messages = Messages> = {\n /**\n * Remove loaded-markers for a locale across all namespaces.\n * Called by CatalogStore.register() when a catalog is replaced.\n * Returns the list of namespace names whose markers were cleared.\n */\n clearLocale(loc: Locale): string[];\n dispose(): void;\n /** Returns true if the namespace has been loaded for the given locale. */\n isLoaded(ns: string, loc: Locale): boolean;\n /** Returns true if the namespace factory is registered. */\n isRegistered(ns: string): boolean;\n /**\n * Load a namespace for the given locale. Deduplicates concurrent and repeated calls.\n * The `patch` callback is responsible for merging the loaded messages into the catalog.\n */\n loadNamespace(ns: string, loc: Locale, patch: (loc: Locale, messages: Messages) => Promise<void>): Promise<void>;\n /** Register a namespace factory. Idempotent — re-registration updates the factory for future loads. */\n registerNamespace(ns: string, factory: NamespaceFactory<M>): void;\n /** Seed from a parent instance (fork). Copies loaded markers; registry is shared by reference. */\n seedFrom(parent: NamespaceStore<M>): void;\n /** Snapshot of loaded markers for fork() */\n snapshotLoaded(): ReadonlyMap<string, ReadonlySet<string>>;\n /** Snapshot of the registry for fork() */\n snapshotRegistry(): ReadonlyMap<string, NamespaceFactory<M>>;\n};\n\nexport function createNamespaceStore<M extends Messages = Messages>(disposed: () => boolean): NamespaceStore<M> {\n const registry = new Map<string, NamespaceFactory<M>>();\n // Two-level: Map<namespace, Set<locale>>\n const loaded = new Map<string, Set<string>>();\n const tasks = new Map<string, Map<string, Promise<void>>>();\n\n return {\n clearLocale(loc) {\n const cleared: string[] = [];\n\n for (const [ns, localeSet] of loaded.entries()) {\n if (localeSet.delete(loc)) cleared.push(ns);\n }\n\n return cleared;\n },\n\n dispose() {\n registry.clear();\n loaded.clear();\n tasks.clear();\n },\n\n isLoaded(ns, loc) {\n return loaded.get(ns)?.has(loc) ?? false;\n },\n\n isRegistered(ns) {\n return registry.has(ns);\n },\n\n loadNamespace(ns, loc, patch) {\n const early = checkDisposedAsync(disposed());\n\n if (early) return early;\n\n const factory = registry.get(ns);\n\n if (!factory) {\n return Promise.reject(\n new LinguaNamespaceMissingError(`Namespace '${ns}' is not registered. Call registerNamespace() first.`),\n );\n }\n\n if (loaded.get(ns)?.has(loc)) return Promise.resolve();\n\n const nsTasks = tasks.get(ns);\n const existing = nsTasks?.get(loc);\n\n if (existing) return existing;\n\n const task = factory(loc)\n .then((messages) => patch(loc, messages as Messages))\n .then(\n () => {\n let localeSet = loaded.get(ns);\n\n if (!localeSet) {\n localeSet = new Set();\n loaded.set(ns, localeSet);\n }\n\n localeSet.add(loc);\n tasks.get(ns)?.delete(loc);\n },\n (err: unknown) => {\n tasks.get(ns)?.delete(loc);\n throw err;\n },\n );\n\n if (!tasks.has(ns)) tasks.set(ns, new Map());\n\n tasks.get(ns)!.set(loc, task);\n\n return task;\n },\n\n registerNamespace(ns, factory) {\n checkDisposed(disposed());\n registry.set(ns, factory);\n },\n\n seedFrom(parent) {\n for (const [ns, factory] of parent.snapshotRegistry()) {\n registry.set(ns, factory);\n }\n\n for (const [ns, localeSet] of parent.snapshotLoaded()) {\n loaded.set(ns, new Set(localeSet));\n }\n },\n\n snapshotLoaded() {\n return loaded as ReadonlyMap<string, ReadonlySet<string>>;\n },\n\n snapshotRegistry() {\n return registry as ReadonlyMap<string, NamespaceFactory<M>>;\n },\n };\n}\n"],"mappings":"gCAqCA,SAAgB,EAAoD,EAA4C,CAC9G,IAAM,EAAW,IAAI,IAEf,EAAS,IAAI,IACb,EAAQ,IAAI,IAElB,MAAO,CACL,YAAY,EAAK,CACf,IAAM,EAAoB,CAAC,EAE3B,IAAK,GAAM,CAAC,EAAI,KAAc,EAAO,QAAQ,EACvC,EAAU,OAAO,CAAG,GAAG,EAAQ,KAAK,CAAE,EAG5C,OAAO,CACT,EAEA,SAAU,CACR,EAAS,MAAM,EACf,EAAO,MAAM,EACb,EAAM,MAAM,CACd,EAEA,SAAS,EAAI,EAAK,CAChB,OAAO,EAAO,IAAI,CAAE,CAAC,EAAE,IAAI,CAAG,GAAK,EACrC,EAEA,aAAa,EAAI,CACf,OAAO,EAAS,IAAI,CAAE,CACxB,EAEA,cAAc,EAAI,EAAK,EAAO,CAC5B,IAAM,EAAQ,EAAA,mBAAmB,EAAS,CAAC,EAE3C,GAAI,EAAO,OAAO,EAElB,IAAM,EAAU,EAAS,IAAI,CAAE,EAE/B,GAAI,CAAC,EACH,OAAO,QAAQ,OACb,IAAI,EAAA,4BAA4B,cAAc,EAAG,qDAAqD,CACxG,EAGF,GAAI,EAAO,IAAI,CAAE,CAAC,EAAE,IAAI,CAAG,EAAG,OAAO,QAAQ,QAAQ,EAGrD,IAAM,EADU,EAAM,IAAI,CACT,CAAA,EAAS,IAAI,CAAG,EAEjC,GAAI,EAAU,OAAO,EAErB,IAAM,EAAO,EAAQ,CAAG,CAAC,CACtB,KAAM,GAAa,EAAM,EAAK,CAAoB,CAAC,CAAC,CACpD,SACO,CACJ,IAAI,EAAY,EAAO,IAAI,CAAE,EAExB,IACH,EAAY,IAAI,IAChB,EAAO,IAAI,EAAI,CAAS,GAG1B,EAAU,IAAI,CAAG,EACjB,EAAM,IAAI,CAAE,CAAC,EAAE,OAAO,CAAG,CAC3B,EACC,GAAiB,CAEhB,MADA,EAAM,IAAI,CAAE,CAAC,EAAE,OAAO,CAAG,EACnB,CACR,CACF,EAMF,OAJK,EAAM,IAAI,CAAE,GAAG,EAAM,IAAI,EAAI,IAAI,GAAK,EAE3C,EAAM,IAAI,CAAE,CAAC,CAAE,IAAI,EAAK,CAAI,EAErB,CACT,EAEA,kBAAkB,EAAI,EAAS,CAC7B,EAAA,cAAc,EAAS,CAAC,EACxB,EAAS,IAAI,EAAI,CAAO,CAC1B,EAEA,SAAS,EAAQ,CACf,IAAK,GAAM,CAAC,EAAI,KAAY,EAAO,iBAAiB,EAClD,EAAS,IAAI,EAAI,CAAO,EAG1B,IAAK,GAAM,CAAC,EAAI,KAAc,EAAO,eAAe,EAClD,EAAO,IAAI,EAAI,IAAI,IAAI,CAAS,CAAC,CAErC,EAEA,gBAAiB,CACf,OAAO,CACT,EAEA,kBAAmB,CACjB,OAAO,CACT,CACF,CACF"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { Messages } from './_catalog';
|
|
2
|
-
export type Locale = string;
|
|
3
|
-
export type NamespaceFactory<M extends Messages = Messages> = (locale: Locale) => Promise<M>;
|
|
4
|
-
export type NamespaceStore<M extends Messages = Messages> = {
|
|
5
|
-
/**
|
|
6
|
-
* Remove loaded-markers for a locale across all namespaces.
|
|
7
|
-
* Called by CatalogStore.register() when a catalog is replaced.
|
|
8
|
-
* Returns the list of namespace names whose markers were cleared.
|
|
9
|
-
*/
|
|
10
|
-
clearLocale(loc: Locale): string[];
|
|
11
|
-
dispose(): void;
|
|
12
|
-
/** Returns true if the namespace has been loaded for the given locale. */
|
|
13
|
-
isLoaded(ns: string, loc: Locale): boolean;
|
|
14
|
-
/** Returns true if the namespace factory is registered. */
|
|
15
|
-
isRegistered(ns: string): boolean;
|
|
16
|
-
/**
|
|
17
|
-
* Load a namespace for the given locale. Deduplicates concurrent and repeated calls.
|
|
18
|
-
* The `patch` callback is responsible for merging the loaded messages into the catalog.
|
|
19
|
-
*/
|
|
20
|
-
loadNamespace(ns: string, loc: Locale, patch: (loc: Locale, messages: Messages) => Promise<void>): Promise<void>;
|
|
21
|
-
/** Register a namespace factory. Idempotent — re-registration updates the factory for future loads. */
|
|
22
|
-
registerNamespace(ns: string, factory: NamespaceFactory<M>): void;
|
|
23
|
-
/** Seed from a parent instance (fork). Copies loaded markers; registry is shared by reference. */
|
|
24
|
-
seedFrom(parent: NamespaceStore<M>): void;
|
|
25
|
-
/** Snapshot of loaded markers for fork() */
|
|
26
|
-
snapshotLoaded(): ReadonlyMap<string, ReadonlySet<string>>;
|
|
27
|
-
/** Snapshot of the registry for fork() */
|
|
28
|
-
snapshotRegistry(): ReadonlyMap<string, NamespaceFactory<M>>;
|
|
29
|
-
};
|
|
30
|
-
export declare function createNamespaceStore<M extends Messages = Messages>(disposed: () => boolean): NamespaceStore<M>;
|
|
31
|
-
//# sourceMappingURL=_namespace-store.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_namespace-store.d.ts","sourceRoot":"","sources":["../src/_namespace-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI3C,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAC5B,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAE7F,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI;IAC1D;;;;OAIG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACnC,OAAO,IAAI,IAAI,CAAC;IAChB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3C,2DAA2D;IAC3D,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC;;;OAGG;IACH,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjH,uGAAuG;IACvG,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAClE,kGAAkG;IAClG,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC1C,4CAA4C;IAC5C,cAAc,IAAI,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3D,0CAA0C;IAC1C,gBAAgB,IAAI,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;CAC9D,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,EAAE,QAAQ,EAAE,MAAM,OAAO,GAAG,cAAc,CAAC,CAAC,CAAC,CAqG9G"}
|
package/dist/_namespace-store.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { LinguaNamespaceMissingError as e, checkDisposed as t, checkDisposedAsync as n } from "./errors.js";
|
|
2
|
-
//#region src/_namespace-store.ts
|
|
3
|
-
function r(r) {
|
|
4
|
-
let i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map();
|
|
5
|
-
return {
|
|
6
|
-
clearLocale(e) {
|
|
7
|
-
let t = [];
|
|
8
|
-
for (let [n, r] of a.entries()) r.delete(e) && t.push(n);
|
|
9
|
-
return t;
|
|
10
|
-
},
|
|
11
|
-
dispose() {
|
|
12
|
-
i.clear(), a.clear(), o.clear();
|
|
13
|
-
},
|
|
14
|
-
isLoaded(e, t) {
|
|
15
|
-
return a.get(e)?.has(t) ?? !1;
|
|
16
|
-
},
|
|
17
|
-
isRegistered(e) {
|
|
18
|
-
return i.has(e);
|
|
19
|
-
},
|
|
20
|
-
loadNamespace(t, s, c) {
|
|
21
|
-
let l = n(r());
|
|
22
|
-
if (l) return l;
|
|
23
|
-
let u = i.get(t);
|
|
24
|
-
if (!u) return Promise.reject(new e(`Namespace '${t}' is not registered. Call registerNamespace() first.`));
|
|
25
|
-
if (a.get(t)?.has(s)) return Promise.resolve();
|
|
26
|
-
let d = o.get(t)?.get(s);
|
|
27
|
-
if (d) return d;
|
|
28
|
-
let f = u(s).then((e) => c(s, e)).then(() => {
|
|
29
|
-
let e = a.get(t);
|
|
30
|
-
e || (e = /* @__PURE__ */ new Set(), a.set(t, e)), e.add(s), o.get(t)?.delete(s);
|
|
31
|
-
}, (e) => {
|
|
32
|
-
throw o.get(t)?.delete(s), e;
|
|
33
|
-
});
|
|
34
|
-
return o.has(t) || o.set(t, /* @__PURE__ */ new Map()), o.get(t).set(s, f), f;
|
|
35
|
-
},
|
|
36
|
-
registerNamespace(e, n) {
|
|
37
|
-
t(r()), i.set(e, n);
|
|
38
|
-
},
|
|
39
|
-
seedFrom(e) {
|
|
40
|
-
for (let [t, n] of e.snapshotRegistry()) i.set(t, n);
|
|
41
|
-
for (let [t, n] of e.snapshotLoaded()) a.set(t, new Set(n));
|
|
42
|
-
},
|
|
43
|
-
snapshotLoaded() {
|
|
44
|
-
return a;
|
|
45
|
-
},
|
|
46
|
-
snapshotRegistry() {
|
|
47
|
-
return i;
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
//#endregion
|
|
52
|
-
export { r as createNamespaceStore };
|
|
53
|
-
|
|
54
|
-
//# sourceMappingURL=_namespace-store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_namespace-store.js","names":[],"sources":["../src/_namespace-store.ts"],"sourcesContent":["// Internal — not part of the public API.\n// Owns namespace factory registry, per-locale loaded markers, and in-flight namespace tasks.\n\nimport type { Messages } from './_catalog';\n\nimport { LinguaNamespaceMissingError, checkDisposed, checkDisposedAsync } from './errors';\n\nexport type Locale = string;\nexport type NamespaceFactory<M extends Messages = Messages> = (locale: Locale) => Promise<M>;\n\nexport type NamespaceStore<M extends Messages = Messages> = {\n /**\n * Remove loaded-markers for a locale across all namespaces.\n * Called by CatalogStore.register() when a catalog is replaced.\n * Returns the list of namespace names whose markers were cleared.\n */\n clearLocale(loc: Locale): string[];\n dispose(): void;\n /** Returns true if the namespace has been loaded for the given locale. */\n isLoaded(ns: string, loc: Locale): boolean;\n /** Returns true if the namespace factory is registered. */\n isRegistered(ns: string): boolean;\n /**\n * Load a namespace for the given locale. Deduplicates concurrent and repeated calls.\n * The `patch` callback is responsible for merging the loaded messages into the catalog.\n */\n loadNamespace(ns: string, loc: Locale, patch: (loc: Locale, messages: Messages) => Promise<void>): Promise<void>;\n /** Register a namespace factory. Idempotent — re-registration updates the factory for future loads. */\n registerNamespace(ns: string, factory: NamespaceFactory<M>): void;\n /** Seed from a parent instance (fork). Copies loaded markers; registry is shared by reference. */\n seedFrom(parent: NamespaceStore<M>): void;\n /** Snapshot of loaded markers for fork() */\n snapshotLoaded(): ReadonlyMap<string, ReadonlySet<string>>;\n /** Snapshot of the registry for fork() */\n snapshotRegistry(): ReadonlyMap<string, NamespaceFactory<M>>;\n};\n\nexport function createNamespaceStore<M extends Messages = Messages>(disposed: () => boolean): NamespaceStore<M> {\n const registry = new Map<string, NamespaceFactory<M>>();\n // Two-level: Map<namespace, Set<locale>>\n const loaded = new Map<string, Set<string>>();\n const tasks = new Map<string, Map<string, Promise<void>>>();\n\n return {\n clearLocale(loc) {\n const cleared: string[] = [];\n\n for (const [ns, localeSet] of loaded.entries()) {\n if (localeSet.delete(loc)) cleared.push(ns);\n }\n\n return cleared;\n },\n\n dispose() {\n registry.clear();\n loaded.clear();\n tasks.clear();\n },\n\n isLoaded(ns, loc) {\n return loaded.get(ns)?.has(loc) ?? false;\n },\n\n isRegistered(ns) {\n return registry.has(ns);\n },\n\n loadNamespace(ns, loc, patch) {\n const early = checkDisposedAsync(disposed());\n\n if (early) return early;\n\n const factory = registry.get(ns);\n\n if (!factory) {\n return Promise.reject(\n new LinguaNamespaceMissingError(`Namespace '${ns}' is not registered. Call registerNamespace() first.`),\n );\n }\n\n if (loaded.get(ns)?.has(loc)) return Promise.resolve();\n\n const nsTasks = tasks.get(ns);\n const existing = nsTasks?.get(loc);\n\n if (existing) return existing;\n\n const task = factory(loc)\n .then((messages) => patch(loc, messages as Messages))\n .then(\n () => {\n let localeSet = loaded.get(ns);\n\n if (!localeSet) {\n localeSet = new Set();\n loaded.set(ns, localeSet);\n }\n\n localeSet.add(loc);\n tasks.get(ns)?.delete(loc);\n },\n (err: unknown) => {\n tasks.get(ns)?.delete(loc);\n throw err;\n },\n );\n\n if (!tasks.has(ns)) tasks.set(ns, new Map());\n\n tasks.get(ns)!.set(loc, task);\n\n return task;\n },\n\n registerNamespace(ns, factory) {\n checkDisposed(disposed());\n registry.set(ns, factory);\n },\n\n seedFrom(parent) {\n for (const [ns, factory] of parent.snapshotRegistry()) {\n registry.set(ns, factory);\n }\n\n for (const [ns, localeSet] of parent.snapshotLoaded()) {\n loaded.set(ns, new Set(localeSet));\n }\n },\n\n snapshotLoaded() {\n return loaded as ReadonlyMap<string, ReadonlySet<string>>;\n },\n\n snapshotRegistry() {\n return registry as ReadonlyMap<string, NamespaceFactory<M>>;\n },\n };\n}\n"],"mappings":";;AAqCA,SAAgB,EAAoD,GAA4C;CAC9G,IAAM,oBAAW,IAAI,IAAiC,GAEhD,oBAAS,IAAI,IAAyB,GACtC,oBAAQ,IAAI,IAAwC;CAE1D,OAAO;EACL,YAAY,GAAK;GACf,IAAM,IAAoB,CAAC;GAE3B,KAAK,IAAM,CAAC,GAAI,MAAc,EAAO,QAAQ,GAC3C,AAAI,EAAU,OAAO,CAAG,KAAG,EAAQ,KAAK,CAAE;GAG5C,OAAO;EACT;EAEA,UAAU;GAGR,AAFA,EAAS,MAAM,GACf,EAAO,MAAM,GACb,EAAM,MAAM;EACd;EAEA,SAAS,GAAI,GAAK;GAChB,OAAO,EAAO,IAAI,CAAE,CAAC,EAAE,IAAI,CAAG,KAAK;EACrC;EAEA,aAAa,GAAI;GACf,OAAO,EAAS,IAAI,CAAE;EACxB;EAEA,cAAc,GAAI,GAAK,GAAO;GAC5B,IAAM,IAAQ,EAAmB,EAAS,CAAC;GAE3C,IAAI,GAAO,OAAO;GAElB,IAAM,IAAU,EAAS,IAAI,CAAE;GAE/B,IAAI,CAAC,GACH,OAAO,QAAQ,OACb,IAAI,EAA4B,cAAc,EAAG,qDAAqD,CACxG;GAGF,IAAI,EAAO,IAAI,CAAE,CAAC,EAAE,IAAI,CAAG,GAAG,OAAO,QAAQ,QAAQ;GAGrD,IAAM,IADU,EAAM,IAAI,CACT,CAAA,EAAS,IAAI,CAAG;GAEjC,IAAI,GAAU,OAAO;GAErB,IAAM,IAAO,EAAQ,CAAG,CAAC,CACtB,MAAM,MAAa,EAAM,GAAK,CAAoB,CAAC,CAAC,CACpD,WACO;IACJ,IAAI,IAAY,EAAO,IAAI,CAAE;IAQ7B,AANK,MACH,oBAAY,IAAI,IAAI,GACpB,EAAO,IAAI,GAAI,CAAS,IAG1B,EAAU,IAAI,CAAG,GACjB,EAAM,IAAI,CAAE,CAAC,EAAE,OAAO,CAAG;GAC3B,IACC,MAAiB;IAEhB,MADA,EAAM,IAAI,CAAE,CAAC,EAAE,OAAO,CAAG,GACnB;GACR,CACF;GAMF,OAJK,EAAM,IAAI,CAAE,KAAG,EAAM,IAAI,mBAAI,IAAI,IAAI,CAAC,GAE3C,EAAM,IAAI,CAAE,CAAC,CAAE,IAAI,GAAK,CAAI,GAErB;EACT;EAEA,kBAAkB,GAAI,GAAS;GAE7B,AADA,EAAc,EAAS,CAAC,GACxB,EAAS,IAAI,GAAI,CAAO;EAC1B;EAEA,SAAS,GAAQ;GACf,KAAK,IAAM,CAAC,GAAI,MAAY,EAAO,iBAAiB,GAClD,EAAS,IAAI,GAAI,CAAO;GAG1B,KAAK,IAAM,CAAC,GAAI,MAAc,EAAO,eAAe,GAClD,EAAO,IAAI,GAAI,IAAI,IAAI,CAAS,CAAC;EAErC;EAEA,iBAAiB;GACf,OAAO;EACT;EAEA,mBAAmB;GACjB,OAAO;EACT;CACF;AACF"}
|
package/dist/_translate.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("./_dev.cjs"),t=require("./template.cjs"),n=require("./errors.cjs"),r=require("./_chain.cjs");function i(e,t){for(let n of e.chain){let r=e.catalogStore.resolve(n)?.get(t);if(r!==void 0)return r}}function a(e,t){for(let n of e.chain)if(e.catalogStore.resolve(n)?.prefixes.has(t))return!0;return!1}function o(e,t){return i(e,t)!==void 0||a(e,t)}function s(e,n,r,i){return t.renderTemplate(r.compiled,i,n,e.locale,e.onMissingVar)}function c(t,n,r){let o=i(t,n);return o?s(t,n,o,r):(e.devOnly(()=>{a(t,n)&&e.warn(`t('${n}') resolved to the missing-key fallback, but '${n}' exists as a plural branch — use tp('${n}', count) instead.`)}),t.onMissingKey(n,t.locale))}function l(e,t,n,r){let i=[];return!r&&n===0&&i.push(`${e}.zero`),(t!==`zero`||r)&&i.push(`${e}.${t}`),t!==`other`&&i.push(`${e}.other`),i}function u(e,t,i,a){if(!Number.isFinite(i))throw new n.LinguaInvalidCountError("`count` must be a finite number.");let o=a?.vars,c=a?.ordinal??!1;if(o&&Object.hasOwn(o,`count`))throw new n.LinguaCountInVarsError("`tp` does not allow `vars.count`; `count` is injected automatically.");let u=o?{count:i,...o}:{count:i};for(let n of e.chain){let a=e.catalogStore.resolve(n);if(!a)continue;let o=l(t,r.selectPluralForm(n,i,c,e.caches),i,c);for(let t of o){let n=a.get(t);if(n!==void 0)return s(e,t,n,u)}}return e.onMissingKey(t,e.locale)}exports.hasKey=o,exports.translate=c,exports.translatePlural=u;
|
|
2
|
-
//# sourceMappingURL=_translate.cjs.map
|
package/dist/_translate.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_translate.cjs","names":[],"sources":["../src/_translate.ts"],"sourcesContent":["// Internal — not part of the public API.\n// The translation algorithm: fallback-chain key lookup, plural-form selection, and\n// interpolation. Extracted out of i18n.ts's factory closure so it has its own unit-test seam\n// independent of the full `createI18n()` setup — mirrors `_catalog-store.ts`/`_namespace-store.ts`,\n// which already got this treatment; this was the one piece of comparable complexity left inline.\n\nimport type { CatalogEntry, CatalogEntryData } from './_catalog';\nimport type { LocaleCaches } from './_chain';\nimport type { Locale, TpOptions, TranslateVars } from './i18n-types';\n\nimport { selectPluralForm } from './_chain';\nimport { devOnly, warn } from './_dev';\nimport { LinguaCountInVarsError, LinguaInvalidCountError } from './errors';\nimport { renderTemplate } from './template';\n\n/** Only the read-side of `CatalogStore` this module needs — avoids importing its `M` generic. */\nexport type CatalogResolver = { resolve(loc: Locale): CatalogEntry | undefined };\n\nexport type TranslateContext = {\n readonly caches: LocaleCaches;\n readonly catalogStore: CatalogResolver;\n /** Active fallback chain, most-specific locale first (e.g. `['en-US', 'en']`). */\n readonly chain: readonly Locale[];\n readonly locale: Locale;\n readonly onMissingKey: (key: string, locale: Locale) => string;\n readonly onMissingVar: (varName: string, key: string, locale: Locale) => string;\n};\n\n// Single-pass entry lookup across the active fallback chain.\nfunction findEntry(ctx: TranslateContext, key: string): CatalogEntryData | undefined {\n for (const candidate of ctx.chain) {\n const found = ctx.catalogStore.resolve(candidate)?.get(key);\n\n if (found !== undefined) return found;\n }\n\n return undefined;\n}\n\n// True if `base` exists as a plural branch prefix (e.g. `items` when only `items.one`/\n// `items.other` are registered) anywhere in the fallback chain. Shared by `hasKey()` and\n// `translate()`'s dev-mode miss diagnostic below — both need to distinguish \"key genuinely\n// doesn't exist\" from \"key exists, but only as a plural branch — you want tp(), not t()\".\nfunction isPluralBranch(ctx: TranslateContext, base: string): boolean {\n for (const candidate of ctx.chain) {\n const catalog = ctx.catalogStore.resolve(candidate);\n\n if (catalog?.prefixes.has(base)) return true;\n }\n\n return false;\n}\n\n/** True if `base` exists as a leaf key or a plural branch prefix, anywhere in the fallback chain. */\nexport function hasKey(ctx: TranslateContext, base: string): boolean {\n return findEntry(ctx, base) !== undefined || isPluralBranch(ctx, base);\n}\n\nfunction interpolate(\n ctx: TranslateContext,\n key: string,\n found: CatalogEntryData,\n vars: TranslateVars | undefined,\n): string {\n return renderTemplate(found.compiled, vars, key, ctx.locale, ctx.onMissingVar);\n}\n\nexport function translate(ctx: TranslateContext, key: string, vars?: TranslateVars): string {\n const found = findEntry(ctx, key);\n\n if (!found) {\n // has(key) returns true for a plural-branch-only key (no leaf entry), but t() can't resolve\n // one — the common `if (i18n.has(key)) i18n.t(key)` pattern silently returns the raw key in\n // that case, indistinguishable from a genuinely missing key without this warning.\n devOnly(() => {\n if (isPluralBranch(ctx, key)) {\n warn(\n `t('${key}') resolved to the missing-key fallback, but '${key}' exists as a plural branch — use tp('${key}', count) instead.`,\n );\n }\n });\n\n return ctx.onMissingKey(key, ctx.locale);\n }\n\n return interpolate(ctx, key, found, vars);\n}\n\n// Plural key priority: cardinal zero tries `.zero` override first, then the CLDR form, then\n// `.other` as the final fallback. Ordinal / non-zero skips the `.zero` special case.\nfunction pluralKeyPriority(base: string, form: string, count: number, ordinal: boolean): string[] {\n const keys: string[] = [];\n\n if (!ordinal && count === 0) keys.push(`${base}.zero`);\n\n if (form !== 'zero' || ordinal) keys.push(`${base}.${form}`);\n\n if (form !== 'other') keys.push(`${base}.other`);\n\n return keys;\n}\n\nexport function translatePlural(ctx: TranslateContext, key: string, count: number, options?: TpOptions): string {\n if (!Number.isFinite(count)) {\n throw new LinguaInvalidCountError('`count` must be a finite number.');\n }\n\n const vars = options?.vars;\n const ordinal = options?.ordinal ?? false;\n\n if (vars && Object.hasOwn(vars, 'count')) {\n throw new LinguaCountInVarsError('`tp` does not allow `vars.count`; `count` is injected automatically.');\n }\n\n const mergedVars = vars ? { count, ...vars } : { count };\n\n // Walk the fallback chain locale-by-locale, selecting CLDR plural form using each locale's\n // own rules. This ensures cross-locale fallbacks produce grammatically correct forms.\n for (const candidate of ctx.chain) {\n const catalog = ctx.catalogStore.resolve(candidate);\n\n if (!catalog) continue;\n\n const form = selectPluralForm(candidate, count, ordinal, ctx.caches);\n const keys = pluralKeyPriority(key, form, count, ordinal);\n\n for (const k of keys) {\n const found = catalog.get(k);\n\n if (found !== undefined) return interpolate(ctx, k, found, mergedVars);\n }\n }\n\n return ctx.onMissingKey(key, ctx.locale);\n}\n"],"mappings":"8GA6BA,SAAS,EAAU,EAAuB,EAA2C,CACnF,IAAK,IAAM,KAAa,EAAI,MAAO,CACjC,IAAM,EAAQ,EAAI,aAAa,QAAQ,CAAS,CAAC,EAAE,IAAI,CAAG,EAE1D,GAAI,IAAU,IAAA,GAAW,OAAO,CAClC,CAGF,CAMA,SAAS,EAAe,EAAuB,EAAuB,CACpE,IAAK,IAAM,KAAa,EAAI,MAG1B,GAFgB,EAAI,aAAa,QAAQ,CAErC,CAAA,EAAS,SAAS,IAAI,CAAI,EAAG,MAAO,GAG1C,MAAO,EACT,CAGA,SAAgB,EAAO,EAAuB,EAAuB,CACnE,OAAO,EAAU,EAAK,CAAI,IAAM,IAAA,IAAa,EAAe,EAAK,CAAI,CACvE,CAEA,SAAS,EACP,EACA,EACA,EACA,EACQ,CACR,OAAO,EAAA,eAAe,EAAM,SAAU,EAAM,EAAK,EAAI,OAAQ,EAAI,YAAY,CAC/E,CAEA,SAAgB,EAAU,EAAuB,EAAa,EAA8B,CAC1F,IAAM,EAAQ,EAAU,EAAK,CAAG,EAiBhC,OAfK,EAeE,EAAY,EAAK,EAAK,EAAO,CAAI,GAXtC,EAAA,YAAc,CACR,EAAe,EAAK,CAAG,GACzB,EAAA,KACE,MAAM,EAAI,gDAAgD,EAAI,wCAAwC,EAAI,mBAC5G,CAEJ,CAAC,EAEM,EAAI,aAAa,EAAK,EAAI,MAAM,EAI3C,CAIA,SAAS,EAAkB,EAAc,EAAc,EAAe,EAA4B,CAChG,IAAM,EAAiB,CAAC,EAQxB,MANI,CAAC,GAAW,IAAU,GAAG,EAAK,KAAK,GAAG,EAAK,MAAM,GAEjD,IAAS,QAAU,IAAS,EAAK,KAAK,GAAG,EAAK,GAAG,GAAM,EAEvD,IAAS,SAAS,EAAK,KAAK,GAAG,EAAK,OAAO,EAExC,CACT,CAEA,SAAgB,EAAgB,EAAuB,EAAa,EAAe,EAA6B,CAC9G,GAAI,CAAC,OAAO,SAAS,CAAK,EACxB,MAAM,IAAI,EAAA,wBAAwB,kCAAkC,EAGtE,IAAM,EAAO,GAAS,KAChB,EAAU,GAAS,SAAW,GAEpC,GAAI,GAAQ,OAAO,OAAO,EAAM,OAAO,EACrC,MAAM,IAAI,EAAA,uBAAuB,sEAAsE,EAGzG,IAAM,EAAa,EAAO,CAAE,QAAO,GAAG,CAAK,EAAI,CAAE,OAAM,EAIvD,IAAK,IAAM,KAAa,EAAI,MAAO,CACjC,IAAM,EAAU,EAAI,aAAa,QAAQ,CAAS,EAElD,GAAI,CAAC,EAAS,SAGd,IAAM,EAAO,EAAkB,EADlB,EAAA,iBAAiB,EAAW,EAAO,EAAS,EAAI,MACzB,EAAM,EAAO,CAAO,EAExD,IAAK,IAAM,KAAK,EAAM,CACpB,IAAM,EAAQ,EAAQ,IAAI,CAAC,EAE3B,GAAI,IAAU,IAAA,GAAW,OAAO,EAAY,EAAK,EAAG,EAAO,CAAU,CACvE,CACF,CAEA,OAAO,EAAI,aAAa,EAAK,EAAI,MAAM,CACzC"}
|
package/dist/_translate.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { CatalogEntry } from './_catalog';
|
|
2
|
-
import type { LocaleCaches } from './_chain';
|
|
3
|
-
import type { Locale, TpOptions, TranslateVars } from './i18n-types';
|
|
4
|
-
/** Only the read-side of `CatalogStore` this module needs — avoids importing its `M` generic. */
|
|
5
|
-
export type CatalogResolver = {
|
|
6
|
-
resolve(loc: Locale): CatalogEntry | undefined;
|
|
7
|
-
};
|
|
8
|
-
export type TranslateContext = {
|
|
9
|
-
readonly caches: LocaleCaches;
|
|
10
|
-
readonly catalogStore: CatalogResolver;
|
|
11
|
-
/** Active fallback chain, most-specific locale first (e.g. `['en-US', 'en']`). */
|
|
12
|
-
readonly chain: readonly Locale[];
|
|
13
|
-
readonly locale: Locale;
|
|
14
|
-
readonly onMissingKey: (key: string, locale: Locale) => string;
|
|
15
|
-
readonly onMissingVar: (varName: string, key: string, locale: Locale) => string;
|
|
16
|
-
};
|
|
17
|
-
/** True if `base` exists as a leaf key or a plural branch prefix, anywhere in the fallback chain. */
|
|
18
|
-
export declare function hasKey(ctx: TranslateContext, base: string): boolean;
|
|
19
|
-
export declare function translate(ctx: TranslateContext, key: string, vars?: TranslateVars): string;
|
|
20
|
-
export declare function translatePlural(ctx: TranslateContext, key: string, count: number, options?: TpOptions): string;
|
|
21
|
-
//# sourceMappingURL=_translate.d.ts.map
|
package/dist/_translate.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_translate.d.ts","sourceRoot":"","sources":["../src/_translate.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,YAAY,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAOrE,iGAAiG;AACjG,MAAM,MAAM,eAAe,GAAG;IAAE,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAA;CAAE,CAAC;AAEjF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC;IACvC,kFAAkF;IAClF,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/D,QAAQ,CAAC,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CACjF,CAAC;AA2BF,qGAAqG;AACrG,wBAAgB,MAAM,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnE;AAWD,wBAAgB,SAAS,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,CAmB1F;AAgBD,wBAAgB,eAAe,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,GAAG,MAAM,CAgC9G"}
|