@fluenti/solid 0.4.0-rc.1 → 0.4.0-rc.3

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.
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./use-i18n-oAO3vYS7.cjs`);let t=require(`solid-js`),n=require(`solid-js/web`),r=require(`@fluenti/core/internal`);function i(e){return typeof Node<`u`&&e instanceof Node}function a(e){return typeof e==`function`&&!e.length?e():e}function o(e){let t=[],n=``;function s(e){let c=a(e);if(c==null||typeof c==`boolean`)return;if(Array.isArray(c)){for(let e of c)s(e);return}if(typeof c==`string`||typeof c==`number`){n+=String(c);return}if(!i(c))return;if(c.nodeType===Node.TEXT_NODE){n+=c.textContent??``;return}if(c.nodeType===Node.DOCUMENT_FRAGMENT_NODE){s(Array.from(c.childNodes));return}let l=t.length,u=o(Array.from(c.childNodes));t.push(c.cloneNode(!1)),t.push(...u.components),u.message===``&&u.components.length===0?n+=`<${l}/>`:n+=`<${l}>${(0,r.offsetIndices)(u.message,l+1)}</${l}>`}return s(e),{message:n,components:t}}function s(e,t){let n=a(t);if(!(n==null||typeof n==`boolean`)){if(Array.isArray(n)){for(let t of n)s(e,t);return}if(typeof n==`string`||typeof n==`number`){e.appendChild(document.createTextNode(String(n)));return}i(n)&&e.appendChild(n)}}function c(e,t){let n=/<(\d+)(?:\/>|(>)([\s\S]*?)<\/\1>)/g,r=[],i=0,a;for(n.lastIndex=0,a=n.exec(e);a!==null;){a.index>i&&r.push(e.slice(i,a.index));let o=Number(a[1]),l=a[2]===void 0;if(!Number.isInteger(o)||o<0||o>=t.length){l||r.push(a[3]??``),i=n.lastIndex,a=n.exec(e);continue}let u=t[o];if(l)u&&r.push(u.cloneNode(!1));else{let e=c(a[2]===void 0?``:a[3],t);if(u){let t=u.cloneNode(!1);s(t,e),r.push(t)}else r.push(a[3]??``)}i=n.lastIndex,a=n.exec(e)}return i<e.length&&r.push(e.slice(i)),r.length<=1?r[0]??``:r}function l(e,t){let n={},i=[];for(let a of e){let e=t[a];if(e===void 0)continue;let s=o(e);n[a]=(0,r.offsetIndices)(s.message,i.length),i.push(...s.components)}for(let[a,s]of Object.entries(t)){if(e.includes(a)||s===void 0)continue;let t=o(s);n[a]=(0,r.offsetIndices)(t.message,i.length),i.push(...t.components)}return{messages:n,components:i}}var u=100;function d(e,t=0){if(t>u)return[{type:`text`,value:e}];let n=[],r=0;for(;r<e.length;){let i=e.indexOf(`<`,r);if(i===-1){n.push({type:`text`,value:e.slice(r)});break}i>r&&n.push({type:`text`,value:e.slice(r,i)});let a=e.slice(i).match(/^<(\w+)\s*\/>/);if(a){n.push({type:`tag`,name:a[1],children:[]}),r=i+a[0].length;continue}let o=e.slice(i).match(/^<(\w+)>/);if(!o){n.push({type:`text`,value:`<`}),r=i+1;continue}let s=o[1],c=i+o[0].length,l=f(e,s,c);if(l===-1){n.push({type:`text`,value:e.slice(i,c)}),r=c;continue}let u=e.slice(c,l),p=`</${s}>`;n.push({type:`tag`,name:s,children:d(u,t+1)}),r=l+p.length}return n}function f(e,t,n){let r=`<${t}>`,i=`</${t}>`,a=1,o=n;for(;o<e.length&&a>0;){let t=e.indexOf(r,o),n=e.indexOf(i,o);if(n===-1)return-1;if(t!==-1&&t<n)a++,o=t+r.length;else{if(a--,a===0)return n;o=n+i.length}}return-1}function p(e,t){let r=e.map(e=>{if(e.type===`text`)return e.value;let r=t[e.name];return r?(0,n.createComponent)(n.Dynamic,{component:r,children:e.children.length>0?p(e.children,t):void 0}):p(e.children,t)});return r.length===1?r[0]:r}var m=r=>{let{t:i}=e.t(),a=(0,t.children)(()=>r.children),s=(0,t.createMemo)(()=>{let e=r.__message??r.message;return typeof e==`function`?e():e}),l=(0,t.createMemo)(()=>r.__components??r.components);return(()=>{let e=s(),t=l();if(e!==void 0&&t)return p(d(i({...r.id===void 0?{}:{id:r.id},message:e,...r.context===void 0?{}:{context:r.context},...r.comment===void 0?{}:{comment:r.comment}})),t);let u=a.toArray();if(u.length===0)return null;let f=o(u),m=i({...r.id===void 0?{}:{id:r.id},message:f.message,...r.context===void 0?{}:{context:r.context},...r.comment===void 0?{}:{comment:r.comment}}),h=f.components.length>0?c(m,f.components):m;return Array.isArray(h)&&h.length>1&&r.tag?(0,n.createComponent)(n.Dynamic,{get component(){return r.tag},children:h}):h})},h=t=>{let{t:i}=e.t();function a(e){return typeof e==`function`?e():e}return(()=>{let e={};for(let n of r.PLURAL_CATEGORIES){let r=a(t[n]);r!==void 0&&(e[n]=r)}let{messages:o,components:s}=l(r.PLURAL_CATEGORIES,e),u=(0,r.buildICUPluralMessage)({...o.zero!==void 0&&{zero:o.zero},...o.one!==void 0&&{one:o.one},...o.two!==void 0&&{two:o.two},...o.few!==void 0&&{few:o.few},...o.many!==void 0&&{many:o.many},other:o.other??``},t.offset),d=i({id:t.id??(t.context===void 0?u:(0,r.hashMessage)(u,t.context)),message:u,...t.context===void 0?{}:{context:t.context},...t.comment===void 0?{}:{comment:t.comment}},{count:t.value}),f=s.length>0?c(d,s):d;return t.tag?(0,n.createComponent)(n.Dynamic,{get component(){return t.tag},children:f}):f})},g=t=>{let{t:i}=e.t(),a=()=>{let e=t.options===void 0?{...Object.fromEntries(Object.entries(t).filter(([e])=>![`value`,`id`,`context`,`comment`,`options`,`other`,`tag`].includes(e))),other:t.other}:{...t.options,other:t.other},n=[...Object.keys(e).filter(e=>e!==`other`),`other`],{messages:a,components:o}=l(n,e),s=(0,r.normalizeSelectForms)(Object.fromEntries([...n].map(e=>[e,a[e]??``]))),u=i({id:t.id??(t.context===void 0?(0,r.buildICUSelectMessage)(s.forms):(0,r.hashMessage)((0,r.buildICUSelectMessage)(s.forms),t.context)),message:(0,r.buildICUSelectMessage)(s.forms),...t.context===void 0?{}:{context:t.context},...t.comment===void 0?{}:{comment:t.comment}},{value:s.valueMap[t.value]??`other`});return o.length>0?c(u,o):u};return(()=>t.tag?(0,n.createComponent)(n.Dynamic,{get component(){return t.tag},get children(){return a()}}):(0,n.memo)(a))};function _(t){let{d:r}=e.t();return(0,n.memo)(()=>r(t.value,t.format))}function v(t){let{n:r}=e.t();return(0,n.memo)(()=>r(t.value,t.format))}exports.DateTime=_,exports.NumberFormat=v,exports.Plural=h,exports.Select=g,exports.Trans=m,Object.defineProperty(exports,`interpolate`,{enumerable:!0,get:function(){return r.interpolate}});
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./use-i18n-B8NgKzjN.cjs`);let t=require(`solid-js`),n=require(`solid-js/web`),r=require(`@fluenti/core/internal`);function i(e){return typeof Node<`u`&&e instanceof Node}function a(e){return typeof e==`function`&&!e.length?e():e}function o(e){let t=[],n=``;function s(e){let c=a(e);if(c==null||typeof c==`boolean`)return;if(Array.isArray(c)){for(let e of c)s(e);return}if(typeof c==`string`||typeof c==`number`){n+=String(c);return}if(!i(c))return;if(c.nodeType===Node.TEXT_NODE){n+=c.textContent??``;return}if(c.nodeType===Node.DOCUMENT_FRAGMENT_NODE){s(Array.from(c.childNodes));return}let l=t.length,u=o(Array.from(c.childNodes));t.push(c.cloneNode(!1)),t.push(...u.components),u.message===``&&u.components.length===0?n+=`<${l}/>`:n+=`<${l}>${(0,r.offsetIndices)(u.message,l+1)}</${l}>`}return s(e),{message:n,components:t}}function s(e,t){let n=a(t);if(!(n==null||typeof n==`boolean`)){if(Array.isArray(n)){for(let t of n)s(e,t);return}if(typeof n==`string`||typeof n==`number`){e.appendChild(document.createTextNode(String(n)));return}i(n)&&e.appendChild(n)}}function c(e,t){let n=/<(\d+)(?:\/>|(>)([\s\S]*?)<\/\1>)/g,r=[],i=0,a;for(n.lastIndex=0,a=n.exec(e);a!==null;){a.index>i&&r.push(e.slice(i,a.index));let o=Number(a[1]),l=a[2]===void 0;if(!Number.isInteger(o)||o<0||o>=t.length){l||r.push(a[3]??``),i=n.lastIndex,a=n.exec(e);continue}let u=t[o];if(l)u&&r.push(u.cloneNode(!1));else{let e=c(a[2]===void 0?``:a[3],t);if(u){let t=u.cloneNode(!1);s(t,e),r.push(t)}else r.push(a[3]??``)}i=n.lastIndex,a=n.exec(e)}return i<e.length&&r.push(e.slice(i)),r.length<=1?r[0]??``:r}function l(e,t){let n={},i=[];for(let a of e){let e=t[a];if(e===void 0)continue;let s=o(e);n[a]=(0,r.offsetIndices)(s.message,i.length),i.push(...s.components)}for(let[a,s]of Object.entries(t)){if(e.includes(a)||s===void 0)continue;let t=o(s);n[a]=(0,r.offsetIndices)(t.message,i.length),i.push(...t.components)}return{messages:n,components:i}}var u=100;function d(e,t=0){if(t>u)return[{type:`text`,value:e}];let n=[],r=0;for(;r<e.length;){let i=e.indexOf(`<`,r);if(i===-1){n.push({type:`text`,value:e.slice(r)});break}i>r&&n.push({type:`text`,value:e.slice(r,i)});let a=e.slice(i).match(/^<(\w+)\s*\/>/);if(a){n.push({type:`tag`,name:a[1],children:[]}),r=i+a[0].length;continue}let o=e.slice(i).match(/^<(\w+)>/);if(!o){n.push({type:`text`,value:`<`}),r=i+1;continue}let s=o[1],c=i+o[0].length,l=f(e,s,c);if(l===-1){n.push({type:`text`,value:e.slice(i,c)}),r=c;continue}let u=e.slice(c,l),p=`</${s}>`;n.push({type:`tag`,name:s,children:d(u,t+1)}),r=l+p.length}return n}function f(e,t,n){let r=`<${t}>`,i=`</${t}>`,a=1,o=n;for(;o<e.length&&a>0;){let t=e.indexOf(r,o),n=e.indexOf(i,o);if(n===-1)return-1;if(t!==-1&&t<n)a++,o=t+r.length;else{if(a--,a===0)return n;o=n+i.length}}return-1}function p(e,t){let r=e.map(e=>{if(e.type===`text`)return e.value;let r=t[e.name];return r?(0,n.createComponent)(n.Dynamic,{component:r,children:e.children.length>0?p(e.children,t):void 0}):p(e.children,t)});return r.length===1?r[0]:r}var m=r=>{let{t:i}=e.t(),a=(0,t.children)(()=>r.children),s=(0,t.createMemo)(()=>{let e=r.__message??r.message;return typeof e==`function`?e():e}),l=(0,t.createMemo)(()=>r.__components??r.components);return(()=>{let e=s(),t=l();if(e!==void 0&&t)return p(d(i({...r.id===void 0?{}:{id:r.id},message:e,...r.context===void 0?{}:{context:r.context},...r.comment===void 0?{}:{comment:r.comment}})),t);let u=a.toArray();if(u.length===0)return null;let f=o(u),m=i({...r.id===void 0?{}:{id:r.id},message:f.message,...r.context===void 0?{}:{context:r.context},...r.comment===void 0?{}:{comment:r.comment}}),h=f.components.length>0?c(m,f.components):m;return Array.isArray(h)&&h.length>1&&r.tag?(0,n.createComponent)(n.Dynamic,{get component(){return r.tag},children:h}):h})},h=t=>{let{t:i}=e.t();function a(e){return typeof e==`function`?e():e}return(()=>{let e={};for(let n of r.PLURAL_CATEGORIES){let r=a(t[n]);r!==void 0&&(e[n]=r)}let{messages:o,components:s}=l(r.PLURAL_CATEGORIES,e),u=(0,r.buildICUPluralMessage)({...o.zero!==void 0&&{zero:o.zero},...o.one!==void 0&&{one:o.one},...o.two!==void 0&&{two:o.two},...o.few!==void 0&&{few:o.few},...o.many!==void 0&&{many:o.many},other:o.other??``},t.offset),d=i({id:t.id??(t.context===void 0?u:(0,r.hashMessage)(u,t.context)),message:u,...t.context===void 0?{}:{context:t.context},...t.comment===void 0?{}:{comment:t.comment}},{count:t.value}),f=s.length>0?c(d,s):d;return t.tag?(0,n.createComponent)(n.Dynamic,{get component(){return t.tag},children:f}):f})},g=t=>{let{t:i}=e.t(),a=()=>{let e=t.options===void 0?{...Object.fromEntries(Object.entries(t).filter(([e])=>![`value`,`id`,`context`,`comment`,`options`,`other`,`tag`].includes(e))),other:t.other}:{...t.options,other:t.other},n=[...Object.keys(e).filter(e=>e!==`other`),`other`],{messages:a,components:o}=l(n,e),s=(0,r.normalizeSelectForms)(Object.fromEntries([...n].map(e=>[e,a[e]??``]))),u=i({id:t.id??(t.context===void 0?(0,r.buildICUSelectMessage)(s.forms):(0,r.hashMessage)((0,r.buildICUSelectMessage)(s.forms),t.context)),message:(0,r.buildICUSelectMessage)(s.forms),...t.context===void 0?{}:{context:t.context},...t.comment===void 0?{}:{comment:t.comment}},{value:s.valueMap[t.value]??`other`});return o.length>0?c(u,o):u};return(()=>t.tag?(0,n.createComponent)(n.Dynamic,{get component(){return t.tag},get children(){return a()}}):(0,n.memo)(a))};function _(t){let{d:r}=e.t();return(0,n.memo)(()=>r(t.value,t.format))}function v(t){let{n:r}=e.t();return(0,n.memo)(()=>r(t.value,t.format))}exports.DateTime=_,exports.NumberFormat=v,exports.Plural=h,exports.Select=g,exports.Trans=m,Object.defineProperty(exports,`interpolate`,{enumerable:!0,get:function(){return r.interpolate}});
2
2
  //# sourceMappingURL=components-entry.cjs.map
@@ -1,4 +1,4 @@
1
- import { t as e } from "./use-i18n-DPb98Dw1.js";
1
+ import { t as e } from "./use-i18n-5u9iEPWp.js";
2
2
  import { children as t, createMemo as n } from "solid-js";
3
3
  import { Dynamic as r, createComponent as i, memo as a } from "solid-js/web";
4
4
  import { PLURAL_CATEGORIES as o, buildICUPluralMessage as s, buildICUSelectMessage as c, hashMessage as l, interpolate as u, normalizeSelectForms as d, offsetIndices as f } from "@fluenti/core/internal";
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./use-i18n-oAO3vYS7.cjs`);let t=require(`@fluenti/core`);var n=((...e)=>{throw Error("[fluenti] `t` imported from '@fluenti/solid' is a compile-time API. Use it only with the Fluenti build transform inside a component or custom hook. For runtime lookups, use useI18n().t(...).")});exports.I18nProvider=e.n,exports.createFluentiContext=e.r,Object.defineProperty(exports,`msg`,{enumerable:!0,get:function(){return t.msg}}),exports.t=n,exports.useI18n=e.t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./use-i18n-B8NgKzjN.cjs`);let t=require(`@fluenti/core`);var n=((...e)=>{throw Error("[fluenti] `t` imported from '@fluenti/solid' is a compile-time API. Use it only with the Fluenti build transform inside a component or custom hook. For runtime lookups, use useI18n().t(...).")});exports.I18nProvider=e.r,exports.createFluentiContext=e.i,Object.defineProperty(exports,`msg`,{enumerable:!0,get:function(){return t.msg}}),exports.t=n,exports.useI18n=e.t,exports.useLocale=e.n;
2
2
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { createFluentiContext } from './context';
2
2
  export type { FluentiContext, FluentiConfig } from './context';
3
3
  export { I18nProvider } from './provider';
4
- export { useI18n } from './use-i18n';
4
+ export { useI18n, useLocale } from './use-i18n';
5
5
  export { t } from './compile-time-t';
6
6
  export { msg } from './msg';
7
7
  export type { FluentiTransProps } from './trans';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAChD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACpC,OAAO,EAAE,CAAC,EAAE,MAAM,kBAAkB,CAAA;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAI3B,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAClD,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAClD,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAChF,YAAY,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAChD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,EAAE,CAAC,EAAE,MAAM,kBAAkB,CAAA;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAI3B,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAClD,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAClD,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAChF,YAAY,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAA"}
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import { n as e, r as t, t as n } from "./use-i18n-DPb98Dw1.js";
2
- import { msg as r } from "@fluenti/core";
1
+ import { i as e, n as t, r as n, t as r } from "./use-i18n-5u9iEPWp.js";
2
+ import { msg as i } from "@fluenti/core";
3
3
  //#region src/compile-time-t.ts
4
- var i = ((...e) => {
4
+ var a = ((...e) => {
5
5
  throw Error("[fluenti] `t` imported from '@fluenti/solid' is a compile-time API. Use it only with the Fluenti build transform inside a component or custom hook. For runtime lookups, use useI18n().t(...).");
6
6
  });
7
7
  //#endregion
8
- export { e as I18nProvider, t as createFluentiContext, r as msg, i as t, n as useI18n };
8
+ export { n as I18nProvider, e as createFluentiContext, i as msg, a as t, r as useI18n, t as useLocale };
9
9
 
10
10
  //# sourceMappingURL=index.js.map
@@ -86,7 +86,7 @@ function d(e) {
86
86
  ...h.numberFormats
87
87
  }
88
88
  };
89
- e.fallbackLocale !== void 0 && (_.fallbackLocale = e.fallbackLocale), h.fallbackChain !== void 0 && (_.fallbackChain = h.fallbackChain), e.missing !== void 0 && (_.missing = e.missing), h.diagnostics !== void 0 && (_.diagnostics = h.diagnostics), h.interpolate !== void 0 && (_.interpolate = h.interpolate);
89
+ e.fallbackLocale !== void 0 && (_.fallbackLocale = e.fallbackLocale), h.fallbackChain !== void 0 && (_.fallbackChain = h.fallbackChain), e.missing !== void 0 && (_.missing = e.missing), h.diagnostics !== void 0 && (_.diagnostics = h.diagnostics), h.interpolate !== void 0 && (_.interpolate = h.interpolate), _.devWarnings = _.devWarnings ?? (typeof process < "u" && process.env.NODE_ENV === "development");
90
90
  let v = r(_);
91
91
  function y(e, ...t) {
92
92
  let r = n();
@@ -195,7 +195,10 @@ function m() {
195
195
  if (e) return e;
196
196
  throw Error("useI18n() must be used inside an <I18nProvider>.");
197
197
  }
198
+ function h() {
199
+ return m().locale;
200
+ }
198
201
  //#endregion
199
- export { p as n, d as r, m as t };
202
+ export { d as i, h as n, p as r, m as t };
200
203
 
201
- //# sourceMappingURL=use-i18n-DPb98Dw1.js.map
204
+ //# sourceMappingURL=use-i18n-5u9iEPWp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-i18n-5u9iEPWp.js","names":["createContext","ParentComponent","createFluentiContext","FluentiConfig","FluentiContext","I18nCtx","I18nProvider","props","ctx","_$createComponent","Provider","value","children"],"sources":["../src/context.ts","../src/provider.tsx","../src/use-i18n.ts"],"sourcesContent":["import { createSignal, type Accessor } from 'solid-js'\nimport { createFluentiCore } from '@fluenti/core'\nimport type { FluentiCoreConfig, FluentiCoreConfigFull, Locale, LocalizedString, Messages, CompiledMessage, MessageDescriptor, DateFormatOptions, NumberFormatOptions, DiagnosticsConfig, CustomFormatter } from '@fluenti/core'\n\n/** Chunk loader for lazy locale loading */\nexport type ChunkLoader = (\n locale: string,\n) => Promise<Record<string, CompiledMessage> | { default: Record<string, CompiledMessage> }>\n\ninterface SplitRuntimeModule {\n __switchLocale?: (locale: string) => Promise<void>\n __preloadLocale?: (locale: string) => Promise<void>\n}\n\nconst SPLIT_RUNTIME_KEY = Symbol.for('fluenti.runtime.solid.v1')\n\nfunction getSplitRuntimeModule(): SplitRuntimeModule | null {\n const runtime = (globalThis as Record<PropertyKey, unknown>)[SPLIT_RUNTIME_KEY]\n return typeof runtime === 'object' && runtime !== null\n ? runtime as SplitRuntimeModule\n : null\n}\n\nfunction resolveChunkMessages(\n loaded: Record<string, CompiledMessage> | { default: Record<string, CompiledMessage> },\n): Record<string, CompiledMessage> {\n return typeof loaded === 'object' && loaded !== null && 'default' in loaded\n ? (loaded as { default: Record<string, CompiledMessage> }).default\n : loaded\n}\n\n/** @internal Map locale → default currency code */\nconst LOCALE_CURRENCY_MAP: Record<string, string> = {\n 'en': 'USD', 'en-US': 'USD', 'en-GB': 'GBP', 'en-AU': 'AUD', 'en-CA': 'CAD',\n 'zh-CN': 'CNY', 'zh-TW': 'TWD', 'zh-HK': 'HKD',\n 'ja': 'JPY', 'ja-JP': 'JPY',\n 'ko': 'KRW', 'ko-KR': 'KRW',\n 'de': 'EUR', 'de-DE': 'EUR', 'de-AT': 'EUR',\n 'fr': 'EUR', 'fr-FR': 'EUR', 'fr-CA': 'CAD',\n 'es': 'EUR', 'es-ES': 'EUR', 'es-MX': 'MXN',\n 'pt': 'EUR', 'pt-BR': 'BRL', 'pt-PT': 'EUR',\n 'it': 'EUR', 'ru': 'RUB', 'ar': 'SAR', 'hi': 'INR',\n}\n\n/** @internal Built-in date format styles (merged under user-provided dateFormats) */\nconst DEFAULT_DATE_FORMATS: Record<string, Intl.DateTimeFormatOptions> = {\n short: { year: 'numeric', month: 'numeric', day: 'numeric' },\n long: { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' },\n time: { hour: 'numeric', minute: 'numeric' },\n datetime: { year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric' },\n}\n\n/** @internal Built-in number format styles (merged under user-provided numberFormats) */\nconst DEFAULT_NUMBER_FORMATS: Record<string, Intl.NumberFormatOptions | ((locale: Locale) => Intl.NumberFormatOptions)> = {\n currency: (locale: string) => ({\n style: 'currency',\n currency: LOCALE_CURRENCY_MAP[locale] ?? LOCALE_CURRENCY_MAP[locale.split('-')[0]!] ?? 'USD',\n }),\n percent: { style: 'percent' },\n decimal: { minimumFractionDigits: 2, maximumFractionDigits: 2 },\n}\n\n/** Extended config with lazy locale loading support */\nexport interface FluentiConfig extends FluentiCoreConfig {\n /** Async chunk loader for lazy locale loading */\n chunkLoader?: ChunkLoader\n /** Enable lazy locale loading through chunkLoader */\n lazyLocaleLoading?: boolean\n /** Locale-specific fallback chains */\n fallbackChain?: Record<string, Locale[]>\n /** Named date format styles */\n dateFormats?: DateFormatOptions\n /** Named number format styles */\n numberFormats?: NumberFormatOptions\n /** Runtime diagnostics configuration */\n diagnostics?: DiagnosticsConfig\n /**\n * Custom message interpolation function.\n *\n * By default, the runtime uses a lightweight `{key}` replacer.\n * Pass the full `interpolate` from `@fluenti/core/internal` for\n * runtime ICU MessageFormat support (plurals, selects, nested arguments).\n */\n interpolate?: (\n message: string,\n values: Record<string, unknown> | undefined,\n locale: string,\n formatters?: Record<string, CustomFormatter>,\n ) => string\n}\n\n/** Reactive i18n context holding locale signal and translation utilities */\nexport interface FluentiContext {\n /** Reactive accessor for the current locale */\n locale(): Locale\n /** Set the active locale (async when lazy locale loading is enabled) */\n setLocale(locale: Locale): Promise<void>\n /** Translate a message by id with optional interpolation values */\n t(id: string | MessageDescriptor, values?: Record<string, unknown>): LocalizedString\n /** Tagged template form: t`Hello ${name}` */\n t(strings: TemplateStringsArray, ...exprs: unknown[]): LocalizedString\n /** Merge additional messages into a locale catalog at runtime */\n loadMessages(locale: Locale, messages: Messages): void\n /** Return all locale codes that have loaded messages */\n getLocales(): Locale[]\n /** Format a date value for the current locale */\n d(value: Date | number, style?: string): LocalizedString\n /** Format a number value for the current locale */\n n(value: number, style?: string): LocalizedString\n /** Format an ICU message string directly (no catalog lookup) */\n format(message: string, values?: Record<string, unknown>): LocalizedString\n /** Whether a locale chunk is currently being loaded */\n isLoading: Accessor<boolean>\n /** Set of locales whose messages have been loaded */\n loadedLocales: Accessor<Set<string>>\n /** Preload a locale in the background without switching to it */\n preloadLocale(locale: string): void\n /** Check if a translation key exists for the given or current locale */\n te(key: string, loc?: string): boolean\n /** Get the raw compiled message for a key without interpolation */\n tm(key: string, loc?: string): CompiledMessage | undefined\n}\n\n/**\n * Create a reactive i18n context backed by Solid signals.\n *\n * The returned `t()` reads the internal `locale()` signal, so any\n * Solid computation that calls `t()` will re-run when the locale changes.\n *\n * @example\n * ```tsx\n * import { createFluentiContext } from '@fluenti/solid'\n * import messages from './locales/compiled/en.js'\n *\n * const ctx = createFluentiContext({\n * locale: 'en',\n * messages: { en: messages },\n * })\n *\n * // Use t`` tagged template (preferred)\n * const greeting = ctx.t`Hello, {name}!`\n * ```\n */\nexport function createFluentiContext(config: FluentiCoreConfig | FluentiConfig): FluentiContext {\n const [locale, setLocaleSignal] = createSignal<Locale>(config.locale)\n const [isLoading, setIsLoading] = createSignal(false)\n const loadedLocalesSet = new Set<string>([config.locale])\n const [loadedLocales, setLoadedLocales] = createSignal(new Set(loadedLocalesSet))\n const messages: Record<string, Messages> = { ...config.messages }\n const i18nConfig = config as FluentiConfig\n const lazyLocaleLoading = i18nConfig.lazyLocaleLoading\n ?? (config as FluentiConfig & { splitting?: boolean }).splitting\n ?? false\n\n // Create a core instance that handles all translation, lookup, fallback, and formatting logic.\n // Merge built-in date/number format styles under user-provided overrides.\n // Build config incrementally to satisfy exactOptionalPropertyTypes —\n // optional properties must not receive `undefined` as a value.\n const coreConfig: FluentiCoreConfigFull = {\n locale: config.locale,\n messages: config.messages ?? {},\n dateFormats: { ...DEFAULT_DATE_FORMATS, ...i18nConfig.dateFormats },\n numberFormats: { ...DEFAULT_NUMBER_FORMATS, ...i18nConfig.numberFormats },\n }\n if (config.fallbackLocale !== undefined) coreConfig.fallbackLocale = config.fallbackLocale\n if (i18nConfig.fallbackChain !== undefined) coreConfig.fallbackChain = i18nConfig.fallbackChain\n if (config.missing !== undefined) coreConfig.missing = config.missing\n if (i18nConfig.diagnostics !== undefined) coreConfig.diagnostics = i18nConfig.diagnostics as FluentiCoreConfigFull['diagnostics']\n if (i18nConfig.interpolate !== undefined) coreConfig.interpolate = i18nConfig.interpolate\n coreConfig.devWarnings = coreConfig.devWarnings ?? (typeof process !== 'undefined' && process.env?.['NODE_ENV'] === 'development')\n const i18n = createFluentiCore(coreConfig)\n\n function t(strings: TemplateStringsArray, ...exprs: unknown[]): LocalizedString\n function t(id: string | MessageDescriptor, values?: Record<string, unknown>): LocalizedString\n function t(idOrStrings: string | MessageDescriptor | TemplateStringsArray, ...rest: unknown[]): LocalizedString {\n const current = locale() // READ SIGNAL → reactive dependency for Solid re-renders\n if (i18n.locale !== current) i18n.locale = current\n // Dispatch to the correct overload based on input type\n if (Array.isArray(idOrStrings) && 'raw' in idOrStrings) {\n return i18n.t(idOrStrings as TemplateStringsArray, ...rest) as LocalizedString\n }\n return i18n.t(idOrStrings as string | MessageDescriptor, rest[0] as Record<string, unknown> | undefined) as LocalizedString\n }\n\n const loadMessages = (loc: Locale, msgs: Messages): void => {\n i18n.loadMessages(loc, msgs)\n // Keep local messages in sync for te/tm which check the local object\n // Intentional mutation: messages record is locally scoped to this context closure\n messages[loc] = { ...messages[loc], ...msgs }\n loadedLocalesSet.add(loc)\n setLoadedLocales(new Set(loadedLocalesSet))\n }\n\n let _localeRequestId = 0\n\n const setLocale = async (newLocale: Locale): Promise<void> => {\n if (!lazyLocaleLoading || !i18nConfig.chunkLoader) {\n setLocaleSignal(newLocale)\n return\n }\n\n const splitRuntime = getSplitRuntimeModule()\n\n if (loadedLocalesSet.has(newLocale)) {\n try {\n if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\n }\n } catch (e) {\n console.warn(`[fluenti] split runtime switch failed for locale \"${newLocale}\"`, e)\n }\n setLocaleSignal(newLocale)\n return\n }\n\n // Race-condition protection: track request ID\n const thisRequest = ++_localeRequestId\n setIsLoading(true)\n try {\n const loaded = resolveChunkMessages(await i18nConfig.chunkLoader(newLocale))\n // Always store loaded messages — they may be needed if locale is switched back\n i18n.loadMessages(newLocale, loaded)\n // Intentional mutation: messages record is locally scoped to this context closure\n messages[newLocale] = { ...messages[newLocale], ...loaded }\n loadedLocalesSet.add(newLocale)\n setLoadedLocales(new Set(loadedLocalesSet))\n // Stale request — a newer setLocale call superseded this one; don't switch locale\n if (thisRequest !== _localeRequestId) return\n try {\n if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\n }\n } catch (e) {\n console.warn(`[fluenti] split runtime switch failed for locale \"${newLocale}\"`, e)\n }\n // Re-check after async __switchLocale — a newer setLocale() may have superseded this one\n if (thisRequest !== _localeRequestId) return\n setLocaleSignal(newLocale)\n } finally {\n if (thisRequest === _localeRequestId) {\n setIsLoading(false)\n }\n }\n }\n\n const _preloadInFlight = new Set<string>()\n\n const preloadLocale = (loc: string): void => {\n if (!lazyLocaleLoading || loadedLocalesSet.has(loc) || !i18nConfig.chunkLoader || _preloadInFlight.has(loc)) return\n _preloadInFlight.add(loc)\n const splitRuntime = getSplitRuntimeModule()\n i18nConfig.chunkLoader(loc).then(async (loaded) => {\n const resolved = resolveChunkMessages(loaded)\n i18n.loadMessages(loc, resolved)\n // Intentional mutation: messages record is locally scoped to this context closure\n messages[loc] = { ...messages[loc], ...resolved }\n loadedLocalesSet.add(loc)\n setLoadedLocales(new Set(loadedLocalesSet))\n if (splitRuntime?.__preloadLocale) {\n await splitRuntime.__preloadLocale(loc)\n }\n }).catch((e: unknown) => {\n console.warn('[fluenti] preload failed:', loc, e)\n }).finally(() => {\n _preloadInFlight.delete(loc)\n })\n }\n\n const getLocales = (): Locale[] => i18n.getLocales()\n\n const d = (value: Date | number, style?: string): LocalizedString => {\n const current = locale() // READ SIGNAL → reactive dependency\n if (i18n.locale !== current) i18n.locale = current\n return i18n.d(value, style) as LocalizedString\n }\n\n const n = (value: number, style?: string): LocalizedString => {\n const current = locale() // READ SIGNAL → reactive dependency\n if (i18n.locale !== current) i18n.locale = current\n return i18n.n(value, style) as LocalizedString\n }\n\n const format = (message: string, values?: Record<string, unknown>): LocalizedString => {\n const current = locale() // READ SIGNAL → reactive dependency\n if (i18n.locale !== current) i18n.locale = current\n return i18n.format(message, values) as LocalizedString\n }\n\n const te = (key: string, loc?: string): boolean => {\n const msgs = messages[loc ?? locale()]\n return msgs !== undefined && key in msgs\n }\n\n const tm = (key: string, loc?: string): CompiledMessage | undefined => {\n const msgs = messages[loc ?? locale()]\n return msgs ? msgs[key] : undefined\n }\n\n return { locale, setLocale, t, loadMessages, getLocales, d, n, format, isLoading, loadedLocales, preloadLocale, te, tm }\n}\n","import { createContext } from 'solid-js'\nimport type { ParentComponent } from 'solid-js'\nimport { createFluentiContext } from './context'\nimport type { FluentiConfig, FluentiContext } from './context'\n\n/** Solid context object for i18n — used internally by useI18n() */\nexport const I18nCtx = createContext<FluentiContext>()\n\n/**\n * Provides the Fluenti i18n context to the Solid component tree.\n *\n * @example\n * ```tsx\n * import { I18nProvider, useI18n } from '@fluenti/solid'\n * import messages from './locales/compiled/en.js'\n *\n * function App() {\n * return (\n * <I18nProvider locale=\"en\" messages={{ en: messages }}>\n * <Content />\n * </I18nProvider>\n * )\n * }\n *\n * function Content() {\n * const { t } = useI18n()\n * return <h1>{t`Welcome to our app`}</h1>\n * }\n * ```\n */\nexport const I18nProvider: ParentComponent<FluentiConfig> = (props) => {\n const ctx = createFluentiContext(props)\n return <I18nCtx.Provider value={ctx}>{props.children}</I18nCtx.Provider>\n}\n","import { useContext } from 'solid-js'\nimport { I18nCtx } from './provider'\nimport type { FluentiContext } from './context'\n\n/**\n * Access the i18n context from the nearest `<I18nProvider>`.\n *\n * Throws if no provider is found in the component tree.\n */\nexport function useI18n(): FluentiContext {\n const ctx = useContext(I18nCtx)\n if (ctx) {\n return ctx\n }\n\n throw new Error(\n 'useI18n() must be used inside an <I18nProvider>.',\n )\n}\n\n/** Shorthand hook that returns only the current locale accessor. */\nexport function useLocale() {\n return useI18n().locale\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ let e=require(`solid-js`),t=require(`@fluenti/core`),n=require(`solid-js/web`);var r=Symbol.for(`fluenti.runtime.solid.v1`);function i(){let e=globalThis[r];return typeof e==`object`&&e?e:null}function a(e){return typeof e==`object`&&e&&`default`in e?e.default:e}var o={en:`USD`,"en-US":`USD`,"en-GB":`GBP`,"en-AU":`AUD`,"en-CA":`CAD`,"zh-CN":`CNY`,"zh-TW":`TWD`,"zh-HK":`HKD`,ja:`JPY`,"ja-JP":`JPY`,ko:`KRW`,"ko-KR":`KRW`,de:`EUR`,"de-DE":`EUR`,"de-AT":`EUR`,fr:`EUR`,"fr-FR":`EUR`,"fr-CA":`CAD`,es:`EUR`,"es-ES":`EUR`,"es-MX":`MXN`,pt:`EUR`,"pt-BR":`BRL`,"pt-PT":`EUR`,it:`EUR`,ru:`RUB`,ar:`SAR`,hi:`INR`},s={short:{year:`numeric`,month:`numeric`,day:`numeric`},long:{year:`numeric`,month:`long`,day:`numeric`,weekday:`long`},time:{hour:`numeric`,minute:`numeric`},datetime:{year:`numeric`,month:`short`,day:`numeric`,hour:`numeric`,minute:`numeric`}},c={currency:e=>({style:`currency`,currency:o[e]??o[e.split(`-`)[0]]??`USD`}),percent:{style:`percent`},decimal:{minimumFractionDigits:2,maximumFractionDigits:2}};function l(n){let[r,o]=(0,e.createSignal)(n.locale),[l,u]=(0,e.createSignal)(!1),d=new Set([n.locale]),[f,p]=(0,e.createSignal)(new Set(d)),m={...n.messages},h=n,g=h.lazyLocaleLoading??n.splitting??!1,_={locale:n.locale,messages:n.messages??{},dateFormats:{...s,...h.dateFormats},numberFormats:{...c,...h.numberFormats}};n.fallbackLocale!==void 0&&(_.fallbackLocale=n.fallbackLocale),h.fallbackChain!==void 0&&(_.fallbackChain=h.fallbackChain),n.missing!==void 0&&(_.missing=n.missing),h.diagnostics!==void 0&&(_.diagnostics=h.diagnostics),h.interpolate!==void 0&&(_.interpolate=h.interpolate),_.devWarnings=_.devWarnings??(typeof process<`u`&&process.env.NODE_ENV===`development`);let v=(0,t.createFluentiCore)(_);function y(e,...t){let n=r();return v.locale!==n&&(v.locale=n),Array.isArray(e)&&`raw`in e?v.t(e,...t):v.t(e,t[0])}let b=(e,t)=>{v.loadMessages(e,t),m[e]={...m[e],...t},d.add(e),p(new Set(d))},x=0,S=async e=>{if(!g||!h.chunkLoader){o(e);return}let t=i();if(d.has(e)){try{t?.__switchLocale&&await t.__switchLocale(e)}catch(t){console.warn(`[fluenti] split runtime switch failed for locale "${e}"`,t)}o(e);return}let n=++x;u(!0);try{let r=a(await h.chunkLoader(e));if(v.loadMessages(e,r),m[e]={...m[e],...r},d.add(e),p(new Set(d)),n!==x)return;try{t?.__switchLocale&&await t.__switchLocale(e)}catch(t){console.warn(`[fluenti] split runtime switch failed for locale "${e}"`,t)}if(n!==x)return;o(e)}finally{n===x&&u(!1)}},C=new Set;return{locale:r,setLocale:S,t:y,loadMessages:b,getLocales:()=>v.getLocales(),d:(e,t)=>{let n=r();return v.locale!==n&&(v.locale=n),v.d(e,t)},n:(e,t)=>{let n=r();return v.locale!==n&&(v.locale=n),v.n(e,t)},format:(e,t)=>{let n=r();return v.locale!==n&&(v.locale=n),v.format(e,t)},isLoading:l,loadedLocales:f,preloadLocale:e=>{if(!g||d.has(e)||!h.chunkLoader||C.has(e))return;C.add(e);let t=i();h.chunkLoader(e).then(async n=>{let r=a(n);v.loadMessages(e,r),m[e]={...m[e],...r},d.add(e),p(new Set(d)),t?.__preloadLocale&&await t.__preloadLocale(e)}).catch(t=>{console.warn(`[fluenti] preload failed:`,e,t)}).finally(()=>{C.delete(e)})},te:(e,t)=>{let n=m[t??r()];return n!==void 0&&e in n},tm:(e,t)=>{let n=m[t??r()];return n?n[e]:void 0}}}var u=(0,e.createContext)(),d=e=>{let t=l(e);return(0,n.createComponent)(u.Provider,{value:t,get children(){return e.children}})};function f(){let t=(0,e.useContext)(u);if(t)return t;throw Error(`useI18n() must be used inside an <I18nProvider>.`)}function p(){return f().locale}Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return f}});
2
+ //# sourceMappingURL=use-i18n-B8NgKzjN.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-i18n-B8NgKzjN.cjs","names":["createContext","ParentComponent","createFluentiContext","FluentiConfig","FluentiContext","I18nCtx","I18nProvider","props","ctx","_$createComponent","Provider","value","children"],"sources":["../src/context.ts","../src/provider.tsx","../src/use-i18n.ts"],"sourcesContent":["import { createSignal, type Accessor } from 'solid-js'\nimport { createFluentiCore } from '@fluenti/core'\nimport type { FluentiCoreConfig, FluentiCoreConfigFull, Locale, LocalizedString, Messages, CompiledMessage, MessageDescriptor, DateFormatOptions, NumberFormatOptions, DiagnosticsConfig, CustomFormatter } from '@fluenti/core'\n\n/** Chunk loader for lazy locale loading */\nexport type ChunkLoader = (\n locale: string,\n) => Promise<Record<string, CompiledMessage> | { default: Record<string, CompiledMessage> }>\n\ninterface SplitRuntimeModule {\n __switchLocale?: (locale: string) => Promise<void>\n __preloadLocale?: (locale: string) => Promise<void>\n}\n\nconst SPLIT_RUNTIME_KEY = Symbol.for('fluenti.runtime.solid.v1')\n\nfunction getSplitRuntimeModule(): SplitRuntimeModule | null {\n const runtime = (globalThis as Record<PropertyKey, unknown>)[SPLIT_RUNTIME_KEY]\n return typeof runtime === 'object' && runtime !== null\n ? runtime as SplitRuntimeModule\n : null\n}\n\nfunction resolveChunkMessages(\n loaded: Record<string, CompiledMessage> | { default: Record<string, CompiledMessage> },\n): Record<string, CompiledMessage> {\n return typeof loaded === 'object' && loaded !== null && 'default' in loaded\n ? (loaded as { default: Record<string, CompiledMessage> }).default\n : loaded\n}\n\n/** @internal Map locale → default currency code */\nconst LOCALE_CURRENCY_MAP: Record<string, string> = {\n 'en': 'USD', 'en-US': 'USD', 'en-GB': 'GBP', 'en-AU': 'AUD', 'en-CA': 'CAD',\n 'zh-CN': 'CNY', 'zh-TW': 'TWD', 'zh-HK': 'HKD',\n 'ja': 'JPY', 'ja-JP': 'JPY',\n 'ko': 'KRW', 'ko-KR': 'KRW',\n 'de': 'EUR', 'de-DE': 'EUR', 'de-AT': 'EUR',\n 'fr': 'EUR', 'fr-FR': 'EUR', 'fr-CA': 'CAD',\n 'es': 'EUR', 'es-ES': 'EUR', 'es-MX': 'MXN',\n 'pt': 'EUR', 'pt-BR': 'BRL', 'pt-PT': 'EUR',\n 'it': 'EUR', 'ru': 'RUB', 'ar': 'SAR', 'hi': 'INR',\n}\n\n/** @internal Built-in date format styles (merged under user-provided dateFormats) */\nconst DEFAULT_DATE_FORMATS: Record<string, Intl.DateTimeFormatOptions> = {\n short: { year: 'numeric', month: 'numeric', day: 'numeric' },\n long: { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' },\n time: { hour: 'numeric', minute: 'numeric' },\n datetime: { year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric' },\n}\n\n/** @internal Built-in number format styles (merged under user-provided numberFormats) */\nconst DEFAULT_NUMBER_FORMATS: Record<string, Intl.NumberFormatOptions | ((locale: Locale) => Intl.NumberFormatOptions)> = {\n currency: (locale: string) => ({\n style: 'currency',\n currency: LOCALE_CURRENCY_MAP[locale] ?? LOCALE_CURRENCY_MAP[locale.split('-')[0]!] ?? 'USD',\n }),\n percent: { style: 'percent' },\n decimal: { minimumFractionDigits: 2, maximumFractionDigits: 2 },\n}\n\n/** Extended config with lazy locale loading support */\nexport interface FluentiConfig extends FluentiCoreConfig {\n /** Async chunk loader for lazy locale loading */\n chunkLoader?: ChunkLoader\n /** Enable lazy locale loading through chunkLoader */\n lazyLocaleLoading?: boolean\n /** Locale-specific fallback chains */\n fallbackChain?: Record<string, Locale[]>\n /** Named date format styles */\n dateFormats?: DateFormatOptions\n /** Named number format styles */\n numberFormats?: NumberFormatOptions\n /** Runtime diagnostics configuration */\n diagnostics?: DiagnosticsConfig\n /**\n * Custom message interpolation function.\n *\n * By default, the runtime uses a lightweight `{key}` replacer.\n * Pass the full `interpolate` from `@fluenti/core/internal` for\n * runtime ICU MessageFormat support (plurals, selects, nested arguments).\n */\n interpolate?: (\n message: string,\n values: Record<string, unknown> | undefined,\n locale: string,\n formatters?: Record<string, CustomFormatter>,\n ) => string\n}\n\n/** Reactive i18n context holding locale signal and translation utilities */\nexport interface FluentiContext {\n /** Reactive accessor for the current locale */\n locale(): Locale\n /** Set the active locale (async when lazy locale loading is enabled) */\n setLocale(locale: Locale): Promise<void>\n /** Translate a message by id with optional interpolation values */\n t(id: string | MessageDescriptor, values?: Record<string, unknown>): LocalizedString\n /** Tagged template form: t`Hello ${name}` */\n t(strings: TemplateStringsArray, ...exprs: unknown[]): LocalizedString\n /** Merge additional messages into a locale catalog at runtime */\n loadMessages(locale: Locale, messages: Messages): void\n /** Return all locale codes that have loaded messages */\n getLocales(): Locale[]\n /** Format a date value for the current locale */\n d(value: Date | number, style?: string): LocalizedString\n /** Format a number value for the current locale */\n n(value: number, style?: string): LocalizedString\n /** Format an ICU message string directly (no catalog lookup) */\n format(message: string, values?: Record<string, unknown>): LocalizedString\n /** Whether a locale chunk is currently being loaded */\n isLoading: Accessor<boolean>\n /** Set of locales whose messages have been loaded */\n loadedLocales: Accessor<Set<string>>\n /** Preload a locale in the background without switching to it */\n preloadLocale(locale: string): void\n /** Check if a translation key exists for the given or current locale */\n te(key: string, loc?: string): boolean\n /** Get the raw compiled message for a key without interpolation */\n tm(key: string, loc?: string): CompiledMessage | undefined\n}\n\n/**\n * Create a reactive i18n context backed by Solid signals.\n *\n * The returned `t()` reads the internal `locale()` signal, so any\n * Solid computation that calls `t()` will re-run when the locale changes.\n *\n * @example\n * ```tsx\n * import { createFluentiContext } from '@fluenti/solid'\n * import messages from './locales/compiled/en.js'\n *\n * const ctx = createFluentiContext({\n * locale: 'en',\n * messages: { en: messages },\n * })\n *\n * // Use t`` tagged template (preferred)\n * const greeting = ctx.t`Hello, {name}!`\n * ```\n */\nexport function createFluentiContext(config: FluentiCoreConfig | FluentiConfig): FluentiContext {\n const [locale, setLocaleSignal] = createSignal<Locale>(config.locale)\n const [isLoading, setIsLoading] = createSignal(false)\n const loadedLocalesSet = new Set<string>([config.locale])\n const [loadedLocales, setLoadedLocales] = createSignal(new Set(loadedLocalesSet))\n const messages: Record<string, Messages> = { ...config.messages }\n const i18nConfig = config as FluentiConfig\n const lazyLocaleLoading = i18nConfig.lazyLocaleLoading\n ?? (config as FluentiConfig & { splitting?: boolean }).splitting\n ?? false\n\n // Create a core instance that handles all translation, lookup, fallback, and formatting logic.\n // Merge built-in date/number format styles under user-provided overrides.\n // Build config incrementally to satisfy exactOptionalPropertyTypes —\n // optional properties must not receive `undefined` as a value.\n const coreConfig: FluentiCoreConfigFull = {\n locale: config.locale,\n messages: config.messages ?? {},\n dateFormats: { ...DEFAULT_DATE_FORMATS, ...i18nConfig.dateFormats },\n numberFormats: { ...DEFAULT_NUMBER_FORMATS, ...i18nConfig.numberFormats },\n }\n if (config.fallbackLocale !== undefined) coreConfig.fallbackLocale = config.fallbackLocale\n if (i18nConfig.fallbackChain !== undefined) coreConfig.fallbackChain = i18nConfig.fallbackChain\n if (config.missing !== undefined) coreConfig.missing = config.missing\n if (i18nConfig.diagnostics !== undefined) coreConfig.diagnostics = i18nConfig.diagnostics as FluentiCoreConfigFull['diagnostics']\n if (i18nConfig.interpolate !== undefined) coreConfig.interpolate = i18nConfig.interpolate\n coreConfig.devWarnings = coreConfig.devWarnings ?? (typeof process !== 'undefined' && process.env?.['NODE_ENV'] === 'development')\n const i18n = createFluentiCore(coreConfig)\n\n function t(strings: TemplateStringsArray, ...exprs: unknown[]): LocalizedString\n function t(id: string | MessageDescriptor, values?: Record<string, unknown>): LocalizedString\n function t(idOrStrings: string | MessageDescriptor | TemplateStringsArray, ...rest: unknown[]): LocalizedString {\n const current = locale() // READ SIGNAL → reactive dependency for Solid re-renders\n if (i18n.locale !== current) i18n.locale = current\n // Dispatch to the correct overload based on input type\n if (Array.isArray(idOrStrings) && 'raw' in idOrStrings) {\n return i18n.t(idOrStrings as TemplateStringsArray, ...rest) as LocalizedString\n }\n return i18n.t(idOrStrings as string | MessageDescriptor, rest[0] as Record<string, unknown> | undefined) as LocalizedString\n }\n\n const loadMessages = (loc: Locale, msgs: Messages): void => {\n i18n.loadMessages(loc, msgs)\n // Keep local messages in sync for te/tm which check the local object\n // Intentional mutation: messages record is locally scoped to this context closure\n messages[loc] = { ...messages[loc], ...msgs }\n loadedLocalesSet.add(loc)\n setLoadedLocales(new Set(loadedLocalesSet))\n }\n\n let _localeRequestId = 0\n\n const setLocale = async (newLocale: Locale): Promise<void> => {\n if (!lazyLocaleLoading || !i18nConfig.chunkLoader) {\n setLocaleSignal(newLocale)\n return\n }\n\n const splitRuntime = getSplitRuntimeModule()\n\n if (loadedLocalesSet.has(newLocale)) {\n try {\n if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\n }\n } catch (e) {\n console.warn(`[fluenti] split runtime switch failed for locale \"${newLocale}\"`, e)\n }\n setLocaleSignal(newLocale)\n return\n }\n\n // Race-condition protection: track request ID\n const thisRequest = ++_localeRequestId\n setIsLoading(true)\n try {\n const loaded = resolveChunkMessages(await i18nConfig.chunkLoader(newLocale))\n // Always store loaded messages — they may be needed if locale is switched back\n i18n.loadMessages(newLocale, loaded)\n // Intentional mutation: messages record is locally scoped to this context closure\n messages[newLocale] = { ...messages[newLocale], ...loaded }\n loadedLocalesSet.add(newLocale)\n setLoadedLocales(new Set(loadedLocalesSet))\n // Stale request — a newer setLocale call superseded this one; don't switch locale\n if (thisRequest !== _localeRequestId) return\n try {\n if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\n }\n } catch (e) {\n console.warn(`[fluenti] split runtime switch failed for locale \"${newLocale}\"`, e)\n }\n // Re-check after async __switchLocale — a newer setLocale() may have superseded this one\n if (thisRequest !== _localeRequestId) return\n setLocaleSignal(newLocale)\n } finally {\n if (thisRequest === _localeRequestId) {\n setIsLoading(false)\n }\n }\n }\n\n const _preloadInFlight = new Set<string>()\n\n const preloadLocale = (loc: string): void => {\n if (!lazyLocaleLoading || loadedLocalesSet.has(loc) || !i18nConfig.chunkLoader || _preloadInFlight.has(loc)) return\n _preloadInFlight.add(loc)\n const splitRuntime = getSplitRuntimeModule()\n i18nConfig.chunkLoader(loc).then(async (loaded) => {\n const resolved = resolveChunkMessages(loaded)\n i18n.loadMessages(loc, resolved)\n // Intentional mutation: messages record is locally scoped to this context closure\n messages[loc] = { ...messages[loc], ...resolved }\n loadedLocalesSet.add(loc)\n setLoadedLocales(new Set(loadedLocalesSet))\n if (splitRuntime?.__preloadLocale) {\n await splitRuntime.__preloadLocale(loc)\n }\n }).catch((e: unknown) => {\n console.warn('[fluenti] preload failed:', loc, e)\n }).finally(() => {\n _preloadInFlight.delete(loc)\n })\n }\n\n const getLocales = (): Locale[] => i18n.getLocales()\n\n const d = (value: Date | number, style?: string): LocalizedString => {\n const current = locale() // READ SIGNAL → reactive dependency\n if (i18n.locale !== current) i18n.locale = current\n return i18n.d(value, style) as LocalizedString\n }\n\n const n = (value: number, style?: string): LocalizedString => {\n const current = locale() // READ SIGNAL → reactive dependency\n if (i18n.locale !== current) i18n.locale = current\n return i18n.n(value, style) as LocalizedString\n }\n\n const format = (message: string, values?: Record<string, unknown>): LocalizedString => {\n const current = locale() // READ SIGNAL → reactive dependency\n if (i18n.locale !== current) i18n.locale = current\n return i18n.format(message, values) as LocalizedString\n }\n\n const te = (key: string, loc?: string): boolean => {\n const msgs = messages[loc ?? locale()]\n return msgs !== undefined && key in msgs\n }\n\n const tm = (key: string, loc?: string): CompiledMessage | undefined => {\n const msgs = messages[loc ?? locale()]\n return msgs ? msgs[key] : undefined\n }\n\n return { locale, setLocale, t, loadMessages, getLocales, d, n, format, isLoading, loadedLocales, preloadLocale, te, tm }\n}\n","import { createContext } from 'solid-js'\nimport type { ParentComponent } from 'solid-js'\nimport { createFluentiContext } from './context'\nimport type { FluentiConfig, FluentiContext } from './context'\n\n/** Solid context object for i18n — used internally by useI18n() */\nexport const I18nCtx = createContext<FluentiContext>()\n\n/**\n * Provides the Fluenti i18n context to the Solid component tree.\n *\n * @example\n * ```tsx\n * import { I18nProvider, useI18n } from '@fluenti/solid'\n * import messages from './locales/compiled/en.js'\n *\n * function App() {\n * return (\n * <I18nProvider locale=\"en\" messages={{ en: messages }}>\n * <Content />\n * </I18nProvider>\n * )\n * }\n *\n * function Content() {\n * const { t } = useI18n()\n * return <h1>{t`Welcome to our app`}</h1>\n * }\n * ```\n */\nexport const I18nProvider: ParentComponent<FluentiConfig> = (props) => {\n const ctx = createFluentiContext(props)\n return <I18nCtx.Provider value={ctx}>{props.children}</I18nCtx.Provider>\n}\n","import { useContext } from 'solid-js'\nimport { I18nCtx } from './provider'\nimport type { FluentiContext } from './context'\n\n/**\n * Access the i18n context from the nearest `<I18nProvider>`.\n *\n * Throws if no provider is found in the component tree.\n */\nexport function useI18n(): FluentiContext {\n const ctx = useContext(I18nCtx)\n if (ctx) {\n return ctx\n }\n\n throw new Error(\n 'useI18n() must be used inside an <I18nProvider>.',\n )\n}\n\n/** Shorthand hook that returns only the current locale accessor. */\nexport function useLocale() {\n return useI18n().locale\n}\n"],"mappings":"+EAcA,IAAM,EAAoB,OAAO,IAAI,2BAA2B,CAEhE,SAAS,GAAmD,CAC1D,IAAM,EAAW,WAA4C,GAC7D,OAAO,OAAO,GAAY,UAAY,EAClC,EACA,KAGN,SAAS,EACP,EACiC,CACjC,OAAO,OAAO,GAAW,UAAY,GAAmB,YAAa,EAChE,EAAwD,QACzD,EAIN,IAAM,EAA8C,CAClD,GAAM,MAAO,QAAS,MAAO,QAAS,MAAO,QAAS,MAAO,QAAS,MACtE,QAAS,MAAO,QAAS,MAAO,QAAS,MACzC,GAAM,MAAO,QAAS,MACtB,GAAM,MAAO,QAAS,MACtB,GAAM,MAAO,QAAS,MAAO,QAAS,MACtC,GAAM,MAAO,QAAS,MAAO,QAAS,MACtC,GAAM,MAAO,QAAS,MAAO,QAAS,MACtC,GAAM,MAAO,QAAS,MAAO,QAAS,MACtC,GAAM,MAAO,GAAM,MAAO,GAAM,MAAO,GAAM,MAC9C,CAGK,EAAmE,CACvE,MAAO,CAAE,KAAM,UAAW,MAAO,UAAW,IAAK,UAAW,CAC5D,KAAM,CAAE,KAAM,UAAW,MAAO,OAAQ,IAAK,UAAW,QAAS,OAAQ,CACzE,KAAM,CAAE,KAAM,UAAW,OAAQ,UAAW,CAC5C,SAAU,CAAE,KAAM,UAAW,MAAO,QAAS,IAAK,UAAW,KAAM,UAAW,OAAQ,UAAW,CAClG,CAGK,EAAoH,CACxH,SAAW,IAAoB,CAC7B,MAAO,WACP,SAAU,EAAoB,IAAW,EAAoB,EAAO,MAAM,IAAI,CAAC,KAAQ,MACxF,EACD,QAAS,CAAE,MAAO,UAAW,CAC7B,QAAS,CAAE,sBAAuB,EAAG,sBAAuB,EAAG,CAChE,CAmFD,SAAgB,EAAqB,EAA2D,CAC9F,GAAM,CAAC,EAAQ,IAAA,EAAA,EAAA,cAAwC,EAAO,OAAO,CAC/D,CAAC,EAAW,IAAA,EAAA,EAAA,cAA6B,GAAM,CAC/C,EAAmB,IAAI,IAAY,CAAC,EAAO,OAAO,CAAC,CACnD,CAAC,EAAe,IAAA,EAAA,EAAA,cAAiC,IAAI,IAAI,EAAiB,CAAC,CAC3E,EAAqC,CAAE,GAAG,EAAO,SAAU,CAC3D,EAAa,EACb,EAAoB,EAAW,mBAC/B,EAAmD,WACpD,GAMC,EAAoC,CACxC,OAAQ,EAAO,OACf,SAAU,EAAO,UAAY,EAAE,CAC/B,YAAa,CAAE,GAAG,EAAsB,GAAG,EAAW,YAAa,CACnE,cAAe,CAAE,GAAG,EAAwB,GAAG,EAAW,cAAe,CAC1E,CACG,EAAO,iBAAmB,IAAA,KAAW,EAAW,eAAiB,EAAO,gBACxE,EAAW,gBAAkB,IAAA,KAAW,EAAW,cAAgB,EAAW,eAC9E,EAAO,UAAY,IAAA,KAAW,EAAW,QAAU,EAAO,SAC1D,EAAW,cAAgB,IAAA,KAAW,EAAW,YAAc,EAAW,aAC1E,EAAW,cAAgB,IAAA,KAAW,EAAW,YAAc,EAAW,aAC9E,EAAW,YAAc,EAAW,cAAgB,OAAO,QAAY,KAAA,QAAA,IAAA,WAA6C,eACpH,IAAM,GAAA,EAAA,EAAA,mBAAyB,EAAW,CAI1C,SAAS,EAAE,EAAgE,GAAG,EAAkC,CAC9G,IAAM,EAAU,GAAQ,CAMxB,OALI,EAAK,SAAW,IAAS,EAAK,OAAS,GAEvC,MAAM,QAAQ,EAAY,EAAI,QAAS,EAClC,EAAK,EAAE,EAAqC,GAAG,EAAK,CAEtD,EAAK,EAAE,EAA2C,EAAK,GAA0C,CAG1G,IAAM,GAAgB,EAAa,IAAyB,CAC1D,EAAK,aAAa,EAAK,EAAK,CAG5B,EAAS,GAAO,CAAE,GAAG,EAAS,GAAM,GAAG,EAAM,CAC7C,EAAiB,IAAI,EAAI,CACzB,EAAiB,IAAI,IAAI,EAAiB,CAAC,EAGzC,EAAmB,EAEjB,EAAY,KAAO,IAAqC,CAC5D,GAAI,CAAC,GAAqB,CAAC,EAAW,YAAa,CACjD,EAAgB,EAAU,CAC1B,OAGF,IAAM,EAAe,GAAuB,CAE5C,GAAI,EAAiB,IAAI,EAAU,CAAE,CACnC,GAAI,CACE,GAAc,gBAChB,MAAM,EAAa,eAAe,EAAU,OAEvC,EAAG,CACV,QAAQ,KAAK,qDAAqD,EAAU,GAAI,EAAE,CAEpF,EAAgB,EAAU,CAC1B,OAIF,IAAM,EAAc,EAAE,EACtB,EAAa,GAAK,CAClB,GAAI,CACF,IAAM,EAAS,EAAqB,MAAM,EAAW,YAAY,EAAU,CAAC,CAQ5E,GANA,EAAK,aAAa,EAAW,EAAO,CAEpC,EAAS,GAAa,CAAE,GAAG,EAAS,GAAY,GAAG,EAAQ,CAC3D,EAAiB,IAAI,EAAU,CAC/B,EAAiB,IAAI,IAAI,EAAiB,CAAC,CAEvC,IAAgB,EAAkB,OACtC,GAAI,CACE,GAAc,gBAChB,MAAM,EAAa,eAAe,EAAU,OAEvC,EAAG,CACV,QAAQ,KAAK,qDAAqD,EAAU,GAAI,EAAE,CAGpF,GAAI,IAAgB,EAAkB,OACtC,EAAgB,EAAU,QAClB,CACJ,IAAgB,GAClB,EAAa,GAAM,GAKnB,EAAmB,IAAI,IAqD7B,MAAO,CAAE,SAAQ,YAAW,IAAG,eAAc,eA9BV,EAAK,YAAY,CA8BK,GA5B9C,EAAsB,IAAoC,CACnE,IAAM,EAAU,GAAQ,CAExB,OADI,EAAK,SAAW,IAAS,EAAK,OAAS,GACpC,EAAK,EAAE,EAAO,EAAM,EAyB+B,GAtBjD,EAAe,IAAoC,CAC5D,IAAM,EAAU,GAAQ,CAExB,OADI,EAAK,SAAW,IAAS,EAAK,OAAS,GACpC,EAAK,EAAE,EAAO,EAAM,EAmBkC,QAhB/C,EAAiB,IAAsD,CACrF,IAAM,EAAU,GAAQ,CAExB,OADI,EAAK,SAAW,IAAS,EAAK,OAAS,GACpC,EAAK,OAAO,EAAS,EAAO,EAakC,YAAW,gBAAe,cAnD1E,GAAsB,CAC3C,GAAI,CAAC,GAAqB,EAAiB,IAAI,EAAI,EAAI,CAAC,EAAW,aAAe,EAAiB,IAAI,EAAI,CAAE,OAC7G,EAAiB,IAAI,EAAI,CACzB,IAAM,EAAe,GAAuB,CAC5C,EAAW,YAAY,EAAI,CAAC,KAAK,KAAO,IAAW,CACjD,IAAM,EAAW,EAAqB,EAAO,CAC7C,EAAK,aAAa,EAAK,EAAS,CAEhC,EAAS,GAAO,CAAE,GAAG,EAAS,GAAM,GAAG,EAAU,CACjD,EAAiB,IAAI,EAAI,CACzB,EAAiB,IAAI,IAAI,EAAiB,CAAC,CACvC,GAAc,iBAChB,MAAM,EAAa,gBAAgB,EAAI,EAEzC,CAAC,MAAO,GAAe,CACvB,QAAQ,KAAK,4BAA6B,EAAK,EAAE,EACjD,CAAC,YAAc,CACf,EAAiB,OAAO,EAAI,EAC5B,EAiC4G,IAVpG,EAAa,IAA0B,CACjD,IAAM,EAAO,EAAS,GAAO,GAAQ,EACrC,OAAO,IAAS,IAAA,IAAa,KAAO,GAQ8E,IALxG,EAAa,IAA8C,CACrE,IAAM,EAAO,EAAS,GAAO,GAAQ,EACrC,OAAO,EAAO,EAAK,GAAO,IAAA,IAG4F,CCpS1H,IAAaK,GAAAA,EAAAA,EAAAA,gBAAyC,CAwBzCC,EAAgDC,GAAU,CACrE,IAAMC,EAAMN,EAAqBK,EAAM,CACvC,OAAA,EAAA,EAAA,iBAAQF,EAAQK,SAAQ,CAACC,MAAOH,EAAG,IAAAI,UAAA,CAAA,OAAGL,EAAMK,UAAQ,CAAA,ECvBtD,SAAgB,GAA0B,CACxC,IAAM,GAAA,EAAA,EAAA,YAAiB,EAAQ,CAC/B,GAAI,EACF,OAAO,EAGT,MAAU,MACR,mDACD,CAIH,SAAgB,GAAY,CAC1B,OAAO,GAAS,CAAC"}
@@ -5,4 +5,6 @@ import { FluentiContext } from './context';
5
5
  * Throws if no provider is found in the component tree.
6
6
  */
7
7
  export declare function useI18n(): FluentiContext;
8
+ /** Shorthand hook that returns only the current locale accessor. */
9
+ export declare function useLocale(): () => import('@fluenti/core').Locale;
8
10
  //# sourceMappingURL=use-i18n.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-i18n.d.ts","sourceRoot":"","sources":["../src/use-i18n.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAE/C;;;;GAIG;AACH,wBAAgB,OAAO,IAAI,cAAc,CASxC"}
1
+ {"version":3,"file":"use-i18n.d.ts","sourceRoot":"","sources":["../src/use-i18n.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAE/C;;;;GAIG;AACH,wBAAgB,OAAO,IAAI,cAAc,CASxC;AAED,oEAAoE;AACpE,wBAAgB,SAAS,yCAExB"}
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin.cjs","names":[],"sources":["../src/solid-runtime.ts","../src/vite-plugin.ts"],"sourcesContent":["import { createRuntimeGenerator } from '@fluenti/vite-plugin'\nimport type { RuntimeGenerator } from '@fluenti/vite-plugin'\n\nexport const solidRuntimeGenerator: RuntimeGenerator = createRuntimeGenerator({\n imports: `import { createSignal } from 'solid-js'\\nimport { createStore, reconcile } from 'solid-js/store'`,\n catalogInit: 'const [__catalog, __setCatalog] = createStore({ ...__defaultMsgs })',\n localeInit: (defaultLocale) => `const [__currentLocale, __setCurrentLocale] = createSignal('${defaultLocale}')`,\n loadingInit: 'const [__loading, __setLoading] = createSignal(false)',\n catalogUpdate: (msgs) => `__setCatalog(reconcile(${msgs}))`,\n localeUpdate: (locale) => `__setCurrentLocale(${locale})`,\n loadingUpdate: (value) => `__setLoading(${value})`,\n localeRead: '__currentLocale()',\n runtimeKey: 'fluenti.runtime.solid.v1',\n})\n","import type { Plugin } from 'vite'\nimport type { FluentiPluginOptions } from '@fluenti/vite-plugin'\nimport { createFluentiPlugins } from '@fluenti/vite-plugin'\nimport { solidRuntimeGenerator } from './solid-runtime'\n\nexport type { FluentiPluginOptions as FluentiSolidOptions } from '@fluenti/vite-plugin'\n\nexport default function fluentiSolid(options?: FluentiPluginOptions): Plugin[] {\n return createFluentiPlugins(\n { ...(options?.config !== undefined ? { config: options.config } : {}), framework: 'solid' },\n [],\n solidRuntimeGenerator,\n )\n}\n"],"mappings":"sCAGA,IAAa,GAAA,EAAA,EAAA,wBAAiE,CAC5E,QAAS;yDACT,YAAa,sEACb,WAAa,GAAkB,+DAA+D,EAAc,IAC5G,YAAa,wDACb,cAAgB,GAAS,0BAA0B,EAAK,IACxD,aAAe,GAAW,sBAAsB,EAAO,GACvD,cAAgB,GAAU,gBAAgB,EAAM,GAChD,WAAY,oBACZ,WAAY,2BACb,CAAC,CCNF,SAAwB,EAAa,EAA0C,CAC7E,OAAA,EAAA,EAAA,sBACE,CAAE,GAAI,GAAS,SAAW,IAAA,GAAyC,EAAE,CAA/B,CAAE,OAAQ,EAAQ,OAAQ,CAAQ,UAAW,QAAS,CAC5F,EAAE,CACF,EACD"}
1
+ {"version":3,"file":"vite-plugin.cjs","names":[],"sources":["../src/solid-runtime.ts","../src/vite-plugin.ts"],"sourcesContent":["import { createRuntimeGenerator } from '@fluenti/vite-plugin'\nimport type { RuntimeGenerator } from '@fluenti/vite-plugin'\n\nexport const solidRuntimeGenerator: RuntimeGenerator = createRuntimeGenerator({\n imports: `import { createSignal } from 'solid-js'\\nimport { createStore, reconcile } from 'solid-js/store'`,\n catalogInit: 'const [__catalog, __setCatalog] = createStore({ ...__defaultMsgs })',\n localeInit: (defaultLocale) => `const [__currentLocale, __setCurrentLocale] = createSignal('${defaultLocale}')`,\n loadingInit: 'const [__loading, __setLoading] = createSignal(false)',\n catalogUpdate: (msgs) => `__setCatalog(reconcile(${msgs}))`,\n localeUpdate: (locale) => `__setCurrentLocale(${locale})`,\n loadingUpdate: (value) => `__setLoading(${value})`,\n localeRead: '__currentLocale()',\n runtimeKey: 'fluenti.runtime.solid.v1',\n})\n","import type { Plugin } from 'vite'\nimport type { FluentiPluginOptions } from '@fluenti/vite-plugin'\nimport { createFluentiPlugins } from '@fluenti/vite-plugin'\nimport { solidRuntimeGenerator } from './solid-runtime'\n\nexport type { FluentiPluginOptions as FluentiSolidOptions } from '@fluenti/vite-plugin'\n\n/**\n * Fluenti SolidJS Vite plugin.\n *\n * @example Minimal — no fluenti.config.ts needed\n * ```ts\n * // vite.config.ts\n * import fluentiSolid from '@fluenti/solid/vite-plugin'\n *\n * export default defineConfig({\n * plugins: [fluentiSolid({ config: { locales: ['en', 'ja'] } })],\n * })\n * ```\n *\n * @example With fluenti.config.ts (for advanced options)\n * ```ts\n * export default defineConfig({\n * plugins: [fluentiSolid()], // auto-reads fluenti.config.ts\n * })\n * ```\n */\nexport default function fluentiSolid(options?: FluentiPluginOptions): Plugin[] {\n return createFluentiPlugins(\n { ...(options?.config !== undefined ? { config: options.config } : {}), framework: 'solid' },\n [],\n solidRuntimeGenerator,\n )\n}\n"],"mappings":"sCAGA,IAAa,GAAA,EAAA,EAAA,wBAAiE,CAC5E,QAAS;yDACT,YAAa,sEACb,WAAa,GAAkB,+DAA+D,EAAc,IAC5G,YAAa,wDACb,cAAgB,GAAS,0BAA0B,EAAK,IACxD,aAAe,GAAW,sBAAsB,EAAO,GACvD,cAAgB,GAAU,gBAAgB,EAAM,GAChD,WAAY,oBACZ,WAAY,2BACb,CAAC,CCcF,SAAwB,EAAa,EAA0C,CAC7E,OAAA,EAAA,EAAA,sBACE,CAAE,GAAI,GAAS,SAAW,IAAA,GAAyC,EAAE,CAA/B,CAAE,OAAQ,EAAQ,OAAQ,CAAQ,UAAW,QAAS,CAC5F,EAAE,CACF,EACD"}
@@ -1,5 +1,25 @@
1
1
  import { Plugin } from 'vite';
2
2
  import { FluentiPluginOptions } from '@fluenti/vite-plugin';
3
3
  export type { FluentiPluginOptions as FluentiSolidOptions } from '@fluenti/vite-plugin';
4
+ /**
5
+ * Fluenti SolidJS Vite plugin.
6
+ *
7
+ * @example Minimal — no fluenti.config.ts needed
8
+ * ```ts
9
+ * // vite.config.ts
10
+ * import fluentiSolid from '@fluenti/solid/vite-plugin'
11
+ *
12
+ * export default defineConfig({
13
+ * plugins: [fluentiSolid({ config: { locales: ['en', 'ja'] } })],
14
+ * })
15
+ * ```
16
+ *
17
+ * @example With fluenti.config.ts (for advanced options)
18
+ * ```ts
19
+ * export default defineConfig({
20
+ * plugins: [fluentiSolid()], // auto-reads fluenti.config.ts
21
+ * })
22
+ * ```
23
+ */
4
24
  export default function fluentiSolid(options?: FluentiPluginOptions): Plugin[];
5
25
  //# sourceMappingURL=vite-plugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAClC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAIhE,YAAY,EAAE,oBAAoB,IAAI,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAEvF,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,MAAM,EAAE,CAM7E"}
1
+ {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAClC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAIhE,YAAY,EAAE,oBAAoB,IAAI,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAEvF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,MAAM,EAAE,CAM7E"}
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin.js","names":[],"sources":["../src/solid-runtime.ts","../src/vite-plugin.ts"],"sourcesContent":["import { createRuntimeGenerator } from '@fluenti/vite-plugin'\nimport type { RuntimeGenerator } from '@fluenti/vite-plugin'\n\nexport const solidRuntimeGenerator: RuntimeGenerator = createRuntimeGenerator({\n imports: `import { createSignal } from 'solid-js'\\nimport { createStore, reconcile } from 'solid-js/store'`,\n catalogInit: 'const [__catalog, __setCatalog] = createStore({ ...__defaultMsgs })',\n localeInit: (defaultLocale) => `const [__currentLocale, __setCurrentLocale] = createSignal('${defaultLocale}')`,\n loadingInit: 'const [__loading, __setLoading] = createSignal(false)',\n catalogUpdate: (msgs) => `__setCatalog(reconcile(${msgs}))`,\n localeUpdate: (locale) => `__setCurrentLocale(${locale})`,\n loadingUpdate: (value) => `__setLoading(${value})`,\n localeRead: '__currentLocale()',\n runtimeKey: 'fluenti.runtime.solid.v1',\n})\n","import type { Plugin } from 'vite'\nimport type { FluentiPluginOptions } from '@fluenti/vite-plugin'\nimport { createFluentiPlugins } from '@fluenti/vite-plugin'\nimport { solidRuntimeGenerator } from './solid-runtime'\n\nexport type { FluentiPluginOptions as FluentiSolidOptions } from '@fluenti/vite-plugin'\n\nexport default function fluentiSolid(options?: FluentiPluginOptions): Plugin[] {\n return createFluentiPlugins(\n { ...(options?.config !== undefined ? { config: options.config } : {}), framework: 'solid' },\n [],\n solidRuntimeGenerator,\n )\n}\n"],"mappings":";;AAGA,IAAa,IAA0C,EAAuB;CAC5E,SAAS;CACT,aAAa;CACb,aAAa,MAAkB,+DAA+D,EAAc;CAC5G,aAAa;CACb,gBAAgB,MAAS,0BAA0B,EAAK;CACxD,eAAe,MAAW,sBAAsB,EAAO;CACvD,gBAAgB,MAAU,gBAAgB,EAAM;CAChD,YAAY;CACZ,YAAY;CACb,CAAC;;;ACNF,SAAwB,EAAa,GAA0C;AAC7E,QAAO,EACL;EAAE,GAAI,GAAS,WAAW,KAAA,IAAyC,EAAE,GAA/B,EAAE,QAAQ,EAAQ,QAAQ;EAAQ,WAAW;EAAS,EAC5F,EAAE,EACF,EACD"}
1
+ {"version":3,"file":"vite-plugin.js","names":[],"sources":["../src/solid-runtime.ts","../src/vite-plugin.ts"],"sourcesContent":["import { createRuntimeGenerator } from '@fluenti/vite-plugin'\nimport type { RuntimeGenerator } from '@fluenti/vite-plugin'\n\nexport const solidRuntimeGenerator: RuntimeGenerator = createRuntimeGenerator({\n imports: `import { createSignal } from 'solid-js'\\nimport { createStore, reconcile } from 'solid-js/store'`,\n catalogInit: 'const [__catalog, __setCatalog] = createStore({ ...__defaultMsgs })',\n localeInit: (defaultLocale) => `const [__currentLocale, __setCurrentLocale] = createSignal('${defaultLocale}')`,\n loadingInit: 'const [__loading, __setLoading] = createSignal(false)',\n catalogUpdate: (msgs) => `__setCatalog(reconcile(${msgs}))`,\n localeUpdate: (locale) => `__setCurrentLocale(${locale})`,\n loadingUpdate: (value) => `__setLoading(${value})`,\n localeRead: '__currentLocale()',\n runtimeKey: 'fluenti.runtime.solid.v1',\n})\n","import type { Plugin } from 'vite'\nimport type { FluentiPluginOptions } from '@fluenti/vite-plugin'\nimport { createFluentiPlugins } from '@fluenti/vite-plugin'\nimport { solidRuntimeGenerator } from './solid-runtime'\n\nexport type { FluentiPluginOptions as FluentiSolidOptions } from '@fluenti/vite-plugin'\n\n/**\n * Fluenti SolidJS Vite plugin.\n *\n * @example Minimal — no fluenti.config.ts needed\n * ```ts\n * // vite.config.ts\n * import fluentiSolid from '@fluenti/solid/vite-plugin'\n *\n * export default defineConfig({\n * plugins: [fluentiSolid({ config: { locales: ['en', 'ja'] } })],\n * })\n * ```\n *\n * @example With fluenti.config.ts (for advanced options)\n * ```ts\n * export default defineConfig({\n * plugins: [fluentiSolid()], // auto-reads fluenti.config.ts\n * })\n * ```\n */\nexport default function fluentiSolid(options?: FluentiPluginOptions): Plugin[] {\n return createFluentiPlugins(\n { ...(options?.config !== undefined ? { config: options.config } : {}), framework: 'solid' },\n [],\n solidRuntimeGenerator,\n )\n}\n"],"mappings":";;AAGA,IAAa,IAA0C,EAAuB;CAC5E,SAAS;CACT,aAAa;CACb,aAAa,MAAkB,+DAA+D,EAAc;CAC5G,aAAa;CACb,gBAAgB,MAAS,0BAA0B,EAAK;CACxD,eAAe,MAAW,sBAAsB,EAAO;CACvD,gBAAgB,MAAU,gBAAgB,EAAM;CAChD,YAAY;CACZ,YAAY;CACb,CAAC;;;ACcF,SAAwB,EAAa,GAA0C;AAC7E,QAAO,EACL;EAAE,GAAI,GAAS,WAAW,KAAA,IAAyC,EAAE,GAA/B,EAAE,QAAQ,EAAQ,QAAQ;EAAQ,WAAW;EAAS,EAC5F,EAAE,EACF,EACD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluenti/solid",
3
- "version": "0.4.0-rc.1",
3
+ "version": "0.4.0-rc.3",
4
4
  "type": "module",
5
5
  "description": "SolidJS compile-time i18n — Trans/Plural/Select components, I18nProvider, useI18n",
6
6
  "homepage": "https://fluenti.dev",
@@ -95,8 +95,8 @@
95
95
  }
96
96
  },
97
97
  "dependencies": {
98
- "@fluenti/core": "0.4.0-rc.1",
99
- "@fluenti/vite-plugin": "0.4.0-rc.1"
98
+ "@fluenti/core": "0.4.0-rc.3",
99
+ "@fluenti/vite-plugin": "0.4.0-rc.3"
100
100
  },
101
101
  "devDependencies": {
102
102
  "@solidjs/testing-library": "^0.8",
package/src/context.ts CHANGED
@@ -167,6 +167,7 @@ export function createFluentiContext(config: FluentiCoreConfig | FluentiConfig):
167
167
  if (config.missing !== undefined) coreConfig.missing = config.missing
168
168
  if (i18nConfig.diagnostics !== undefined) coreConfig.diagnostics = i18nConfig.diagnostics as FluentiCoreConfigFull['diagnostics']
169
169
  if (i18nConfig.interpolate !== undefined) coreConfig.interpolate = i18nConfig.interpolate
170
+ coreConfig.devWarnings = coreConfig.devWarnings ?? (typeof process !== 'undefined' && process.env?.['NODE_ENV'] === 'development')
170
171
  const i18n = createFluentiCore(coreConfig)
171
172
 
172
173
  function t(strings: TemplateStringsArray, ...exprs: unknown[]): LocalizedString
package/src/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { createFluentiContext } from './context'
2
2
  export type { FluentiContext, FluentiConfig } from './context'
3
3
  export { I18nProvider } from './provider'
4
- export { useI18n } from './use-i18n'
4
+ export { useI18n, useLocale } from './use-i18n'
5
5
  export { t } from './compile-time-t'
6
6
  export { msg } from './msg'
7
7
 
package/src/use-i18n.ts CHANGED
@@ -17,3 +17,8 @@ export function useI18n(): FluentiContext {
17
17
  'useI18n() must be used inside an <I18nProvider>.',
18
18
  )
19
19
  }
20
+
21
+ /** Shorthand hook that returns only the current locale accessor. */
22
+ export function useLocale() {
23
+ return useI18n().locale
24
+ }
@@ -5,6 +5,26 @@ import { solidRuntimeGenerator } from './solid-runtime'
5
5
 
6
6
  export type { FluentiPluginOptions as FluentiSolidOptions } from '@fluenti/vite-plugin'
7
7
 
8
+ /**
9
+ * Fluenti SolidJS Vite plugin.
10
+ *
11
+ * @example Minimal — no fluenti.config.ts needed
12
+ * ```ts
13
+ * // vite.config.ts
14
+ * import fluentiSolid from '@fluenti/solid/vite-plugin'
15
+ *
16
+ * export default defineConfig({
17
+ * plugins: [fluentiSolid({ config: { locales: ['en', 'ja'] } })],
18
+ * })
19
+ * ```
20
+ *
21
+ * @example With fluenti.config.ts (for advanced options)
22
+ * ```ts
23
+ * export default defineConfig({
24
+ * plugins: [fluentiSolid()], // auto-reads fluenti.config.ts
25
+ * })
26
+ * ```
27
+ */
8
28
  export default function fluentiSolid(options?: FluentiPluginOptions): Plugin[] {
9
29
  return createFluentiPlugins(
10
30
  { ...(options?.config !== undefined ? { config: options.config } : {}), framework: 'solid' },
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-i18n-DPb98Dw1.js","names":["createContext","ParentComponent","createFluentiContext","FluentiConfig","FluentiContext","I18nCtx","I18nProvider","props","ctx","_$createComponent","Provider","value","children"],"sources":["../src/context.ts","../src/provider.tsx","../src/use-i18n.ts"],"sourcesContent":["import { createSignal, type Accessor } from 'solid-js'\nimport { createFluentiCore } from '@fluenti/core'\nimport type { FluentiCoreConfig, FluentiCoreConfigFull, Locale, LocalizedString, Messages, CompiledMessage, MessageDescriptor, DateFormatOptions, NumberFormatOptions, DiagnosticsConfig, CustomFormatter } from '@fluenti/core'\n\n/** Chunk loader for lazy locale loading */\nexport type ChunkLoader = (\n locale: string,\n) => Promise<Record<string, CompiledMessage> | { default: Record<string, CompiledMessage> }>\n\ninterface SplitRuntimeModule {\n __switchLocale?: (locale: string) => Promise<void>\n __preloadLocale?: (locale: string) => Promise<void>\n}\n\nconst SPLIT_RUNTIME_KEY = Symbol.for('fluenti.runtime.solid.v1')\n\nfunction getSplitRuntimeModule(): SplitRuntimeModule | null {\n const runtime = (globalThis as Record<PropertyKey, unknown>)[SPLIT_RUNTIME_KEY]\n return typeof runtime === 'object' && runtime !== null\n ? runtime as SplitRuntimeModule\n : null\n}\n\nfunction resolveChunkMessages(\n loaded: Record<string, CompiledMessage> | { default: Record<string, CompiledMessage> },\n): Record<string, CompiledMessage> {\n return typeof loaded === 'object' && loaded !== null && 'default' in loaded\n ? (loaded as { default: Record<string, CompiledMessage> }).default\n : loaded\n}\n\n/** @internal Map locale → default currency code */\nconst LOCALE_CURRENCY_MAP: Record<string, string> = {\n 'en': 'USD', 'en-US': 'USD', 'en-GB': 'GBP', 'en-AU': 'AUD', 'en-CA': 'CAD',\n 'zh-CN': 'CNY', 'zh-TW': 'TWD', 'zh-HK': 'HKD',\n 'ja': 'JPY', 'ja-JP': 'JPY',\n 'ko': 'KRW', 'ko-KR': 'KRW',\n 'de': 'EUR', 'de-DE': 'EUR', 'de-AT': 'EUR',\n 'fr': 'EUR', 'fr-FR': 'EUR', 'fr-CA': 'CAD',\n 'es': 'EUR', 'es-ES': 'EUR', 'es-MX': 'MXN',\n 'pt': 'EUR', 'pt-BR': 'BRL', 'pt-PT': 'EUR',\n 'it': 'EUR', 'ru': 'RUB', 'ar': 'SAR', 'hi': 'INR',\n}\n\n/** @internal Built-in date format styles (merged under user-provided dateFormats) */\nconst DEFAULT_DATE_FORMATS: Record<string, Intl.DateTimeFormatOptions> = {\n short: { year: 'numeric', month: 'numeric', day: 'numeric' },\n long: { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' },\n time: { hour: 'numeric', minute: 'numeric' },\n datetime: { year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric' },\n}\n\n/** @internal Built-in number format styles (merged under user-provided numberFormats) */\nconst DEFAULT_NUMBER_FORMATS: Record<string, Intl.NumberFormatOptions | ((locale: Locale) => Intl.NumberFormatOptions)> = {\n currency: (locale: string) => ({\n style: 'currency',\n currency: LOCALE_CURRENCY_MAP[locale] ?? LOCALE_CURRENCY_MAP[locale.split('-')[0]!] ?? 'USD',\n }),\n percent: { style: 'percent' },\n decimal: { minimumFractionDigits: 2, maximumFractionDigits: 2 },\n}\n\n/** Extended config with lazy locale loading support */\nexport interface FluentiConfig extends FluentiCoreConfig {\n /** Async chunk loader for lazy locale loading */\n chunkLoader?: ChunkLoader\n /** Enable lazy locale loading through chunkLoader */\n lazyLocaleLoading?: boolean\n /** Locale-specific fallback chains */\n fallbackChain?: Record<string, Locale[]>\n /** Named date format styles */\n dateFormats?: DateFormatOptions\n /** Named number format styles */\n numberFormats?: NumberFormatOptions\n /** Runtime diagnostics configuration */\n diagnostics?: DiagnosticsConfig\n /**\n * Custom message interpolation function.\n *\n * By default, the runtime uses a lightweight `{key}` replacer.\n * Pass the full `interpolate` from `@fluenti/core/internal` for\n * runtime ICU MessageFormat support (plurals, selects, nested arguments).\n */\n interpolate?: (\n message: string,\n values: Record<string, unknown> | undefined,\n locale: string,\n formatters?: Record<string, CustomFormatter>,\n ) => string\n}\n\n/** Reactive i18n context holding locale signal and translation utilities */\nexport interface FluentiContext {\n /** Reactive accessor for the current locale */\n locale(): Locale\n /** Set the active locale (async when lazy locale loading is enabled) */\n setLocale(locale: Locale): Promise<void>\n /** Translate a message by id with optional interpolation values */\n t(id: string | MessageDescriptor, values?: Record<string, unknown>): LocalizedString\n /** Tagged template form: t`Hello ${name}` */\n t(strings: TemplateStringsArray, ...exprs: unknown[]): LocalizedString\n /** Merge additional messages into a locale catalog at runtime */\n loadMessages(locale: Locale, messages: Messages): void\n /** Return all locale codes that have loaded messages */\n getLocales(): Locale[]\n /** Format a date value for the current locale */\n d(value: Date | number, style?: string): LocalizedString\n /** Format a number value for the current locale */\n n(value: number, style?: string): LocalizedString\n /** Format an ICU message string directly (no catalog lookup) */\n format(message: string, values?: Record<string, unknown>): LocalizedString\n /** Whether a locale chunk is currently being loaded */\n isLoading: Accessor<boolean>\n /** Set of locales whose messages have been loaded */\n loadedLocales: Accessor<Set<string>>\n /** Preload a locale in the background without switching to it */\n preloadLocale(locale: string): void\n /** Check if a translation key exists for the given or current locale */\n te(key: string, loc?: string): boolean\n /** Get the raw compiled message for a key without interpolation */\n tm(key: string, loc?: string): CompiledMessage | undefined\n}\n\n/**\n * Create a reactive i18n context backed by Solid signals.\n *\n * The returned `t()` reads the internal `locale()` signal, so any\n * Solid computation that calls `t()` will re-run when the locale changes.\n *\n * @example\n * ```tsx\n * import { createFluentiContext } from '@fluenti/solid'\n * import messages from './locales/compiled/en.js'\n *\n * const ctx = createFluentiContext({\n * locale: 'en',\n * messages: { en: messages },\n * })\n *\n * // Use t`` tagged template (preferred)\n * const greeting = ctx.t`Hello, {name}!`\n * ```\n */\nexport function createFluentiContext(config: FluentiCoreConfig | FluentiConfig): FluentiContext {\n const [locale, setLocaleSignal] = createSignal<Locale>(config.locale)\n const [isLoading, setIsLoading] = createSignal(false)\n const loadedLocalesSet = new Set<string>([config.locale])\n const [loadedLocales, setLoadedLocales] = createSignal(new Set(loadedLocalesSet))\n const messages: Record<string, Messages> = { ...config.messages }\n const i18nConfig = config as FluentiConfig\n const lazyLocaleLoading = i18nConfig.lazyLocaleLoading\n ?? (config as FluentiConfig & { splitting?: boolean }).splitting\n ?? false\n\n // Create a core instance that handles all translation, lookup, fallback, and formatting logic.\n // Merge built-in date/number format styles under user-provided overrides.\n // Build config incrementally to satisfy exactOptionalPropertyTypes —\n // optional properties must not receive `undefined` as a value.\n const coreConfig: FluentiCoreConfigFull = {\n locale: config.locale,\n messages: config.messages ?? {},\n dateFormats: { ...DEFAULT_DATE_FORMATS, ...i18nConfig.dateFormats },\n numberFormats: { ...DEFAULT_NUMBER_FORMATS, ...i18nConfig.numberFormats },\n }\n if (config.fallbackLocale !== undefined) coreConfig.fallbackLocale = config.fallbackLocale\n if (i18nConfig.fallbackChain !== undefined) coreConfig.fallbackChain = i18nConfig.fallbackChain\n if (config.missing !== undefined) coreConfig.missing = config.missing\n if (i18nConfig.diagnostics !== undefined) coreConfig.diagnostics = i18nConfig.diagnostics as FluentiCoreConfigFull['diagnostics']\n if (i18nConfig.interpolate !== undefined) coreConfig.interpolate = i18nConfig.interpolate\n const i18n = createFluentiCore(coreConfig)\n\n function t(strings: TemplateStringsArray, ...exprs: unknown[]): LocalizedString\n function t(id: string | MessageDescriptor, values?: Record<string, unknown>): LocalizedString\n function t(idOrStrings: string | MessageDescriptor | TemplateStringsArray, ...rest: unknown[]): LocalizedString {\n const current = locale() // READ SIGNAL → reactive dependency for Solid re-renders\n if (i18n.locale !== current) i18n.locale = current\n // Dispatch to the correct overload based on input type\n if (Array.isArray(idOrStrings) && 'raw' in idOrStrings) {\n return i18n.t(idOrStrings as TemplateStringsArray, ...rest) as LocalizedString\n }\n return i18n.t(idOrStrings as string | MessageDescriptor, rest[0] as Record<string, unknown> | undefined) as LocalizedString\n }\n\n const loadMessages = (loc: Locale, msgs: Messages): void => {\n i18n.loadMessages(loc, msgs)\n // Keep local messages in sync for te/tm which check the local object\n // Intentional mutation: messages record is locally scoped to this context closure\n messages[loc] = { ...messages[loc], ...msgs }\n loadedLocalesSet.add(loc)\n setLoadedLocales(new Set(loadedLocalesSet))\n }\n\n let _localeRequestId = 0\n\n const setLocale = async (newLocale: Locale): Promise<void> => {\n if (!lazyLocaleLoading || !i18nConfig.chunkLoader) {\n setLocaleSignal(newLocale)\n return\n }\n\n const splitRuntime = getSplitRuntimeModule()\n\n if (loadedLocalesSet.has(newLocale)) {\n try {\n if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\n }\n } catch (e) {\n console.warn(`[fluenti] split runtime switch failed for locale \"${newLocale}\"`, e)\n }\n setLocaleSignal(newLocale)\n return\n }\n\n // Race-condition protection: track request ID\n const thisRequest = ++_localeRequestId\n setIsLoading(true)\n try {\n const loaded = resolveChunkMessages(await i18nConfig.chunkLoader(newLocale))\n // Always store loaded messages — they may be needed if locale is switched back\n i18n.loadMessages(newLocale, loaded)\n // Intentional mutation: messages record is locally scoped to this context closure\n messages[newLocale] = { ...messages[newLocale], ...loaded }\n loadedLocalesSet.add(newLocale)\n setLoadedLocales(new Set(loadedLocalesSet))\n // Stale request — a newer setLocale call superseded this one; don't switch locale\n if (thisRequest !== _localeRequestId) return\n try {\n if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\n }\n } catch (e) {\n console.warn(`[fluenti] split runtime switch failed for locale \"${newLocale}\"`, e)\n }\n // Re-check after async __switchLocale — a newer setLocale() may have superseded this one\n if (thisRequest !== _localeRequestId) return\n setLocaleSignal(newLocale)\n } finally {\n if (thisRequest === _localeRequestId) {\n setIsLoading(false)\n }\n }\n }\n\n const _preloadInFlight = new Set<string>()\n\n const preloadLocale = (loc: string): void => {\n if (!lazyLocaleLoading || loadedLocalesSet.has(loc) || !i18nConfig.chunkLoader || _preloadInFlight.has(loc)) return\n _preloadInFlight.add(loc)\n const splitRuntime = getSplitRuntimeModule()\n i18nConfig.chunkLoader(loc).then(async (loaded) => {\n const resolved = resolveChunkMessages(loaded)\n i18n.loadMessages(loc, resolved)\n // Intentional mutation: messages record is locally scoped to this context closure\n messages[loc] = { ...messages[loc], ...resolved }\n loadedLocalesSet.add(loc)\n setLoadedLocales(new Set(loadedLocalesSet))\n if (splitRuntime?.__preloadLocale) {\n await splitRuntime.__preloadLocale(loc)\n }\n }).catch((e: unknown) => {\n console.warn('[fluenti] preload failed:', loc, e)\n }).finally(() => {\n _preloadInFlight.delete(loc)\n })\n }\n\n const getLocales = (): Locale[] => i18n.getLocales()\n\n const d = (value: Date | number, style?: string): LocalizedString => {\n const current = locale() // READ SIGNAL → reactive dependency\n if (i18n.locale !== current) i18n.locale = current\n return i18n.d(value, style) as LocalizedString\n }\n\n const n = (value: number, style?: string): LocalizedString => {\n const current = locale() // READ SIGNAL → reactive dependency\n if (i18n.locale !== current) i18n.locale = current\n return i18n.n(value, style) as LocalizedString\n }\n\n const format = (message: string, values?: Record<string, unknown>): LocalizedString => {\n const current = locale() // READ SIGNAL → reactive dependency\n if (i18n.locale !== current) i18n.locale = current\n return i18n.format(message, values) as LocalizedString\n }\n\n const te = (key: string, loc?: string): boolean => {\n const msgs = messages[loc ?? locale()]\n return msgs !== undefined && key in msgs\n }\n\n const tm = (key: string, loc?: string): CompiledMessage | undefined => {\n const msgs = messages[loc ?? locale()]\n return msgs ? msgs[key] : undefined\n }\n\n return { locale, setLocale, t, loadMessages, getLocales, d, n, format, isLoading, loadedLocales, preloadLocale, te, tm }\n}\n","import { createContext } from 'solid-js'\nimport type { ParentComponent } from 'solid-js'\nimport { createFluentiContext } from './context'\nimport type { FluentiConfig, FluentiContext } from './context'\n\n/** Solid context object for i18n — used internally by useI18n() */\nexport const I18nCtx = createContext<FluentiContext>()\n\n/**\n * Provides the Fluenti i18n context to the Solid component tree.\n *\n * @example\n * ```tsx\n * import { I18nProvider, useI18n } from '@fluenti/solid'\n * import messages from './locales/compiled/en.js'\n *\n * function App() {\n * return (\n * <I18nProvider locale=\"en\" messages={{ en: messages }}>\n * <Content />\n * </I18nProvider>\n * )\n * }\n *\n * function Content() {\n * const { t } = useI18n()\n * return <h1>{t`Welcome to our app`}</h1>\n * }\n * ```\n */\nexport const I18nProvider: ParentComponent<FluentiConfig> = (props) => {\n const ctx = createFluentiContext(props)\n return <I18nCtx.Provider value={ctx}>{props.children}</I18nCtx.Provider>\n}\n","import { useContext } from 'solid-js'\nimport { I18nCtx } from './provider'\nimport type { FluentiContext } from './context'\n\n/**\n * Access the i18n context from the nearest `<I18nProvider>`.\n *\n * Throws if no provider is found in the component tree.\n */\nexport function useI18n(): FluentiContext {\n const ctx = useContext(I18nCtx)\n if (ctx) {\n return ctx\n }\n\n throw new Error(\n 'useI18n() must be used inside an <I18nProvider>.',\n )\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- let e=require(`solid-js`),t=require(`@fluenti/core`),n=require(`solid-js/web`);var r=Symbol.for(`fluenti.runtime.solid.v1`);function i(){let e=globalThis[r];return typeof e==`object`&&e?e:null}function a(e){return typeof e==`object`&&e&&`default`in e?e.default:e}var o={en:`USD`,"en-US":`USD`,"en-GB":`GBP`,"en-AU":`AUD`,"en-CA":`CAD`,"zh-CN":`CNY`,"zh-TW":`TWD`,"zh-HK":`HKD`,ja:`JPY`,"ja-JP":`JPY`,ko:`KRW`,"ko-KR":`KRW`,de:`EUR`,"de-DE":`EUR`,"de-AT":`EUR`,fr:`EUR`,"fr-FR":`EUR`,"fr-CA":`CAD`,es:`EUR`,"es-ES":`EUR`,"es-MX":`MXN`,pt:`EUR`,"pt-BR":`BRL`,"pt-PT":`EUR`,it:`EUR`,ru:`RUB`,ar:`SAR`,hi:`INR`},s={short:{year:`numeric`,month:`numeric`,day:`numeric`},long:{year:`numeric`,month:`long`,day:`numeric`,weekday:`long`},time:{hour:`numeric`,minute:`numeric`},datetime:{year:`numeric`,month:`short`,day:`numeric`,hour:`numeric`,minute:`numeric`}},c={currency:e=>({style:`currency`,currency:o[e]??o[e.split(`-`)[0]]??`USD`}),percent:{style:`percent`},decimal:{minimumFractionDigits:2,maximumFractionDigits:2}};function l(n){let[r,o]=(0,e.createSignal)(n.locale),[l,u]=(0,e.createSignal)(!1),d=new Set([n.locale]),[f,p]=(0,e.createSignal)(new Set(d)),m={...n.messages},h=n,g=h.lazyLocaleLoading??n.splitting??!1,_={locale:n.locale,messages:n.messages??{},dateFormats:{...s,...h.dateFormats},numberFormats:{...c,...h.numberFormats}};n.fallbackLocale!==void 0&&(_.fallbackLocale=n.fallbackLocale),h.fallbackChain!==void 0&&(_.fallbackChain=h.fallbackChain),n.missing!==void 0&&(_.missing=n.missing),h.diagnostics!==void 0&&(_.diagnostics=h.diagnostics),h.interpolate!==void 0&&(_.interpolate=h.interpolate);let v=(0,t.createFluentiCore)(_);function y(e,...t){let n=r();return v.locale!==n&&(v.locale=n),Array.isArray(e)&&`raw`in e?v.t(e,...t):v.t(e,t[0])}let b=(e,t)=>{v.loadMessages(e,t),m[e]={...m[e],...t},d.add(e),p(new Set(d))},x=0,S=async e=>{if(!g||!h.chunkLoader){o(e);return}let t=i();if(d.has(e)){try{t?.__switchLocale&&await t.__switchLocale(e)}catch(t){console.warn(`[fluenti] split runtime switch failed for locale "${e}"`,t)}o(e);return}let n=++x;u(!0);try{let r=a(await h.chunkLoader(e));if(v.loadMessages(e,r),m[e]={...m[e],...r},d.add(e),p(new Set(d)),n!==x)return;try{t?.__switchLocale&&await t.__switchLocale(e)}catch(t){console.warn(`[fluenti] split runtime switch failed for locale "${e}"`,t)}if(n!==x)return;o(e)}finally{n===x&&u(!1)}},C=new Set;return{locale:r,setLocale:S,t:y,loadMessages:b,getLocales:()=>v.getLocales(),d:(e,t)=>{let n=r();return v.locale!==n&&(v.locale=n),v.d(e,t)},n:(e,t)=>{let n=r();return v.locale!==n&&(v.locale=n),v.n(e,t)},format:(e,t)=>{let n=r();return v.locale!==n&&(v.locale=n),v.format(e,t)},isLoading:l,loadedLocales:f,preloadLocale:e=>{if(!g||d.has(e)||!h.chunkLoader||C.has(e))return;C.add(e);let t=i();h.chunkLoader(e).then(async n=>{let r=a(n);v.loadMessages(e,r),m[e]={...m[e],...r},d.add(e),p(new Set(d)),t?.__preloadLocale&&await t.__preloadLocale(e)}).catch(t=>{console.warn(`[fluenti] preload failed:`,e,t)}).finally(()=>{C.delete(e)})},te:(e,t)=>{let n=m[t??r()];return n!==void 0&&e in n},tm:(e,t)=>{let n=m[t??r()];return n?n[e]:void 0}}}var u=(0,e.createContext)(),d=e=>{let t=l(e);return(0,n.createComponent)(u.Provider,{value:t,get children(){return e.children}})};function f(){let t=(0,e.useContext)(u);if(t)return t;throw Error(`useI18n() must be used inside an <I18nProvider>.`)}Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return f}});
2
- //# sourceMappingURL=use-i18n-oAO3vYS7.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-i18n-oAO3vYS7.cjs","names":["createContext","ParentComponent","createFluentiContext","FluentiConfig","FluentiContext","I18nCtx","I18nProvider","props","ctx","_$createComponent","Provider","value","children"],"sources":["../src/context.ts","../src/provider.tsx","../src/use-i18n.ts"],"sourcesContent":["import { createSignal, type Accessor } from 'solid-js'\nimport { createFluentiCore } from '@fluenti/core'\nimport type { FluentiCoreConfig, FluentiCoreConfigFull, Locale, LocalizedString, Messages, CompiledMessage, MessageDescriptor, DateFormatOptions, NumberFormatOptions, DiagnosticsConfig, CustomFormatter } from '@fluenti/core'\n\n/** Chunk loader for lazy locale loading */\nexport type ChunkLoader = (\n locale: string,\n) => Promise<Record<string, CompiledMessage> | { default: Record<string, CompiledMessage> }>\n\ninterface SplitRuntimeModule {\n __switchLocale?: (locale: string) => Promise<void>\n __preloadLocale?: (locale: string) => Promise<void>\n}\n\nconst SPLIT_RUNTIME_KEY = Symbol.for('fluenti.runtime.solid.v1')\n\nfunction getSplitRuntimeModule(): SplitRuntimeModule | null {\n const runtime = (globalThis as Record<PropertyKey, unknown>)[SPLIT_RUNTIME_KEY]\n return typeof runtime === 'object' && runtime !== null\n ? runtime as SplitRuntimeModule\n : null\n}\n\nfunction resolveChunkMessages(\n loaded: Record<string, CompiledMessage> | { default: Record<string, CompiledMessage> },\n): Record<string, CompiledMessage> {\n return typeof loaded === 'object' && loaded !== null && 'default' in loaded\n ? (loaded as { default: Record<string, CompiledMessage> }).default\n : loaded\n}\n\n/** @internal Map locale → default currency code */\nconst LOCALE_CURRENCY_MAP: Record<string, string> = {\n 'en': 'USD', 'en-US': 'USD', 'en-GB': 'GBP', 'en-AU': 'AUD', 'en-CA': 'CAD',\n 'zh-CN': 'CNY', 'zh-TW': 'TWD', 'zh-HK': 'HKD',\n 'ja': 'JPY', 'ja-JP': 'JPY',\n 'ko': 'KRW', 'ko-KR': 'KRW',\n 'de': 'EUR', 'de-DE': 'EUR', 'de-AT': 'EUR',\n 'fr': 'EUR', 'fr-FR': 'EUR', 'fr-CA': 'CAD',\n 'es': 'EUR', 'es-ES': 'EUR', 'es-MX': 'MXN',\n 'pt': 'EUR', 'pt-BR': 'BRL', 'pt-PT': 'EUR',\n 'it': 'EUR', 'ru': 'RUB', 'ar': 'SAR', 'hi': 'INR',\n}\n\n/** @internal Built-in date format styles (merged under user-provided dateFormats) */\nconst DEFAULT_DATE_FORMATS: Record<string, Intl.DateTimeFormatOptions> = {\n short: { year: 'numeric', month: 'numeric', day: 'numeric' },\n long: { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' },\n time: { hour: 'numeric', minute: 'numeric' },\n datetime: { year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric' },\n}\n\n/** @internal Built-in number format styles (merged under user-provided numberFormats) */\nconst DEFAULT_NUMBER_FORMATS: Record<string, Intl.NumberFormatOptions | ((locale: Locale) => Intl.NumberFormatOptions)> = {\n currency: (locale: string) => ({\n style: 'currency',\n currency: LOCALE_CURRENCY_MAP[locale] ?? LOCALE_CURRENCY_MAP[locale.split('-')[0]!] ?? 'USD',\n }),\n percent: { style: 'percent' },\n decimal: { minimumFractionDigits: 2, maximumFractionDigits: 2 },\n}\n\n/** Extended config with lazy locale loading support */\nexport interface FluentiConfig extends FluentiCoreConfig {\n /** Async chunk loader for lazy locale loading */\n chunkLoader?: ChunkLoader\n /** Enable lazy locale loading through chunkLoader */\n lazyLocaleLoading?: boolean\n /** Locale-specific fallback chains */\n fallbackChain?: Record<string, Locale[]>\n /** Named date format styles */\n dateFormats?: DateFormatOptions\n /** Named number format styles */\n numberFormats?: NumberFormatOptions\n /** Runtime diagnostics configuration */\n diagnostics?: DiagnosticsConfig\n /**\n * Custom message interpolation function.\n *\n * By default, the runtime uses a lightweight `{key}` replacer.\n * Pass the full `interpolate` from `@fluenti/core/internal` for\n * runtime ICU MessageFormat support (plurals, selects, nested arguments).\n */\n interpolate?: (\n message: string,\n values: Record<string, unknown> | undefined,\n locale: string,\n formatters?: Record<string, CustomFormatter>,\n ) => string\n}\n\n/** Reactive i18n context holding locale signal and translation utilities */\nexport interface FluentiContext {\n /** Reactive accessor for the current locale */\n locale(): Locale\n /** Set the active locale (async when lazy locale loading is enabled) */\n setLocale(locale: Locale): Promise<void>\n /** Translate a message by id with optional interpolation values */\n t(id: string | MessageDescriptor, values?: Record<string, unknown>): LocalizedString\n /** Tagged template form: t`Hello ${name}` */\n t(strings: TemplateStringsArray, ...exprs: unknown[]): LocalizedString\n /** Merge additional messages into a locale catalog at runtime */\n loadMessages(locale: Locale, messages: Messages): void\n /** Return all locale codes that have loaded messages */\n getLocales(): Locale[]\n /** Format a date value for the current locale */\n d(value: Date | number, style?: string): LocalizedString\n /** Format a number value for the current locale */\n n(value: number, style?: string): LocalizedString\n /** Format an ICU message string directly (no catalog lookup) */\n format(message: string, values?: Record<string, unknown>): LocalizedString\n /** Whether a locale chunk is currently being loaded */\n isLoading: Accessor<boolean>\n /** Set of locales whose messages have been loaded */\n loadedLocales: Accessor<Set<string>>\n /** Preload a locale in the background without switching to it */\n preloadLocale(locale: string): void\n /** Check if a translation key exists for the given or current locale */\n te(key: string, loc?: string): boolean\n /** Get the raw compiled message for a key without interpolation */\n tm(key: string, loc?: string): CompiledMessage | undefined\n}\n\n/**\n * Create a reactive i18n context backed by Solid signals.\n *\n * The returned `t()` reads the internal `locale()` signal, so any\n * Solid computation that calls `t()` will re-run when the locale changes.\n *\n * @example\n * ```tsx\n * import { createFluentiContext } from '@fluenti/solid'\n * import messages from './locales/compiled/en.js'\n *\n * const ctx = createFluentiContext({\n * locale: 'en',\n * messages: { en: messages },\n * })\n *\n * // Use t`` tagged template (preferred)\n * const greeting = ctx.t`Hello, {name}!`\n * ```\n */\nexport function createFluentiContext(config: FluentiCoreConfig | FluentiConfig): FluentiContext {\n const [locale, setLocaleSignal] = createSignal<Locale>(config.locale)\n const [isLoading, setIsLoading] = createSignal(false)\n const loadedLocalesSet = new Set<string>([config.locale])\n const [loadedLocales, setLoadedLocales] = createSignal(new Set(loadedLocalesSet))\n const messages: Record<string, Messages> = { ...config.messages }\n const i18nConfig = config as FluentiConfig\n const lazyLocaleLoading = i18nConfig.lazyLocaleLoading\n ?? (config as FluentiConfig & { splitting?: boolean }).splitting\n ?? false\n\n // Create a core instance that handles all translation, lookup, fallback, and formatting logic.\n // Merge built-in date/number format styles under user-provided overrides.\n // Build config incrementally to satisfy exactOptionalPropertyTypes —\n // optional properties must not receive `undefined` as a value.\n const coreConfig: FluentiCoreConfigFull = {\n locale: config.locale,\n messages: config.messages ?? {},\n dateFormats: { ...DEFAULT_DATE_FORMATS, ...i18nConfig.dateFormats },\n numberFormats: { ...DEFAULT_NUMBER_FORMATS, ...i18nConfig.numberFormats },\n }\n if (config.fallbackLocale !== undefined) coreConfig.fallbackLocale = config.fallbackLocale\n if (i18nConfig.fallbackChain !== undefined) coreConfig.fallbackChain = i18nConfig.fallbackChain\n if (config.missing !== undefined) coreConfig.missing = config.missing\n if (i18nConfig.diagnostics !== undefined) coreConfig.diagnostics = i18nConfig.diagnostics as FluentiCoreConfigFull['diagnostics']\n if (i18nConfig.interpolate !== undefined) coreConfig.interpolate = i18nConfig.interpolate\n const i18n = createFluentiCore(coreConfig)\n\n function t(strings: TemplateStringsArray, ...exprs: unknown[]): LocalizedString\n function t(id: string | MessageDescriptor, values?: Record<string, unknown>): LocalizedString\n function t(idOrStrings: string | MessageDescriptor | TemplateStringsArray, ...rest: unknown[]): LocalizedString {\n const current = locale() // READ SIGNAL → reactive dependency for Solid re-renders\n if (i18n.locale !== current) i18n.locale = current\n // Dispatch to the correct overload based on input type\n if (Array.isArray(idOrStrings) && 'raw' in idOrStrings) {\n return i18n.t(idOrStrings as TemplateStringsArray, ...rest) as LocalizedString\n }\n return i18n.t(idOrStrings as string | MessageDescriptor, rest[0] as Record<string, unknown> | undefined) as LocalizedString\n }\n\n const loadMessages = (loc: Locale, msgs: Messages): void => {\n i18n.loadMessages(loc, msgs)\n // Keep local messages in sync for te/tm which check the local object\n // Intentional mutation: messages record is locally scoped to this context closure\n messages[loc] = { ...messages[loc], ...msgs }\n loadedLocalesSet.add(loc)\n setLoadedLocales(new Set(loadedLocalesSet))\n }\n\n let _localeRequestId = 0\n\n const setLocale = async (newLocale: Locale): Promise<void> => {\n if (!lazyLocaleLoading || !i18nConfig.chunkLoader) {\n setLocaleSignal(newLocale)\n return\n }\n\n const splitRuntime = getSplitRuntimeModule()\n\n if (loadedLocalesSet.has(newLocale)) {\n try {\n if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\n }\n } catch (e) {\n console.warn(`[fluenti] split runtime switch failed for locale \"${newLocale}\"`, e)\n }\n setLocaleSignal(newLocale)\n return\n }\n\n // Race-condition protection: track request ID\n const thisRequest = ++_localeRequestId\n setIsLoading(true)\n try {\n const loaded = resolveChunkMessages(await i18nConfig.chunkLoader(newLocale))\n // Always store loaded messages — they may be needed if locale is switched back\n i18n.loadMessages(newLocale, loaded)\n // Intentional mutation: messages record is locally scoped to this context closure\n messages[newLocale] = { ...messages[newLocale], ...loaded }\n loadedLocalesSet.add(newLocale)\n setLoadedLocales(new Set(loadedLocalesSet))\n // Stale request — a newer setLocale call superseded this one; don't switch locale\n if (thisRequest !== _localeRequestId) return\n try {\n if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\n }\n } catch (e) {\n console.warn(`[fluenti] split runtime switch failed for locale \"${newLocale}\"`, e)\n }\n // Re-check after async __switchLocale — a newer setLocale() may have superseded this one\n if (thisRequest !== _localeRequestId) return\n setLocaleSignal(newLocale)\n } finally {\n if (thisRequest === _localeRequestId) {\n setIsLoading(false)\n }\n }\n }\n\n const _preloadInFlight = new Set<string>()\n\n const preloadLocale = (loc: string): void => {\n if (!lazyLocaleLoading || loadedLocalesSet.has(loc) || !i18nConfig.chunkLoader || _preloadInFlight.has(loc)) return\n _preloadInFlight.add(loc)\n const splitRuntime = getSplitRuntimeModule()\n i18nConfig.chunkLoader(loc).then(async (loaded) => {\n const resolved = resolveChunkMessages(loaded)\n i18n.loadMessages(loc, resolved)\n // Intentional mutation: messages record is locally scoped to this context closure\n messages[loc] = { ...messages[loc], ...resolved }\n loadedLocalesSet.add(loc)\n setLoadedLocales(new Set(loadedLocalesSet))\n if (splitRuntime?.__preloadLocale) {\n await splitRuntime.__preloadLocale(loc)\n }\n }).catch((e: unknown) => {\n console.warn('[fluenti] preload failed:', loc, e)\n }).finally(() => {\n _preloadInFlight.delete(loc)\n })\n }\n\n const getLocales = (): Locale[] => i18n.getLocales()\n\n const d = (value: Date | number, style?: string): LocalizedString => {\n const current = locale() // READ SIGNAL → reactive dependency\n if (i18n.locale !== current) i18n.locale = current\n return i18n.d(value, style) as LocalizedString\n }\n\n const n = (value: number, style?: string): LocalizedString => {\n const current = locale() // READ SIGNAL → reactive dependency\n if (i18n.locale !== current) i18n.locale = current\n return i18n.n(value, style) as LocalizedString\n }\n\n const format = (message: string, values?: Record<string, unknown>): LocalizedString => {\n const current = locale() // READ SIGNAL → reactive dependency\n if (i18n.locale !== current) i18n.locale = current\n return i18n.format(message, values) as LocalizedString\n }\n\n const te = (key: string, loc?: string): boolean => {\n const msgs = messages[loc ?? locale()]\n return msgs !== undefined && key in msgs\n }\n\n const tm = (key: string, loc?: string): CompiledMessage | undefined => {\n const msgs = messages[loc ?? locale()]\n return msgs ? msgs[key] : undefined\n }\n\n return { locale, setLocale, t, loadMessages, getLocales, d, n, format, isLoading, loadedLocales, preloadLocale, te, tm }\n}\n","import { createContext } from 'solid-js'\nimport type { ParentComponent } from 'solid-js'\nimport { createFluentiContext } from './context'\nimport type { FluentiConfig, FluentiContext } from './context'\n\n/** Solid context object for i18n — used internally by useI18n() */\nexport const I18nCtx = createContext<FluentiContext>()\n\n/**\n * Provides the Fluenti i18n context to the Solid component tree.\n *\n * @example\n * ```tsx\n * import { I18nProvider, useI18n } from '@fluenti/solid'\n * import messages from './locales/compiled/en.js'\n *\n * function App() {\n * return (\n * <I18nProvider locale=\"en\" messages={{ en: messages }}>\n * <Content />\n * </I18nProvider>\n * )\n * }\n *\n * function Content() {\n * const { t } = useI18n()\n * return <h1>{t`Welcome to our app`}</h1>\n * }\n * ```\n */\nexport const I18nProvider: ParentComponent<FluentiConfig> = (props) => {\n const ctx = createFluentiContext(props)\n return <I18nCtx.Provider value={ctx}>{props.children}</I18nCtx.Provider>\n}\n","import { useContext } from 'solid-js'\nimport { I18nCtx } from './provider'\nimport type { FluentiContext } from './context'\n\n/**\n * Access the i18n context from the nearest `<I18nProvider>`.\n *\n * Throws if no provider is found in the component tree.\n */\nexport function useI18n(): FluentiContext {\n const ctx = useContext(I18nCtx)\n if (ctx) {\n return ctx\n }\n\n throw new Error(\n 'useI18n() must be used inside an <I18nProvider>.',\n )\n}\n"],"mappings":"+EAcA,IAAM,EAAoB,OAAO,IAAI,2BAA2B,CAEhE,SAAS,GAAmD,CAC1D,IAAM,EAAW,WAA4C,GAC7D,OAAO,OAAO,GAAY,UAAY,EAClC,EACA,KAGN,SAAS,EACP,EACiC,CACjC,OAAO,OAAO,GAAW,UAAY,GAAmB,YAAa,EAChE,EAAwD,QACzD,EAIN,IAAM,EAA8C,CAClD,GAAM,MAAO,QAAS,MAAO,QAAS,MAAO,QAAS,MAAO,QAAS,MACtE,QAAS,MAAO,QAAS,MAAO,QAAS,MACzC,GAAM,MAAO,QAAS,MACtB,GAAM,MAAO,QAAS,MACtB,GAAM,MAAO,QAAS,MAAO,QAAS,MACtC,GAAM,MAAO,QAAS,MAAO,QAAS,MACtC,GAAM,MAAO,QAAS,MAAO,QAAS,MACtC,GAAM,MAAO,QAAS,MAAO,QAAS,MACtC,GAAM,MAAO,GAAM,MAAO,GAAM,MAAO,GAAM,MAC9C,CAGK,EAAmE,CACvE,MAAO,CAAE,KAAM,UAAW,MAAO,UAAW,IAAK,UAAW,CAC5D,KAAM,CAAE,KAAM,UAAW,MAAO,OAAQ,IAAK,UAAW,QAAS,OAAQ,CACzE,KAAM,CAAE,KAAM,UAAW,OAAQ,UAAW,CAC5C,SAAU,CAAE,KAAM,UAAW,MAAO,QAAS,IAAK,UAAW,KAAM,UAAW,OAAQ,UAAW,CAClG,CAGK,EAAoH,CACxH,SAAW,IAAoB,CAC7B,MAAO,WACP,SAAU,EAAoB,IAAW,EAAoB,EAAO,MAAM,IAAI,CAAC,KAAQ,MACxF,EACD,QAAS,CAAE,MAAO,UAAW,CAC7B,QAAS,CAAE,sBAAuB,EAAG,sBAAuB,EAAG,CAChE,CAmFD,SAAgB,EAAqB,EAA2D,CAC9F,GAAM,CAAC,EAAQ,IAAA,EAAA,EAAA,cAAwC,EAAO,OAAO,CAC/D,CAAC,EAAW,IAAA,EAAA,EAAA,cAA6B,GAAM,CAC/C,EAAmB,IAAI,IAAY,CAAC,EAAO,OAAO,CAAC,CACnD,CAAC,EAAe,IAAA,EAAA,EAAA,cAAiC,IAAI,IAAI,EAAiB,CAAC,CAC3E,EAAqC,CAAE,GAAG,EAAO,SAAU,CAC3D,EAAa,EACb,EAAoB,EAAW,mBAC/B,EAAmD,WACpD,GAMC,EAAoC,CACxC,OAAQ,EAAO,OACf,SAAU,EAAO,UAAY,EAAE,CAC/B,YAAa,CAAE,GAAG,EAAsB,GAAG,EAAW,YAAa,CACnE,cAAe,CAAE,GAAG,EAAwB,GAAG,EAAW,cAAe,CAC1E,CACG,EAAO,iBAAmB,IAAA,KAAW,EAAW,eAAiB,EAAO,gBACxE,EAAW,gBAAkB,IAAA,KAAW,EAAW,cAAgB,EAAW,eAC9E,EAAO,UAAY,IAAA,KAAW,EAAW,QAAU,EAAO,SAC1D,EAAW,cAAgB,IAAA,KAAW,EAAW,YAAc,EAAW,aAC1E,EAAW,cAAgB,IAAA,KAAW,EAAW,YAAc,EAAW,aAC9E,IAAM,GAAA,EAAA,EAAA,mBAAyB,EAAW,CAI1C,SAAS,EAAE,EAAgE,GAAG,EAAkC,CAC9G,IAAM,EAAU,GAAQ,CAMxB,OALI,EAAK,SAAW,IAAS,EAAK,OAAS,GAEvC,MAAM,QAAQ,EAAY,EAAI,QAAS,EAClC,EAAK,EAAE,EAAqC,GAAG,EAAK,CAEtD,EAAK,EAAE,EAA2C,EAAK,GAA0C,CAG1G,IAAM,GAAgB,EAAa,IAAyB,CAC1D,EAAK,aAAa,EAAK,EAAK,CAG5B,EAAS,GAAO,CAAE,GAAG,EAAS,GAAM,GAAG,EAAM,CAC7C,EAAiB,IAAI,EAAI,CACzB,EAAiB,IAAI,IAAI,EAAiB,CAAC,EAGzC,EAAmB,EAEjB,EAAY,KAAO,IAAqC,CAC5D,GAAI,CAAC,GAAqB,CAAC,EAAW,YAAa,CACjD,EAAgB,EAAU,CAC1B,OAGF,IAAM,EAAe,GAAuB,CAE5C,GAAI,EAAiB,IAAI,EAAU,CAAE,CACnC,GAAI,CACE,GAAc,gBAChB,MAAM,EAAa,eAAe,EAAU,OAEvC,EAAG,CACV,QAAQ,KAAK,qDAAqD,EAAU,GAAI,EAAE,CAEpF,EAAgB,EAAU,CAC1B,OAIF,IAAM,EAAc,EAAE,EACtB,EAAa,GAAK,CAClB,GAAI,CACF,IAAM,EAAS,EAAqB,MAAM,EAAW,YAAY,EAAU,CAAC,CAQ5E,GANA,EAAK,aAAa,EAAW,EAAO,CAEpC,EAAS,GAAa,CAAE,GAAG,EAAS,GAAY,GAAG,EAAQ,CAC3D,EAAiB,IAAI,EAAU,CAC/B,EAAiB,IAAI,IAAI,EAAiB,CAAC,CAEvC,IAAgB,EAAkB,OACtC,GAAI,CACE,GAAc,gBAChB,MAAM,EAAa,eAAe,EAAU,OAEvC,EAAG,CACV,QAAQ,KAAK,qDAAqD,EAAU,GAAI,EAAE,CAGpF,GAAI,IAAgB,EAAkB,OACtC,EAAgB,EAAU,QAClB,CACJ,IAAgB,GAClB,EAAa,GAAM,GAKnB,EAAmB,IAAI,IAqD7B,MAAO,CAAE,SAAQ,YAAW,IAAG,eAAc,eA9BV,EAAK,YAAY,CA8BK,GA5B9C,EAAsB,IAAoC,CACnE,IAAM,EAAU,GAAQ,CAExB,OADI,EAAK,SAAW,IAAS,EAAK,OAAS,GACpC,EAAK,EAAE,EAAO,EAAM,EAyB+B,GAtBjD,EAAe,IAAoC,CAC5D,IAAM,EAAU,GAAQ,CAExB,OADI,EAAK,SAAW,IAAS,EAAK,OAAS,GACpC,EAAK,EAAE,EAAO,EAAM,EAmBkC,QAhB/C,EAAiB,IAAsD,CACrF,IAAM,EAAU,GAAQ,CAExB,OADI,EAAK,SAAW,IAAS,EAAK,OAAS,GACpC,EAAK,OAAO,EAAS,EAAO,EAakC,YAAW,gBAAe,cAnD1E,GAAsB,CAC3C,GAAI,CAAC,GAAqB,EAAiB,IAAI,EAAI,EAAI,CAAC,EAAW,aAAe,EAAiB,IAAI,EAAI,CAAE,OAC7G,EAAiB,IAAI,EAAI,CACzB,IAAM,EAAe,GAAuB,CAC5C,EAAW,YAAY,EAAI,CAAC,KAAK,KAAO,IAAW,CACjD,IAAM,EAAW,EAAqB,EAAO,CAC7C,EAAK,aAAa,EAAK,EAAS,CAEhC,EAAS,GAAO,CAAE,GAAG,EAAS,GAAM,GAAG,EAAU,CACjD,EAAiB,IAAI,EAAI,CACzB,EAAiB,IAAI,IAAI,EAAiB,CAAC,CACvC,GAAc,iBAChB,MAAM,EAAa,gBAAgB,EAAI,EAEzC,CAAC,MAAO,GAAe,CACvB,QAAQ,KAAK,4BAA6B,EAAK,EAAE,EACjD,CAAC,YAAc,CACf,EAAiB,OAAO,EAAI,EAC5B,EAiC4G,IAVpG,EAAa,IAA0B,CACjD,IAAM,EAAO,EAAS,GAAO,GAAQ,EACrC,OAAO,IAAS,IAAA,IAAa,KAAO,GAQ8E,IALxG,EAAa,IAA8C,CACrE,IAAM,EAAO,EAAS,GAAO,GAAQ,EACrC,OAAO,EAAO,EAAK,GAAO,IAAA,IAG4F,CCnS1H,IAAaK,GAAAA,EAAAA,EAAAA,gBAAyC,CAwBzCC,EAAgDC,GAAU,CACrE,IAAMC,EAAMN,EAAqBK,EAAM,CACvC,OAAA,EAAA,EAAA,iBAAQF,EAAQK,SAAQ,CAACC,MAAOH,EAAG,IAAAI,UAAA,CAAA,OAAGL,EAAMK,UAAQ,CAAA,ECvBtD,SAAgB,GAA0B,CACxC,IAAM,GAAA,EAAA,EAAA,YAAiB,EAAQ,CAC/B,GAAI,EACF,OAAO,EAGT,MAAU,MACR,mDACD"}