@fluenti/solid 0.4.0-rc.0 → 0.4.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components-entry.cjs +1 -1
- package/dist/components-entry.js +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/solid-runtime.d.ts.map +1 -1
- package/dist/{use-i18n-Bb-Ivibx.js → use-i18n-DPb98Dw1.js} +14 -3
- package/dist/{use-i18n-Bb-Ivibx.js.map → use-i18n-DPb98Dw1.js.map} +1 -1
- package/dist/{use-i18n-CooxLxjG.cjs → use-i18n-oAO3vYS7.cjs} +2 -2
- package/dist/{use-i18n-CooxLxjG.cjs.map → use-i18n-oAO3vYS7.cjs.map} +1 -1
- package/dist/vite-plugin.cjs +1 -1
- package/dist/vite-plugin.cjs.map +1 -1
- package/dist/vite-plugin.d.ts +20 -0
- package/dist/vite-plugin.d.ts.map +1 -1
- package/dist/vite-plugin.js +0 -1
- package/dist/vite-plugin.js.map +1 -1
- package/package.json +3 -3
- package/src/context.ts +12 -4
- package/src/solid-runtime.ts +0 -1
- package/src/vite-plugin.ts +20 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./use-i18n-
|
|
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}});
|
|
2
2
|
//# sourceMappingURL=components-entry.cjs.map
|
package/dist/components-entry.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as e } from "./use-i18n-
|
|
1
|
+
import { t as e } from "./use-i18n-DPb98Dw1.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";
|
package/dist/context.d.ts.map
CHANGED
|
@@ -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-
|
|
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;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"solid-runtime.d.ts","sourceRoot":"","sources":["../src/solid-runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAE5D,eAAO,MAAM,qBAAqB,EAAE,
|
|
1
|
+
{"version":3,"file":"solid-runtime.d.ts","sourceRoot":"","sources":["../src/solid-runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAE5D,eAAO,MAAM,qBAAqB,EAAE,gBAUlC,CAAA"}
|
|
@@ -104,7 +104,12 @@ function d(e) {
|
|
|
104
104
|
}
|
|
105
105
|
let t = o();
|
|
106
106
|
if (d.has(e)) {
|
|
107
|
-
|
|
107
|
+
try {
|
|
108
|
+
t?.__switchLocale && await t.__switchLocale(e);
|
|
109
|
+
} catch (t) {
|
|
110
|
+
console.warn(`[fluenti] split runtime switch failed for locale "${e}"`, t);
|
|
111
|
+
}
|
|
112
|
+
i(e);
|
|
108
113
|
return;
|
|
109
114
|
}
|
|
110
115
|
let n = ++x;
|
|
@@ -114,7 +119,13 @@ function d(e) {
|
|
|
114
119
|
if (v.loadMessages(e, r), m[e] = {
|
|
115
120
|
...m[e],
|
|
116
121
|
...r
|
|
117
|
-
}, d.add(e), p(new Set(d)), n !== x
|
|
122
|
+
}, d.add(e), p(new Set(d)), n !== x) return;
|
|
123
|
+
try {
|
|
124
|
+
t?.__switchLocale && await t.__switchLocale(e);
|
|
125
|
+
} catch (t) {
|
|
126
|
+
console.warn(`[fluenti] split runtime switch failed for locale "${e}"`, t);
|
|
127
|
+
}
|
|
128
|
+
if (n !== x) return;
|
|
118
129
|
i(e);
|
|
119
130
|
} finally {
|
|
120
131
|
n === x && c(!1);
|
|
@@ -187,4 +198,4 @@ function m() {
|
|
|
187
198
|
//#endregion
|
|
188
199
|
export { p as n, d as r, m as t };
|
|
189
200
|
|
|
190
|
-
//# sourceMappingURL=use-i18n-
|
|
201
|
+
//# sourceMappingURL=use-i18n-DPb98Dw1.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-i18n-Bb-Ivibx.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 if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\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 if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\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
|
+
{"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 +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);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)){t?.__switchLocale&&await t.__switchLocale(e)
|
|
2
|
-
//# sourceMappingURL=use-i18n-
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-i18n-CooxLxjG.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 if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\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 if (splitRuntime?.__switchLocale) {\n await splitRuntime.__switchLocale(newLocale)\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
|
+
{"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":"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"}
|
package/dist/vite-plugin.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
let e=require(`@fluenti/vite-plugin`);var t=(0,e.createRuntimeGenerator)({imports:`import { createSignal } from 'solid-js'
|
|
2
|
-
import { createStore, reconcile } from 'solid-js/store'`,catalogInit:`const [__catalog, __setCatalog] = createStore({ ...__defaultMsgs })`,localeInit:e=>`const [__currentLocale, __setCurrentLocale] = createSignal('${e}')`,loadingInit:`const [__loading, __setLoading] = createSignal(false)`,catalogUpdate:e=>`__setCatalog(reconcile(${e}))`,
|
|
2
|
+
import { createStore, reconcile } from 'solid-js/store'`,catalogInit:`const [__catalog, __setCatalog] = createStore({ ...__defaultMsgs })`,localeInit:e=>`const [__currentLocale, __setCurrentLocale] = createSignal('${e}')`,loadingInit:`const [__loading, __setLoading] = createSignal(false)`,catalogUpdate:e=>`__setCatalog(reconcile(${e}))`,localeUpdate:e=>`__setCurrentLocale(${e})`,loadingUpdate:e=>`__setLoading(${e})`,localeRead:`__currentLocale()`,runtimeKey:`fluenti.runtime.solid.v1`});function n(n){return(0,e.createFluentiPlugins)({...n?.config===void 0?{}:{config:n.config},framework:`solid`},[],t)}module.exports=n;
|
|
3
3
|
//# sourceMappingURL=vite-plugin.cjs.map
|
package/dist/vite-plugin.cjs.map
CHANGED
|
@@ -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
|
|
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"}
|
package/dist/vite-plugin.d.ts
CHANGED
|
@@ -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"}
|
package/dist/vite-plugin.js
CHANGED
|
@@ -6,7 +6,6 @@ var n = t({
|
|
|
6
6
|
localeInit: (e) => `const [__currentLocale, __setCurrentLocale] = createSignal('${e}')`,
|
|
7
7
|
loadingInit: "const [__loading, __setLoading] = createSignal(false)",
|
|
8
8
|
catalogUpdate: (e) => `__setCatalog(reconcile(${e}))`,
|
|
9
|
-
catalogMerge: (e) => `__setCatalog(reconcile({ ...__catalog, ...${e} }))`,
|
|
10
9
|
localeUpdate: (e) => `__setCurrentLocale(${e})`,
|
|
11
10
|
loadingUpdate: (e) => `__setLoading(${e})`,
|
|
12
11
|
localeRead: "__currentLocale()",
|
package/dist/vite-plugin.js.map
CHANGED
|
@@ -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
|
|
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.
|
|
3
|
+
"version": "0.4.0-rc.2",
|
|
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/
|
|
99
|
-
"@fluenti/
|
|
98
|
+
"@fluenti/vite-plugin": "0.4.0-rc.2",
|
|
99
|
+
"@fluenti/core": "0.4.0-rc.2"
|
|
100
100
|
},
|
|
101
101
|
"devDependencies": {
|
|
102
102
|
"@solidjs/testing-library": "^0.8",
|
package/src/context.ts
CHANGED
|
@@ -201,8 +201,12 @@ export function createFluentiContext(config: FluentiCoreConfig | FluentiConfig):
|
|
|
201
201
|
const splitRuntime = getSplitRuntimeModule()
|
|
202
202
|
|
|
203
203
|
if (loadedLocalesSet.has(newLocale)) {
|
|
204
|
-
|
|
205
|
-
|
|
204
|
+
try {
|
|
205
|
+
if (splitRuntime?.__switchLocale) {
|
|
206
|
+
await splitRuntime.__switchLocale(newLocale)
|
|
207
|
+
}
|
|
208
|
+
} catch (e) {
|
|
209
|
+
console.warn(`[fluenti] split runtime switch failed for locale "${newLocale}"`, e)
|
|
206
210
|
}
|
|
207
211
|
setLocaleSignal(newLocale)
|
|
208
212
|
return
|
|
@@ -221,8 +225,12 @@ export function createFluentiContext(config: FluentiCoreConfig | FluentiConfig):
|
|
|
221
225
|
setLoadedLocales(new Set(loadedLocalesSet))
|
|
222
226
|
// Stale request — a newer setLocale call superseded this one; don't switch locale
|
|
223
227
|
if (thisRequest !== _localeRequestId) return
|
|
224
|
-
|
|
225
|
-
|
|
228
|
+
try {
|
|
229
|
+
if (splitRuntime?.__switchLocale) {
|
|
230
|
+
await splitRuntime.__switchLocale(newLocale)
|
|
231
|
+
}
|
|
232
|
+
} catch (e) {
|
|
233
|
+
console.warn(`[fluenti] split runtime switch failed for locale "${newLocale}"`, e)
|
|
226
234
|
}
|
|
227
235
|
// Re-check after async __switchLocale — a newer setLocale() may have superseded this one
|
|
228
236
|
if (thisRequest !== _localeRequestId) return
|
package/src/solid-runtime.ts
CHANGED
|
@@ -7,7 +7,6 @@ export const solidRuntimeGenerator: RuntimeGenerator = createRuntimeGenerator({
|
|
|
7
7
|
localeInit: (defaultLocale) => `const [__currentLocale, __setCurrentLocale] = createSignal('${defaultLocale}')`,
|
|
8
8
|
loadingInit: 'const [__loading, __setLoading] = createSignal(false)',
|
|
9
9
|
catalogUpdate: (msgs) => `__setCatalog(reconcile(${msgs}))`,
|
|
10
|
-
catalogMerge: (msgs) => `__setCatalog(reconcile({ ...__catalog, ...${msgs} }))`,
|
|
11
10
|
localeUpdate: (locale) => `__setCurrentLocale(${locale})`,
|
|
12
11
|
loadingUpdate: (value) => `__setLoading(${value})`,
|
|
13
12
|
localeRead: '__currentLocale()',
|
package/src/vite-plugin.ts
CHANGED
|
@@ -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' },
|