@fluenti/react 0.4.0-rc.2 → 0.4.0-rc.4

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 +1 @@
1
- {"version":3,"file":"create-fluenti.d.ts","sourceRoot":"","sources":["../src/create-fluenti.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,uBAAuB,IAAI,sBAAsB,EACjD,eAAe,EACf,MAAM,EACN,QAAQ,EACR,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,iBAAiB,EAClB,MAAM,eAAe,CAAA;AAEtB;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;IAClC,oDAAoD;IACpD,YAAY,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,GAAG;QAAE,OAAO,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC,GAAG,SAAS,CAAA;IAC1F,oDAAoD;IACpD,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,wCAAwC;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,CAAA;IACpD,yBAAyB;IACzB,WAAW,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAA;IAC3C,2BAA2B;IAC3B,aAAa,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAA;IAC/C,8BAA8B;IAC9B,OAAO,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAA;IAC1E,2DAA2D;IAC3D,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IACjC,oEAAoE;IACpE,WAAW,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,GAAG,SAAS,CAAA;CAC3J;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,mEAAmE;IACnE,CAAC,EAAE;QACD,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,CAAA;QACnF,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,GAAG,eAAe,CAAA;KACtE,CAAA;IACD,iDAAiD;IACjD,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,eAAe,CAAA;IAC5D,mDAAmD;IACnD,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,eAAe,CAAA;IACrD,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,yDAAyD;IACzD,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C,iDAAiD;IACjD,SAAS,EAAE,OAAO,CAAA;IAClB,iEAAiE;IACjE,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAChD,6EAA6E;IAC7E,EAAE,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAA;IAC7C,mEAAmE;IACnE,EAAE,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,eAAe,GAAG,SAAS,CAAA;IACjE,qEAAqE;IACrE,IAAI,EAAE,sBAAsB,CAAA;IAC5B,gEAAgE;IAChE,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,eAAe,CAAA;IAC9E,iEAAiE;IACjE,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAA;IAC1D,wDAAwD;IACxD,UAAU,EAAE,MAAM,MAAM,EAAE,CAAA;IAC1B,qDAAqD;IACrD,aAAa,EAAE,MAAM,EAAE,CAAA;CACxB;AAYD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,eAAe,CAmLpE"}
1
+ {"version":3,"file":"create-fluenti.d.ts","sourceRoot":"","sources":["../src/create-fluenti.ts"],"names":[],"mappings":"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"}
@@ -8,4 +8,13 @@ import { FluentiContext } from '../types';
8
8
  * @throws If used outside of `<I18nProvider>`
9
9
  */
10
10
  export declare function useI18n(): FluentiContext;
11
+ /**
12
+ * Shorthand hook that returns only the current locale string.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * const locale = useLocale() // 'en'
17
+ * ```
18
+ */
19
+ export declare function useLocale(): string;
11
20
  //# sourceMappingURL=useI18n.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useI18n.d.ts","sourceRoot":"","sources":["../../src/hooks/useI18n.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAE9C;;;;;;;GAOG;AACH,wBAAgB,OAAO,IAAI,cAAc,CASxC"}
1
+ {"version":3,"file":"useI18n.d.ts","sourceRoot":"","sources":["../../src/hooks/useI18n.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAE9C;;;;;;;GAOG;AACH,wBAAgB,OAAO,IAAI,cAAc,CASxC;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAElC"}
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./context-DVbvrSE8.cjs`);let t=require(`react`),n=require(`@fluenti/core`),r=require(`react/jsx-runtime`);function i(e){let t={};for(let[n,r]of Object.entries(e))t[n]=typeof r==`object`&&r&&`default`in r?r.default:r;return t}function a(e){let{locale:r,messages:a,loadMessages:o,fallbackLocale:s,fallbackChain:c,dateFormats:l,numberFormats:u,missing:d,diagnostics:f,interpolate:p}=e,[m,h]=(0,t.useState)(r),[g,_]=(0,t.useState)(!1),[v,y]=(0,t.useState)(a?i(a):{}),[b,x]=(0,t.useState)(a?Object.keys(a):[]),S=(0,t.useRef)(v);S.current=v;let C=(0,t.useRef)(0),w=Symbol.for(`fluenti.runtime.react.v1`);function T(){let e=globalThis[w];return typeof e==`object`&&e?e:null}let E=(0,t.useMemo)(()=>{let e={locale:m,messages:v};return s!==void 0&&(e.fallbackLocale=s),c!==void 0&&(e.fallbackChain=c),l!==void 0&&(e.dateFormats=l),u!==void 0&&(e.numberFormats=u),d!==void 0&&(e.missing=d),f!==void 0&&(e.diagnostics=f),p!==void 0&&(e.interpolate=p),(0,n.createFluentiCore)(e)},[m,v,s,c,l,u,d,f,p]);(0,t.useEffect)(()=>{r!==m&&D(r)},[r]);let D=(0,t.useCallback)(async e=>{let t=++C.current,n=o?T():null;if(S.current[e]&&!o){h(e);return}if(S.current[e]){try{n?.__switchLocale&&await n.__switchLocale(e)}catch(t){console.warn(`[fluenti] split runtime switch failed for locale "${e}"`,t)}h(e);return}if(!o){console.warn(`[fluenti] No messages for locale "${e}" and no loadMessages function provided`);return}_(!0);try{let r=await o(e);if(t!==C.current)return;let i=typeof r==`object`&&r&&`default`in r?r.default:r;try{n?.__switchLocale&&await n.__switchLocale(e)}catch(t){console.warn(`[fluenti] split runtime switch failed for locale "${e}"`,t)}if(t!==C.current)return;y(t=>({...t,[e]:i})),x(t=>[...new Set([...t,e])]),h(e)}catch(n){t===C.current&&console.error(`[fluenti] Failed to load locale "${e}"`,n)}finally{t===C.current&&_(!1)}},[o]),O=(0,t.useCallback)(async e=>{if(!(S.current[e]||!o))try{let t=await o(e),n=typeof t==`object`&&t&&`default`in t?t.default:t;y(t=>({...t,[e]:n})),x(t=>[...new Set([...t,e])]);let r=T();r?.__preloadLocale&&await r.__preloadLocale(e)}catch{}},[o]),k=(0,t.useCallback)((e,t)=>{let n=v[t??m];return n!==void 0&&e in n},[v,m]),A=(0,t.useCallback)((e,t)=>{let n=v[t??m];if(n)return n[e]},[v,m]);return(0,t.useMemo)(()=>({t:E.t.bind(E),d:E.d.bind(E),n:E.n.bind(E),locale:m,setLocale:D,isLoading:g,preloadLocale:O,te:k,tm:A,i18n:E,format:E.format.bind(E),loadMessages:E.loadMessages.bind(E),getLocales:E.getLocales.bind(E),loadedLocales:b}),[E,m,D,g,O,k,A,b])}function o(e){globalThis.__fluenti_i18n=e}function s({instance:n,children:i}){let a=(0,t.useMemo)(()=>({t:n.t,d:n.d,n:n.n,format:n.format,loadMessages:n.loadMessages,getLocales:n.getLocales,locale:n.locale,setLocale:n.setLocale,isLoading:n.isLoading,loadedLocales:n.loadedLocales,preloadLocale:n.preloadLocale,te:n.te,tm:n.tm,i18n:n.i18n}),[n]);return(0,r.jsx)(e.t.Provider,{value:a,children:i})}function c(e){return e.instance?(0,r.jsx)(s,{instance:e.instance,children:e.children}):(0,r.jsx)(l,{...e})}function l({locale:e,fallbackLocale:n,messages:i,loadMessages:c,fallbackChain:l,dateFormats:u,numberFormats:d,missing:f,diagnostics:p,interpolate:m,children:h}){let g=a({locale:e??`en`,messages:i,loadMessages:c,fallbackLocale:n,fallbackChain:l,dateFormats:u,numberFormats:d,missing:f,diagnostics:p,interpolate:m});return(0,t.useEffect)(()=>{o(g.i18n)},[g.i18n]),(0,r.jsx)(s,{instance:g,children:h})}function u(){let n=(0,t.useContext)(e.t);if(!n)throw Error(`[fluenti] useI18n() must be used within an <I18nProvider>. Wrap your app with <I18nProvider> to provide i18n context.`);return n}var d=((...e)=>{throw Error("[fluenti] `t` imported from '@fluenti/react' 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.I18nContext=e.t,exports.I18nProvider=c,exports.createFluenti=a,Object.defineProperty(exports,`msg`,{enumerable:!0,get:function(){return n.msg}}),exports.t=d,exports.useI18n=u;
2
+ "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./context-DVbvrSE8.cjs`);let t=require(`react`),n=require(`@fluenti/core`),r=require(`react/jsx-runtime`);function i(e){let t={};for(let[n,r]of Object.entries(e))t[n]=typeof r==`object`&&r&&`default`in r?r.default:r;return t}function a(e){let{locale:r,messages:a,loadMessages:o,fallbackLocale:s,fallbackChain:c,dateFormats:l,numberFormats:u,missing:d,diagnostics:f,interpolate:p}=e,[m,h]=(0,t.useState)(r),[g,_]=(0,t.useState)(!1),[v,y]=(0,t.useState)(a?i(a):{}),[b,x]=(0,t.useState)(a?Object.keys(a):[]),S=(0,t.useRef)(v);S.current=v;let C=(0,t.useRef)(0),w=Symbol.for(`fluenti.runtime.react.v1`);function T(){let e=globalThis[w];return typeof e==`object`&&e?e:null}let E=(0,t.useMemo)(()=>{let e={locale:m,messages:v};return s!==void 0&&(e.fallbackLocale=s),c!==void 0&&(e.fallbackChain=c),l!==void 0&&(e.dateFormats=l),u!==void 0&&(e.numberFormats=u),d!==void 0&&(e.missing=d),f!==void 0&&(e.diagnostics=f),p!==void 0&&(e.interpolate=p),e.devWarnings=e.devWarnings??(typeof process<`u`&&process.env.NODE_ENV===`development`),(0,n.createFluentiCore)(e)},[m,v,s,c,l,u,d,f,p]);(0,t.useEffect)(()=>{r!==m&&D(r)},[r]);let D=(0,t.useCallback)(async e=>{let t=++C.current,n=o?T():null;if(S.current[e]&&!o){h(e);return}if(S.current[e]){try{n?.__switchLocale&&await n.__switchLocale(e)}catch(t){console.warn(`[fluenti] split runtime switch failed for locale "${e}"`,t)}h(e);return}if(!o){console.warn(`[fluenti] No messages for locale "${e}" and no loadMessages function provided`);return}_(!0);try{let r=await o(e);if(t!==C.current)return;let i=typeof r==`object`&&r&&`default`in r?r.default:r;try{n?.__switchLocale&&await n.__switchLocale(e)}catch(t){console.warn(`[fluenti] split runtime switch failed for locale "${e}"`,t)}if(t!==C.current)return;y(t=>({...t,[e]:i})),x(t=>[...new Set([...t,e])]),h(e)}catch(n){t===C.current&&console.error(`[fluenti] Failed to load locale "${e}"`,n)}finally{t===C.current&&_(!1)}},[o]),O=(0,t.useCallback)(async e=>{if(!(S.current[e]||!o))try{let t=await o(e),n=typeof t==`object`&&t&&`default`in t?t.default:t;y(t=>({...t,[e]:n})),x(t=>[...new Set([...t,e])]);let r=T();r?.__preloadLocale&&await r.__preloadLocale(e)}catch{}},[o]),k=(0,t.useCallback)((e,t)=>{let n=v[t??m];return n!==void 0&&e in n},[v,m]),A=(0,t.useCallback)((e,t)=>{let n=v[t??m];if(n)return n[e]},[v,m]);return(0,t.useMemo)(()=>({t:E.t.bind(E),d:E.d.bind(E),n:E.n.bind(E),locale:m,setLocale:D,isLoading:g,preloadLocale:O,te:k,tm:A,i18n:E,format:E.format.bind(E),loadMessages:E.loadMessages.bind(E),getLocales:E.getLocales.bind(E),loadedLocales:b}),[E,m,D,g,O,k,A,b])}function o(e){globalThis.__fluenti_i18n=e}function s({instance:n,children:i}){let a=(0,t.useMemo)(()=>({t:n.t,d:n.d,n:n.n,format:n.format,loadMessages:n.loadMessages,getLocales:n.getLocales,locale:n.locale,setLocale:n.setLocale,isLoading:n.isLoading,loadedLocales:n.loadedLocales,preloadLocale:n.preloadLocale,te:n.te,tm:n.tm,i18n:n.i18n}),[n]);return(0,r.jsx)(e.t.Provider,{value:a,children:i})}function c(e){return e.instance?(0,r.jsx)(s,{instance:e.instance,children:e.children}):(0,r.jsx)(l,{...e})}function l({locale:e,fallbackLocale:n,messages:i,loadMessages:c,fallbackChain:l,dateFormats:u,numberFormats:d,missing:f,diagnostics:p,interpolate:m,children:h}){let g=a({locale:e??`en`,messages:i,loadMessages:c,fallbackLocale:n,fallbackChain:l,dateFormats:u,numberFormats:d,missing:f,diagnostics:p,interpolate:m});return(0,t.useEffect)(()=>{o(g.i18n)},[g.i18n]),(0,r.jsx)(s,{instance:g,children:h})}function u(){let n=(0,t.useContext)(e.t);if(!n)throw Error(`[fluenti] useI18n() must be used within an <I18nProvider>. Wrap your app with <I18nProvider> to provide i18n context.`);return n}function d(){return u().locale}var f=((...e)=>{throw Error("[fluenti] `t` imported from '@fluenti/react' 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.I18nContext=e.t,exports.I18nProvider=c,exports.createFluenti=a,Object.defineProperty(exports,`msg`,{enumerable:!0,get:function(){return n.msg}}),exports.t=f,exports.useI18n=u,exports.useLocale=d;
3
3
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../src/create-fluenti.ts","../src/global-registry.ts","../src/provider.tsx","../src/hooks/useI18n.ts","../src/compile-time-t.ts"],"sourcesContent":["import { useState, useCallback, useEffect, useMemo, useRef } from 'react'\nimport { createFluentiCore } from '@fluenti/core'\nimport type {\n FluentiCoreInstanceFull as FluentInstanceExtended,\n CompiledMessage,\n Locale,\n Messages,\n AllMessages,\n DateFormatOptions,\n NumberFormatOptions,\n LocalizedString,\n MessageDescriptor,\n} from '@fluenti/core'\n\n/**\n * Configuration for `createFluenti()`.\n */\nexport interface FluentiConfig {\n /** Active locale code */\n locale: string\n /** Static message catalogs keyed by locale */\n messages?: AllMessages | undefined\n /** Async loader for lazy-loading locale messages */\n loadMessages?: ((locale: string) => Promise<Messages | { default: Messages }>) | undefined\n /** Fallback locale when a translation is missing */\n fallbackLocale?: string | undefined\n /** Custom fallback chains per locale */\n fallbackChain?: Record<string, string[]> | undefined\n /** Date format styles */\n dateFormats?: DateFormatOptions | undefined\n /** Number format styles */\n numberFormats?: NumberFormatOptions | undefined\n /** Missing message handler */\n missing?: ((locale: Locale, id: string) => string | undefined) | undefined\n /** Runtime diagnostics (pre-created instance or config) */\n diagnostics?: unknown | undefined\n /** Custom interpolation function for full ICU support at runtime */\n interpolate?: ((message: string, values: Record<string, unknown> | undefined, locale: string, formatters?: Record<string, unknown>) => string) | undefined\n}\n\n/**\n * The object returned by `createFluenti()`.\n *\n * Contains all i18n state and methods. Pass to `<I18nProvider instance={...}>`\n * or use directly in tests/non-React contexts.\n */\nexport interface FluentiInstance {\n /** Translate a message by id with optional interpolation values */\n t: {\n (id: string | MessageDescriptor, values?: Record<string, unknown>): LocalizedString\n (strings: TemplateStringsArray, ...exprs: unknown[]): LocalizedString\n }\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 /** Current locale */\n locale: string\n /** Change the active locale (async when lazy loading) */\n setLocale: (locale: string) => Promise<void>\n /** Whether a locale is currently being loaded */\n isLoading: boolean\n /** Preload a locale in the background without switching to it */\n preloadLocale: (locale: string) => Promise<void>\n /** Check whether a translation key exists for the given or current locale */\n te: (key: string, locale?: string) => boolean\n /** Get the raw compiled message for a key without interpolation */\n tm: (key: string, locale?: string) => CompiledMessage | undefined\n /** The underlying Fluent instance (escape hatch for advanced use) */\n i18n: FluentInstanceExtended\n /** Format an ICU message string directly (no catalog lookup) */\n format: (message: string, values?: Record<string, unknown>) => LocalizedString\n /** Merge additional messages into a locale catalog at runtime */\n loadMessages: (locale: string, messages: Messages) => void\n /** Return all locale codes that have loaded messages */\n getLocales: () => string[]\n /** Set of locales whose messages have been loaded */\n loadedLocales: string[]\n}\n\nfunction unwrapMessages(allMessages: Record<string, unknown>): Record<string, Messages> {\n const result: Record<string, Messages> = {}\n for (const [locale, msgs] of Object.entries(allMessages)) {\n result[locale] = typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : msgs as Messages\n }\n return result\n}\n\n/**\n * Create a standalone Fluenti i18n instance.\n *\n * This is a React hook that manages locale state, message loading, and\n * provides all i18n methods. The returned instance can be passed to\n * `<I18nProvider instance={...}>` to share it with the component tree.\n *\n * @example\n * ```tsx\n * function App() {\n * const i18n = createFluenti({\n * locale: 'en',\n * messages: { en: enMessages, fr: frMessages },\n * })\n * return (\n * <I18nProvider instance={i18n}>\n * <MyApp />\n * </I18nProvider>\n * )\n * }\n * ```\n */\nexport function createFluenti(config: FluentiConfig): FluentiInstance {\n const {\n locale: initialLocale,\n messages: initialMessages,\n loadMessages: loadMessagesFn,\n fallbackLocale,\n fallbackChain,\n dateFormats,\n numberFormats,\n missing,\n diagnostics,\n interpolate,\n } = config\n\n const [currentLocale, setCurrentLocale] = useState(initialLocale)\n const [isLoading, setIsLoading] = useState(false)\n const [loadedMessages, setLoadedMessages] = useState<Record<string, Messages>>(\n initialMessages ? unwrapMessages(initialMessages) : {},\n )\n const [loadedLocales, setLoadedLocales] = useState<string[]>(\n initialMessages ? Object.keys(initialMessages) : [],\n )\n\n const loadedMessagesRef = useRef(loadedMessages)\n loadedMessagesRef.current = loadedMessages\n\n const localeRequestRef = useRef(0)\n\n // Split runtime integration (for Vite plugin code splitting)\n const SPLIT_RUNTIME_KEY = Symbol.for('fluenti.runtime.react.v1')\n function getSplitRuntime(): { __switchLocale?: (l: string) => Promise<void>; __preloadLocale?: (l: string) => Promise<void> } | null {\n const rt = (globalThis as Record<PropertyKey, unknown>)[SPLIT_RUNTIME_KEY]\n return typeof rt === 'object' && rt !== null ? rt as any : null\n }\n\n const i18n = useMemo(() => {\n const cfg: Parameters<typeof createFluentiCore>[0] = {\n locale: currentLocale,\n messages: loadedMessages,\n }\n if (fallbackLocale !== undefined) cfg.fallbackLocale = fallbackLocale\n if (fallbackChain !== undefined) cfg.fallbackChain = fallbackChain\n if (dateFormats !== undefined) cfg.dateFormats = dateFormats\n if (numberFormats !== undefined) cfg.numberFormats = numberFormats\n if (missing !== undefined) cfg.missing = missing\n if (diagnostics !== undefined) cfg.diagnostics = diagnostics as Parameters<typeof createFluentiCore>[0]['diagnostics']\n if (interpolate !== undefined) cfg.interpolate = interpolate\n return createFluentiCore(cfg)\n }, [currentLocale, loadedMessages, fallbackLocale, fallbackChain, dateFormats, numberFormats, missing, diagnostics, interpolate])\n\n // Sync external locale changes\n useEffect(() => {\n if (initialLocale !== currentLocale) {\n void handleSetLocale(initialLocale)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [initialLocale])\n\n const handleSetLocale = useCallback(\n async (newLocale: string) => {\n const requestId = ++localeRequestRef.current\n\n const splitRuntime = loadMessagesFn ? getSplitRuntime() : null\n\n if (loadedMessagesRef.current[newLocale] && !loadMessagesFn) {\n setCurrentLocale(newLocale)\n return\n }\n\n if (loadedMessagesRef.current[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 setCurrentLocale(newLocale)\n return\n }\n\n if (!loadMessagesFn) {\n console.warn(\n `[fluenti] No messages for locale \"${newLocale}\" and no loadMessages function provided`,\n )\n return\n }\n\n setIsLoading(true)\n try {\n const msgs = await loadMessagesFn(newLocale)\n if (requestId !== localeRequestRef.current) return\n\n const resolved: Messages =\n typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : (msgs as Messages)\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 if (requestId !== localeRequestRef.current) return\n setLoadedMessages((prev) => ({ ...prev, [newLocale]: resolved }))\n setLoadedLocales((prev) => [...new Set([...prev, newLocale])])\n setCurrentLocale(newLocale)\n } catch (err) {\n if (requestId === localeRequestRef.current) {\n console.error(`[fluenti] Failed to load locale \"${newLocale}\"`, err)\n }\n } finally {\n if (requestId === localeRequestRef.current) {\n setIsLoading(false)\n }\n }\n },\n [loadMessagesFn],\n )\n\n const preloadLocale = useCallback(\n async (loc: string) => {\n if (loadedMessagesRef.current[loc] || !loadMessagesFn) return\n try {\n const msgs = await loadMessagesFn(loc)\n const resolved: Messages =\n typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : (msgs as Messages)\n setLoadedMessages((prev) => ({ ...prev, [loc]: resolved }))\n setLoadedLocales((prev) => [...new Set([...prev, loc])])\n const splitRuntime = getSplitRuntime()\n if (splitRuntime?.__preloadLocale) {\n await splitRuntime.__preloadLocale(loc)\n }\n } catch {\n // Silent fail for preload\n }\n },\n [loadMessagesFn],\n )\n\n const te = useCallback(\n (key: string, loc?: string): boolean => {\n const msgs = loadedMessages[loc ?? currentLocale]\n return msgs !== undefined && key in msgs\n },\n [loadedMessages, currentLocale],\n )\n\n const tm = useCallback(\n (key: string, loc?: string): Messages[string] | undefined => {\n const msgs = loadedMessages[loc ?? currentLocale]\n if (!msgs) return undefined\n return msgs[key]\n },\n [loadedMessages, currentLocale],\n )\n\n return useMemo(\n () => ({\n t: i18n.t.bind(i18n),\n d: i18n.d.bind(i18n),\n n: i18n.n.bind(i18n),\n locale: currentLocale,\n setLocale: handleSetLocale,\n isLoading,\n preloadLocale,\n te,\n tm,\n i18n,\n format: i18n.format.bind(i18n),\n loadMessages: i18n.loadMessages.bind(i18n),\n getLocales: i18n.getLocales.bind(i18n),\n loadedLocales,\n }),\n [i18n, currentLocale, handleSetLocale, isLoading, preloadLocale, te, tm, loadedLocales],\n )\n}\n","import type { FluentiCoreInstanceFull } from '@fluenti/core'\n\n/**\n * Global i18n instance registry.\n *\n * Used by `@fluenti/next` webpack loader and `@fluenti/vite-plugin` to access\n * the i18n instance from module-level code via a Proxy. The instance is set by\n * `<I18nProvider>` on mount.\n */\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __fluenti_i18n: FluentiCoreInstanceFull | undefined\n}\n\n/** Get the global i18n instance (set by `<I18nProvider>`). */\nexport function getGlobalI18n(): FluentiCoreInstanceFull | undefined {\n return globalThis.__fluenti_i18n\n}\n\n/** Set the global i18n instance. Called by `<I18nProvider>` on mount. */\nexport function setGlobalI18n(instance: FluentiCoreInstanceFull): void {\n globalThis.__fluenti_i18n = instance\n}\n\n/** Clear the global i18n instance. Primarily for testing. */\nexport function clearGlobalI18n(): void {\n globalThis.__fluenti_i18n = undefined\n}\n","import { useEffect, useMemo } from 'react'\nimport { I18nContext } from './context'\nimport type { FluentiProviderProps, FluentiContext } from './types'\nimport type { FluentiInstance } from './create-fluenti'\nimport { createFluenti } from './create-fluenti'\nimport { setGlobalI18n } from './global-registry'\n\n/**\n * Internal provider that uses a pre-created `FluentiInstance`.\n */\nfunction InstanceProvider({ instance, children }: { instance: FluentiInstance; children: React.ReactNode }) {\n const ctx: FluentiContext = useMemo(\n () => ({\n t: instance.t,\n d: instance.d,\n n: instance.n,\n format: instance.format,\n loadMessages: instance.loadMessages,\n getLocales: instance.getLocales,\n locale: instance.locale,\n setLocale: instance.setLocale,\n isLoading: instance.isLoading,\n loadedLocales: instance.loadedLocales,\n preloadLocale: instance.preloadLocale,\n te: instance.te,\n tm: instance.tm,\n // Internal: used by __useI18n hook and compiled components — not part of public API\n i18n: instance.i18n,\n }) as FluentiContext,\n [instance],\n )\n\n return <I18nContext.Provider value={ctx}>{children}</I18nContext.Provider>\n}\n\n/**\n * Provides the Fluenti i18n context to the React component tree.\n *\n * Accepts either a `locale` + `messages` pair for inline configuration,\n * or a pre-created `instance` from `createFluenti()`.\n *\n * @example\n * ```tsx\n * import { I18nProvider, useI18n } from '@fluenti/react'\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 *\n * @example Using a pre-created instance\n * ```tsx\n * import { I18nProvider, createFluenti } from '@fluenti/react'\n * import messages from './locales/compiled/en.js'\n *\n * const i18n = createFluenti({ locale: 'en', messages: { en: messages } })\n *\n * function App() {\n * return (\n * <I18nProvider instance={i18n}>\n * <Content />\n * </I18nProvider>\n * )\n * }\n * ```\n */\nexport function I18nProvider(props: FluentiProviderProps) {\n if (props.instance) {\n return <InstanceProvider instance={props.instance}>{props.children}</InstanceProvider>\n }\n\n return <InlineProvider {...props} />\n}\n\n/**\n * Inline provider that delegates to `createFluenti()` for state management.\n */\nfunction InlineProvider({\n locale,\n fallbackLocale,\n messages,\n loadMessages,\n fallbackChain,\n dateFormats,\n numberFormats,\n missing,\n diagnostics,\n interpolate,\n children,\n}: FluentiProviderProps) {\n const instance = createFluenti({\n locale: locale ?? 'en',\n messages,\n loadMessages,\n fallbackLocale,\n fallbackChain,\n dateFormats,\n numberFormats,\n missing,\n diagnostics,\n interpolate,\n })\n\n // Set global i18n instance for webpack loader / vite plugin access\n useEffect(() => {\n setGlobalI18n(instance.i18n)\n }, [instance.i18n])\n\n return <InstanceProvider instance={instance}>{children}</InstanceProvider>\n}\n","import { useContext } from 'react'\nimport { I18nContext } from '../context'\nimport type { FluentiContext } from '../types'\n\n/**\n * Primary hook for accessing i18n functions.\n *\n * Returns locale, setLocale, isLoading, loadedLocales, preloadLocale,\n * and the underlying i18n instance with t(), d(), n() methods.\n *\n * @throws If used outside of `<I18nProvider>`\n */\nexport function useI18n(): FluentiContext {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error(\n '[fluenti] useI18n() must be used within an <I18nProvider>. ' +\n 'Wrap your app with <I18nProvider> to provide i18n context.',\n )\n }\n return ctx\n}\n","import type { CompileTimeT } from '@fluenti/core'\n\nexport const t: CompileTimeT = ((..._args: unknown[]) => {\n throw new Error(\n \"[fluenti] `t` imported from '@fluenti/react' is a compile-time API. \" +\n 'Use it only with the Fluenti build transform inside a component or custom hook. ' +\n 'For runtime lookups, use useI18n().t(...).',\n )\n}) as CompileTimeT\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/create-fluenti.ts","../src/global-registry.ts","../src/provider.tsx","../src/hooks/useI18n.ts","../src/compile-time-t.ts"],"sourcesContent":["import { useState, useCallback, useEffect, useMemo, useRef } from 'react'\nimport { createFluentiCore } from '@fluenti/core'\nimport type {\n FluentiCoreInstanceFull as FluentInstanceExtended,\n CompiledMessage,\n Locale,\n Messages,\n AllMessages,\n DateFormatOptions,\n NumberFormatOptions,\n LocalizedString,\n MessageDescriptor,\n} from '@fluenti/core'\n\n/**\n * Configuration for `createFluenti()`.\n */\nexport interface FluentiConfig {\n /** Active locale code */\n locale: string\n /** Static message catalogs keyed by locale */\n messages?: AllMessages | undefined\n /** Async loader for lazy-loading locale messages */\n loadMessages?: ((locale: string) => Promise<Messages | { default: Messages }>) | undefined\n /** Fallback locale when a translation is missing */\n fallbackLocale?: string | undefined\n /** Custom fallback chains per locale */\n fallbackChain?: Record<string, string[]> | undefined\n /** Date format styles */\n dateFormats?: DateFormatOptions | undefined\n /** Number format styles */\n numberFormats?: NumberFormatOptions | undefined\n /** Missing message handler */\n missing?: ((locale: Locale, id: string) => string | undefined) | undefined\n /** Runtime diagnostics (pre-created instance or config) */\n diagnostics?: unknown | undefined\n /** Custom interpolation function for full ICU support at runtime */\n interpolate?: ((message: string, values: Record<string, unknown> | undefined, locale: string, formatters?: Record<string, unknown>) => string) | undefined\n}\n\n/**\n * The object returned by `createFluenti()`.\n *\n * Contains all i18n state and methods. Pass to `<I18nProvider instance={...}>`\n * or use directly in tests/non-React contexts.\n */\nexport interface FluentiInstance {\n /** Translate a message by id with optional interpolation values */\n t: {\n (id: string | MessageDescriptor, values?: Record<string, unknown>): LocalizedString\n (strings: TemplateStringsArray, ...exprs: unknown[]): LocalizedString\n }\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 /** Current locale */\n locale: string\n /** Change the active locale (async when lazy loading) */\n setLocale: (locale: string) => Promise<void>\n /** Whether a locale is currently being loaded */\n isLoading: boolean\n /** Preload a locale in the background without switching to it */\n preloadLocale: (locale: string) => Promise<void>\n /** Check whether a translation key exists for the given or current locale */\n te: (key: string, locale?: string) => boolean\n /** Get the raw compiled message for a key without interpolation */\n tm: (key: string, locale?: string) => CompiledMessage | undefined\n /** The underlying Fluent instance (escape hatch for advanced use) */\n i18n: FluentInstanceExtended\n /** Format an ICU message string directly (no catalog lookup) */\n format: (message: string, values?: Record<string, unknown>) => LocalizedString\n /** Merge additional messages into a locale catalog at runtime */\n loadMessages: (locale: string, messages: Messages) => void\n /** Return all locale codes that have loaded messages */\n getLocales: () => string[]\n /** Set of locales whose messages have been loaded */\n loadedLocales: string[]\n}\n\nfunction unwrapMessages(allMessages: Record<string, unknown>): Record<string, Messages> {\n const result: Record<string, Messages> = {}\n for (const [locale, msgs] of Object.entries(allMessages)) {\n result[locale] = typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : msgs as Messages\n }\n return result\n}\n\n/**\n * Create a standalone Fluenti i18n instance.\n *\n * This is a React hook that manages locale state, message loading, and\n * provides all i18n methods. The returned instance can be passed to\n * `<I18nProvider instance={...}>` to share it with the component tree.\n *\n * @example\n * ```tsx\n * function App() {\n * const i18n = createFluenti({\n * locale: 'en',\n * messages: { en: enMessages, fr: frMessages },\n * })\n * return (\n * <I18nProvider instance={i18n}>\n * <MyApp />\n * </I18nProvider>\n * )\n * }\n * ```\n */\nexport function createFluenti(config: FluentiConfig): FluentiInstance {\n const {\n locale: initialLocale,\n messages: initialMessages,\n loadMessages: loadMessagesFn,\n fallbackLocale,\n fallbackChain,\n dateFormats,\n numberFormats,\n missing,\n diagnostics,\n interpolate,\n } = config\n\n const [currentLocale, setCurrentLocale] = useState(initialLocale)\n const [isLoading, setIsLoading] = useState(false)\n const [loadedMessages, setLoadedMessages] = useState<Record<string, Messages>>(\n initialMessages ? unwrapMessages(initialMessages) : {},\n )\n const [loadedLocales, setLoadedLocales] = useState<string[]>(\n initialMessages ? Object.keys(initialMessages) : [],\n )\n\n const loadedMessagesRef = useRef(loadedMessages)\n loadedMessagesRef.current = loadedMessages\n\n const localeRequestRef = useRef(0)\n\n // Split runtime integration (for Vite plugin code splitting)\n const SPLIT_RUNTIME_KEY = Symbol.for('fluenti.runtime.react.v1')\n function getSplitRuntime(): { __switchLocale?: (l: string) => Promise<void>; __preloadLocale?: (l: string) => Promise<void> } | null {\n const rt = (globalThis as Record<PropertyKey, unknown>)[SPLIT_RUNTIME_KEY]\n return typeof rt === 'object' && rt !== null ? rt as any : null\n }\n\n const i18n = useMemo(() => {\n const cfg: Parameters<typeof createFluentiCore>[0] = {\n locale: currentLocale,\n messages: loadedMessages,\n }\n if (fallbackLocale !== undefined) cfg.fallbackLocale = fallbackLocale\n if (fallbackChain !== undefined) cfg.fallbackChain = fallbackChain\n if (dateFormats !== undefined) cfg.dateFormats = dateFormats\n if (numberFormats !== undefined) cfg.numberFormats = numberFormats\n if (missing !== undefined) cfg.missing = missing\n if (diagnostics !== undefined) cfg.diagnostics = diagnostics as Parameters<typeof createFluentiCore>[0]['diagnostics']\n if (interpolate !== undefined) cfg.interpolate = interpolate\n cfg.devWarnings = cfg.devWarnings ?? (typeof process !== 'undefined' && process.env?.['NODE_ENV'] === 'development')\n return createFluentiCore(cfg)\n }, [currentLocale, loadedMessages, fallbackLocale, fallbackChain, dateFormats, numberFormats, missing, diagnostics, interpolate])\n\n // Sync external locale changes\n useEffect(() => {\n if (initialLocale !== currentLocale) {\n void handleSetLocale(initialLocale)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [initialLocale])\n\n const handleSetLocale = useCallback(\n async (newLocale: string) => {\n const requestId = ++localeRequestRef.current\n\n const splitRuntime = loadMessagesFn ? getSplitRuntime() : null\n\n if (loadedMessagesRef.current[newLocale] && !loadMessagesFn) {\n setCurrentLocale(newLocale)\n return\n }\n\n if (loadedMessagesRef.current[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 setCurrentLocale(newLocale)\n return\n }\n\n if (!loadMessagesFn) {\n console.warn(\n `[fluenti] No messages for locale \"${newLocale}\" and no loadMessages function provided`,\n )\n return\n }\n\n setIsLoading(true)\n try {\n const msgs = await loadMessagesFn(newLocale)\n if (requestId !== localeRequestRef.current) return\n\n const resolved: Messages =\n typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : (msgs as Messages)\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 if (requestId !== localeRequestRef.current) return\n setLoadedMessages((prev) => ({ ...prev, [newLocale]: resolved }))\n setLoadedLocales((prev) => [...new Set([...prev, newLocale])])\n setCurrentLocale(newLocale)\n } catch (err) {\n if (requestId === localeRequestRef.current) {\n console.error(`[fluenti] Failed to load locale \"${newLocale}\"`, err)\n }\n } finally {\n if (requestId === localeRequestRef.current) {\n setIsLoading(false)\n }\n }\n },\n [loadMessagesFn],\n )\n\n const preloadLocale = useCallback(\n async (loc: string) => {\n if (loadedMessagesRef.current[loc] || !loadMessagesFn) return\n try {\n const msgs = await loadMessagesFn(loc)\n const resolved: Messages =\n typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : (msgs as Messages)\n setLoadedMessages((prev) => ({ ...prev, [loc]: resolved }))\n setLoadedLocales((prev) => [...new Set([...prev, loc])])\n const splitRuntime = getSplitRuntime()\n if (splitRuntime?.__preloadLocale) {\n await splitRuntime.__preloadLocale(loc)\n }\n } catch {\n // Silent fail for preload\n }\n },\n [loadMessagesFn],\n )\n\n const te = useCallback(\n (key: string, loc?: string): boolean => {\n const msgs = loadedMessages[loc ?? currentLocale]\n return msgs !== undefined && key in msgs\n },\n [loadedMessages, currentLocale],\n )\n\n const tm = useCallback(\n (key: string, loc?: string): Messages[string] | undefined => {\n const msgs = loadedMessages[loc ?? currentLocale]\n if (!msgs) return undefined\n return msgs[key]\n },\n [loadedMessages, currentLocale],\n )\n\n return useMemo(\n () => ({\n t: i18n.t.bind(i18n),\n d: i18n.d.bind(i18n),\n n: i18n.n.bind(i18n),\n locale: currentLocale,\n setLocale: handleSetLocale,\n isLoading,\n preloadLocale,\n te,\n tm,\n i18n,\n format: i18n.format.bind(i18n),\n loadMessages: i18n.loadMessages.bind(i18n),\n getLocales: i18n.getLocales.bind(i18n),\n loadedLocales,\n }),\n [i18n, currentLocale, handleSetLocale, isLoading, preloadLocale, te, tm, loadedLocales],\n )\n}\n","import type { FluentiCoreInstanceFull } from '@fluenti/core'\n\n/**\n * Global i18n instance registry.\n *\n * Used by `@fluenti/next` webpack loader and `@fluenti/vite-plugin` to access\n * the i18n instance from module-level code via a Proxy. The instance is set by\n * `<I18nProvider>` on mount.\n */\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __fluenti_i18n: FluentiCoreInstanceFull | undefined\n}\n\n/** Get the global i18n instance (set by `<I18nProvider>`). */\nexport function getGlobalI18n(): FluentiCoreInstanceFull | undefined {\n return globalThis.__fluenti_i18n\n}\n\n/** Set the global i18n instance. Called by `<I18nProvider>` on mount. */\nexport function setGlobalI18n(instance: FluentiCoreInstanceFull): void {\n globalThis.__fluenti_i18n = instance\n}\n\n/** Clear the global i18n instance. Primarily for testing. */\nexport function clearGlobalI18n(): void {\n globalThis.__fluenti_i18n = undefined\n}\n","import { useEffect, useMemo } from 'react'\nimport { I18nContext } from './context'\nimport type { FluentiProviderProps, FluentiContext } from './types'\nimport type { FluentiInstance } from './create-fluenti'\nimport { createFluenti } from './create-fluenti'\nimport { setGlobalI18n } from './global-registry'\n\n/**\n * Internal provider that uses a pre-created `FluentiInstance`.\n */\nfunction InstanceProvider({ instance, children }: { instance: FluentiInstance; children: React.ReactNode }) {\n const ctx: FluentiContext = useMemo(\n () => ({\n t: instance.t,\n d: instance.d,\n n: instance.n,\n format: instance.format,\n loadMessages: instance.loadMessages,\n getLocales: instance.getLocales,\n locale: instance.locale,\n setLocale: instance.setLocale,\n isLoading: instance.isLoading,\n loadedLocales: instance.loadedLocales,\n preloadLocale: instance.preloadLocale,\n te: instance.te,\n tm: instance.tm,\n // Internal: used by __useI18n hook and compiled components — not part of public API\n i18n: instance.i18n,\n }) as FluentiContext,\n [instance],\n )\n\n return <I18nContext.Provider value={ctx}>{children}</I18nContext.Provider>\n}\n\n/**\n * Provides the Fluenti i18n context to the React component tree.\n *\n * Accepts either a `locale` + `messages` pair for inline configuration,\n * or a pre-created `instance` from `createFluenti()`.\n *\n * @example\n * ```tsx\n * import { I18nProvider, useI18n } from '@fluenti/react'\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 *\n * @example Using a pre-created instance\n * ```tsx\n * import { I18nProvider, createFluenti } from '@fluenti/react'\n * import messages from './locales/compiled/en.js'\n *\n * const i18n = createFluenti({ locale: 'en', messages: { en: messages } })\n *\n * function App() {\n * return (\n * <I18nProvider instance={i18n}>\n * <Content />\n * </I18nProvider>\n * )\n * }\n * ```\n */\nexport function I18nProvider(props: FluentiProviderProps) {\n if (props.instance) {\n return <InstanceProvider instance={props.instance}>{props.children}</InstanceProvider>\n }\n\n return <InlineProvider {...props} />\n}\n\n/**\n * Inline provider that delegates to `createFluenti()` for state management.\n */\nfunction InlineProvider({\n locale,\n fallbackLocale,\n messages,\n loadMessages,\n fallbackChain,\n dateFormats,\n numberFormats,\n missing,\n diagnostics,\n interpolate,\n children,\n}: FluentiProviderProps) {\n const instance = createFluenti({\n locale: locale ?? 'en',\n messages,\n loadMessages,\n fallbackLocale,\n fallbackChain,\n dateFormats,\n numberFormats,\n missing,\n diagnostics,\n interpolate,\n })\n\n // Set global i18n instance for webpack loader / vite plugin access\n useEffect(() => {\n setGlobalI18n(instance.i18n)\n }, [instance.i18n])\n\n return <InstanceProvider instance={instance}>{children}</InstanceProvider>\n}\n","import { useContext } from 'react'\nimport { I18nContext } from '../context'\nimport type { FluentiContext } from '../types'\n\n/**\n * Primary hook for accessing i18n functions.\n *\n * Returns locale, setLocale, isLoading, loadedLocales, preloadLocale,\n * and the underlying i18n instance with t(), d(), n() methods.\n *\n * @throws If used outside of `<I18nProvider>`\n */\nexport function useI18n(): FluentiContext {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error(\n '[fluenti] useI18n() must be used within an <I18nProvider>. ' +\n 'Wrap your app with <I18nProvider> to provide i18n context.',\n )\n }\n return ctx\n}\n\n/**\n * Shorthand hook that returns only the current locale string.\n *\n * @example\n * ```tsx\n * const locale = useLocale() // 'en'\n * ```\n */\nexport function useLocale(): string {\n return useI18n().locale\n}\n","import type { CompileTimeT } from '@fluenti/core'\n\nexport const t: CompileTimeT = ((..._args: unknown[]) => {\n throw new Error(\n \"[fluenti] `t` imported from '@fluenti/react' is a compile-time API. \" +\n 'Use it only with the Fluenti build transform inside a component or custom hook. ' +\n 'For runtime lookups, use useI18n().t(...).',\n )\n}) as CompileTimeT\n"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export { createFluenti } from './create-fluenti';
2
2
  export type { FluentiConfig, FluentiInstance } from './create-fluenti';
3
3
  export { I18nProvider } from './provider';
4
4
  export { I18nContext } from './context';
5
- export { useI18n } from './hooks/useI18n';
5
+ export { useI18n, useLocale } from './hooks/useI18n';
6
6
  export { t } from './compile-time-t';
7
7
  export { msg } from './msg';
8
8
  export type { FluentiContext, I18nProviderProps, Messages, AllMessages, MessageDescriptor, CompileTimeMessageDescriptor, CompileTimeT, Locale, DateFormatOptions, NumberFormatOptions, } from './types';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAGtE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAGzC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAGvC,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,kBAAkB,CAAA;AAGpC,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAG3B,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,QAAQ,EACR,WAAW,EACX,iBAAiB,EACjB,4BAA4B,EAC5B,YAAY,EACZ,MAAM,EACN,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,SAAS,CAAA;AAIhB,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AACjE,YAAY,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAGtE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAGzC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAGvC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AACpD,OAAO,EAAE,CAAC,EAAE,MAAM,kBAAkB,CAAA;AAGpC,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAG3B,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,QAAQ,EACR,WAAW,EACX,iBAAiB,EACjB,4BAA4B,EAC5B,YAAY,EACZ,MAAM,EACN,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,SAAS,CAAA;AAIhB,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AACjE,YAAY,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAA"}
package/dist/index.js CHANGED
@@ -23,7 +23,7 @@ function d(e) {
23
23
  locale: v,
24
24
  messages: S
25
25
  };
26
- return d !== void 0 && (e.fallbackLocale = d), f !== void 0 && (e.fallbackChain = f), p !== void 0 && (e.dateFormats = p), m !== void 0 && (e.numberFormats = m), h !== void 0 && (e.missing = h), g !== void 0 && (e.diagnostics = g), _ !== void 0 && (e.interpolate = _), s(e);
26
+ return d !== void 0 && (e.fallbackLocale = d), f !== void 0 && (e.fallbackChain = f), p !== void 0 && (e.dateFormats = p), m !== void 0 && (e.numberFormats = m), h !== void 0 && (e.missing = h), g !== void 0 && (e.diagnostics = g), _ !== void 0 && (e.interpolate = _), e.devWarnings = e.devWarnings ?? (typeof process < "u" && process.env.NODE_ENV === "development"), s(e);
27
27
  }, [
28
28
  v,
29
29
  S,
@@ -182,12 +182,15 @@ function g() {
182
182
  if (!t) throw Error("[fluenti] useI18n() must be used within an <I18nProvider>. Wrap your app with <I18nProvider> to provide i18n context.");
183
183
  return t;
184
184
  }
185
+ function _() {
186
+ return g().locale;
187
+ }
185
188
  //#endregion
186
189
  //#region src/compile-time-t.ts
187
- var _ = ((...e) => {
190
+ var v = ((...e) => {
188
191
  throw Error("[fluenti] `t` imported from '@fluenti/react' 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(...).");
189
192
  });
190
193
  //#endregion
191
- export { e as I18nContext, m as I18nProvider, d as createFluenti, c as msg, _ as t, g as useI18n };
194
+ export { e as I18nContext, m as I18nProvider, d as createFluenti, c as msg, v as t, g as useI18n, _ as useLocale };
192
195
 
193
196
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/create-fluenti.ts","../src/global-registry.ts","../src/provider.tsx","../src/hooks/useI18n.ts","../src/compile-time-t.ts"],"sourcesContent":["import { useState, useCallback, useEffect, useMemo, useRef } from 'react'\nimport { createFluentiCore } from '@fluenti/core'\nimport type {\n FluentiCoreInstanceFull as FluentInstanceExtended,\n CompiledMessage,\n Locale,\n Messages,\n AllMessages,\n DateFormatOptions,\n NumberFormatOptions,\n LocalizedString,\n MessageDescriptor,\n} from '@fluenti/core'\n\n/**\n * Configuration for `createFluenti()`.\n */\nexport interface FluentiConfig {\n /** Active locale code */\n locale: string\n /** Static message catalogs keyed by locale */\n messages?: AllMessages | undefined\n /** Async loader for lazy-loading locale messages */\n loadMessages?: ((locale: string) => Promise<Messages | { default: Messages }>) | undefined\n /** Fallback locale when a translation is missing */\n fallbackLocale?: string | undefined\n /** Custom fallback chains per locale */\n fallbackChain?: Record<string, string[]> | undefined\n /** Date format styles */\n dateFormats?: DateFormatOptions | undefined\n /** Number format styles */\n numberFormats?: NumberFormatOptions | undefined\n /** Missing message handler */\n missing?: ((locale: Locale, id: string) => string | undefined) | undefined\n /** Runtime diagnostics (pre-created instance or config) */\n diagnostics?: unknown | undefined\n /** Custom interpolation function for full ICU support at runtime */\n interpolate?: ((message: string, values: Record<string, unknown> | undefined, locale: string, formatters?: Record<string, unknown>) => string) | undefined\n}\n\n/**\n * The object returned by `createFluenti()`.\n *\n * Contains all i18n state and methods. Pass to `<I18nProvider instance={...}>`\n * or use directly in tests/non-React contexts.\n */\nexport interface FluentiInstance {\n /** Translate a message by id with optional interpolation values */\n t: {\n (id: string | MessageDescriptor, values?: Record<string, unknown>): LocalizedString\n (strings: TemplateStringsArray, ...exprs: unknown[]): LocalizedString\n }\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 /** Current locale */\n locale: string\n /** Change the active locale (async when lazy loading) */\n setLocale: (locale: string) => Promise<void>\n /** Whether a locale is currently being loaded */\n isLoading: boolean\n /** Preload a locale in the background without switching to it */\n preloadLocale: (locale: string) => Promise<void>\n /** Check whether a translation key exists for the given or current locale */\n te: (key: string, locale?: string) => boolean\n /** Get the raw compiled message for a key without interpolation */\n tm: (key: string, locale?: string) => CompiledMessage | undefined\n /** The underlying Fluent instance (escape hatch for advanced use) */\n i18n: FluentInstanceExtended\n /** Format an ICU message string directly (no catalog lookup) */\n format: (message: string, values?: Record<string, unknown>) => LocalizedString\n /** Merge additional messages into a locale catalog at runtime */\n loadMessages: (locale: string, messages: Messages) => void\n /** Return all locale codes that have loaded messages */\n getLocales: () => string[]\n /** Set of locales whose messages have been loaded */\n loadedLocales: string[]\n}\n\nfunction unwrapMessages(allMessages: Record<string, unknown>): Record<string, Messages> {\n const result: Record<string, Messages> = {}\n for (const [locale, msgs] of Object.entries(allMessages)) {\n result[locale] = typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : msgs as Messages\n }\n return result\n}\n\n/**\n * Create a standalone Fluenti i18n instance.\n *\n * This is a React hook that manages locale state, message loading, and\n * provides all i18n methods. The returned instance can be passed to\n * `<I18nProvider instance={...}>` to share it with the component tree.\n *\n * @example\n * ```tsx\n * function App() {\n * const i18n = createFluenti({\n * locale: 'en',\n * messages: { en: enMessages, fr: frMessages },\n * })\n * return (\n * <I18nProvider instance={i18n}>\n * <MyApp />\n * </I18nProvider>\n * )\n * }\n * ```\n */\nexport function createFluenti(config: FluentiConfig): FluentiInstance {\n const {\n locale: initialLocale,\n messages: initialMessages,\n loadMessages: loadMessagesFn,\n fallbackLocale,\n fallbackChain,\n dateFormats,\n numberFormats,\n missing,\n diagnostics,\n interpolate,\n } = config\n\n const [currentLocale, setCurrentLocale] = useState(initialLocale)\n const [isLoading, setIsLoading] = useState(false)\n const [loadedMessages, setLoadedMessages] = useState<Record<string, Messages>>(\n initialMessages ? unwrapMessages(initialMessages) : {},\n )\n const [loadedLocales, setLoadedLocales] = useState<string[]>(\n initialMessages ? Object.keys(initialMessages) : [],\n )\n\n const loadedMessagesRef = useRef(loadedMessages)\n loadedMessagesRef.current = loadedMessages\n\n const localeRequestRef = useRef(0)\n\n // Split runtime integration (for Vite plugin code splitting)\n const SPLIT_RUNTIME_KEY = Symbol.for('fluenti.runtime.react.v1')\n function getSplitRuntime(): { __switchLocale?: (l: string) => Promise<void>; __preloadLocale?: (l: string) => Promise<void> } | null {\n const rt = (globalThis as Record<PropertyKey, unknown>)[SPLIT_RUNTIME_KEY]\n return typeof rt === 'object' && rt !== null ? rt as any : null\n }\n\n const i18n = useMemo(() => {\n const cfg: Parameters<typeof createFluentiCore>[0] = {\n locale: currentLocale,\n messages: loadedMessages,\n }\n if (fallbackLocale !== undefined) cfg.fallbackLocale = fallbackLocale\n if (fallbackChain !== undefined) cfg.fallbackChain = fallbackChain\n if (dateFormats !== undefined) cfg.dateFormats = dateFormats\n if (numberFormats !== undefined) cfg.numberFormats = numberFormats\n if (missing !== undefined) cfg.missing = missing\n if (diagnostics !== undefined) cfg.diagnostics = diagnostics as Parameters<typeof createFluentiCore>[0]['diagnostics']\n if (interpolate !== undefined) cfg.interpolate = interpolate\n return createFluentiCore(cfg)\n }, [currentLocale, loadedMessages, fallbackLocale, fallbackChain, dateFormats, numberFormats, missing, diagnostics, interpolate])\n\n // Sync external locale changes\n useEffect(() => {\n if (initialLocale !== currentLocale) {\n void handleSetLocale(initialLocale)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [initialLocale])\n\n const handleSetLocale = useCallback(\n async (newLocale: string) => {\n const requestId = ++localeRequestRef.current\n\n const splitRuntime = loadMessagesFn ? getSplitRuntime() : null\n\n if (loadedMessagesRef.current[newLocale] && !loadMessagesFn) {\n setCurrentLocale(newLocale)\n return\n }\n\n if (loadedMessagesRef.current[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 setCurrentLocale(newLocale)\n return\n }\n\n if (!loadMessagesFn) {\n console.warn(\n `[fluenti] No messages for locale \"${newLocale}\" and no loadMessages function provided`,\n )\n return\n }\n\n setIsLoading(true)\n try {\n const msgs = await loadMessagesFn(newLocale)\n if (requestId !== localeRequestRef.current) return\n\n const resolved: Messages =\n typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : (msgs as Messages)\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 if (requestId !== localeRequestRef.current) return\n setLoadedMessages((prev) => ({ ...prev, [newLocale]: resolved }))\n setLoadedLocales((prev) => [...new Set([...prev, newLocale])])\n setCurrentLocale(newLocale)\n } catch (err) {\n if (requestId === localeRequestRef.current) {\n console.error(`[fluenti] Failed to load locale \"${newLocale}\"`, err)\n }\n } finally {\n if (requestId === localeRequestRef.current) {\n setIsLoading(false)\n }\n }\n },\n [loadMessagesFn],\n )\n\n const preloadLocale = useCallback(\n async (loc: string) => {\n if (loadedMessagesRef.current[loc] || !loadMessagesFn) return\n try {\n const msgs = await loadMessagesFn(loc)\n const resolved: Messages =\n typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : (msgs as Messages)\n setLoadedMessages((prev) => ({ ...prev, [loc]: resolved }))\n setLoadedLocales((prev) => [...new Set([...prev, loc])])\n const splitRuntime = getSplitRuntime()\n if (splitRuntime?.__preloadLocale) {\n await splitRuntime.__preloadLocale(loc)\n }\n } catch {\n // Silent fail for preload\n }\n },\n [loadMessagesFn],\n )\n\n const te = useCallback(\n (key: string, loc?: string): boolean => {\n const msgs = loadedMessages[loc ?? currentLocale]\n return msgs !== undefined && key in msgs\n },\n [loadedMessages, currentLocale],\n )\n\n const tm = useCallback(\n (key: string, loc?: string): Messages[string] | undefined => {\n const msgs = loadedMessages[loc ?? currentLocale]\n if (!msgs) return undefined\n return msgs[key]\n },\n [loadedMessages, currentLocale],\n )\n\n return useMemo(\n () => ({\n t: i18n.t.bind(i18n),\n d: i18n.d.bind(i18n),\n n: i18n.n.bind(i18n),\n locale: currentLocale,\n setLocale: handleSetLocale,\n isLoading,\n preloadLocale,\n te,\n tm,\n i18n,\n format: i18n.format.bind(i18n),\n loadMessages: i18n.loadMessages.bind(i18n),\n getLocales: i18n.getLocales.bind(i18n),\n loadedLocales,\n }),\n [i18n, currentLocale, handleSetLocale, isLoading, preloadLocale, te, tm, loadedLocales],\n )\n}\n","import type { FluentiCoreInstanceFull } from '@fluenti/core'\n\n/**\n * Global i18n instance registry.\n *\n * Used by `@fluenti/next` webpack loader and `@fluenti/vite-plugin` to access\n * the i18n instance from module-level code via a Proxy. The instance is set by\n * `<I18nProvider>` on mount.\n */\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __fluenti_i18n: FluentiCoreInstanceFull | undefined\n}\n\n/** Get the global i18n instance (set by `<I18nProvider>`). */\nexport function getGlobalI18n(): FluentiCoreInstanceFull | undefined {\n return globalThis.__fluenti_i18n\n}\n\n/** Set the global i18n instance. Called by `<I18nProvider>` on mount. */\nexport function setGlobalI18n(instance: FluentiCoreInstanceFull): void {\n globalThis.__fluenti_i18n = instance\n}\n\n/** Clear the global i18n instance. Primarily for testing. */\nexport function clearGlobalI18n(): void {\n globalThis.__fluenti_i18n = undefined\n}\n","import { useEffect, useMemo } from 'react'\nimport { I18nContext } from './context'\nimport type { FluentiProviderProps, FluentiContext } from './types'\nimport type { FluentiInstance } from './create-fluenti'\nimport { createFluenti } from './create-fluenti'\nimport { setGlobalI18n } from './global-registry'\n\n/**\n * Internal provider that uses a pre-created `FluentiInstance`.\n */\nfunction InstanceProvider({ instance, children }: { instance: FluentiInstance; children: React.ReactNode }) {\n const ctx: FluentiContext = useMemo(\n () => ({\n t: instance.t,\n d: instance.d,\n n: instance.n,\n format: instance.format,\n loadMessages: instance.loadMessages,\n getLocales: instance.getLocales,\n locale: instance.locale,\n setLocale: instance.setLocale,\n isLoading: instance.isLoading,\n loadedLocales: instance.loadedLocales,\n preloadLocale: instance.preloadLocale,\n te: instance.te,\n tm: instance.tm,\n // Internal: used by __useI18n hook and compiled components — not part of public API\n i18n: instance.i18n,\n }) as FluentiContext,\n [instance],\n )\n\n return <I18nContext.Provider value={ctx}>{children}</I18nContext.Provider>\n}\n\n/**\n * Provides the Fluenti i18n context to the React component tree.\n *\n * Accepts either a `locale` + `messages` pair for inline configuration,\n * or a pre-created `instance` from `createFluenti()`.\n *\n * @example\n * ```tsx\n * import { I18nProvider, useI18n } from '@fluenti/react'\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 *\n * @example Using a pre-created instance\n * ```tsx\n * import { I18nProvider, createFluenti } from '@fluenti/react'\n * import messages from './locales/compiled/en.js'\n *\n * const i18n = createFluenti({ locale: 'en', messages: { en: messages } })\n *\n * function App() {\n * return (\n * <I18nProvider instance={i18n}>\n * <Content />\n * </I18nProvider>\n * )\n * }\n * ```\n */\nexport function I18nProvider(props: FluentiProviderProps) {\n if (props.instance) {\n return <InstanceProvider instance={props.instance}>{props.children}</InstanceProvider>\n }\n\n return <InlineProvider {...props} />\n}\n\n/**\n * Inline provider that delegates to `createFluenti()` for state management.\n */\nfunction InlineProvider({\n locale,\n fallbackLocale,\n messages,\n loadMessages,\n fallbackChain,\n dateFormats,\n numberFormats,\n missing,\n diagnostics,\n interpolate,\n children,\n}: FluentiProviderProps) {\n const instance = createFluenti({\n locale: locale ?? 'en',\n messages,\n loadMessages,\n fallbackLocale,\n fallbackChain,\n dateFormats,\n numberFormats,\n missing,\n diagnostics,\n interpolate,\n })\n\n // Set global i18n instance for webpack loader / vite plugin access\n useEffect(() => {\n setGlobalI18n(instance.i18n)\n }, [instance.i18n])\n\n return <InstanceProvider instance={instance}>{children}</InstanceProvider>\n}\n","import { useContext } from 'react'\nimport { I18nContext } from '../context'\nimport type { FluentiContext } from '../types'\n\n/**\n * Primary hook for accessing i18n functions.\n *\n * Returns locale, setLocale, isLoading, loadedLocales, preloadLocale,\n * and the underlying i18n instance with t(), d(), n() methods.\n *\n * @throws If used outside of `<I18nProvider>`\n */\nexport function useI18n(): FluentiContext {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error(\n '[fluenti] useI18n() must be used within an <I18nProvider>. ' +\n 'Wrap your app with <I18nProvider> to provide i18n context.',\n )\n }\n return ctx\n}\n","import type { CompileTimeT } from '@fluenti/core'\n\nexport const t: CompileTimeT = ((..._args: unknown[]) => {\n throw new Error(\n \"[fluenti] `t` imported from '@fluenti/react' is a compile-time API. \" +\n 'Use it only with the Fluenti build transform inside a component or custom hook. ' +\n 'For runtime lookups, use useI18n().t(...).',\n )\n}) as CompileTimeT\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/create-fluenti.ts","../src/global-registry.ts","../src/provider.tsx","../src/hooks/useI18n.ts","../src/compile-time-t.ts"],"sourcesContent":["import { useState, useCallback, useEffect, useMemo, useRef } from 'react'\nimport { createFluentiCore } from '@fluenti/core'\nimport type {\n FluentiCoreInstanceFull as FluentInstanceExtended,\n CompiledMessage,\n Locale,\n Messages,\n AllMessages,\n DateFormatOptions,\n NumberFormatOptions,\n LocalizedString,\n MessageDescriptor,\n} from '@fluenti/core'\n\n/**\n * Configuration for `createFluenti()`.\n */\nexport interface FluentiConfig {\n /** Active locale code */\n locale: string\n /** Static message catalogs keyed by locale */\n messages?: AllMessages | undefined\n /** Async loader for lazy-loading locale messages */\n loadMessages?: ((locale: string) => Promise<Messages | { default: Messages }>) | undefined\n /** Fallback locale when a translation is missing */\n fallbackLocale?: string | undefined\n /** Custom fallback chains per locale */\n fallbackChain?: Record<string, string[]> | undefined\n /** Date format styles */\n dateFormats?: DateFormatOptions | undefined\n /** Number format styles */\n numberFormats?: NumberFormatOptions | undefined\n /** Missing message handler */\n missing?: ((locale: Locale, id: string) => string | undefined) | undefined\n /** Runtime diagnostics (pre-created instance or config) */\n diagnostics?: unknown | undefined\n /** Custom interpolation function for full ICU support at runtime */\n interpolate?: ((message: string, values: Record<string, unknown> | undefined, locale: string, formatters?: Record<string, unknown>) => string) | undefined\n}\n\n/**\n * The object returned by `createFluenti()`.\n *\n * Contains all i18n state and methods. Pass to `<I18nProvider instance={...}>`\n * or use directly in tests/non-React contexts.\n */\nexport interface FluentiInstance {\n /** Translate a message by id with optional interpolation values */\n t: {\n (id: string | MessageDescriptor, values?: Record<string, unknown>): LocalizedString\n (strings: TemplateStringsArray, ...exprs: unknown[]): LocalizedString\n }\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 /** Current locale */\n locale: string\n /** Change the active locale (async when lazy loading) */\n setLocale: (locale: string) => Promise<void>\n /** Whether a locale is currently being loaded */\n isLoading: boolean\n /** Preload a locale in the background without switching to it */\n preloadLocale: (locale: string) => Promise<void>\n /** Check whether a translation key exists for the given or current locale */\n te: (key: string, locale?: string) => boolean\n /** Get the raw compiled message for a key without interpolation */\n tm: (key: string, locale?: string) => CompiledMessage | undefined\n /** The underlying Fluent instance (escape hatch for advanced use) */\n i18n: FluentInstanceExtended\n /** Format an ICU message string directly (no catalog lookup) */\n format: (message: string, values?: Record<string, unknown>) => LocalizedString\n /** Merge additional messages into a locale catalog at runtime */\n loadMessages: (locale: string, messages: Messages) => void\n /** Return all locale codes that have loaded messages */\n getLocales: () => string[]\n /** Set of locales whose messages have been loaded */\n loadedLocales: string[]\n}\n\nfunction unwrapMessages(allMessages: Record<string, unknown>): Record<string, Messages> {\n const result: Record<string, Messages> = {}\n for (const [locale, msgs] of Object.entries(allMessages)) {\n result[locale] = typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : msgs as Messages\n }\n return result\n}\n\n/**\n * Create a standalone Fluenti i18n instance.\n *\n * This is a React hook that manages locale state, message loading, and\n * provides all i18n methods. The returned instance can be passed to\n * `<I18nProvider instance={...}>` to share it with the component tree.\n *\n * @example\n * ```tsx\n * function App() {\n * const i18n = createFluenti({\n * locale: 'en',\n * messages: { en: enMessages, fr: frMessages },\n * })\n * return (\n * <I18nProvider instance={i18n}>\n * <MyApp />\n * </I18nProvider>\n * )\n * }\n * ```\n */\nexport function createFluenti(config: FluentiConfig): FluentiInstance {\n const {\n locale: initialLocale,\n messages: initialMessages,\n loadMessages: loadMessagesFn,\n fallbackLocale,\n fallbackChain,\n dateFormats,\n numberFormats,\n missing,\n diagnostics,\n interpolate,\n } = config\n\n const [currentLocale, setCurrentLocale] = useState(initialLocale)\n const [isLoading, setIsLoading] = useState(false)\n const [loadedMessages, setLoadedMessages] = useState<Record<string, Messages>>(\n initialMessages ? unwrapMessages(initialMessages) : {},\n )\n const [loadedLocales, setLoadedLocales] = useState<string[]>(\n initialMessages ? Object.keys(initialMessages) : [],\n )\n\n const loadedMessagesRef = useRef(loadedMessages)\n loadedMessagesRef.current = loadedMessages\n\n const localeRequestRef = useRef(0)\n\n // Split runtime integration (for Vite plugin code splitting)\n const SPLIT_RUNTIME_KEY = Symbol.for('fluenti.runtime.react.v1')\n function getSplitRuntime(): { __switchLocale?: (l: string) => Promise<void>; __preloadLocale?: (l: string) => Promise<void> } | null {\n const rt = (globalThis as Record<PropertyKey, unknown>)[SPLIT_RUNTIME_KEY]\n return typeof rt === 'object' && rt !== null ? rt as any : null\n }\n\n const i18n = useMemo(() => {\n const cfg: Parameters<typeof createFluentiCore>[0] = {\n locale: currentLocale,\n messages: loadedMessages,\n }\n if (fallbackLocale !== undefined) cfg.fallbackLocale = fallbackLocale\n if (fallbackChain !== undefined) cfg.fallbackChain = fallbackChain\n if (dateFormats !== undefined) cfg.dateFormats = dateFormats\n if (numberFormats !== undefined) cfg.numberFormats = numberFormats\n if (missing !== undefined) cfg.missing = missing\n if (diagnostics !== undefined) cfg.diagnostics = diagnostics as Parameters<typeof createFluentiCore>[0]['diagnostics']\n if (interpolate !== undefined) cfg.interpolate = interpolate\n cfg.devWarnings = cfg.devWarnings ?? (typeof process !== 'undefined' && process.env?.['NODE_ENV'] === 'development')\n return createFluentiCore(cfg)\n }, [currentLocale, loadedMessages, fallbackLocale, fallbackChain, dateFormats, numberFormats, missing, diagnostics, interpolate])\n\n // Sync external locale changes\n useEffect(() => {\n if (initialLocale !== currentLocale) {\n void handleSetLocale(initialLocale)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [initialLocale])\n\n const handleSetLocale = useCallback(\n async (newLocale: string) => {\n const requestId = ++localeRequestRef.current\n\n const splitRuntime = loadMessagesFn ? getSplitRuntime() : null\n\n if (loadedMessagesRef.current[newLocale] && !loadMessagesFn) {\n setCurrentLocale(newLocale)\n return\n }\n\n if (loadedMessagesRef.current[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 setCurrentLocale(newLocale)\n return\n }\n\n if (!loadMessagesFn) {\n console.warn(\n `[fluenti] No messages for locale \"${newLocale}\" and no loadMessages function provided`,\n )\n return\n }\n\n setIsLoading(true)\n try {\n const msgs = await loadMessagesFn(newLocale)\n if (requestId !== localeRequestRef.current) return\n\n const resolved: Messages =\n typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : (msgs as Messages)\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 if (requestId !== localeRequestRef.current) return\n setLoadedMessages((prev) => ({ ...prev, [newLocale]: resolved }))\n setLoadedLocales((prev) => [...new Set([...prev, newLocale])])\n setCurrentLocale(newLocale)\n } catch (err) {\n if (requestId === localeRequestRef.current) {\n console.error(`[fluenti] Failed to load locale \"${newLocale}\"`, err)\n }\n } finally {\n if (requestId === localeRequestRef.current) {\n setIsLoading(false)\n }\n }\n },\n [loadMessagesFn],\n )\n\n const preloadLocale = useCallback(\n async (loc: string) => {\n if (loadedMessagesRef.current[loc] || !loadMessagesFn) return\n try {\n const msgs = await loadMessagesFn(loc)\n const resolved: Messages =\n typeof msgs === 'object' && msgs !== null && 'default' in msgs\n ? (msgs as { default: Messages }).default\n : (msgs as Messages)\n setLoadedMessages((prev) => ({ ...prev, [loc]: resolved }))\n setLoadedLocales((prev) => [...new Set([...prev, loc])])\n const splitRuntime = getSplitRuntime()\n if (splitRuntime?.__preloadLocale) {\n await splitRuntime.__preloadLocale(loc)\n }\n } catch {\n // Silent fail for preload\n }\n },\n [loadMessagesFn],\n )\n\n const te = useCallback(\n (key: string, loc?: string): boolean => {\n const msgs = loadedMessages[loc ?? currentLocale]\n return msgs !== undefined && key in msgs\n },\n [loadedMessages, currentLocale],\n )\n\n const tm = useCallback(\n (key: string, loc?: string): Messages[string] | undefined => {\n const msgs = loadedMessages[loc ?? currentLocale]\n if (!msgs) return undefined\n return msgs[key]\n },\n [loadedMessages, currentLocale],\n )\n\n return useMemo(\n () => ({\n t: i18n.t.bind(i18n),\n d: i18n.d.bind(i18n),\n n: i18n.n.bind(i18n),\n locale: currentLocale,\n setLocale: handleSetLocale,\n isLoading,\n preloadLocale,\n te,\n tm,\n i18n,\n format: i18n.format.bind(i18n),\n loadMessages: i18n.loadMessages.bind(i18n),\n getLocales: i18n.getLocales.bind(i18n),\n loadedLocales,\n }),\n [i18n, currentLocale, handleSetLocale, isLoading, preloadLocale, te, tm, loadedLocales],\n )\n}\n","import type { FluentiCoreInstanceFull } from '@fluenti/core'\n\n/**\n * Global i18n instance registry.\n *\n * Used by `@fluenti/next` webpack loader and `@fluenti/vite-plugin` to access\n * the i18n instance from module-level code via a Proxy. The instance is set by\n * `<I18nProvider>` on mount.\n */\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __fluenti_i18n: FluentiCoreInstanceFull | undefined\n}\n\n/** Get the global i18n instance (set by `<I18nProvider>`). */\nexport function getGlobalI18n(): FluentiCoreInstanceFull | undefined {\n return globalThis.__fluenti_i18n\n}\n\n/** Set the global i18n instance. Called by `<I18nProvider>` on mount. */\nexport function setGlobalI18n(instance: FluentiCoreInstanceFull): void {\n globalThis.__fluenti_i18n = instance\n}\n\n/** Clear the global i18n instance. Primarily for testing. */\nexport function clearGlobalI18n(): void {\n globalThis.__fluenti_i18n = undefined\n}\n","import { useEffect, useMemo } from 'react'\nimport { I18nContext } from './context'\nimport type { FluentiProviderProps, FluentiContext } from './types'\nimport type { FluentiInstance } from './create-fluenti'\nimport { createFluenti } from './create-fluenti'\nimport { setGlobalI18n } from './global-registry'\n\n/**\n * Internal provider that uses a pre-created `FluentiInstance`.\n */\nfunction InstanceProvider({ instance, children }: { instance: FluentiInstance; children: React.ReactNode }) {\n const ctx: FluentiContext = useMemo(\n () => ({\n t: instance.t,\n d: instance.d,\n n: instance.n,\n format: instance.format,\n loadMessages: instance.loadMessages,\n getLocales: instance.getLocales,\n locale: instance.locale,\n setLocale: instance.setLocale,\n isLoading: instance.isLoading,\n loadedLocales: instance.loadedLocales,\n preloadLocale: instance.preloadLocale,\n te: instance.te,\n tm: instance.tm,\n // Internal: used by __useI18n hook and compiled components — not part of public API\n i18n: instance.i18n,\n }) as FluentiContext,\n [instance],\n )\n\n return <I18nContext.Provider value={ctx}>{children}</I18nContext.Provider>\n}\n\n/**\n * Provides the Fluenti i18n context to the React component tree.\n *\n * Accepts either a `locale` + `messages` pair for inline configuration,\n * or a pre-created `instance` from `createFluenti()`.\n *\n * @example\n * ```tsx\n * import { I18nProvider, useI18n } from '@fluenti/react'\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 *\n * @example Using a pre-created instance\n * ```tsx\n * import { I18nProvider, createFluenti } from '@fluenti/react'\n * import messages from './locales/compiled/en.js'\n *\n * const i18n = createFluenti({ locale: 'en', messages: { en: messages } })\n *\n * function App() {\n * return (\n * <I18nProvider instance={i18n}>\n * <Content />\n * </I18nProvider>\n * )\n * }\n * ```\n */\nexport function I18nProvider(props: FluentiProviderProps) {\n if (props.instance) {\n return <InstanceProvider instance={props.instance}>{props.children}</InstanceProvider>\n }\n\n return <InlineProvider {...props} />\n}\n\n/**\n * Inline provider that delegates to `createFluenti()` for state management.\n */\nfunction InlineProvider({\n locale,\n fallbackLocale,\n messages,\n loadMessages,\n fallbackChain,\n dateFormats,\n numberFormats,\n missing,\n diagnostics,\n interpolate,\n children,\n}: FluentiProviderProps) {\n const instance = createFluenti({\n locale: locale ?? 'en',\n messages,\n loadMessages,\n fallbackLocale,\n fallbackChain,\n dateFormats,\n numberFormats,\n missing,\n diagnostics,\n interpolate,\n })\n\n // Set global i18n instance for webpack loader / vite plugin access\n useEffect(() => {\n setGlobalI18n(instance.i18n)\n }, [instance.i18n])\n\n return <InstanceProvider instance={instance}>{children}</InstanceProvider>\n}\n","import { useContext } from 'react'\nimport { I18nContext } from '../context'\nimport type { FluentiContext } from '../types'\n\n/**\n * Primary hook for accessing i18n functions.\n *\n * Returns locale, setLocale, isLoading, loadedLocales, preloadLocale,\n * and the underlying i18n instance with t(), d(), n() methods.\n *\n * @throws If used outside of `<I18nProvider>`\n */\nexport function useI18n(): FluentiContext {\n const ctx = useContext(I18nContext)\n if (!ctx) {\n throw new Error(\n '[fluenti] useI18n() must be used within an <I18nProvider>. ' +\n 'Wrap your app with <I18nProvider> to provide i18n context.',\n )\n }\n return ctx\n}\n\n/**\n * Shorthand hook that returns only the current locale string.\n *\n * @example\n * ```tsx\n * const locale = useLocale() // 'en'\n * ```\n */\nexport function useLocale(): string {\n return useI18n().locale\n}\n","import type { CompileTimeT } from '@fluenti/core'\n\nexport const t: CompileTimeT = ((..._args: unknown[]) => {\n throw new Error(\n \"[fluenti] `t` imported from '@fluenti/react' is a compile-time API. \" +\n 'Use it only with the Fluenti build transform inside a component or custom hook. ' +\n 'For runtime lookups, use useI18n().t(...).',\n )\n}) as CompileTimeT\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluenti/react",
3
- "version": "0.4.0-rc.2",
3
+ "version": "0.4.0-rc.4",
4
4
  "type": "module",
5
5
  "description": "React bindings for Fluenti — I18nProvider, useI18n, Trans/Plural/Select components",
6
6
  "homepage": "https://fluenti.dev",
@@ -89,8 +89,8 @@
89
89
  }
90
90
  },
91
91
  "dependencies": {
92
- "@fluenti/core": "0.4.0-rc.2",
93
- "@fluenti/vite-plugin": "0.4.0-rc.2"
92
+ "@fluenti/core": "0.4.0-rc.4",
93
+ "@fluenti/vite-plugin": "0.4.0-rc.4"
94
94
  },
95
95
  "devDependencies": {
96
96
  "typescript": "^5.9",