@fluenti/react 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/components/DateTime.d.ts +2 -2
  2. package/dist/components/DateTime.d.ts.map +1 -1
  3. package/dist/components/Number.d.ts +2 -2
  4. package/dist/components/Number.d.ts.map +1 -1
  5. package/dist/components/Plural.d.ts +2 -2
  6. package/dist/components/Plural.d.ts.map +1 -1
  7. package/dist/components/Select.d.ts +5 -3
  8. package/dist/components/Select.d.ts.map +1 -1
  9. package/dist/components/Trans.d.ts +4 -2
  10. package/dist/components/Trans.d.ts.map +1 -1
  11. package/dist/components/icu-rich.d.ts +2 -9
  12. package/dist/components/icu-rich.d.ts.map +1 -1
  13. package/dist/components/plural-core.d.ts +2 -2
  14. package/dist/components/plural-core.d.ts.map +1 -1
  15. package/dist/components/trans-core.d.ts +1 -2
  16. package/dist/components/trans-core.d.ts.map +1 -1
  17. package/dist/context.d.ts +2 -2
  18. package/dist/context.d.ts.map +1 -1
  19. package/dist/create-fluenti.d.ts +87 -0
  20. package/dist/create-fluenti.d.ts.map +1 -0
  21. package/dist/global-registry.d.ts +4 -4
  22. package/dist/global-registry.d.ts.map +1 -1
  23. package/dist/hooks/__useI18n.d.ts +2 -2
  24. package/dist/hooks/__useI18n.d.ts.map +1 -1
  25. package/dist/hooks/useI18n.d.ts +2 -2
  26. package/dist/hooks/useI18n.d.ts.map +1 -1
  27. package/dist/icu-rich-BOtj4Oxu.js +71 -0
  28. package/dist/icu-rich-BOtj4Oxu.js.map +1 -0
  29. package/dist/icu-rich-vPU-0wGQ.cjs +2 -0
  30. package/dist/icu-rich-vPU-0wGQ.cjs.map +1 -0
  31. package/dist/index.cjs +1 -1
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.ts +8 -6
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +252 -107
  36. package/dist/index.js.map +1 -1
  37. package/dist/provider.d.ts +2 -2
  38. package/dist/provider.d.ts.map +1 -1
  39. package/dist/react-runtime.d.ts.map +1 -1
  40. package/dist/server.cjs +1 -1
  41. package/dist/server.cjs.map +1 -1
  42. package/dist/server.d.ts +13 -3
  43. package/dist/server.d.ts.map +1 -1
  44. package/dist/server.js +24 -13
  45. package/dist/server.js.map +1 -1
  46. package/dist/types.d.ts +17 -10
  47. package/dist/types.d.ts.map +1 -1
  48. package/dist/vite-plugin.cjs +1 -109
  49. package/dist/vite-plugin.cjs.map +1 -1
  50. package/dist/vite-plugin.js +13 -119
  51. package/dist/vite-plugin.js.map +1 -1
  52. package/llms-full.txt +185 -0
  53. package/llms-migration.txt +272 -0
  54. package/llms.txt +62 -0
  55. package/package.json +7 -5
  56. package/dist/icu-rich-DBeWY1k6.js +0 -108
  57. package/dist/icu-rich-DBeWY1k6.js.map +0 -1
  58. package/dist/icu-rich-XY1SdM5K.cjs +0 -2
  59. package/dist/icu-rich-XY1SdM5K.cjs.map +0 -1
package/dist/types.d.ts CHANGED
@@ -1,19 +1,17 @@
1
1
  import { ReactNode } from 'react';
2
- import { Locale, Messages, AllMessages, MessageDescriptor, CompileTimeMessageDescriptor, CompileTimeT, DateFormatOptions, NumberFormatOptions, FluentInstanceExtended } from '@fluenti/core';
3
- export interface I18nContextValue {
4
- /** The underlying Fluent instance (escape hatch for advanced use) */
5
- i18n: FluentInstanceExtended;
2
+ import { Locale, LocalizedString, Messages, AllMessages, CompiledMessage, MessageDescriptor, CompileTimeMessageDescriptor, CompileTimeT, DateFormatOptions, NumberFormatOptions, DiagnosticsConfig } from '@fluenti/core';
3
+ export interface FluentiContext {
6
4
  /** Translate a message by id with optional interpolation values */
7
5
  t: {
8
- (id: string | MessageDescriptor, values?: Record<string, unknown>): string;
9
- (strings: TemplateStringsArray, ...exprs: unknown[]): string;
6
+ (id: string | MessageDescriptor, values?: Record<string, unknown>): LocalizedString;
7
+ (strings: TemplateStringsArray, ...exprs: unknown[]): LocalizedString;
10
8
  };
11
9
  /** Format a date value for the current locale */
12
- d: (value: Date | number, style?: string) => string;
10
+ d: (value: Date | number, style?: string) => LocalizedString;
13
11
  /** Format a number value for the current locale */
14
- n: (value: number, style?: string) => string;
12
+ n: (value: number, style?: string) => LocalizedString;
15
13
  /** Format an ICU message string directly (no catalog lookup) */
16
- format: (message: string, values?: Record<string, unknown>) => string;
14
+ format: (message: string, values?: Record<string, unknown>) => LocalizedString;
17
15
  /** Merge additional messages into a locale catalog at runtime */
18
16
  loadMessages: (locale: string, messages: Messages) => void;
19
17
  /** Return all locale codes that have loaded messages */
@@ -28,6 +26,10 @@ export interface I18nContextValue {
28
26
  loadedLocales: string[];
29
27
  /** Preload a locale in the background without switching to it */
30
28
  preloadLocale: (locale: string) => Promise<void>;
29
+ /** Check if a translation key exists for the given or current locale */
30
+ te: (key: string, locale?: string) => boolean;
31
+ /** Get the raw compiled message for a key without interpolation */
32
+ tm: (key: string, locale?: string) => CompiledMessage | undefined;
31
33
  }
32
34
  export interface I18nProviderProps {
33
35
  /** Active locale code */
@@ -48,8 +50,13 @@ export interface I18nProviderProps {
48
50
  numberFormats?: NumberFormatOptions;
49
51
  /** Missing message handler */
50
52
  missing?: (locale: Locale, id: string) => string | undefined;
53
+ /** Runtime diagnostics configuration */
54
+ diagnostics?: DiagnosticsConfig;
51
55
  /** App content */
52
56
  children: ReactNode;
57
+ /** Pre-created FluentiInstance (alternative to inline config) */
58
+ instance?: import('./create-fluenti').FluentiInstance;
53
59
  }
54
- export type { Locale, Messages, AllMessages, MessageDescriptor, CompileTimeMessageDescriptor, CompileTimeT, DateFormatOptions, NumberFormatOptions, FluentInstanceExtended, };
60
+ export type FluentiProviderProps = I18nProviderProps;
61
+ export type { Locale, LocalizedString, Messages, AllMessages, MessageDescriptor, CompileTimeMessageDescriptor, CompileTimeT, DateFormatOptions, NumberFormatOptions, };
55
62
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EACV,MAAM,EACN,QAAQ,EACR,WAAW,EACX,iBAAiB,EACjB,4BAA4B,EAC5B,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,eAAe,CAAA;AAEtB,MAAM,WAAW,gBAAgB;IAC/B,qEAAqE;IACrE,IAAI,EAAE,sBAAsB,CAAA;IAC5B,mEAAmE;IACnE,CAAC,EAAE;QACD,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAA;QAC1E,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,CAAA;KAC7D,CAAA;IACD,iDAAiD;IACjD,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IACnD,mDAAmD;IACnD,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IAC5C,gEAAgE;IAChE,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAA;IACrE,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,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,qDAAqD;IACrD,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,iEAAiE;IACjE,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACjD;AAED,MAAM,WAAW,iBAAiB;IAChC,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,kDAAkD;IAClD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,WAAW,CAAA;IACtB,oCAAoC;IACpC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,GAAG;QAAE,OAAO,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAA;IAC5E,wCAAwC;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IACxC,yBAAyB;IACzB,WAAW,CAAC,EAAE,iBAAiB,CAAA;IAC/B,2BAA2B;IAC3B,aAAa,CAAC,EAAE,mBAAmB,CAAA;IACnC,8BAA8B;IAC9B,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAA;IAC5D,kBAAkB;IAClB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,YAAY,EACV,MAAM,EACN,QAAQ,EACR,WAAW,EACX,iBAAiB,EACjB,4BAA4B,EAC5B,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,GACvB,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1,110 +1,2 @@
1
- let e=require(`@fluenti/vite-plugin`),t=require(`node:path`);var n={generateRuntime(e){let{catalogDir:n,locales:r,sourceLocale:i,defaultBuildLocale:a}=e,o=a||i,s=(0,t.resolve)(process.cwd(),n);return`
2
- import __defaultMsgs from '${s}/${o}.js'
3
-
4
- const __catalog = { ...__defaultMsgs }
5
- let __currentLocale = '${o}'
6
- const __loadedLocales = new Set(['${o}'])
7
- let __loading = false
8
- const __cache = new Map()
9
- const __normalizeMessages = (mod) => mod.default ?? mod
10
-
11
- const __loaders = {
12
- ${r.filter(e=>e!==o).map(e=>` '${e}': () => import('${s}/${e}.js'),`).join(`
13
- `)}
14
- }
15
-
16
- async function __switchLocale(locale) {
17
- if (__loadedLocales.has(locale)) {
18
- Object.assign(__catalog, __cache.get(locale) || __defaultMsgs)
19
- __currentLocale = locale
20
- return
21
- }
22
- __loading = true
23
- try {
24
- const mod = __normalizeMessages(await __loaders[locale]())
25
- __cache.set(locale, mod)
26
- __loadedLocales.add(locale)
27
- Object.assign(__catalog, mod)
28
- __currentLocale = locale
29
- } finally {
30
- __loading = false
31
- }
32
- }
33
-
34
- async function __preloadLocale(locale) {
35
- if (__loadedLocales.has(locale) || !__loaders[locale]) return
36
- try {
37
- const mod = __normalizeMessages(await __loaders[locale]())
38
- __cache.set(locale, mod)
39
- __loadedLocales.add(locale)
40
- } catch (e) { console.warn('[fluenti] preload failed:', locale, e) }
41
- }
42
-
43
- globalThis[Symbol.for('fluenti.runtime.react')] = { __switchLocale, __preloadLocale }
44
-
45
- export { __catalog, __switchLocale, __preloadLocale, __currentLocale, __loading, __loadedLocales }
46
- `},generateRouteRuntime(e){let{catalogDir:n,locales:r,sourceLocale:i,defaultBuildLocale:a}=e,o=a||i,s=(0,t.resolve)(process.cwd(),n);return`
47
- import __defaultMsgs from '${s}/${o}.js'
48
-
49
- const __catalog = { ...__defaultMsgs }
50
- let __currentLocale = '${o}'
51
- const __loadedLocales = new Set(['${o}'])
52
- let __loading = false
53
- const __cache = new Map()
54
- const __loadedRoutes = new Set()
55
- const __normalizeMessages = (mod) => mod.default ?? mod
56
-
57
- const __loaders = {
58
- ${r.filter(e=>e!==o).map(e=>` '${e}': () => import('${s}/${e}.js'),`).join(`
59
- `)}
60
- }
61
-
62
- const __routeLoaders = {}
63
-
64
- function __registerRouteLoader(routeId, locale, loader) {
65
- const key = routeId + ':' + locale
66
- __routeLoaders[key] = loader
67
- }
68
-
69
- async function __loadRoute(routeId, locale) {
70
- const key = routeId + ':' + (locale || __currentLocale)
71
- if (__loadedRoutes.has(key)) return
72
- const loader = __routeLoaders[key]
73
- if (!loader) return
74
- const mod = __normalizeMessages(await loader())
75
- Object.assign(__catalog, mod)
76
- __loadedRoutes.add(key)
77
- }
78
-
79
- async function __switchLocale(locale) {
80
- if (locale === __currentLocale) return
81
- __loading = true
82
- try {
83
- if (__cache.has(locale)) {
84
- Object.assign(__catalog, __cache.get(locale))
85
- } else {
86
- const mod = __normalizeMessages(await __loaders[locale]())
87
- __cache.set(locale, mod)
88
- Object.assign(__catalog, mod)
89
- }
90
- __loadedLocales.add(locale)
91
- __currentLocale = locale
92
- } finally {
93
- __loading = false
94
- }
95
- }
96
-
97
- async function __preloadLocale(locale) {
98
- if (__cache.has(locale) || !__loaders[locale]) return
99
- try {
100
- const mod = __normalizeMessages(await __loaders[locale]())
101
- __cache.set(locale, mod)
102
- __loadedLocales.add(locale)
103
- } catch (e) { console.warn('[fluenti] preload failed:', locale, e) }
104
- }
105
-
106
- globalThis[Symbol.for('fluenti.runtime.react')] = { __switchLocale, __preloadLocale }
107
-
108
- export { __catalog, __switchLocale, __preloadLocale, __loadRoute, __registerRouteLoader, __currentLocale, __loading, __loadedLocales }
109
- `}};function r(t){return(0,e.createFluentiPlugins)({...t,framework:`react`},[],n)}module.exports=r;
1
+ let e=require(`@fluenti/vite-plugin`);var t=(0,e.createRuntimeGenerator)({imports:``,catalogInit:`const __catalog = { ...__defaultMsgs }`,localeInit:e=>`let __currentLocale = '${e}'`,loadingInit:`let __loading = false`,catalogUpdate:e=>`Object.assign(__catalog, ${e})`,localeUpdate:e=>`__currentLocale = ${e}`,loadingUpdate:e=>`__loading = ${e}`,localeRead:`__currentLocale`,runtimeKey:`fluenti.runtime.react.v1`});function n(n){return(0,e.createFluentiPlugins)({...n?.config===void 0?{}:{config:n.config},framework:`react`},[],t)}module.exports=n;
110
2
  //# sourceMappingURL=vite-plugin.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin.cjs","names":[],"sources":["../src/react-runtime.ts","../src/vite-plugin.ts"],"sourcesContent":["import { resolve } from 'node:path'\nimport type { RuntimeGenerator, RuntimeGeneratorOptions } from '@fluenti/vite-plugin'\n\nexport const reactRuntimeGenerator: RuntimeGenerator = {\n generateRuntime(options: RuntimeGeneratorOptions): string {\n const { catalogDir, locales, sourceLocale, defaultBuildLocale } = options\n const defaultLocale = defaultBuildLocale || sourceLocale\n const absoluteCatalogDir = resolve(process.cwd(), catalogDir)\n const runtimeKey = 'fluenti.runtime.react'\n const lazyLocales = locales.filter((locale) => locale !== defaultLocale)\n\n return `\nimport __defaultMsgs from '${absoluteCatalogDir}/${defaultLocale}.js'\n\nconst __catalog = { ...__defaultMsgs }\nlet __currentLocale = '${defaultLocale}'\nconst __loadedLocales = new Set(['${defaultLocale}'])\nlet __loading = false\nconst __cache = new Map()\nconst __normalizeMessages = (mod) => mod.default ?? mod\n\nconst __loaders = {\n${lazyLocales.map((l) => ` '${l}': () => import('${absoluteCatalogDir}/${l}.js'),`).join('\\n')}\n}\n\nasync function __switchLocale(locale) {\n if (__loadedLocales.has(locale)) {\n Object.assign(__catalog, __cache.get(locale) || __defaultMsgs)\n __currentLocale = locale\n return\n }\n __loading = true\n try {\n const mod = __normalizeMessages(await __loaders[locale]())\n __cache.set(locale, mod)\n __loadedLocales.add(locale)\n Object.assign(__catalog, mod)\n __currentLocale = locale\n } finally {\n __loading = false\n }\n}\n\nasync function __preloadLocale(locale) {\n if (__loadedLocales.has(locale) || !__loaders[locale]) return\n try {\n const mod = __normalizeMessages(await __loaders[locale]())\n __cache.set(locale, mod)\n __loadedLocales.add(locale)\n } catch (e) { console.warn('[fluenti] preload failed:', locale, e) }\n}\n\nglobalThis[Symbol.for('${runtimeKey}')] = { __switchLocale, __preloadLocale }\n\nexport { __catalog, __switchLocale, __preloadLocale, __currentLocale, __loading, __loadedLocales }\n`\n },\n\n generateRouteRuntime(options: RuntimeGeneratorOptions): string {\n const { catalogDir, locales, sourceLocale, defaultBuildLocale } = options\n const defaultLocale = defaultBuildLocale || sourceLocale\n const absoluteCatalogDir = resolve(process.cwd(), catalogDir)\n const runtimeKey = 'fluenti.runtime.react'\n const lazyLocales = locales.filter((locale) => locale !== defaultLocale)\n\n return `\nimport __defaultMsgs from '${absoluteCatalogDir}/${defaultLocale}.js'\n\nconst __catalog = { ...__defaultMsgs }\nlet __currentLocale = '${defaultLocale}'\nconst __loadedLocales = new Set(['${defaultLocale}'])\nlet __loading = false\nconst __cache = new Map()\nconst __loadedRoutes = new Set()\nconst __normalizeMessages = (mod) => mod.default ?? mod\n\nconst __loaders = {\n${lazyLocales.map((l) => ` '${l}': () => import('${absoluteCatalogDir}/${l}.js'),`).join('\\n')}\n}\n\nconst __routeLoaders = {}\n\nfunction __registerRouteLoader(routeId, locale, loader) {\n const key = routeId + ':' + locale\n __routeLoaders[key] = loader\n}\n\nasync function __loadRoute(routeId, locale) {\n const key = routeId + ':' + (locale || __currentLocale)\n if (__loadedRoutes.has(key)) return\n const loader = __routeLoaders[key]\n if (!loader) return\n const mod = __normalizeMessages(await loader())\n Object.assign(__catalog, mod)\n __loadedRoutes.add(key)\n}\n\nasync function __switchLocale(locale) {\n if (locale === __currentLocale) return\n __loading = true\n try {\n if (__cache.has(locale)) {\n Object.assign(__catalog, __cache.get(locale))\n } else {\n const mod = __normalizeMessages(await __loaders[locale]())\n __cache.set(locale, mod)\n Object.assign(__catalog, mod)\n }\n __loadedLocales.add(locale)\n __currentLocale = locale\n } finally {\n __loading = false\n }\n}\n\nasync function __preloadLocale(locale) {\n if (__cache.has(locale) || !__loaders[locale]) return\n try {\n const mod = __normalizeMessages(await __loaders[locale]())\n __cache.set(locale, mod)\n __loadedLocales.add(locale)\n } catch (e) { console.warn('[fluenti] preload failed:', locale, e) }\n}\n\nglobalThis[Symbol.for('${runtimeKey}')] = { __switchLocale, __preloadLocale }\n\nexport { __catalog, __switchLocale, __preloadLocale, __loadRoute, __registerRouteLoader, __currentLocale, __loading, __loadedLocales }\n`\n },\n}\n","import type { Plugin } from 'vite'\nimport type { FluentiPluginOptions } from '@fluenti/vite-plugin'\nimport { createFluentiPlugins } from '@fluenti/vite-plugin'\nimport { reactRuntimeGenerator } from './react-runtime'\n\nexport type { FluentiPluginOptions as FluentiReactOptions } from '@fluenti/vite-plugin'\n\nexport default function fluentiReact(options?: FluentiPluginOptions): Plugin[] {\n return createFluentiPlugins(\n { ...options, framework: 'react' },\n [],\n reactRuntimeGenerator,\n )\n}\n"],"mappings":"6DAGA,IAAa,EAA0C,CACrD,gBAAgB,EAA0C,CACxD,GAAM,CAAE,aAAY,UAAS,eAAc,sBAAuB,EAC5D,EAAgB,GAAsB,EACtC,GAAA,EAAA,EAAA,SAA6B,QAAQ,KAAK,CAAE,EAAW,CAI7D,MAAO;6BACkB,EAAmB,GAAG,EAAc;;;yBAGxC,EAAc;oCACH,EAAc;;;;;;EAP1B,EAAQ,OAAQ,GAAW,IAAW,EAAc,CAa9D,IAAK,GAAM,MAAM,EAAE,mBAAmB,EAAmB,GAAG,EAAE,QAAQ,CAAC,KAAK;EAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoC9F,qBAAqB,EAA0C,CAC7D,GAAM,CAAE,aAAY,UAAS,eAAc,sBAAuB,EAC5D,EAAgB,GAAsB,EACtC,GAAA,EAAA,EAAA,SAA6B,QAAQ,KAAK,CAAE,EAAW,CAI7D,MAAO;6BACkB,EAAmB,GAAG,EAAc;;;yBAGxC,EAAc;oCACH,EAAc;;;;;;;EAP1B,EAAQ,OAAQ,GAAW,IAAW,EAAc,CAc9D,IAAK,GAAM,MAAM,EAAE,mBAAmB,EAAmB,GAAG,EAAE,QAAQ,CAAC,KAAK;EAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoD/F,CC1HD,SAAwB,EAAa,EAA0C,CAC7E,OAAA,EAAA,EAAA,sBACE,CAAE,GAAG,EAAS,UAAW,QAAS,CAClC,EAAE,CACF,EACD"}
1
+ {"version":3,"file":"vite-plugin.cjs","names":[],"sources":["../src/react-runtime.ts","../src/vite-plugin.ts"],"sourcesContent":["import { createRuntimeGenerator } from '@fluenti/vite-plugin'\nimport type { RuntimeGenerator } from '@fluenti/vite-plugin'\n\nexport const reactRuntimeGenerator: RuntimeGenerator = createRuntimeGenerator({\n imports: '',\n catalogInit: 'const __catalog = { ...__defaultMsgs }',\n localeInit: (defaultLocale) => `let __currentLocale = '${defaultLocale}'`,\n loadingInit: 'let __loading = false',\n catalogUpdate: (msgs) => `Object.assign(__catalog, ${msgs})`,\n localeUpdate: (locale) => `__currentLocale = ${locale}`,\n loadingUpdate: (value) => `__loading = ${value}`,\n localeRead: '__currentLocale',\n runtimeKey: 'fluenti.runtime.react.v1',\n})\n","import type { Plugin } from 'vite'\nimport type { FluentiPluginOptions } from '@fluenti/vite-plugin'\nimport { createFluentiPlugins } from '@fluenti/vite-plugin'\nimport { reactRuntimeGenerator } from './react-runtime'\n\nexport type { FluentiPluginOptions as FluentiReactOptions } from '@fluenti/vite-plugin'\n\nexport default function fluentiReact(options?: FluentiPluginOptions): Plugin[] {\n return createFluentiPlugins(\n { ...(options?.config !== undefined ? { config: options.config } : {}), framework: 'react' },\n [],\n reactRuntimeGenerator,\n )\n}\n"],"mappings":"sCAGA,IAAa,GAAA,EAAA,EAAA,wBAAiE,CAC5E,QAAS,GACT,YAAa,yCACb,WAAa,GAAkB,0BAA0B,EAAc,GACvE,YAAa,wBACb,cAAgB,GAAS,4BAA4B,EAAK,GAC1D,aAAe,GAAW,qBAAqB,IAC/C,cAAgB,GAAU,eAAe,IACzC,WAAY,kBACZ,WAAY,2BACb,CAAC,CCNF,SAAwB,EAAa,EAA0C,CAC7E,OAAA,EAAA,EAAA,sBACE,CAAE,GAAI,GAAS,SAAW,IAAA,GAAyC,EAAE,CAA/B,CAAE,OAAQ,EAAQ,OAAQ,CAAQ,UAAW,QAAS,CAC5F,EAAE,CACF,EACD"}
@@ -1,127 +1,21 @@
1
- import { createFluentiPlugins as e } from "@fluenti/vite-plugin";
2
- import { resolve as t } from "node:path";
1
+ import { createFluentiPlugins as e, createRuntimeGenerator as t } from "@fluenti/vite-plugin";
3
2
  //#region src/react-runtime.ts
4
- var n = {
5
- generateRuntime(e) {
6
- let { catalogDir: n, locales: r, sourceLocale: i, defaultBuildLocale: a } = e, o = a || i, s = t(process.cwd(), n);
7
- return `
8
- import __defaultMsgs from '${s}/${o}.js'
9
-
10
- const __catalog = { ...__defaultMsgs }
11
- let __currentLocale = '${o}'
12
- const __loadedLocales = new Set(['${o}'])
13
- let __loading = false
14
- const __cache = new Map()
15
- const __normalizeMessages = (mod) => mod.default ?? mod
16
-
17
- const __loaders = {
18
- ${r.filter((e) => e !== o).map((e) => ` '${e}': () => import('${s}/${e}.js'),`).join("\n")}
19
- }
20
-
21
- async function __switchLocale(locale) {
22
- if (__loadedLocales.has(locale)) {
23
- Object.assign(__catalog, __cache.get(locale) || __defaultMsgs)
24
- __currentLocale = locale
25
- return
26
- }
27
- __loading = true
28
- try {
29
- const mod = __normalizeMessages(await __loaders[locale]())
30
- __cache.set(locale, mod)
31
- __loadedLocales.add(locale)
32
- Object.assign(__catalog, mod)
33
- __currentLocale = locale
34
- } finally {
35
- __loading = false
36
- }
37
- }
38
-
39
- async function __preloadLocale(locale) {
40
- if (__loadedLocales.has(locale) || !__loaders[locale]) return
41
- try {
42
- const mod = __normalizeMessages(await __loaders[locale]())
43
- __cache.set(locale, mod)
44
- __loadedLocales.add(locale)
45
- } catch (e) { console.warn('[fluenti] preload failed:', locale, e) }
46
- }
47
-
48
- globalThis[Symbol.for('fluenti.runtime.react')] = { __switchLocale, __preloadLocale }
49
-
50
- export { __catalog, __switchLocale, __preloadLocale, __currentLocale, __loading, __loadedLocales }
51
- `;
52
- },
53
- generateRouteRuntime(e) {
54
- let { catalogDir: n, locales: r, sourceLocale: i, defaultBuildLocale: a } = e, o = a || i, s = t(process.cwd(), n);
55
- return `
56
- import __defaultMsgs from '${s}/${o}.js'
57
-
58
- const __catalog = { ...__defaultMsgs }
59
- let __currentLocale = '${o}'
60
- const __loadedLocales = new Set(['${o}'])
61
- let __loading = false
62
- const __cache = new Map()
63
- const __loadedRoutes = new Set()
64
- const __normalizeMessages = (mod) => mod.default ?? mod
65
-
66
- const __loaders = {
67
- ${r.filter((e) => e !== o).map((e) => ` '${e}': () => import('${s}/${e}.js'),`).join("\n")}
68
- }
69
-
70
- const __routeLoaders = {}
71
-
72
- function __registerRouteLoader(routeId, locale, loader) {
73
- const key = routeId + ':' + locale
74
- __routeLoaders[key] = loader
75
- }
76
-
77
- async function __loadRoute(routeId, locale) {
78
- const key = routeId + ':' + (locale || __currentLocale)
79
- if (__loadedRoutes.has(key)) return
80
- const loader = __routeLoaders[key]
81
- if (!loader) return
82
- const mod = __normalizeMessages(await loader())
83
- Object.assign(__catalog, mod)
84
- __loadedRoutes.add(key)
85
- }
86
-
87
- async function __switchLocale(locale) {
88
- if (locale === __currentLocale) return
89
- __loading = true
90
- try {
91
- if (__cache.has(locale)) {
92
- Object.assign(__catalog, __cache.get(locale))
93
- } else {
94
- const mod = __normalizeMessages(await __loaders[locale]())
95
- __cache.set(locale, mod)
96
- Object.assign(__catalog, mod)
97
- }
98
- __loadedLocales.add(locale)
99
- __currentLocale = locale
100
- } finally {
101
- __loading = false
102
- }
103
- }
104
-
105
- async function __preloadLocale(locale) {
106
- if (__cache.has(locale) || !__loaders[locale]) return
107
- try {
108
- const mod = __normalizeMessages(await __loaders[locale]())
109
- __cache.set(locale, mod)
110
- __loadedLocales.add(locale)
111
- } catch (e) { console.warn('[fluenti] preload failed:', locale, e) }
112
- }
113
-
114
- globalThis[Symbol.for('fluenti.runtime.react')] = { __switchLocale, __preloadLocale }
115
-
116
- export { __catalog, __switchLocale, __preloadLocale, __loadRoute, __registerRouteLoader, __currentLocale, __loading, __loadedLocales }
117
- `;
118
- }
119
- };
3
+ var n = t({
4
+ imports: "",
5
+ catalogInit: "const __catalog = { ...__defaultMsgs }",
6
+ localeInit: (e) => `let __currentLocale = '${e}'`,
7
+ loadingInit: "let __loading = false",
8
+ catalogUpdate: (e) => `Object.assign(__catalog, ${e})`,
9
+ localeUpdate: (e) => `__currentLocale = ${e}`,
10
+ loadingUpdate: (e) => `__loading = ${e}`,
11
+ localeRead: "__currentLocale",
12
+ runtimeKey: "fluenti.runtime.react.v1"
13
+ });
120
14
  //#endregion
121
15
  //#region src/vite-plugin.ts
122
16
  function r(t) {
123
17
  return e({
124
- ...t,
18
+ ...t?.config === void 0 ? {} : { config: t.config },
125
19
  framework: "react"
126
20
  }, [], n);
127
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin.js","names":[],"sources":["../src/react-runtime.ts","../src/vite-plugin.ts"],"sourcesContent":["import { resolve } from 'node:path'\nimport type { RuntimeGenerator, RuntimeGeneratorOptions } from '@fluenti/vite-plugin'\n\nexport const reactRuntimeGenerator: RuntimeGenerator = {\n generateRuntime(options: RuntimeGeneratorOptions): string {\n const { catalogDir, locales, sourceLocale, defaultBuildLocale } = options\n const defaultLocale = defaultBuildLocale || sourceLocale\n const absoluteCatalogDir = resolve(process.cwd(), catalogDir)\n const runtimeKey = 'fluenti.runtime.react'\n const lazyLocales = locales.filter((locale) => locale !== defaultLocale)\n\n return `\nimport __defaultMsgs from '${absoluteCatalogDir}/${defaultLocale}.js'\n\nconst __catalog = { ...__defaultMsgs }\nlet __currentLocale = '${defaultLocale}'\nconst __loadedLocales = new Set(['${defaultLocale}'])\nlet __loading = false\nconst __cache = new Map()\nconst __normalizeMessages = (mod) => mod.default ?? mod\n\nconst __loaders = {\n${lazyLocales.map((l) => ` '${l}': () => import('${absoluteCatalogDir}/${l}.js'),`).join('\\n')}\n}\n\nasync function __switchLocale(locale) {\n if (__loadedLocales.has(locale)) {\n Object.assign(__catalog, __cache.get(locale) || __defaultMsgs)\n __currentLocale = locale\n return\n }\n __loading = true\n try {\n const mod = __normalizeMessages(await __loaders[locale]())\n __cache.set(locale, mod)\n __loadedLocales.add(locale)\n Object.assign(__catalog, mod)\n __currentLocale = locale\n } finally {\n __loading = false\n }\n}\n\nasync function __preloadLocale(locale) {\n if (__loadedLocales.has(locale) || !__loaders[locale]) return\n try {\n const mod = __normalizeMessages(await __loaders[locale]())\n __cache.set(locale, mod)\n __loadedLocales.add(locale)\n } catch (e) { console.warn('[fluenti] preload failed:', locale, e) }\n}\n\nglobalThis[Symbol.for('${runtimeKey}')] = { __switchLocale, __preloadLocale }\n\nexport { __catalog, __switchLocale, __preloadLocale, __currentLocale, __loading, __loadedLocales }\n`\n },\n\n generateRouteRuntime(options: RuntimeGeneratorOptions): string {\n const { catalogDir, locales, sourceLocale, defaultBuildLocale } = options\n const defaultLocale = defaultBuildLocale || sourceLocale\n const absoluteCatalogDir = resolve(process.cwd(), catalogDir)\n const runtimeKey = 'fluenti.runtime.react'\n const lazyLocales = locales.filter((locale) => locale !== defaultLocale)\n\n return `\nimport __defaultMsgs from '${absoluteCatalogDir}/${defaultLocale}.js'\n\nconst __catalog = { ...__defaultMsgs }\nlet __currentLocale = '${defaultLocale}'\nconst __loadedLocales = new Set(['${defaultLocale}'])\nlet __loading = false\nconst __cache = new Map()\nconst __loadedRoutes = new Set()\nconst __normalizeMessages = (mod) => mod.default ?? mod\n\nconst __loaders = {\n${lazyLocales.map((l) => ` '${l}': () => import('${absoluteCatalogDir}/${l}.js'),`).join('\\n')}\n}\n\nconst __routeLoaders = {}\n\nfunction __registerRouteLoader(routeId, locale, loader) {\n const key = routeId + ':' + locale\n __routeLoaders[key] = loader\n}\n\nasync function __loadRoute(routeId, locale) {\n const key = routeId + ':' + (locale || __currentLocale)\n if (__loadedRoutes.has(key)) return\n const loader = __routeLoaders[key]\n if (!loader) return\n const mod = __normalizeMessages(await loader())\n Object.assign(__catalog, mod)\n __loadedRoutes.add(key)\n}\n\nasync function __switchLocale(locale) {\n if (locale === __currentLocale) return\n __loading = true\n try {\n if (__cache.has(locale)) {\n Object.assign(__catalog, __cache.get(locale))\n } else {\n const mod = __normalizeMessages(await __loaders[locale]())\n __cache.set(locale, mod)\n Object.assign(__catalog, mod)\n }\n __loadedLocales.add(locale)\n __currentLocale = locale\n } finally {\n __loading = false\n }\n}\n\nasync function __preloadLocale(locale) {\n if (__cache.has(locale) || !__loaders[locale]) return\n try {\n const mod = __normalizeMessages(await __loaders[locale]())\n __cache.set(locale, mod)\n __loadedLocales.add(locale)\n } catch (e) { console.warn('[fluenti] preload failed:', locale, e) }\n}\n\nglobalThis[Symbol.for('${runtimeKey}')] = { __switchLocale, __preloadLocale }\n\nexport { __catalog, __switchLocale, __preloadLocale, __loadRoute, __registerRouteLoader, __currentLocale, __loading, __loadedLocales }\n`\n },\n}\n","import type { Plugin } from 'vite'\nimport type { FluentiPluginOptions } from '@fluenti/vite-plugin'\nimport { createFluentiPlugins } from '@fluenti/vite-plugin'\nimport { reactRuntimeGenerator } from './react-runtime'\n\nexport type { FluentiPluginOptions as FluentiReactOptions } from '@fluenti/vite-plugin'\n\nexport default function fluentiReact(options?: FluentiPluginOptions): Plugin[] {\n return createFluentiPlugins(\n { ...options, framework: 'react' },\n [],\n reactRuntimeGenerator,\n )\n}\n"],"mappings":";;;AAGA,IAAa,IAA0C;CACrD,gBAAgB,GAA0C;EACxD,IAAM,EAAE,eAAY,YAAS,iBAAc,0BAAuB,GAC5D,IAAgB,KAAsB,GACtC,IAAqB,EAAQ,QAAQ,KAAK,EAAE,EAAW;AAI7D,SAAO;6BACkB,EAAmB,GAAG,EAAc;;;yBAGxC,EAAc;oCACH,EAAc;;;;;;EAP1B,EAAQ,QAAQ,MAAW,MAAW,EAAc,CAa9D,KAAK,MAAM,MAAM,EAAE,mBAAmB,EAAmB,GAAG,EAAE,QAAQ,CAAC,KAAK,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoC9F,qBAAqB,GAA0C;EAC7D,IAAM,EAAE,eAAY,YAAS,iBAAc,0BAAuB,GAC5D,IAAgB,KAAsB,GACtC,IAAqB,EAAQ,QAAQ,KAAK,EAAE,EAAW;AAI7D,SAAO;6BACkB,EAAmB,GAAG,EAAc;;;yBAGxC,EAAc;oCACH,EAAc;;;;;;;EAP1B,EAAQ,QAAQ,MAAW,MAAW,EAAc,CAc9D,KAAK,MAAM,MAAM,EAAE,mBAAmB,EAAmB,GAAG,EAAE,QAAQ,CAAC,KAAK,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoD/F;;;AC1HD,SAAwB,EAAa,GAA0C;AAC7E,QAAO,EACL;EAAE,GAAG;EAAS,WAAW;EAAS,EAClC,EAAE,EACF,EACD"}
1
+ {"version":3,"file":"vite-plugin.js","names":[],"sources":["../src/react-runtime.ts","../src/vite-plugin.ts"],"sourcesContent":["import { createRuntimeGenerator } from '@fluenti/vite-plugin'\nimport type { RuntimeGenerator } from '@fluenti/vite-plugin'\n\nexport const reactRuntimeGenerator: RuntimeGenerator = createRuntimeGenerator({\n imports: '',\n catalogInit: 'const __catalog = { ...__defaultMsgs }',\n localeInit: (defaultLocale) => `let __currentLocale = '${defaultLocale}'`,\n loadingInit: 'let __loading = false',\n catalogUpdate: (msgs) => `Object.assign(__catalog, ${msgs})`,\n localeUpdate: (locale) => `__currentLocale = ${locale}`,\n loadingUpdate: (value) => `__loading = ${value}`,\n localeRead: '__currentLocale',\n runtimeKey: 'fluenti.runtime.react.v1',\n})\n","import type { Plugin } from 'vite'\nimport type { FluentiPluginOptions } from '@fluenti/vite-plugin'\nimport { createFluentiPlugins } from '@fluenti/vite-plugin'\nimport { reactRuntimeGenerator } from './react-runtime'\n\nexport type { FluentiPluginOptions as FluentiReactOptions } from '@fluenti/vite-plugin'\n\nexport default function fluentiReact(options?: FluentiPluginOptions): Plugin[] {\n return createFluentiPlugins(\n { ...(options?.config !== undefined ? { config: options.config } : {}), framework: 'react' },\n [],\n reactRuntimeGenerator,\n )\n}\n"],"mappings":";;AAGA,IAAa,IAA0C,EAAuB;CAC5E,SAAS;CACT,aAAa;CACb,aAAa,MAAkB,0BAA0B,EAAc;CACvE,aAAa;CACb,gBAAgB,MAAS,4BAA4B,EAAK;CAC1D,eAAe,MAAW,qBAAqB;CAC/C,gBAAgB,MAAU,eAAe;CACzC,YAAY;CACZ,YAAY;CACb,CAAC;;;ACNF,SAAwB,EAAa,GAA0C;AAC7E,QAAO,EACL;EAAE,GAAI,GAAS,WAAW,KAAA,IAAyC,EAAE,GAA/B,EAAE,QAAQ,EAAQ,QAAQ;EAAQ,WAAW;EAAS,EAC5F,EAAE,EACF,EACD"}
package/llms-full.txt ADDED
@@ -0,0 +1,185 @@
1
+ # @fluenti/react
2
+
3
+ > React bindings for Fluenti — compile-time `t`, runtime-capable components, and client/server i18n helpers.
4
+
5
+ @fluenti/react is the React runtime layer for Fluenti. It supports:
6
+
7
+ - compile-time authoring with `import { t } from '@fluenti/react'`
8
+ - runtime lookup and imperative access with `useI18n()`
9
+ - async locale loading through `I18nProvider`
10
+ - request-scoped server helpers through `@fluenti/react/server`
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ pnpm add @fluenti/core @fluenti/react
16
+ pnpm add -D @fluenti/cli @fluenti/vite-plugin
17
+ ```
18
+
19
+ ## Main entry: `@fluenti/react`
20
+
21
+ ### Public exports
22
+
23
+ - `I18nProvider`
24
+ - `useI18n`
25
+ - `t`
26
+ - `Trans`
27
+ - `Plural`
28
+ - `Select`
29
+ - `DateTime`
30
+ - `NumberFormat`
31
+ - `msg`
32
+ - `I18nContext`
33
+
34
+ Types:
35
+
36
+ - `FluentiContext`
37
+ - `I18nProviderProps`
38
+ - `FluentiTransProps`
39
+ - `FluentiPluralProps`
40
+ - `FluentiSelectProps`
41
+ - `FluentiDateTimeProps`
42
+ - `NumberFormatProps`
43
+ - `CompileTimeT`
44
+
45
+ ### `I18nProvider`
46
+
47
+ Wraps a client React subtree with one Fluenti runtime instance.
48
+
49
+ Important props:
50
+
51
+ - `locale`
52
+ - `messages`
53
+ - `fallbackLocale`
54
+ - `fallbackChain`
55
+ - `loadMessages`
56
+ - `dateFormats`
57
+ - `numberFormats`
58
+ - `missing`
59
+
60
+ `loadMessages(locale)` is the public lazy-loading hook for async locale chunks.
61
+
62
+ ### `useI18n()`
63
+
64
+ Returns the full client runtime API:
65
+
66
+ - `t(idOrDescriptor, values?)`
67
+ - tagged-template `t\`\``
68
+ - `d(value, style?)`
69
+ - `n(value, style?)`
70
+ - `format(message, values?)`
71
+ - `loadMessages(locale, messages)`
72
+ - `getLocales()`
73
+ - `locale`
74
+ - `setLocale(locale)`
75
+ - `isLoading`
76
+ - `loadedLocales`
77
+ - `preloadLocale(locale)`
78
+ - `te(id)` — check if a translation key exists
79
+ - `tm(id)` — get the raw compiled message without interpolation
80
+
81
+ ## Compile-time `t`
82
+
83
+ Imported `t` is compile-time only:
84
+
85
+ ```tsx
86
+ import { t } from '@fluenti/react'
87
+
88
+ const headline = t`Hello ${name}` // ✅ Preferred
89
+ const label = t({ message: 'Hello {name}', context: 'home.hero' }, { name }) // ✅ Preferred
90
+ ```
91
+
92
+ Use `useI18n().t()` for runtime ID lookup or other imperative code:
93
+
94
+ ```tsx
95
+ const { t } = useI18n()
96
+ return <p>{t('dashboard.greeting')}</p> // ⚠️ Runtime fallback — use only for dynamic keys
97
+ ```
98
+
99
+ If imported `t` runs at runtime without the build plugin, it throws a clear error.
100
+
101
+ ## Runtime-capable components
102
+
103
+ These continue to work without the build plugin:
104
+
105
+ - `Trans`
106
+ - `Plural`
107
+ - `Select`
108
+ - `DateTime`
109
+ - `NumberFormat`
110
+
111
+ Cross-framework contract highlights:
112
+
113
+ - `Plural` supports `id`, `context`, `comment`, and `offset`
114
+ - `zero` maps to exact `=0`
115
+ - `#` uses the adjusted count
116
+ - `Select` supports `options`, which take precedence over direct case props
117
+
118
+ ## Example
119
+
120
+ ```tsx
121
+ import { I18nProvider, t, useI18n, Trans, Plural, Select } from '@fluenti/react'
122
+
123
+ function Home() {
124
+ const name = 'Fluenti'
125
+ const headline = t`Hello ${name}`
126
+ const { setLocale, preloadLocale } = useI18n()
127
+
128
+ return (
129
+ <>
130
+ <h1>{headline}</h1>
131
+ <Trans>Read the <a href="/docs">documentation</a></Trans>
132
+ <Plural value={3} one="# item" other="# items" />
133
+ <Select value="admin" admin="Administrator" other="User" />
134
+ <button onMouseEnter={() => void preloadLocale('ja')} onClick={() => void setLocale('ja')}>
135
+ 日本語
136
+ </button>
137
+ </>
138
+ )
139
+ }
140
+
141
+ export default function App() {
142
+ return (
143
+ <I18nProvider
144
+ locale="en"
145
+ fallbackLocale="en"
146
+ messages={{ en }}
147
+ loadMessages={(locale) => import(`./locales/compiled/${locale}.js`)}
148
+ >
149
+ <Home />
150
+ </I18nProvider>
151
+ )
152
+ }
153
+ ```
154
+
155
+ ## Server entry: `@fluenti/react/server`
156
+
157
+ ### `createServerI18n(config)`
158
+
159
+ Creates request-scoped runtime helpers for server rendering.
160
+
161
+ Config:
162
+
163
+ - `loadMessages(locale)`
164
+ - `fallbackLocale`
165
+ - `resolveLocale`
166
+ - `fallbackChain`
167
+ - `dateFormats`
168
+ - `numberFormats`
169
+ - `missing`
170
+
171
+ Returns:
172
+
173
+ - `setLocale(locale)`
174
+ - `getI18n()`
175
+ - `Trans`
176
+ - `Plural`
177
+ - `Select`
178
+ - `DateTime`
179
+ - `NumberFormat`
180
+
181
+ Use this for server-side runtime access. It is distinct from imported compile-time `t`.
182
+
183
+ ## Build plugin relationship
184
+
185
+ `@fluenti/react` is the runtime layer. `@fluenti/vite-plugin` and `@fluenti/next` provide compile-time transforms for imported `t` and component optimizations.