@lssm/lib.translation-runtime 3.0.1
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 +166 -0
- package/dist/adapters/i18next-export.d.ts +2 -0
- package/dist/adapters/i18next-helpers.d.ts +8 -0
- package/dist/adapters/i18next-types.d.ts +93 -0
- package/dist/adapters/i18next.d.ts +8 -0
- package/dist/adapters/i18next.test.d.ts +1 -0
- package/dist/browser/diagnostics.js +1 -0
- package/dist/browser/direction.js +1 -0
- package/dist/browser/fallback.js +1 -0
- package/dist/browser/formatter.js +0 -0
- package/dist/browser/formatters/intl-messageformat.js +1 -0
- package/dist/browser/i18next.js +1 -0
- package/dist/browser/index.js +28 -0
- package/dist/browser/loader.js +1 -0
- package/dist/browser/locale.js +1 -0
- package/dist/browser/overrides.js +1 -0
- package/dist/browser/precompile.js +28 -0
- package/dist/browser/preferences.js +1 -0
- package/dist/browser/snapshot.js +1 -0
- package/dist/diagnostics.d.ts +21 -0
- package/dist/diagnostics.js +2 -0
- package/dist/direction.d.ts +3 -0
- package/dist/direction.js +2 -0
- package/dist/fallback.d.ts +6 -0
- package/dist/fallback.js +2 -0
- package/dist/formatter.d.ts +32 -0
- package/dist/formatter.js +1 -0
- package/dist/formatters/intl-messageformat.d.ts +12 -0
- package/dist/formatters/intl-messageformat.js +2 -0
- package/dist/i18next.d.ts +1 -0
- package/dist/i18next.js +2 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +29 -0
- package/dist/loader.d.ts +42 -0
- package/dist/loader.js +2 -0
- package/dist/loader.test.d.ts +1 -0
- package/dist/locale.d.ts +26 -0
- package/dist/locale.js +2 -0
- package/dist/node/diagnostics.js +1 -0
- package/dist/node/direction.js +1 -0
- package/dist/node/fallback.js +1 -0
- package/dist/node/formatter.js +0 -0
- package/dist/node/formatters/intl-messageformat.js +1 -0
- package/dist/node/i18next.js +1 -0
- package/dist/node/index.js +28 -0
- package/dist/node/loader.js +1 -0
- package/dist/node/locale.js +1 -0
- package/dist/node/overrides.js +1 -0
- package/dist/node/precompile.js +28 -0
- package/dist/node/preferences.js +1 -0
- package/dist/node/snapshot.js +1 -0
- package/dist/overrides.d.ts +10 -0
- package/dist/overrides.js +2 -0
- package/dist/precompile.d.ts +0 -0
- package/dist/precompile.js +29 -0
- package/dist/precompile.test.d.ts +1 -0
- package/dist/preferences.d.ts +17 -0
- package/dist/preferences.js +2 -0
- package/dist/snapshot.d.ts +38 -0
- package/dist/snapshot.js +2 -0
- package/package.json +368 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
class x{items=[];report(e){this.items.push(e)}list(){return[...this.items]}clear(){this.items.length=0}}var C=new Set(["ar","arc","dv","fa","ha","he","ks","ku","ps","ur","yi"]);function h(e){let t=b(e);return C.has(t)?"rtl":"ltr"}function b(e){try{return new Intl.Locale(e).language.toLowerCase()}catch{return e.split("-")[0]?.toLowerCase()??e.toLowerCase()}}function u(e){let t=e.trim();if(!t)return{input:e,valid:!1,error:"Locale is empty"};try{let a=Intl.getCanonicalLocales(t)[0];return a?{input:e,locale:a,valid:!0}:{input:e,valid:!1,error:"Locale did not canonicalize"}}catch(a){return{input:e,valid:!1,error:a instanceof Error?a.message:"Invalid locale"}}}function f(e=[]){let t=[];for(let a of e){let o=u(a);if(o.locale&&!t.includes(o.locale))t.push(o.locale)}return t}function X(e){let t=u(e.defaultLocale).locale??e.defaultLocale,a=f(e.requestedLocales),o=f(e.supportedLocales),r=f(e.fallbackLocales),n=o.length?o:[t];for(let l of a){let s=g(l,t,r).find((d)=>n.includes(d));if(s)return R(s,a,n,t,r)}return R(t,a,n,t,r)}function g(e,t,a=[]){let o=[],r=(n)=>{if(!n)return;let l=u(n).locale??n;if(!o.includes(l))o.push(l)};r(e);for(let n of k(e))r(n);for(let n of a)r(n);return r(t),o}function k(e){let a=(u(e).locale??e).split("-"),o=[];while(a.length>1)a.pop(),o.push(a.join("-"));return o}function R(e,t,a,o,r){return{locale:e,requestedLocales:t,supportedLocales:a,fallbackChain:g(e,o,r),direction:h(e),defaultLocale:o}}function te(e,t){return g(e,t.defaultLocale,t.locales??[])}import{parse as N,TYPE as p}from"@formatjs/icu-messageformat-parser";import O from"intl-messageformat";function ne(e={}){let t=e.cache??new Map,a=e.precompiled;return{compile({id:o,locale:r,message:n,ast:l}){let i=`${r}\x00${o}\x00${n}`,s=t.get(i);if(s)return s;let d=l??a?.({id:o,locale:r,message:n}),c=new O(d??n,r),m={format(P){let L=c.format(P);return Array.isArray(L)?L.join(""):String(L)}};return t.set(i,m),m},validate(o){try{let r=N(o);return M(r)}catch(r){return{valid:!1,error:r instanceof Error?r.message:"Invalid ICU message",arguments:[],plurals:[],selects:[],selectOrdinals:[]}}}}}function M(e){let t=new Set,a=new Set,o=new Set,r=new Set,n=(l)=>{for(let i of l){let s="value"in i?String(i.value):void 0;if(s&&D(i.type))t.add(s);if(s&&i.type===p.select)o.add(s);if(s&&i.type===p.plural)if(t.add(s),"pluralType"in i&&i.pluralType==="ordinal")r.add(s);else a.add(s);if("options"in i)for(let d of Object.values(i.options))n(d.value)}};return n(e),{valid:!0,arguments:[...t],plurals:[...a],selects:[...o],selectOrdinals:[...r]}}function D(e){return e===p.argument||e===p.number||e===p.date||e===p.time||e===p.select||e===p.plural||e===p.pound||e===p.tag}function ie(e){return{async load(t){return e.filter((a)=>E(a.meta.key,t)&&t.locales.includes(a.locale))}}}function E(e,t){let a=t.specKey!==void 0,o=t.specKeys!==void 0&&t.specKeys.length>0;if(!a&&!o)return!0;if(a&&e===t.specKey)return!0;if(o&&t.specKeys?.includes(e))return!0;return!1}function _(e,t){let a=new Set(e),o=[],r=new Set;for(let n of t){if(a.has(n)||r.has(n))continue;r.add(n),o.push(n)}return o}async function le(e,t){let a=_(t.loaded,t.required);if(a.length===0)return[];return e.load({specKeys:a,locales:t.locales})}function pe(e){return[...e].sort((t,a)=>(t.priority??I(t.scope))-(a.priority??I(a.scope)))}function I(e){switch(e){case"base":return 0;case"package":return 10;case"project":return 20;case"tenant":return 30;case"user":return 40;case"request":return 50}}import A from"intl-messageformat";var y="contractspec.icu.precompiled",T=1;function S(e,t){return`${e}\x00${t}`}function F(e,t){return new A(e,t).getAst()}function w(e){let t={};for(let{locale:a,message:o}of e){let r=S(a,o);if(t[r])continue;t[r]={locale:a,message:o,ast:F(o,a)}}return{kind:y,version:T,entries:t}}function me(e){let t=[];for(let a of e)for(let o of Object.values(a.messages))t.push({locale:a.locale,message:o.value});return w(t)}function fe(e){return JSON.stringify(e)}function ge(e){let t=JSON.parse(e),a=q(t);if(a.length>0)throw Error(a.join("; "));return t}function q(e){let t=[];if(!e||e.kind!==y)t.push("Precompiled ICU catalog kind is invalid.");if(e?.version!==T)t.push("Precompiled ICU catalog version is unsupported.");if(!e?.entries||typeof e.entries!=="object")t.push("Precompiled ICU catalog entries must be an object.");return t}function Le(e){return({locale:t,message:a})=>e.entries[S(t,a)]?.ast}var ye={id:"docs.tech.translation-runtime.icu-precompile",title:"Precompiled ICU AST fast-path",summary:"Build-time ICU AST precompilation with an additive runtime parse-skip fast-path.",kind:"reference",visibility:"public",route:"/docs/tech/translation-runtime/icu-precompile",tags:["i18n","icu","performance","translation-runtime"],body:`# Precompiled ICU AST fast-path
|
|
3
|
+
|
|
4
|
+
Precompiles ICU message strings into the exact \`MessageFormatElement[]\` AST that
|
|
5
|
+
\`intl-messageformat\` produces, so the runtime can skip the per-call parse.
|
|
6
|
+
|
|
7
|
+
- \`precompileIcuMessage(message, locale)\` returns the AST via
|
|
8
|
+
\`IntlMessageFormat#getAst()\` \u2014 identical to the on-the-fly string path, so
|
|
9
|
+
formatted output is byte-identical (verified by golden tests across plural,
|
|
10
|
+
select, selectordinal, number, currency, date, and time for en/fr/es/ar-EG).
|
|
11
|
+
- \`buildPrecompiledIcuCatalog\` / \`buildPrecompiledIcuCatalogFromSpecs\` produce a
|
|
12
|
+
serializable \`PrecompiledIcuCatalog\` (\`kind\` =
|
|
13
|
+
\`${y}\`, \`version\` = \`${T}\`) as a
|
|
14
|
+
build-time asset.
|
|
15
|
+
- \`createPrecompiledIcuLookup(catalog)\` yields a lookup the formatter consumes.
|
|
16
|
+
|
|
17
|
+
Wire the lookup via \`createIntlMessageFormatter({ precompiled })\`, or pass a
|
|
18
|
+
per-call \`ast\` on \`compile()\`. When neither is present the formatter parses the
|
|
19
|
+
message string exactly as before \u2014 the surface is **ADDITIVE**.
|
|
20
|
+
|
|
21
|
+
Scope: this precompiles the ICU MessageFormat argument grammar
|
|
22
|
+
(plural/select/selectordinal/number/date/time + number skeletons such as
|
|
23
|
+
currency). List and relative-time rendering is performed by \`Intl.ListFormat\` /
|
|
24
|
+
\`Intl.RelativeTimeFormat\` outside the message AST and has no per-call message
|
|
25
|
+
parse to precompile. The \`createI18nFactory\` stack uses simple \`{key}\`
|
|
26
|
+
interpolation (no ICU parse) and is therefore unaffected by this fast-path.
|
|
27
|
+
|
|
28
|
+
Compatibility classification: **ADDITIVE**.
|
|
29
|
+
`};var K=["app","workspace","team","user","request"],U={app:"appLocale",workspace:"workspaceLocale",team:"teamLocale",user:"userLocale",request:"requestLocale"};function Re(e={},t={}){let a=u(t.fallbackLocale??e.defaultLocale??e.appLocale??"en").locale??"en",o=u(e.defaultLocale??e.appLocale??a).locale??a,r={},n=[];for(let c of K){let m=H(e[U[c]]);if(!m)continue;r[c]=m,n.push({source:c,locale:m,metadata:e.sources?.[c]})}let l=f(e.requestedLocales??[]),i=f(t.additionalRequestedLocales??[]),s=[...n].reverse().map((c)=>c.locale),d=V([...l,...i,...s,o]);return{defaultLocale:o,requestedLocales:d,preferenceLocales:r,sources:[...l.map((c)=>({source:"requested",locale:c})),...n]}}function H(e){if(!e)return;return u(e).locale}function V(e){return[...new Set(e)]}var Se="contractspec.translation-runtime.hydration",ve=1;function j(e){return JSON.stringify(e)}function B(e){return JSON.parse(e)}function v(e){return{kind:"contractspec.translation-runtime.hydration",version:1,snapshot:J(e)}}function Pe(e){return JSON.stringify(e)}function xe(e){let t=JSON.parse(e),a=z(t);if(a.length>0)throw Error(a.map((o)=>o.message).join("; "));return v(t.snapshot)}function Ce(e){return{type:"translation-runtime-snapshot",payload:v(e)}}function z(e){let t=[];if(!e||e.kind!=="contractspec.translation-runtime.hydration")t.push({code:"invalid_snapshot",level:"error",message:"Translation hydration payload kind is invalid."});if(e?.version!==1)t.push({code:"invalid_snapshot",level:"error",message:"Translation hydration payload version is unsupported.",context:{version:e?.version}});return t.push(...Y(e?.snapshot)),t}function Y(e){let t=[];if(!e)return[{code:"invalid_snapshot",level:"error",message:"Translation runtime snapshot is missing."}];if(!e.locale)t.push({code:"invalid_snapshot",level:"error",message:"Translation runtime snapshot locale is missing."});if(!e.defaultLocale)t.push({code:"invalid_snapshot",level:"error",message:"Translation runtime snapshot defaultLocale is missing."});for(let[a,o]of[["fallbackChain",e.fallbackChain],["supportedLocales",e.supportedLocales],["specs",e.specs]])if(!Array.isArray(o))t.push({code:"invalid_snapshot",level:"error",message:`Translation runtime snapshot ${a} must be an array.`,context:{field:a}});return t}function J(e){return B(j(e))}export{y as PRECOMPILED_ICU_KIND,T as PRECOMPILED_ICU_VERSION,ye as PrecompiledIcuDocBlock,Se as TRANSLATION_RUNTIME_HYDRATION_KIND,ve as TRANSLATION_RUNTIME_HYDRATION_VERSION,x as TranslationDiagnosticsCollector,g as buildLocaleFallbackChain,w as buildPrecompiledIcuCatalog,me as buildPrecompiledIcuCatalogFromSpecs,u as canonicalizeLocale,f as canonicalizeLocales,_ as computeShardDelta,ne as createIntlMessageFormatter,Le as createPrecompiledIcuLookup,ie as createStaticBundleLoader,v as createTranslationHydrationPayload,Ce as createTranslationSnapshotStreamChunk,I as defaultOverridePriority,b as getLanguageSubtag,h as getTextDirection,le as loadShardDelta,X as negotiateLocale,ge as parsePrecompiledIcuCatalog,xe as parseTranslationHydrationPayload,B as parseTranslationSnapshot,F as precompileIcuMessage,te as resolveFallbackChain,Re as resolveTranslationPreferenceContext,fe as serializePrecompiledIcuCatalog,Pe as serializeTranslationHydrationPayload,j as serializeTranslationSnapshot,pe as sortOverrideLayers,q as validatePrecompiledIcuCatalog,z as validateTranslationHydrationPayload,Y as validateTranslationSnapshot};
|
package/dist/loader.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Locale, TranslationSpec } from '@lssm/lib.contracts-spec/translations';
|
|
2
|
+
export interface TranslationBundleLoadRequest {
|
|
3
|
+
specKey?: string;
|
|
4
|
+
/**
|
|
5
|
+
* Optional set of spec keys (shards) to load.
|
|
6
|
+
*
|
|
7
|
+
* Additive shard-scoping field. When present, a loader returns specs whose
|
|
8
|
+
* `meta.key` is in this list (in addition to any single `specKey` match).
|
|
9
|
+
* When absent, resolution behavior is byte-for-byte identical to the prior
|
|
10
|
+
* `{ specKey, locales }` contract.
|
|
11
|
+
*/
|
|
12
|
+
specKeys?: readonly string[];
|
|
13
|
+
locales: readonly Locale[];
|
|
14
|
+
}
|
|
15
|
+
export interface TranslationBundleLoader {
|
|
16
|
+
load(request: TranslationBundleLoadRequest): Promise<readonly TranslationSpec[]>;
|
|
17
|
+
}
|
|
18
|
+
export declare function createStaticBundleLoader(specs: readonly TranslationSpec[]): TranslationBundleLoader;
|
|
19
|
+
/** Request describing which route shards are needed vs already loaded. */
|
|
20
|
+
export interface ShardDeltaRequest {
|
|
21
|
+
/** Spec keys already present on the client (shared/global shards). */
|
|
22
|
+
loaded: readonly string[];
|
|
23
|
+
/** Spec keys required to render the target route. */
|
|
24
|
+
required: readonly string[];
|
|
25
|
+
/** Locales to load the newly-required shards for. */
|
|
26
|
+
locales: readonly Locale[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Compute the set of spec keys that are required but not yet loaded.
|
|
30
|
+
*
|
|
31
|
+
* Deduplicates and preserves first-seen order of `required`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function computeShardDelta(loaded: readonly string[], required: readonly string[]): string[];
|
|
34
|
+
/**
|
|
35
|
+
* Lazily fetch only the page/domain shards a route needs but the client does
|
|
36
|
+
* not already have, reusing the already-loaded shared shards.
|
|
37
|
+
*
|
|
38
|
+
* Returns only the newly-loaded specs (the delta), so callers can merge them
|
|
39
|
+
* into an existing factory/catalog set without re-fetching shared shards.
|
|
40
|
+
* When there is no delta, no loader call is made and `[]` is returned.
|
|
41
|
+
*/
|
|
42
|
+
export declare function loadShardDelta(loader: TranslationBundleLoader, request: ShardDeltaRequest): Promise<readonly TranslationSpec[]>;
|
package/dist/loader.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
function c(a){return{async load(e){return a.filter((n)=>s(n.meta.key,e)&&e.locales.includes(n.locale))}}}function s(a,e){let n=e.specKey!==void 0,t=e.specKeys!==void 0&&e.specKeys.length>0;if(!n&&!t)return!0;if(n&&a===e.specKey)return!0;if(t&&e.specKeys?.includes(a))return!0;return!1}function l(a,e){let n=new Set(a),t=[],o=new Set;for(let r of e){if(n.has(r)||o.has(r))continue;o.add(r),t.push(r)}return t}async function d(a,e){let n=l(e.loaded,e.required);if(n.length===0)return[];return a.load({specKeys:n,locales:e.locales})}export{l as computeShardDelta,c as createStaticBundleLoader,d as loadShardDelta};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/locale.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Locale } from '@lssm/lib.contracts-spec/translations';
|
|
2
|
+
import { type TextDirection } from './direction.js';
|
|
3
|
+
export interface LocaleCanonicalizationResult {
|
|
4
|
+
input: string;
|
|
5
|
+
locale?: Locale;
|
|
6
|
+
valid: boolean;
|
|
7
|
+
error?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface LocaleNegotiationOptions {
|
|
10
|
+
requestedLocales?: readonly string[];
|
|
11
|
+
supportedLocales?: readonly string[];
|
|
12
|
+
defaultLocale: string;
|
|
13
|
+
fallbackLocales?: readonly string[];
|
|
14
|
+
}
|
|
15
|
+
export interface LocaleNegotiationResult {
|
|
16
|
+
locale: Locale;
|
|
17
|
+
requestedLocales: Locale[];
|
|
18
|
+
supportedLocales: Locale[];
|
|
19
|
+
fallbackChain: Locale[];
|
|
20
|
+
direction: TextDirection;
|
|
21
|
+
defaultLocale: Locale;
|
|
22
|
+
}
|
|
23
|
+
export declare function canonicalizeLocale(input: string): LocaleCanonicalizationResult;
|
|
24
|
+
export declare function canonicalizeLocales(inputs?: readonly string[]): Locale[];
|
|
25
|
+
export declare function negotiateLocale(options: LocaleNegotiationOptions): LocaleNegotiationResult;
|
|
26
|
+
export declare function buildLocaleFallbackChain(locale: string, defaultLocale: string, explicitFallbacks?: readonly string[]): Locale[];
|
package/dist/locale.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var g=new Set(["ar","arc","dv","fa","ha","he","ks","ku","ps","ur","yi"]);function u(e){let t=p(e);return g.has(t)?"rtl":"ltr"}function p(e){try{return new Intl.Locale(e).language.toLowerCase()}catch{return e.split("-")[0]?.toLowerCase()??e.toLowerCase()}}function r(e){let t=e.trim();if(!t)return{input:e,valid:!1,error:"Locale is empty"};try{let o=Intl.getCanonicalLocales(t)[0];return o?{input:e,locale:o,valid:!0}:{input:e,valid:!1,error:"Locale did not canonicalize"}}catch(o){return{input:e,valid:!1,error:o instanceof Error?o.message:"Invalid locale"}}}function i(e=[]){let t=[];for(let o of e){let a=r(o);if(a.locale&&!t.includes(a.locale))t.push(a.locale)}return t}function m(e){let t=r(e.defaultLocale).locale??e.defaultLocale,o=i(e.requestedLocales),a=i(e.supportedLocales),c=i(e.fallbackLocales),n=a.length?a:[t];for(let l of o){let s=f(l,t,c).find((d)=>n.includes(d));if(s)return L(s,o,n,t,c)}return L(t,o,n,t,c)}function f(e,t,o=[]){let a=[],c=(n)=>{if(!n)return;let l=r(n).locale??n;if(!a.includes(l))a.push(l)};c(e);for(let n of h(e))c(n);for(let n of o)c(n);return c(t),a}function h(e){let o=(r(e).locale??e).split("-"),a=[];while(o.length>1)o.pop(),a.push(o.join("-"));return a}function L(e,t,o,a,c){return{locale:e,requestedLocales:t,supportedLocales:o,fallbackChain:f(e,a,c),direction:u(e),defaultLocale:a}}export{f as buildLocaleFallbackChain,r as canonicalizeLocale,i as canonicalizeLocales,m as negotiateLocale};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class i{items=[];report(e){this.items.push(e)}list(){return[...this.items]}clear(){this.items.length=0}}export{i as TranslationDiagnosticsCollector};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var r=new Set(["ar","arc","dv","fa","ha","he","ks","ku","ps","ur","yi"]);function a(t){let e=n(t);return r.has(e)?"rtl":"ltr"}function n(t){try{return new Intl.Locale(t).language.toLowerCase()}catch{return t.split("-")[0]?.toLowerCase()??t.toLowerCase()}}export{n as getLanguageSubtag,a as getTextDirection};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var g=new Set(["ar","arc","dv","fa","ha","he","ks","ku","ps","ur","yi"]);function L(e){let o=p(e);return g.has(o)?"rtl":"ltr"}function p(e){try{return new Intl.Locale(e).language.toLowerCase()}catch{return e.split("-")[0]?.toLowerCase()??e.toLowerCase()}}function r(e){let o=e.trim();if(!o)return{input:e,valid:!1,error:"Locale is empty"};try{let t=Intl.getCanonicalLocales(o)[0];return t?{input:e,locale:t,valid:!0}:{input:e,valid:!1,error:"Locale did not canonicalize"}}catch(t){return{input:e,valid:!1,error:t instanceof Error?t.message:"Invalid locale"}}}function s(e=[]){let o=[];for(let t of e){let a=r(t);if(a.locale&&!o.includes(a.locale))o.push(a.locale)}return o}function y(e){let o=r(e.defaultLocale).locale??e.defaultLocale,t=s(e.requestedLocales),a=s(e.supportedLocales),c=s(e.fallbackLocales),l=a.length?a:[o];for(let n of t){let u=i(n,o,c).find((d)=>l.includes(d));if(u)return f(u,t,l,o,c)}return f(o,t,l,o,c)}function i(e,o,t=[]){let a=[],c=(l)=>{if(!l)return;let n=r(l).locale??l;if(!a.includes(n))a.push(n)};c(e);for(let l of h(e))c(l);for(let l of t)c(l);return c(o),a}function h(e){let t=(r(e).locale??e).split("-"),a=[];while(t.length>1)t.pop(),a.push(t.join("-"));return a}function f(e,o,t,a,c){return{locale:e,requestedLocales:o,supportedLocales:t,fallbackChain:i(e,a,c),direction:L(e),defaultLocale:a}}function v(e,o){return i(e,o.defaultLocale,o.locales??[])}export{v as resolveFallbackChain};
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{parse as f,TYPE as a}from"@formatjs/icu-messageformat-parser";import M from"intl-messageformat";function w(e={}){let o=e.cache??new Map,l=e.precompiled;return{compile({id:n,locale:s,message:i,ast:c}){let t=`${s}\x00${n}\x00${i}`,r=o.get(t);if(r)return r;let m=c??l?.({id:n,locale:s,message:i}),d=new M(m??i,s),u={format(g){let p=d.format(g);return Array.isArray(p)?p.join(""):String(p)}};return o.set(t,u),u},validate(n){try{let s=f(n);return F(s)}catch(s){return{valid:!1,error:s instanceof Error?s.message:"Invalid ICU message",arguments:[],plurals:[],selects:[],selectOrdinals:[]}}}}}function F(e){let o=new Set,l=new Set,n=new Set,s=new Set,i=(c)=>{for(let t of c){let r="value"in t?String(t.value):void 0;if(r&&v(t.type))o.add(r);if(r&&t.type===a.select)n.add(r);if(r&&t.type===a.plural)if(o.add(r),"pluralType"in t&&t.pluralType==="ordinal")s.add(r);else l.add(r);if("options"in t)for(let m of Object.values(t.options))i(m.value)}};return i(e),{valid:!0,arguments:[...o],plurals:[...l],selects:[...n],selectOrdinals:[...s]}}function v(e){return e===a.argument||e===a.number||e===a.date||e===a.time||e===a.select||e===a.plural||e===a.pound||e===a.tag}export{w as createIntlMessageFormatter};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var v=new Set(["ar","arc","dv","fa","ha","he","ks","ku","ps","ur","yi"]);function x(e){let t=O(e);return v.has(t)?"rtl":"ltr"}function O(e){try{return new Intl.Locale(e).language.toLowerCase()}catch{return e.split("-")[0]?.toLowerCase()??e.toLowerCase()}}function g(e){let t=e.trim();if(!t)return{input:e,valid:!1,error:"Locale is empty"};try{let n=Intl.getCanonicalLocales(t)[0];return n?{input:e,locale:n,valid:!0}:{input:e,valid:!1,error:"Locale did not canonicalize"}}catch(n){return{input:e,valid:!1,error:n instanceof Error?n.message:"Invalid locale"}}}function S(e=[]){let t=[];for(let n of e){let a=g(n);if(a.locale&&!t.includes(a.locale))t.push(a.locale)}return t}function j(e){let t=g(e.defaultLocale).locale??e.defaultLocale,n=S(e.requestedLocales),a=S(e.supportedLocales),o=S(e.fallbackLocales),c=a.length?a:[t];for(let s of n){let r=d(s,t,o).find((l)=>c.includes(l));if(r)return I(r,n,c,t,o)}return I(t,n,c,t,o)}function d(e,t,n=[]){let a=[],o=(c)=>{if(!c)return;let s=g(c).locale??c;if(!a.includes(s))a.push(s)};o(e);for(let c of M(e))o(c);for(let c of n)o(c);return o(t),a}function M(e){let n=(g(e).locale??e).split("-"),a=[];while(n.length>1)n.pop(),a.push(n.join("-"));return a}function I(e,t,n,a,o){return{locale:e,requestedLocales:t,supportedLocales:n,fallbackChain:d(e,a,o),direction:x(e),defaultLocale:a}}function C(e,t="specKey"){if(typeof t==="function")return t(e);return t==="domain"?e.meta.domain:e.meta.key}function b(e,t){let n=e.fallbacks??(e.fallback?[e.fallback]:[]);return d(e.locale,t,n)}function m(e,t,n){let a=g(e);if(a.locale)return a.locale;return t.push({code:"i18next_invalid_locale",level:"warning",message:a.error??`Invalid locale ${e}`,locale:e,specKey:n}),e}function y(e,t,n){if(t.fallbackLng!==void 0)return t.fallbackLng;if(t.includeFallbackLng===!1)return;if(!e.length)return;let a=new Map;for(let c of e){let s=c.fallbackChain.filter((r)=>r!==c.locale),i=a.get(c.locale);if(i&&i.join("\x00")!==s.join("\x00")){n.push({code:"i18next_fallback_projection_lossy",level:"warning",message:`Multiple fallback chains exist for locale ${c.locale}; keeping authoritative chains in the ContractSpec manifest.`,locale:c.locale,namespace:c.namespace,specKey:c.specKey});return}a.set(c.locale,s)}let o=Object.fromEntries([...a.entries()].filter(([,c])=>c.length>0));if(!Object.keys(o).length)return;return o}function k(e){let t=new Map;for(let n of e){let a=n.fallbackChain.filter((c)=>c!==n.locale).join("\x00"),o=t.get(n.locale);if(o&&o!==a)return!0;t.set(n.locale,a)}return!1}function h(e){return[...new Set(e)]}function L(e,t){let n={},a={},o=[],c=[],s=new Map;for(let i of e){let{spec:r}=i,l=m(r.locale,c,r.meta.key),p=t.defaultLocale??r.defaultLocale??r.fallback??l,u=C(r,t.namespace),f=r.formatter?.syntax??"icu";R(s,u,r,c),E(n,a,l,u),o.push({specKey:r.meta.key,version:r.meta.version,domain:r.meta.domain,namespace:u,locale:l,direction:r.direction??x(l),fallbackChain:b(r,p),syntax:f,owners:r.meta.owners,tags:r.meta.tags,source:i.source,scope:i.scope}),w(f,t,l,u,r.meta.key,c),N(n,a,l,u,i,c)}return D(n,a,o,t,c)}function R(e,t,n,a){let o=e.get(t);if(o&&o!==n.meta.key)a.push({code:"i18next_namespace_collision",level:"warning",message:`Namespace ${t} is shared by ${o} and ${n.meta.key}.`,namespace:t,specKey:n.meta.key});else e.set(t,n.meta.key)}function w(e,t,n,a,o,c){if(e!=="icu"||t.assumeIcuFormatter)return;c.push({code:"i18next_icu_plugin_required",level:"warning",message:"ContractSpec ICU message exported to i18next; use an ICU-capable i18next format plugin for runtime formatting parity.",locale:n,namespace:a,specKey:o})}function E(e,t,n,a){e[n]??={},e[n][a]??={},t[n]??={},t[n][a]??={}}function N(e,t,n,a,o,c){let{spec:s}=o,i=e[n]?.[a],r=t[n]?.[a];if(!i||!r)return;for(let[l,p]of Object.entries(s.messages)){let u=i[l],f=r[l];if(u!==void 0&&(u!==p.value||f?.version!==s.meta.version||f?.source!==o.source||f?.scope!==o.scope)){c.push({code:"i18next_resource_collision",level:"error",message:`Message ${l} collides in ${n}/${a}.`,locale:n,namespace:a,specKey:s.meta.key,messageKey:l});continue}i[l]=p.value,r[l]={specKey:s.meta.key,version:s.meta.version,locale:n,namespace:a,messageKey:l,description:p.description,context:p.context,placeholders:p.placeholders,variants:p.variants,maxLength:p.maxLength,tags:p.tags,pluralRules:s.pluralRules,source:o.source,scope:o.scope}}}function D(e,t,n,a,o){let c=Object.keys(e).sort(),s=h(n.map((r)=>r.namespace)).sort(),i=y(n,a,o);return{resources:e,manifest:{defaultLocale:a.defaultLocale?m(a.defaultLocale,o):void 0,locales:c,namespaces:n,messages:t,diagnostics:o},ns:s,lng:a.lng?m(a.lng,o):void 0,defaultNS:s[0],fallbackLng:i}}function P(e,t={}){return L(e.map((n)=>({spec:n})),t)}function H(e,t={}){let n=e.sources?.length?e.sources.map(({scope:a,source:o,spec:c})=>({scope:a,source:o,spec:c})):e.specs.map((a)=>({spec:a}));return L(n,{defaultLocale:e.defaultLocale,lng:e.locale,fallbackLng:e.fallbackChain,...t})}function J(e,t={}){let n=[],a=t.fallbackLng??e.fallbackLng;if(!a&&k(e.manifest.namespaces))n.push({code:"i18next_fallback_projection_lossy",level:"warning",message:"ContractSpec has per-bundle fallback chains that cannot be represented as one i18next fallbackLng value."});let o={resources:e.resources,ns:e.ns,keySeparator:t.keySeparator??!1},c=t.defaultNS??e.defaultNS;if(c)o.defaultNS=c;let s=t.lng??e.lng??e.manifest.defaultLocale;if(s)o.lng=s;if(a)o.fallbackLng=a;if(t.partialBundledLanguages!==void 0)o.partialBundledLanguages=t.partialBundledLanguages;return{options:o,diagnostics:n}}function Q(e,t,n={}){let a=n.deep??!0,o=n.overwrite??!0;for(let[c,s]of Object.entries(t.resources))for(let[i,r]of Object.entries(s))e.addResourceBundle(c,i,r,a,o)}export{Q as addContractSpecResourceBundles,J as createI18nextInitOptions,P as exportContractSpecToI18next,H as exportTranslationSnapshotToI18next};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
class x{items=[];report(e){this.items.push(e)}list(){return[...this.items]}clear(){this.items.length=0}}var C=new Set(["ar","arc","dv","fa","ha","he","ks","ku","ps","ur","yi"]);function h(e){let t=b(e);return C.has(t)?"rtl":"ltr"}function b(e){try{return new Intl.Locale(e).language.toLowerCase()}catch{return e.split("-")[0]?.toLowerCase()??e.toLowerCase()}}function u(e){let t=e.trim();if(!t)return{input:e,valid:!1,error:"Locale is empty"};try{let a=Intl.getCanonicalLocales(t)[0];return a?{input:e,locale:a,valid:!0}:{input:e,valid:!1,error:"Locale did not canonicalize"}}catch(a){return{input:e,valid:!1,error:a instanceof Error?a.message:"Invalid locale"}}}function f(e=[]){let t=[];for(let a of e){let o=u(a);if(o.locale&&!t.includes(o.locale))t.push(o.locale)}return t}function X(e){let t=u(e.defaultLocale).locale??e.defaultLocale,a=f(e.requestedLocales),o=f(e.supportedLocales),r=f(e.fallbackLocales),n=o.length?o:[t];for(let l of a){let s=g(l,t,r).find((d)=>n.includes(d));if(s)return R(s,a,n,t,r)}return R(t,a,n,t,r)}function g(e,t,a=[]){let o=[],r=(n)=>{if(!n)return;let l=u(n).locale??n;if(!o.includes(l))o.push(l)};r(e);for(let n of k(e))r(n);for(let n of a)r(n);return r(t),o}function k(e){let a=(u(e).locale??e).split("-"),o=[];while(a.length>1)a.pop(),o.push(a.join("-"));return o}function R(e,t,a,o,r){return{locale:e,requestedLocales:t,supportedLocales:a,fallbackChain:g(e,o,r),direction:h(e),defaultLocale:o}}function te(e,t){return g(e,t.defaultLocale,t.locales??[])}import{parse as N,TYPE as p}from"@formatjs/icu-messageformat-parser";import O from"intl-messageformat";function ne(e={}){let t=e.cache??new Map,a=e.precompiled;return{compile({id:o,locale:r,message:n,ast:l}){let i=`${r}\x00${o}\x00${n}`,s=t.get(i);if(s)return s;let d=l??a?.({id:o,locale:r,message:n}),c=new O(d??n,r),m={format(P){let L=c.format(P);return Array.isArray(L)?L.join(""):String(L)}};return t.set(i,m),m},validate(o){try{let r=N(o);return M(r)}catch(r){return{valid:!1,error:r instanceof Error?r.message:"Invalid ICU message",arguments:[],plurals:[],selects:[],selectOrdinals:[]}}}}}function M(e){let t=new Set,a=new Set,o=new Set,r=new Set,n=(l)=>{for(let i of l){let s="value"in i?String(i.value):void 0;if(s&&D(i.type))t.add(s);if(s&&i.type===p.select)o.add(s);if(s&&i.type===p.plural)if(t.add(s),"pluralType"in i&&i.pluralType==="ordinal")r.add(s);else a.add(s);if("options"in i)for(let d of Object.values(i.options))n(d.value)}};return n(e),{valid:!0,arguments:[...t],plurals:[...a],selects:[...o],selectOrdinals:[...r]}}function D(e){return e===p.argument||e===p.number||e===p.date||e===p.time||e===p.select||e===p.plural||e===p.pound||e===p.tag}function ie(e){return{async load(t){return e.filter((a)=>E(a.meta.key,t)&&t.locales.includes(a.locale))}}}function E(e,t){let a=t.specKey!==void 0,o=t.specKeys!==void 0&&t.specKeys.length>0;if(!a&&!o)return!0;if(a&&e===t.specKey)return!0;if(o&&t.specKeys?.includes(e))return!0;return!1}function _(e,t){let a=new Set(e),o=[],r=new Set;for(let n of t){if(a.has(n)||r.has(n))continue;r.add(n),o.push(n)}return o}async function le(e,t){let a=_(t.loaded,t.required);if(a.length===0)return[];return e.load({specKeys:a,locales:t.locales})}function pe(e){return[...e].sort((t,a)=>(t.priority??I(t.scope))-(a.priority??I(a.scope)))}function I(e){switch(e){case"base":return 0;case"package":return 10;case"project":return 20;case"tenant":return 30;case"user":return 40;case"request":return 50}}import A from"intl-messageformat";var y="contractspec.icu.precompiled",T=1;function S(e,t){return`${e}\x00${t}`}function F(e,t){return new A(e,t).getAst()}function w(e){let t={};for(let{locale:a,message:o}of e){let r=S(a,o);if(t[r])continue;t[r]={locale:a,message:o,ast:F(o,a)}}return{kind:y,version:T,entries:t}}function me(e){let t=[];for(let a of e)for(let o of Object.values(a.messages))t.push({locale:a.locale,message:o.value});return w(t)}function fe(e){return JSON.stringify(e)}function ge(e){let t=JSON.parse(e),a=q(t);if(a.length>0)throw Error(a.join("; "));return t}function q(e){let t=[];if(!e||e.kind!==y)t.push("Precompiled ICU catalog kind is invalid.");if(e?.version!==T)t.push("Precompiled ICU catalog version is unsupported.");if(!e?.entries||typeof e.entries!=="object")t.push("Precompiled ICU catalog entries must be an object.");return t}function Le(e){return({locale:t,message:a})=>e.entries[S(t,a)]?.ast}var ye={id:"docs.tech.translation-runtime.icu-precompile",title:"Precompiled ICU AST fast-path",summary:"Build-time ICU AST precompilation with an additive runtime parse-skip fast-path.",kind:"reference",visibility:"public",route:"/docs/tech/translation-runtime/icu-precompile",tags:["i18n","icu","performance","translation-runtime"],body:`# Precompiled ICU AST fast-path
|
|
2
|
+
|
|
3
|
+
Precompiles ICU message strings into the exact \`MessageFormatElement[]\` AST that
|
|
4
|
+
\`intl-messageformat\` produces, so the runtime can skip the per-call parse.
|
|
5
|
+
|
|
6
|
+
- \`precompileIcuMessage(message, locale)\` returns the AST via
|
|
7
|
+
\`IntlMessageFormat#getAst()\` — identical to the on-the-fly string path, so
|
|
8
|
+
formatted output is byte-identical (verified by golden tests across plural,
|
|
9
|
+
select, selectordinal, number, currency, date, and time for en/fr/es/ar-EG).
|
|
10
|
+
- \`buildPrecompiledIcuCatalog\` / \`buildPrecompiledIcuCatalogFromSpecs\` produce a
|
|
11
|
+
serializable \`PrecompiledIcuCatalog\` (\`kind\` =
|
|
12
|
+
\`${y}\`, \`version\` = \`${T}\`) as a
|
|
13
|
+
build-time asset.
|
|
14
|
+
- \`createPrecompiledIcuLookup(catalog)\` yields a lookup the formatter consumes.
|
|
15
|
+
|
|
16
|
+
Wire the lookup via \`createIntlMessageFormatter({ precompiled })\`, or pass a
|
|
17
|
+
per-call \`ast\` on \`compile()\`. When neither is present the formatter parses the
|
|
18
|
+
message string exactly as before — the surface is **ADDITIVE**.
|
|
19
|
+
|
|
20
|
+
Scope: this precompiles the ICU MessageFormat argument grammar
|
|
21
|
+
(plural/select/selectordinal/number/date/time + number skeletons such as
|
|
22
|
+
currency). List and relative-time rendering is performed by \`Intl.ListFormat\` /
|
|
23
|
+
\`Intl.RelativeTimeFormat\` outside the message AST and has no per-call message
|
|
24
|
+
parse to precompile. The \`createI18nFactory\` stack uses simple \`{key}\`
|
|
25
|
+
interpolation (no ICU parse) and is therefore unaffected by this fast-path.
|
|
26
|
+
|
|
27
|
+
Compatibility classification: **ADDITIVE**.
|
|
28
|
+
`};var K=["app","workspace","team","user","request"],U={app:"appLocale",workspace:"workspaceLocale",team:"teamLocale",user:"userLocale",request:"requestLocale"};function Re(e={},t={}){let a=u(t.fallbackLocale??e.defaultLocale??e.appLocale??"en").locale??"en",o=u(e.defaultLocale??e.appLocale??a).locale??a,r={},n=[];for(let c of K){let m=H(e[U[c]]);if(!m)continue;r[c]=m,n.push({source:c,locale:m,metadata:e.sources?.[c]})}let l=f(e.requestedLocales??[]),i=f(t.additionalRequestedLocales??[]),s=[...n].reverse().map((c)=>c.locale),d=V([...l,...i,...s,o]);return{defaultLocale:o,requestedLocales:d,preferenceLocales:r,sources:[...l.map((c)=>({source:"requested",locale:c})),...n]}}function H(e){if(!e)return;return u(e).locale}function V(e){return[...new Set(e)]}var Se="contractspec.translation-runtime.hydration",ve=1;function j(e){return JSON.stringify(e)}function B(e){return JSON.parse(e)}function v(e){return{kind:"contractspec.translation-runtime.hydration",version:1,snapshot:J(e)}}function Pe(e){return JSON.stringify(e)}function xe(e){let t=JSON.parse(e),a=z(t);if(a.length>0)throw Error(a.map((o)=>o.message).join("; "));return v(t.snapshot)}function Ce(e){return{type:"translation-runtime-snapshot",payload:v(e)}}function z(e){let t=[];if(!e||e.kind!=="contractspec.translation-runtime.hydration")t.push({code:"invalid_snapshot",level:"error",message:"Translation hydration payload kind is invalid."});if(e?.version!==1)t.push({code:"invalid_snapshot",level:"error",message:"Translation hydration payload version is unsupported.",context:{version:e?.version}});return t.push(...Y(e?.snapshot)),t}function Y(e){let t=[];if(!e)return[{code:"invalid_snapshot",level:"error",message:"Translation runtime snapshot is missing."}];if(!e.locale)t.push({code:"invalid_snapshot",level:"error",message:"Translation runtime snapshot locale is missing."});if(!e.defaultLocale)t.push({code:"invalid_snapshot",level:"error",message:"Translation runtime snapshot defaultLocale is missing."});for(let[a,o]of[["fallbackChain",e.fallbackChain],["supportedLocales",e.supportedLocales],["specs",e.specs]])if(!Array.isArray(o))t.push({code:"invalid_snapshot",level:"error",message:`Translation runtime snapshot ${a} must be an array.`,context:{field:a}});return t}function J(e){return B(j(e))}export{y as PRECOMPILED_ICU_KIND,T as PRECOMPILED_ICU_VERSION,ye as PrecompiledIcuDocBlock,Se as TRANSLATION_RUNTIME_HYDRATION_KIND,ve as TRANSLATION_RUNTIME_HYDRATION_VERSION,x as TranslationDiagnosticsCollector,g as buildLocaleFallbackChain,w as buildPrecompiledIcuCatalog,me as buildPrecompiledIcuCatalogFromSpecs,u as canonicalizeLocale,f as canonicalizeLocales,_ as computeShardDelta,ne as createIntlMessageFormatter,Le as createPrecompiledIcuLookup,ie as createStaticBundleLoader,v as createTranslationHydrationPayload,Ce as createTranslationSnapshotStreamChunk,I as defaultOverridePriority,b as getLanguageSubtag,h as getTextDirection,le as loadShardDelta,X as negotiateLocale,ge as parsePrecompiledIcuCatalog,xe as parseTranslationHydrationPayload,B as parseTranslationSnapshot,F as precompileIcuMessage,te as resolveFallbackChain,Re as resolveTranslationPreferenceContext,fe as serializePrecompiledIcuCatalog,Pe as serializeTranslationHydrationPayload,j as serializeTranslationSnapshot,pe as sortOverrideLayers,q as validatePrecompiledIcuCatalog,z as validateTranslationHydrationPayload,Y as validateTranslationSnapshot};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function c(a){return{async load(e){return a.filter((n)=>s(n.meta.key,e)&&e.locales.includes(n.locale))}}}function s(a,e){let n=e.specKey!==void 0,t=e.specKeys!==void 0&&e.specKeys.length>0;if(!n&&!t)return!0;if(n&&a===e.specKey)return!0;if(t&&e.specKeys?.includes(a))return!0;return!1}function l(a,e){let n=new Set(a),t=[],o=new Set;for(let r of e){if(n.has(r)||o.has(r))continue;o.add(r),t.push(r)}return t}async function d(a,e){let n=l(e.loaded,e.required);if(n.length===0)return[];return a.load({specKeys:n,locales:e.locales})}export{l as computeShardDelta,c as createStaticBundleLoader,d as loadShardDelta};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var g=new Set(["ar","arc","dv","fa","ha","he","ks","ku","ps","ur","yi"]);function u(e){let t=p(e);return g.has(t)?"rtl":"ltr"}function p(e){try{return new Intl.Locale(e).language.toLowerCase()}catch{return e.split("-")[0]?.toLowerCase()??e.toLowerCase()}}function r(e){let t=e.trim();if(!t)return{input:e,valid:!1,error:"Locale is empty"};try{let o=Intl.getCanonicalLocales(t)[0];return o?{input:e,locale:o,valid:!0}:{input:e,valid:!1,error:"Locale did not canonicalize"}}catch(o){return{input:e,valid:!1,error:o instanceof Error?o.message:"Invalid locale"}}}function i(e=[]){let t=[];for(let o of e){let a=r(o);if(a.locale&&!t.includes(a.locale))t.push(a.locale)}return t}function m(e){let t=r(e.defaultLocale).locale??e.defaultLocale,o=i(e.requestedLocales),a=i(e.supportedLocales),c=i(e.fallbackLocales),n=a.length?a:[t];for(let l of o){let s=f(l,t,c).find((d)=>n.includes(d));if(s)return L(s,o,n,t,c)}return L(t,o,n,t,c)}function f(e,t,o=[]){let a=[],c=(n)=>{if(!n)return;let l=r(n).locale??n;if(!a.includes(l))a.push(l)};c(e);for(let n of h(e))c(n);for(let n of o)c(n);return c(t),a}function h(e){let o=(r(e).locale??e).split("-"),a=[];while(o.length>1)o.pop(),a.push(o.join("-"));return a}function L(e,t,o,a,c){return{locale:e,requestedLocales:t,supportedLocales:o,fallbackChain:f(e,a,c),direction:u(e),defaultLocale:a}}export{f as buildLocaleFallbackChain,r as canonicalizeLocale,i as canonicalizeLocales,m as negotiateLocale};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function a(e){return[...e].sort((r,t)=>(r.priority??s(r.scope))-(t.priority??s(t.scope)))}function s(e){switch(e){case"base":return 0;case"package":return 10;case"project":return 20;case"tenant":return 30;case"user":return 40;case"request":return 50}}export{s as defaultOverridePriority,a as sortOverrideLayers};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import n from"intl-messageformat";var s="contractspec.icu.precompiled",a=1;function c(t,e){return`${t}\x00${e}`}function l(t,e){return new n(t,e).getAst()}function p(t){let e={};for(let{locale:r,message:o}of t){let i=c(r,o);if(e[i])continue;e[i]={locale:r,message:o,ast:l(o,r)}}return{kind:s,version:a,entries:e}}function d(t){let e=[];for(let r of t)for(let o of Object.values(r.messages))e.push({locale:r.locale,message:o.value});return p(e)}function g(t){return JSON.stringify(t)}function I(t){let e=JSON.parse(t),r=m(e);if(r.length>0)throw Error(r.join("; "));return e}function m(t){let e=[];if(!t||t.kind!==s)e.push("Precompiled ICU catalog kind is invalid.");if(t?.version!==a)e.push("Precompiled ICU catalog version is unsupported.");if(!t?.entries||typeof t.entries!=="object")e.push("Precompiled ICU catalog entries must be an object.");return e}function f(t){return({locale:e,message:r})=>t.entries[c(e,r)]?.ast}var P={id:"docs.tech.translation-runtime.icu-precompile",title:"Precompiled ICU AST fast-path",summary:"Build-time ICU AST precompilation with an additive runtime parse-skip fast-path.",kind:"reference",visibility:"public",route:"/docs/tech/translation-runtime/icu-precompile",tags:["i18n","icu","performance","translation-runtime"],body:`# Precompiled ICU AST fast-path
|
|
2
|
+
|
|
3
|
+
Precompiles ICU message strings into the exact \`MessageFormatElement[]\` AST that
|
|
4
|
+
\`intl-messageformat\` produces, so the runtime can skip the per-call parse.
|
|
5
|
+
|
|
6
|
+
- \`precompileIcuMessage(message, locale)\` returns the AST via
|
|
7
|
+
\`IntlMessageFormat#getAst()\` — identical to the on-the-fly string path, so
|
|
8
|
+
formatted output is byte-identical (verified by golden tests across plural,
|
|
9
|
+
select, selectordinal, number, currency, date, and time for en/fr/es/ar-EG).
|
|
10
|
+
- \`buildPrecompiledIcuCatalog\` / \`buildPrecompiledIcuCatalogFromSpecs\` produce a
|
|
11
|
+
serializable \`PrecompiledIcuCatalog\` (\`kind\` =
|
|
12
|
+
\`${s}\`, \`version\` = \`${a}\`) as a
|
|
13
|
+
build-time asset.
|
|
14
|
+
- \`createPrecompiledIcuLookup(catalog)\` yields a lookup the formatter consumes.
|
|
15
|
+
|
|
16
|
+
Wire the lookup via \`createIntlMessageFormatter({ precompiled })\`, or pass a
|
|
17
|
+
per-call \`ast\` on \`compile()\`. When neither is present the formatter parses the
|
|
18
|
+
message string exactly as before — the surface is **ADDITIVE**.
|
|
19
|
+
|
|
20
|
+
Scope: this precompiles the ICU MessageFormat argument grammar
|
|
21
|
+
(plural/select/selectordinal/number/date/time + number skeletons such as
|
|
22
|
+
currency). List and relative-time rendering is performed by \`Intl.ListFormat\` /
|
|
23
|
+
\`Intl.RelativeTimeFormat\` outside the message AST and has no per-call message
|
|
24
|
+
parse to precompile. The \`createI18nFactory\` stack uses simple \`{key}\`
|
|
25
|
+
interpolation (no ICU parse) and is therefore unaffected by this fast-path.
|
|
26
|
+
|
|
27
|
+
Compatibility classification: **ADDITIVE**.
|
|
28
|
+
`};export{s as PRECOMPILED_ICU_KIND,a as PRECOMPILED_ICU_VERSION,P as PrecompiledIcuDocBlock,p as buildPrecompiledIcuCatalog,d as buildPrecompiledIcuCatalogFromSpecs,f as createPrecompiledIcuLookup,I as parsePrecompiledIcuCatalog,l as precompileIcuMessage,g as serializePrecompiledIcuCatalog,m as validatePrecompiledIcuCatalog};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var m=new Set(["ar","arc","dv","fa","ha","he","ks","ku","ps","ur","yi"]);function p(e){let o=R(e);return m.has(o)?"rtl":"ltr"}function R(e){try{return new Intl.Locale(e).language.toLowerCase()}catch{return e.split("-")[0]?.toLowerCase()??e.toLowerCase()}}function l(e){let o=e.trim();if(!o)return{input:e,valid:!1,error:"Locale is empty"};try{let a=Intl.getCanonicalLocales(o)[0];return a?{input:e,locale:a,valid:!0}:{input:e,valid:!1,error:"Locale did not canonicalize"}}catch(a){return{input:e,valid:!1,error:a instanceof Error?a.message:"Invalid locale"}}}function i(e=[]){let o=[];for(let a of e){let n=l(a);if(n.locale&&!o.includes(n.locale))o.push(n.locale)}return o}function C(e){let o=l(e.defaultLocale).locale??e.defaultLocale,a=i(e.requestedLocales),n=i(e.supportedLocales),t=i(e.fallbackLocales),r=n.length?n:[o];for(let s of a){let u=T(s,o,t).find((f)=>r.includes(f));if(u)return g(u,a,r,o,t)}return g(o,a,r,o,t)}function T(e,o,a=[]){let n=[],t=(r)=>{if(!r)return;let s=l(r).locale??r;if(!n.includes(s))n.push(s)};t(e);for(let r of P(e))t(r);for(let r of a)t(r);return t(o),n}function P(e){let a=(l(e).locale??e).split("-"),n=[];while(a.length>1)a.pop(),n.push(a.join("-"));return n}function g(e,o,a,n,t){return{locale:e,requestedLocales:o,supportedLocales:a,fallbackChain:T(e,n,t),direction:p(e),defaultLocale:n}}var h=["app","workspace","team","user","request"],x={app:"appLocale",workspace:"workspaceLocale",team:"teamLocale",user:"userLocale",request:"requestLocale"};function E(e={},o={}){let a=l(o.fallbackLocale??e.defaultLocale??e.appLocale??"en").locale??"en",n=l(e.defaultLocale??e.appLocale??a).locale??a,t={},r=[];for(let c of h){let L=q(e[x[c]]);if(!L)continue;t[c]=L,r.push({source:c,locale:L,metadata:e.sources?.[c]})}let s=i(e.requestedLocales??[]),d=i(o.additionalRequestedLocales??[]),u=[...r].reverse().map((c)=>c.locale),f=y([...s,...d,...u,n]);return{defaultLocale:n,requestedLocales:f,preferenceLocales:t,sources:[...s.map((c)=>({source:"requested",locale:c})),...r]}}function q(e){if(!e)return;return l(e).locale}function y(e){return[...new Set(e)]}export{E as resolveTranslationPreferenceContext};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var c="contractspec.translation-runtime.hydration",T=1;function s(n){return JSON.stringify(n)}function e(n){return JSON.parse(n)}function i(n){return{kind:"contractspec.translation-runtime.hydration",version:1,snapshot:p(n)}}function u(n){return JSON.stringify(n)}function d(n){let a=JSON.parse(n),t=r(a);if(t.length>0)throw Error(t.map((o)=>o.message).join("; "));return i(a.snapshot)}function m(n){return{type:"translation-runtime-snapshot",payload:i(n)}}function r(n){let a=[];if(!n||n.kind!=="contractspec.translation-runtime.hydration")a.push({code:"invalid_snapshot",level:"error",message:"Translation hydration payload kind is invalid."});if(n?.version!==1)a.push({code:"invalid_snapshot",level:"error",message:"Translation hydration payload version is unsupported.",context:{version:n?.version}});return a.push(...l(n?.snapshot)),a}function l(n){let a=[];if(!n)return[{code:"invalid_snapshot",level:"error",message:"Translation runtime snapshot is missing."}];if(!n.locale)a.push({code:"invalid_snapshot",level:"error",message:"Translation runtime snapshot locale is missing."});if(!n.defaultLocale)a.push({code:"invalid_snapshot",level:"error",message:"Translation runtime snapshot defaultLocale is missing."});for(let[t,o]of[["fallbackChain",n.fallbackChain],["supportedLocales",n.supportedLocales],["specs",n.specs]])if(!Array.isArray(o))a.push({code:"invalid_snapshot",level:"error",message:`Translation runtime snapshot ${t} must be an array.`,context:{field:t}});return a}function p(n){return e(s(n))}export{c as TRANSLATION_RUNTIME_HYDRATION_KIND,T as TRANSLATION_RUNTIME_HYDRATION_VERSION,i as createTranslationHydrationPayload,m as createTranslationSnapshotStreamChunk,d as parseTranslationHydrationPayload,e as parseTranslationSnapshot,u as serializeTranslationHydrationPayload,s as serializeTranslationSnapshot,r as validateTranslationHydrationPayload,l as validateTranslationSnapshot};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TranslationSpec } from '@lssm/lib.contracts-spec/translations';
|
|
2
|
+
export type OverrideScope = 'base' | 'package' | 'project' | 'tenant' | 'user' | 'request';
|
|
3
|
+
export interface OverrideLayer {
|
|
4
|
+
scope: OverrideScope;
|
|
5
|
+
source: string;
|
|
6
|
+
specs: readonly TranslationSpec[];
|
|
7
|
+
priority?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function sortOverrideLayers(layers: readonly OverrideLayer[]): OverrideLayer[];
|
|
10
|
+
export declare function defaultOverridePriority(scope: OverrideScope): number;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
function a(e){return[...e].sort((r,t)=>(r.priority??s(r.scope))-(t.priority??s(t.scope)))}function s(e){switch(e){case"base":return 0;case"package":return 10;case"project":return 20;case"tenant":return 30;case"user":return 40;case"request":return 50}}export{s as defaultOverridePriority,a as sortOverrideLayers};
|
|
Binary file
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import n from"intl-messageformat";var s="contractspec.icu.precompiled",a=1;function c(t,e){return`${t}\x00${e}`}function l(t,e){return new n(t,e).getAst()}function p(t){let e={};for(let{locale:r,message:o}of t){let i=c(r,o);if(e[i])continue;e[i]={locale:r,message:o,ast:l(o,r)}}return{kind:s,version:a,entries:e}}function d(t){let e=[];for(let r of t)for(let o of Object.values(r.messages))e.push({locale:r.locale,message:o.value});return p(e)}function g(t){return JSON.stringify(t)}function I(t){let e=JSON.parse(t),r=m(e);if(r.length>0)throw Error(r.join("; "));return e}function m(t){let e=[];if(!t||t.kind!==s)e.push("Precompiled ICU catalog kind is invalid.");if(t?.version!==a)e.push("Precompiled ICU catalog version is unsupported.");if(!t?.entries||typeof t.entries!=="object")e.push("Precompiled ICU catalog entries must be an object.");return e}function f(t){return({locale:e,message:r})=>t.entries[c(e,r)]?.ast}var P={id:"docs.tech.translation-runtime.icu-precompile",title:"Precompiled ICU AST fast-path",summary:"Build-time ICU AST precompilation with an additive runtime parse-skip fast-path.",kind:"reference",visibility:"public",route:"/docs/tech/translation-runtime/icu-precompile",tags:["i18n","icu","performance","translation-runtime"],body:`# Precompiled ICU AST fast-path
|
|
3
|
+
|
|
4
|
+
Precompiles ICU message strings into the exact \`MessageFormatElement[]\` AST that
|
|
5
|
+
\`intl-messageformat\` produces, so the runtime can skip the per-call parse.
|
|
6
|
+
|
|
7
|
+
- \`precompileIcuMessage(message, locale)\` returns the AST via
|
|
8
|
+
\`IntlMessageFormat#getAst()\` \u2014 identical to the on-the-fly string path, so
|
|
9
|
+
formatted output is byte-identical (verified by golden tests across plural,
|
|
10
|
+
select, selectordinal, number, currency, date, and time for en/fr/es/ar-EG).
|
|
11
|
+
- \`buildPrecompiledIcuCatalog\` / \`buildPrecompiledIcuCatalogFromSpecs\` produce a
|
|
12
|
+
serializable \`PrecompiledIcuCatalog\` (\`kind\` =
|
|
13
|
+
\`${s}\`, \`version\` = \`${a}\`) as a
|
|
14
|
+
build-time asset.
|
|
15
|
+
- \`createPrecompiledIcuLookup(catalog)\` yields a lookup the formatter consumes.
|
|
16
|
+
|
|
17
|
+
Wire the lookup via \`createIntlMessageFormatter({ precompiled })\`, or pass a
|
|
18
|
+
per-call \`ast\` on \`compile()\`. When neither is present the formatter parses the
|
|
19
|
+
message string exactly as before \u2014 the surface is **ADDITIVE**.
|
|
20
|
+
|
|
21
|
+
Scope: this precompiles the ICU MessageFormat argument grammar
|
|
22
|
+
(plural/select/selectordinal/number/date/time + number skeletons such as
|
|
23
|
+
currency). List and relative-time rendering is performed by \`Intl.ListFormat\` /
|
|
24
|
+
\`Intl.RelativeTimeFormat\` outside the message AST and has no per-call message
|
|
25
|
+
parse to precompile. The \`createI18nFactory\` stack uses simple \`{key}\`
|
|
26
|
+
interpolation (no ICU parse) and is therefore unaffected by this fast-path.
|
|
27
|
+
|
|
28
|
+
Compatibility classification: **ADDITIVE**.
|
|
29
|
+
`};export{s as PRECOMPILED_ICU_KIND,a as PRECOMPILED_ICU_VERSION,P as PrecompiledIcuDocBlock,p as buildPrecompiledIcuCatalog,d as buildPrecompiledIcuCatalogFromSpecs,f as createPrecompiledIcuLookup,I as parsePrecompiledIcuCatalog,l as precompileIcuMessage,g as serializePrecompiledIcuCatalog,m as validatePrecompiledIcuCatalog};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Locale, TranslationPreferenceContext, TranslationPreferenceSource, TranslationPreferenceSourceMetadata } from '@lssm/lib.contracts-spec/translations';
|
|
2
|
+
export interface ResolvedTranslationPreferenceSource {
|
|
3
|
+
source: TranslationPreferenceSource | 'requested';
|
|
4
|
+
locale: Locale;
|
|
5
|
+
metadata?: TranslationPreferenceSourceMetadata;
|
|
6
|
+
}
|
|
7
|
+
export interface TranslationPreferenceResolution {
|
|
8
|
+
defaultLocale: Locale;
|
|
9
|
+
requestedLocales: Locale[];
|
|
10
|
+
preferenceLocales: Partial<Record<TranslationPreferenceSource, Locale>>;
|
|
11
|
+
sources: ResolvedTranslationPreferenceSource[];
|
|
12
|
+
}
|
|
13
|
+
export interface ResolveTranslationPreferenceOptions {
|
|
14
|
+
fallbackLocale?: Locale;
|
|
15
|
+
additionalRequestedLocales?: readonly Locale[];
|
|
16
|
+
}
|
|
17
|
+
export declare function resolveTranslationPreferenceContext(context?: TranslationPreferenceContext, options?: ResolveTranslationPreferenceOptions): TranslationPreferenceResolution;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var m=new Set(["ar","arc","dv","fa","ha","he","ks","ku","ps","ur","yi"]);function p(e){let o=R(e);return m.has(o)?"rtl":"ltr"}function R(e){try{return new Intl.Locale(e).language.toLowerCase()}catch{return e.split("-")[0]?.toLowerCase()??e.toLowerCase()}}function l(e){let o=e.trim();if(!o)return{input:e,valid:!1,error:"Locale is empty"};try{let a=Intl.getCanonicalLocales(o)[0];return a?{input:e,locale:a,valid:!0}:{input:e,valid:!1,error:"Locale did not canonicalize"}}catch(a){return{input:e,valid:!1,error:a instanceof Error?a.message:"Invalid locale"}}}function i(e=[]){let o=[];for(let a of e){let n=l(a);if(n.locale&&!o.includes(n.locale))o.push(n.locale)}return o}function C(e){let o=l(e.defaultLocale).locale??e.defaultLocale,a=i(e.requestedLocales),n=i(e.supportedLocales),t=i(e.fallbackLocales),r=n.length?n:[o];for(let s of a){let u=T(s,o,t).find((f)=>r.includes(f));if(u)return g(u,a,r,o,t)}return g(o,a,r,o,t)}function T(e,o,a=[]){let n=[],t=(r)=>{if(!r)return;let s=l(r).locale??r;if(!n.includes(s))n.push(s)};t(e);for(let r of P(e))t(r);for(let r of a)t(r);return t(o),n}function P(e){let a=(l(e).locale??e).split("-"),n=[];while(a.length>1)a.pop(),n.push(a.join("-"));return n}function g(e,o,a,n,t){return{locale:e,requestedLocales:o,supportedLocales:a,fallbackChain:T(e,n,t),direction:p(e),defaultLocale:n}}var h=["app","workspace","team","user","request"],x={app:"appLocale",workspace:"workspaceLocale",team:"teamLocale",user:"userLocale",request:"requestLocale"};function E(e={},o={}){let a=l(o.fallbackLocale??e.defaultLocale??e.appLocale??"en").locale??"en",n=l(e.defaultLocale??e.appLocale??a).locale??a,t={},r=[];for(let c of h){let L=q(e[x[c]]);if(!L)continue;t[c]=L,r.push({source:c,locale:L,metadata:e.sources?.[c]})}let s=i(e.requestedLocales??[]),d=i(o.additionalRequestedLocales??[]),u=[...r].reverse().map((c)=>c.locale),f=y([...s,...d,...u,n]);return{defaultLocale:n,requestedLocales:f,preferenceLocales:t,sources:[...s.map((c)=>({source:"requested",locale:c})),...r]}}function q(e){if(!e)return;return l(e).locale}function y(e){return[...new Set(e)]}export{E as resolveTranslationPreferenceContext};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Locale, TranslationSpec } from '@lssm/lib.contracts-spec/translations';
|
|
2
|
+
import type { TranslationDiagnostic } from './diagnostics.js';
|
|
3
|
+
import type { OverrideScope } from './overrides.js';
|
|
4
|
+
export interface TranslationRuntimeSnapshotSource {
|
|
5
|
+
scope: OverrideScope;
|
|
6
|
+
source: string;
|
|
7
|
+
spec: TranslationSpec;
|
|
8
|
+
priority: number;
|
|
9
|
+
sequence: number;
|
|
10
|
+
}
|
|
11
|
+
export interface TranslationRuntimeSnapshot {
|
|
12
|
+
locale: Locale;
|
|
13
|
+
defaultLocale: Locale;
|
|
14
|
+
fallbackChain: Locale[];
|
|
15
|
+
supportedLocales: Locale[];
|
|
16
|
+
specs: TranslationSpec[];
|
|
17
|
+
sources?: TranslationRuntimeSnapshotSource[];
|
|
18
|
+
diagnostics?: TranslationDiagnostic[];
|
|
19
|
+
}
|
|
20
|
+
export declare const TRANSLATION_RUNTIME_HYDRATION_KIND = "contractspec.translation-runtime.hydration";
|
|
21
|
+
export declare const TRANSLATION_RUNTIME_HYDRATION_VERSION = 1;
|
|
22
|
+
export interface TranslationRuntimeHydrationPayload {
|
|
23
|
+
kind: typeof TRANSLATION_RUNTIME_HYDRATION_KIND;
|
|
24
|
+
version: typeof TRANSLATION_RUNTIME_HYDRATION_VERSION;
|
|
25
|
+
snapshot: TranslationRuntimeSnapshot;
|
|
26
|
+
}
|
|
27
|
+
export interface TranslationRuntimeStreamChunk {
|
|
28
|
+
type: 'translation-runtime-snapshot';
|
|
29
|
+
payload: TranslationRuntimeHydrationPayload;
|
|
30
|
+
}
|
|
31
|
+
export declare function serializeTranslationSnapshot(snapshot: TranslationRuntimeSnapshot): string;
|
|
32
|
+
export declare function parseTranslationSnapshot(serialized: string): TranslationRuntimeSnapshot;
|
|
33
|
+
export declare function createTranslationHydrationPayload(snapshot: TranslationRuntimeSnapshot): TranslationRuntimeHydrationPayload;
|
|
34
|
+
export declare function serializeTranslationHydrationPayload(payload: TranslationRuntimeHydrationPayload): string;
|
|
35
|
+
export declare function parseTranslationHydrationPayload(serialized: string): TranslationRuntimeHydrationPayload;
|
|
36
|
+
export declare function createTranslationSnapshotStreamChunk(snapshot: TranslationRuntimeSnapshot): TranslationRuntimeStreamChunk;
|
|
37
|
+
export declare function validateTranslationHydrationPayload(payload: Partial<TranslationRuntimeHydrationPayload> | undefined): TranslationDiagnostic[];
|
|
38
|
+
export declare function validateTranslationSnapshot(snapshot: Partial<TranslationRuntimeSnapshot> | undefined): TranslationDiagnostic[];
|
package/dist/snapshot.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var c="contractspec.translation-runtime.hydration",T=1;function s(n){return JSON.stringify(n)}function e(n){return JSON.parse(n)}function i(n){return{kind:"contractspec.translation-runtime.hydration",version:1,snapshot:p(n)}}function u(n){return JSON.stringify(n)}function d(n){let a=JSON.parse(n),t=r(a);if(t.length>0)throw Error(t.map((o)=>o.message).join("; "));return i(a.snapshot)}function m(n){return{type:"translation-runtime-snapshot",payload:i(n)}}function r(n){let a=[];if(!n||n.kind!=="contractspec.translation-runtime.hydration")a.push({code:"invalid_snapshot",level:"error",message:"Translation hydration payload kind is invalid."});if(n?.version!==1)a.push({code:"invalid_snapshot",level:"error",message:"Translation hydration payload version is unsupported.",context:{version:n?.version}});return a.push(...l(n?.snapshot)),a}function l(n){let a=[];if(!n)return[{code:"invalid_snapshot",level:"error",message:"Translation runtime snapshot is missing."}];if(!n.locale)a.push({code:"invalid_snapshot",level:"error",message:"Translation runtime snapshot locale is missing."});if(!n.defaultLocale)a.push({code:"invalid_snapshot",level:"error",message:"Translation runtime snapshot defaultLocale is missing."});for(let[t,o]of[["fallbackChain",n.fallbackChain],["supportedLocales",n.supportedLocales],["specs",n.specs]])if(!Array.isArray(o))a.push({code:"invalid_snapshot",level:"error",message:`Translation runtime snapshot ${t} must be an array.`,context:{field:t}});return a}function p(n){return e(s(n))}export{c as TRANSLATION_RUNTIME_HYDRATION_KIND,T as TRANSLATION_RUNTIME_HYDRATION_VERSION,i as createTranslationHydrationPayload,m as createTranslationSnapshotStreamChunk,d as parseTranslationHydrationPayload,e as parseTranslationSnapshot,u as serializeTranslationHydrationPayload,s as serializeTranslationSnapshot,r as validateTranslationHydrationPayload,l as validateTranslationSnapshot};
|