@fluenti/solid 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/context.d.ts +15 -24
- package/dist/context.d.ts.map +1 -1
- package/dist/hooks/__useI18n.d.ts +2 -2
- package/dist/hooks/__useI18n.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +129 -167
- package/dist/index.js.map +1 -1
- package/dist/plural.d.ts +3 -3
- package/dist/plural.d.ts.map +1 -1
- package/dist/provider.d.ts +3 -3
- package/dist/provider.d.ts.map +1 -1
- package/dist/rich-dom.d.ts +0 -6
- package/dist/rich-dom.d.ts.map +1 -1
- package/dist/select.d.ts +3 -3
- package/dist/select.d.ts.map +1 -1
- package/dist/server.cjs +2 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.ts +33 -17
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +54 -0
- package/dist/server.js.map +1 -0
- package/dist/solid-runtime.d.ts.map +1 -1
- package/dist/trans.d.ts +3 -3
- package/dist/trans.d.ts.map +1 -1
- package/dist/types.d.ts +8 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/use-i18n.d.ts +4 -8
- package/dist/use-i18n.d.ts.map +1 -1
- package/dist/vite-plugin.cjs +2 -113
- package/dist/vite-plugin.cjs.map +1 -1
- package/dist/vite-plugin.js +14 -123
- package/dist/vite-plugin.js.map +1 -1
- package/llms-full.txt +186 -0
- package/llms-migration.txt +176 -0
- package/llms.txt +64 -0
- package/package.json +17 -5
- package/src/context.ts +56 -77
- package/src/hooks/__useI18n.ts +2 -2
- package/src/index.ts +6 -6
- package/src/plural.tsx +9 -38
- package/src/provider.tsx +5 -5
- package/src/rich-dom.tsx +25 -47
- package/src/select.tsx +11 -8
- package/src/server.ts +94 -49
- package/src/solid-runtime.ts +15 -134
- package/src/trans.tsx +7 -4
- package/src/types.ts +9 -8
- package/src/use-i18n.ts +5 -16
- package/src/vite-plugin.ts +1 -1
package/dist/types.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Accessor } from 'solid-js';
|
|
2
|
-
import {
|
|
2
|
+
import { FluentiCoreConfig, Locale, LocalizedString, Messages, CompiledMessage, MessageDescriptor, DateFormatOptions, NumberFormatOptions } from '@fluenti/core';
|
|
3
3
|
/** Chunk loader for lazy locale loading */
|
|
4
4
|
export type ChunkLoader = (locale: string) => Promise<Record<string, CompiledMessage> | {
|
|
5
5
|
default: Record<string, CompiledMessage>;
|
|
6
6
|
}>;
|
|
7
7
|
/** Extended config with lazy locale loading support */
|
|
8
|
-
export interface
|
|
8
|
+
export interface FluentiConfig extends FluentiCoreConfig {
|
|
9
9
|
/** Async chunk loader for lazy locale loading */
|
|
10
10
|
chunkLoader?: ChunkLoader;
|
|
11
11
|
/** Enable lazy locale loading through chunkLoader */
|
|
@@ -16,25 +16,25 @@ export interface I18nConfig extends FluentConfig {
|
|
|
16
16
|
numberFormats?: NumberFormatOptions;
|
|
17
17
|
}
|
|
18
18
|
/** Reactive i18n context holding locale signal and translation utilities */
|
|
19
|
-
export interface
|
|
19
|
+
export interface FluentiContext {
|
|
20
20
|
/** Reactive accessor for the current locale */
|
|
21
21
|
locale(): Locale;
|
|
22
22
|
/** Set the active locale (async when lazy locale loading is enabled) */
|
|
23
23
|
setLocale(locale: Locale): Promise<void>;
|
|
24
24
|
/** Translate a message by id with optional interpolation values */
|
|
25
|
-
t(id: string | MessageDescriptor, values?: Record<string, unknown>):
|
|
25
|
+
t(id: string | MessageDescriptor, values?: Record<string, unknown>): LocalizedString;
|
|
26
26
|
/** Tagged template form: t`Hello ${name}` */
|
|
27
|
-
t(strings: TemplateStringsArray, ...exprs: unknown[]):
|
|
27
|
+
t(strings: TemplateStringsArray, ...exprs: unknown[]): LocalizedString;
|
|
28
28
|
/** Merge additional messages into a locale catalog at runtime */
|
|
29
29
|
loadMessages(locale: Locale, messages: Messages): void;
|
|
30
30
|
/** Return all locale codes that have loaded messages */
|
|
31
31
|
getLocales(): Locale[];
|
|
32
32
|
/** Format a date value for the current locale */
|
|
33
|
-
d(value: Date | number, style?: string):
|
|
33
|
+
d(value: Date | number, style?: string): LocalizedString;
|
|
34
34
|
/** Format a number value for the current locale */
|
|
35
|
-
n(value: number, style?: string):
|
|
35
|
+
n(value: number, style?: string): LocalizedString;
|
|
36
36
|
/** Format an ICU message string directly (no catalog lookup) */
|
|
37
|
-
format(message: string, values?: Record<string, unknown>):
|
|
37
|
+
format(message: string, values?: Record<string, unknown>): LocalizedString;
|
|
38
38
|
/** Whether a locale chunk is currently being loaded */
|
|
39
39
|
isLoading: Accessor<boolean>;
|
|
40
40
|
/** Set of locales whose messages have been loaded */
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,KAAK,EACV,iBAAiB,EACjB,MAAM,EACN,eAAe,EACf,QAAQ,EACR,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,eAAe,CAAA;AAEtB,2CAA2C;AAC3C,MAAM,MAAM,WAAW,GAAG,CACxB,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CAAE,CAAC,CAAA;AAE5F,uDAAuD;AACvD,MAAM,WAAW,aAAc,SAAQ,iBAAiB;IACtD,iDAAiD;IACjD,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,+BAA+B;IAC/B,WAAW,CAAC,EAAE,iBAAiB,CAAA;IAC/B,iCAAiC;IACjC,aAAa,CAAC,EAAE,mBAAmB,CAAA;CACpC;AAED,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,MAAM,IAAI,MAAM,CAAA;IAChB,wEAAwE;IACxE,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACxC,mEAAmE;IACnE,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,CAAA;IACpF,6CAA6C;IAC7C,CAAC,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,GAAG,eAAe,CAAA;IACtE,iEAAiE;IACjE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;IACtD,wDAAwD;IACxD,UAAU,IAAI,MAAM,EAAE,CAAA;IACtB,iDAAiD;IACjD,CAAC,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,eAAe,CAAA;IACxD,mDAAmD;IACnD,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,eAAe,CAAA;IACjD,gEAAgE;IAChE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,CAAA;IAC1E,uDAAuD;IACvD,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC5B,qDAAqD;IACrD,aAAa,EAAE,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;IACpC,iEAAiE;IACjE,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACpC"}
|
package/dist/use-i18n.d.ts
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FluentiContext } from './context';
|
|
2
2
|
/**
|
|
3
|
-
* Access the i18n context
|
|
3
|
+
* Access the i18n context from the nearest `<I18nProvider>`.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* 1. Nearest `<I18nProvider>` in the component tree
|
|
7
|
-
* 2. Module-level singleton created by `createI18n()`
|
|
8
|
-
*
|
|
9
|
-
* Throws if neither is available.
|
|
5
|
+
* Throws if no provider is found in the component tree.
|
|
10
6
|
*/
|
|
11
|
-
export declare function useI18n():
|
|
7
|
+
export declare function useI18n(): FluentiContext;
|
|
12
8
|
//# sourceMappingURL=use-i18n.d.ts.map
|
package/dist/use-i18n.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-i18n.d.ts","sourceRoot":"","sources":["../src/use-i18n.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-i18n.d.ts","sourceRoot":"","sources":["../src/use-i18n.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAE/C;;;;GAIG;AACH,wBAAgB,OAAO,IAAI,cAAc,CASxC"}
|
package/dist/vite-plugin.cjs
CHANGED
|
@@ -1,114 +1,3 @@
|
|
|
1
|
-
let e=require(`@fluenti/vite-plugin`)
|
|
2
|
-
import {
|
|
3
|
-
import { createStore, reconcile } from 'solid-js/store'
|
|
4
|
-
import __defaultMsgs from '${s}/${o}.js'
|
|
5
|
-
|
|
6
|
-
const [__catalog, __setCatalog] = createStore({ ...__defaultMsgs })
|
|
7
|
-
const [__currentLocale, __setCurrentLocale] = createSignal('${o}')
|
|
8
|
-
const __loadedLocales = new Set(['${o}'])
|
|
9
|
-
const [__loading, __setLoading] = createSignal(false)
|
|
10
|
-
const __cache = new Map()
|
|
11
|
-
const __normalizeMessages = (mod) => mod.default ?? mod
|
|
12
|
-
|
|
13
|
-
const __loaders = {
|
|
14
|
-
${r.filter(e=>e!==o).map(e=>` '${e}': () => import('${s}/${e}.js'),`).join(`
|
|
15
|
-
`)}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async function __switchLocale(locale) {
|
|
19
|
-
if (__loadedLocales.has(locale)) {
|
|
20
|
-
__setCatalog(reconcile(__cache.get(locale) || __defaultMsgs))
|
|
21
|
-
__setCurrentLocale(locale)
|
|
22
|
-
return
|
|
23
|
-
}
|
|
24
|
-
__setLoading(true)
|
|
25
|
-
try {
|
|
26
|
-
const mod = __normalizeMessages(await __loaders[locale]())
|
|
27
|
-
__cache.set(locale, mod)
|
|
28
|
-
__loadedLocales.add(locale)
|
|
29
|
-
__setCatalog(reconcile(mod))
|
|
30
|
-
__setCurrentLocale(locale)
|
|
31
|
-
} finally {
|
|
32
|
-
__setLoading(false)
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async function __preloadLocale(locale) {
|
|
37
|
-
if (__loadedLocales.has(locale) || !__loaders[locale]) return
|
|
38
|
-
try {
|
|
39
|
-
const mod = __normalizeMessages(await __loaders[locale]())
|
|
40
|
-
__cache.set(locale, mod)
|
|
41
|
-
__loadedLocales.add(locale)
|
|
42
|
-
} catch (e) { console.warn('[fluenti] preload failed:', locale, e) }
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
globalThis[Symbol.for('fluenti.runtime.solid')] = { __switchLocale, __preloadLocale }
|
|
46
|
-
|
|
47
|
-
export { __catalog, __switchLocale, __preloadLocale, __currentLocale, __loading, __loadedLocales }
|
|
48
|
-
`},generateRouteRuntime(e){let{catalogDir:n,locales:r,sourceLocale:i,defaultBuildLocale:a}=e,o=a||i,s=(0,t.resolve)(process.cwd(),n);return`
|
|
49
|
-
import { createSignal } from 'solid-js'
|
|
50
|
-
import { createStore, reconcile } from 'solid-js/store'
|
|
51
|
-
import __defaultMsgs from '${s}/${o}.js'
|
|
52
|
-
|
|
53
|
-
const [__catalog, __setCatalog] = createStore({ ...__defaultMsgs })
|
|
54
|
-
const [__currentLocale, __setCurrentLocale] = createSignal('${o}')
|
|
55
|
-
const __loadedLocales = new Set(['${o}'])
|
|
56
|
-
const [__loading, __setLoading] = createSignal(false)
|
|
57
|
-
const __cache = new Map()
|
|
58
|
-
const __loadedRoutes = new Set()
|
|
59
|
-
const __normalizeMessages = (mod) => mod.default ?? mod
|
|
60
|
-
|
|
61
|
-
const __loaders = {
|
|
62
|
-
${r.filter(e=>e!==o).map(e=>` '${e}': () => import('${s}/${e}.js'),`).join(`
|
|
63
|
-
`)}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const __routeLoaders = {}
|
|
67
|
-
|
|
68
|
-
function __registerRouteLoader(routeId, locale, loader) {
|
|
69
|
-
const key = routeId + ':' + locale
|
|
70
|
-
__routeLoaders[key] = loader
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async function __loadRoute(routeId, locale) {
|
|
74
|
-
const key = routeId + ':' + (locale || __currentLocale())
|
|
75
|
-
if (__loadedRoutes.has(key)) return
|
|
76
|
-
const loader = __routeLoaders[key]
|
|
77
|
-
if (!loader) return
|
|
78
|
-
const mod = __normalizeMessages(await loader())
|
|
79
|
-
__setCatalog(reconcile({ ...__catalog, ...mod }))
|
|
80
|
-
__loadedRoutes.add(key)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async function __switchLocale(locale) {
|
|
84
|
-
if (locale === __currentLocale()) return
|
|
85
|
-
__setLoading(true)
|
|
86
|
-
try {
|
|
87
|
-
if (__cache.has(locale)) {
|
|
88
|
-
__setCatalog(reconcile(__cache.get(locale)))
|
|
89
|
-
} else {
|
|
90
|
-
const mod = __normalizeMessages(await __loaders[locale]())
|
|
91
|
-
__cache.set(locale, mod)
|
|
92
|
-
__setCatalog(reconcile(mod))
|
|
93
|
-
}
|
|
94
|
-
__loadedLocales.add(locale)
|
|
95
|
-
__setCurrentLocale(locale)
|
|
96
|
-
} finally {
|
|
97
|
-
__setLoading(false)
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
async function __preloadLocale(locale) {
|
|
102
|
-
if (__cache.has(locale) || !__loaders[locale]) return
|
|
103
|
-
try {
|
|
104
|
-
const mod = __normalizeMessages(await __loaders[locale]())
|
|
105
|
-
__cache.set(locale, mod)
|
|
106
|
-
__loadedLocales.add(locale)
|
|
107
|
-
} catch (e) { console.warn('[fluenti] preload failed:', locale, e) }
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
globalThis[Symbol.for('fluenti.runtime.solid')] = { __switchLocale, __preloadLocale }
|
|
111
|
-
|
|
112
|
-
export { __catalog, __switchLocale, __preloadLocale, __loadRoute, __registerRouteLoader, __currentLocale, __loading, __loadedLocales }
|
|
113
|
-
`}};function r(t){return(0,e.createFluentiPlugins)({...t,framework:`solid`},[],n)}module.exports=r;
|
|
1
|
+
let e=require(`@fluenti/vite-plugin`);var t=(0,e.createRuntimeGenerator)({imports:`import { createSignal } from 'solid-js'
|
|
2
|
+
import { createStore, reconcile } from 'solid-js/store'`,catalogInit:`const [__catalog, __setCatalog] = createStore({ ...__defaultMsgs })`,localeInit:e=>`const [__currentLocale, __setCurrentLocale] = createSignal('${e}')`,loadingInit:`const [__loading, __setLoading] = createSignal(false)`,catalogUpdate:e=>`__setCatalog(reconcile(${e}))`,catalogMerge:e=>`__setCatalog(reconcile({ ...__catalog, ...${e} }))`,localeUpdate:e=>`__setCurrentLocale(${e})`,loadingUpdate:e=>`__setLoading(${e})`,localeRead:`__currentLocale()`,runtimeKey:`fluenti.runtime.solid.v1`});function n(n){return(0,e.createFluentiPlugins)({...n?.config===void 0?{}:{config:n.config},framework:`solid`},[],t)}module.exports=n;
|
|
114
3
|
//# sourceMappingURL=vite-plugin.cjs.map
|
package/dist/vite-plugin.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-plugin.cjs","names":[],"sources":["../src/solid-runtime.ts","../src/vite-plugin.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"vite-plugin.cjs","names":[],"sources":["../src/solid-runtime.ts","../src/vite-plugin.ts"],"sourcesContent":["import { createRuntimeGenerator } from '@fluenti/vite-plugin'\nimport type { RuntimeGenerator } from '@fluenti/vite-plugin'\n\nexport const solidRuntimeGenerator: RuntimeGenerator = createRuntimeGenerator({\n imports: `import { createSignal } from 'solid-js'\\nimport { createStore, reconcile } from 'solid-js/store'`,\n catalogInit: 'const [__catalog, __setCatalog] = createStore({ ...__defaultMsgs })',\n localeInit: (defaultLocale) => `const [__currentLocale, __setCurrentLocale] = createSignal('${defaultLocale}')`,\n loadingInit: 'const [__loading, __setLoading] = createSignal(false)',\n catalogUpdate: (msgs) => `__setCatalog(reconcile(${msgs}))`,\n catalogMerge: (msgs) => `__setCatalog(reconcile({ ...__catalog, ...${msgs} }))`,\n localeUpdate: (locale) => `__setCurrentLocale(${locale})`,\n loadingUpdate: (value) => `__setLoading(${value})`,\n localeRead: '__currentLocale()',\n runtimeKey: 'fluenti.runtime.solid.v1',\n})\n","import type { Plugin } from 'vite'\nimport type { FluentiPluginOptions } from '@fluenti/vite-plugin'\nimport { createFluentiPlugins } from '@fluenti/vite-plugin'\nimport { solidRuntimeGenerator } from './solid-runtime'\n\nexport type { FluentiPluginOptions as FluentiSolidOptions } from '@fluenti/vite-plugin'\n\nexport default function fluentiSolid(options?: FluentiPluginOptions): Plugin[] {\n return createFluentiPlugins(\n { ...(options?.config !== undefined ? { config: options.config } : {}), framework: 'solid' },\n [],\n solidRuntimeGenerator,\n )\n}\n"],"mappings":"sCAGA,IAAa,GAAA,EAAA,EAAA,wBAAiE,CAC5E,QAAS;yDACT,YAAa,sEACb,WAAa,GAAkB,+DAA+D,EAAc,IAC5G,YAAa,wDACb,cAAgB,GAAS,0BAA0B,EAAK,IACxD,aAAe,GAAS,6CAA6C,EAAK,MAC1E,aAAe,GAAW,sBAAsB,EAAO,GACvD,cAAgB,GAAU,gBAAgB,EAAM,GAChD,WAAY,oBACZ,WAAY,2BACb,CAAC,CCPF,SAAwB,EAAa,EAA0C,CAC7E,OAAA,EAAA,EAAA,sBACE,CAAE,GAAI,GAAS,SAAW,IAAA,GAAyC,EAAE,CAA/B,CAAE,OAAQ,EAAQ,OAAQ,CAAQ,UAAW,QAAS,CAC5F,EAAE,CACF,EACD"}
|
package/dist/vite-plugin.js
CHANGED
|
@@ -1,131 +1,22 @@
|
|
|
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/solid-runtime.ts
|
|
4
|
-
var n = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const __cache = new Map()
|
|
17
|
-
const __normalizeMessages = (mod) => mod.default ?? mod
|
|
18
|
-
|
|
19
|
-
const __loaders = {
|
|
20
|
-
${r.filter((e) => e !== o).map((e) => ` '${e}': () => import('${s}/${e}.js'),`).join("\n")}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async function __switchLocale(locale) {
|
|
24
|
-
if (__loadedLocales.has(locale)) {
|
|
25
|
-
__setCatalog(reconcile(__cache.get(locale) || __defaultMsgs))
|
|
26
|
-
__setCurrentLocale(locale)
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
__setLoading(true)
|
|
30
|
-
try {
|
|
31
|
-
const mod = __normalizeMessages(await __loaders[locale]())
|
|
32
|
-
__cache.set(locale, mod)
|
|
33
|
-
__loadedLocales.add(locale)
|
|
34
|
-
__setCatalog(reconcile(mod))
|
|
35
|
-
__setCurrentLocale(locale)
|
|
36
|
-
} finally {
|
|
37
|
-
__setLoading(false)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async function __preloadLocale(locale) {
|
|
42
|
-
if (__loadedLocales.has(locale) || !__loaders[locale]) return
|
|
43
|
-
try {
|
|
44
|
-
const mod = __normalizeMessages(await __loaders[locale]())
|
|
45
|
-
__cache.set(locale, mod)
|
|
46
|
-
__loadedLocales.add(locale)
|
|
47
|
-
} catch (e) { console.warn('[fluenti] preload failed:', locale, e) }
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
globalThis[Symbol.for('fluenti.runtime.solid')] = { __switchLocale, __preloadLocale }
|
|
51
|
-
|
|
52
|
-
export { __catalog, __switchLocale, __preloadLocale, __currentLocale, __loading, __loadedLocales }
|
|
53
|
-
`;
|
|
54
|
-
},
|
|
55
|
-
generateRouteRuntime(e) {
|
|
56
|
-
let { catalogDir: n, locales: r, sourceLocale: i, defaultBuildLocale: a } = e, o = a || i, s = t(process.cwd(), n);
|
|
57
|
-
return `
|
|
58
|
-
import { createSignal } from 'solid-js'
|
|
59
|
-
import { createStore, reconcile } from 'solid-js/store'
|
|
60
|
-
import __defaultMsgs from '${s}/${o}.js'
|
|
61
|
-
|
|
62
|
-
const [__catalog, __setCatalog] = createStore({ ...__defaultMsgs })
|
|
63
|
-
const [__currentLocale, __setCurrentLocale] = createSignal('${o}')
|
|
64
|
-
const __loadedLocales = new Set(['${o}'])
|
|
65
|
-
const [__loading, __setLoading] = createSignal(false)
|
|
66
|
-
const __cache = new Map()
|
|
67
|
-
const __loadedRoutes = new Set()
|
|
68
|
-
const __normalizeMessages = (mod) => mod.default ?? mod
|
|
69
|
-
|
|
70
|
-
const __loaders = {
|
|
71
|
-
${r.filter((e) => e !== o).map((e) => ` '${e}': () => import('${s}/${e}.js'),`).join("\n")}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const __routeLoaders = {}
|
|
75
|
-
|
|
76
|
-
function __registerRouteLoader(routeId, locale, loader) {
|
|
77
|
-
const key = routeId + ':' + locale
|
|
78
|
-
__routeLoaders[key] = loader
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async function __loadRoute(routeId, locale) {
|
|
82
|
-
const key = routeId + ':' + (locale || __currentLocale())
|
|
83
|
-
if (__loadedRoutes.has(key)) return
|
|
84
|
-
const loader = __routeLoaders[key]
|
|
85
|
-
if (!loader) return
|
|
86
|
-
const mod = __normalizeMessages(await loader())
|
|
87
|
-
__setCatalog(reconcile({ ...__catalog, ...mod }))
|
|
88
|
-
__loadedRoutes.add(key)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async function __switchLocale(locale) {
|
|
92
|
-
if (locale === __currentLocale()) return
|
|
93
|
-
__setLoading(true)
|
|
94
|
-
try {
|
|
95
|
-
if (__cache.has(locale)) {
|
|
96
|
-
__setCatalog(reconcile(__cache.get(locale)))
|
|
97
|
-
} else {
|
|
98
|
-
const mod = __normalizeMessages(await __loaders[locale]())
|
|
99
|
-
__cache.set(locale, mod)
|
|
100
|
-
__setCatalog(reconcile(mod))
|
|
101
|
-
}
|
|
102
|
-
__loadedLocales.add(locale)
|
|
103
|
-
__setCurrentLocale(locale)
|
|
104
|
-
} finally {
|
|
105
|
-
__setLoading(false)
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
async function __preloadLocale(locale) {
|
|
110
|
-
if (__cache.has(locale) || !__loaders[locale]) return
|
|
111
|
-
try {
|
|
112
|
-
const mod = __normalizeMessages(await __loaders[locale]())
|
|
113
|
-
__cache.set(locale, mod)
|
|
114
|
-
__loadedLocales.add(locale)
|
|
115
|
-
} catch (e) { console.warn('[fluenti] preload failed:', locale, e) }
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
globalThis[Symbol.for('fluenti.runtime.solid')] = { __switchLocale, __preloadLocale }
|
|
119
|
-
|
|
120
|
-
export { __catalog, __switchLocale, __preloadLocale, __loadRoute, __registerRouteLoader, __currentLocale, __loading, __loadedLocales }
|
|
121
|
-
`;
|
|
122
|
-
}
|
|
123
|
-
};
|
|
3
|
+
var n = t({
|
|
4
|
+
imports: "import { createSignal } from 'solid-js'\nimport { createStore, reconcile } from 'solid-js/store'",
|
|
5
|
+
catalogInit: "const [__catalog, __setCatalog] = createStore({ ...__defaultMsgs })",
|
|
6
|
+
localeInit: (e) => `const [__currentLocale, __setCurrentLocale] = createSignal('${e}')`,
|
|
7
|
+
loadingInit: "const [__loading, __setLoading] = createSignal(false)",
|
|
8
|
+
catalogUpdate: (e) => `__setCatalog(reconcile(${e}))`,
|
|
9
|
+
catalogMerge: (e) => `__setCatalog(reconcile({ ...__catalog, ...${e} }))`,
|
|
10
|
+
localeUpdate: (e) => `__setCurrentLocale(${e})`,
|
|
11
|
+
loadingUpdate: (e) => `__setLoading(${e})`,
|
|
12
|
+
localeRead: "__currentLocale()",
|
|
13
|
+
runtimeKey: "fluenti.runtime.solid.v1"
|
|
14
|
+
});
|
|
124
15
|
//#endregion
|
|
125
16
|
//#region src/vite-plugin.ts
|
|
126
17
|
function r(t) {
|
|
127
18
|
return e({
|
|
128
|
-
...t,
|
|
19
|
+
...t?.config === void 0 ? {} : { config: t.config },
|
|
129
20
|
framework: "solid"
|
|
130
21
|
}, [], n);
|
|
131
22
|
}
|
package/dist/vite-plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-plugin.js","names":[],"sources":["../src/solid-runtime.ts","../src/vite-plugin.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"vite-plugin.js","names":[],"sources":["../src/solid-runtime.ts","../src/vite-plugin.ts"],"sourcesContent":["import { createRuntimeGenerator } from '@fluenti/vite-plugin'\nimport type { RuntimeGenerator } from '@fluenti/vite-plugin'\n\nexport const solidRuntimeGenerator: RuntimeGenerator = createRuntimeGenerator({\n imports: `import { createSignal } from 'solid-js'\\nimport { createStore, reconcile } from 'solid-js/store'`,\n catalogInit: 'const [__catalog, __setCatalog] = createStore({ ...__defaultMsgs })',\n localeInit: (defaultLocale) => `const [__currentLocale, __setCurrentLocale] = createSignal('${defaultLocale}')`,\n loadingInit: 'const [__loading, __setLoading] = createSignal(false)',\n catalogUpdate: (msgs) => `__setCatalog(reconcile(${msgs}))`,\n catalogMerge: (msgs) => `__setCatalog(reconcile({ ...__catalog, ...${msgs} }))`,\n localeUpdate: (locale) => `__setCurrentLocale(${locale})`,\n loadingUpdate: (value) => `__setLoading(${value})`,\n localeRead: '__currentLocale()',\n runtimeKey: 'fluenti.runtime.solid.v1',\n})\n","import type { Plugin } from 'vite'\nimport type { FluentiPluginOptions } from '@fluenti/vite-plugin'\nimport { createFluentiPlugins } from '@fluenti/vite-plugin'\nimport { solidRuntimeGenerator } from './solid-runtime'\n\nexport type { FluentiPluginOptions as FluentiSolidOptions } from '@fluenti/vite-plugin'\n\nexport default function fluentiSolid(options?: FluentiPluginOptions): Plugin[] {\n return createFluentiPlugins(\n { ...(options?.config !== undefined ? { config: options.config } : {}), framework: 'solid' },\n [],\n solidRuntimeGenerator,\n )\n}\n"],"mappings":";;AAGA,IAAa,IAA0C,EAAuB;CAC5E,SAAS;CACT,aAAa;CACb,aAAa,MAAkB,+DAA+D,EAAc;CAC5G,aAAa;CACb,gBAAgB,MAAS,0BAA0B,EAAK;CACxD,eAAe,MAAS,6CAA6C,EAAK;CAC1E,eAAe,MAAW,sBAAsB,EAAO;CACvD,gBAAgB,MAAU,gBAAgB,EAAM;CAChD,YAAY;CACZ,YAAY;CACb,CAAC;;;ACPF,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,186 @@
|
|
|
1
|
+
# @fluenti/solid
|
|
2
|
+
|
|
3
|
+
> SolidJS bindings for Fluenti — compile-time `t`, runtime-capable components, and signal-based locale switching.
|
|
4
|
+
|
|
5
|
+
@fluenti/solid is the Solid runtime layer for Fluenti. It supports:
|
|
6
|
+
|
|
7
|
+
- compile-time authoring with `import { t } from '@fluenti/solid'`
|
|
8
|
+
- runtime lookup and imperative APIs through `useI18n()`
|
|
9
|
+
- signal-driven locale reactivity
|
|
10
|
+
- runtime-capable components that keep working without the build plugin
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm add @fluenti/core @fluenti/solid @fluenti/vite-plugin
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Public Exports
|
|
19
|
+
|
|
20
|
+
- `createFluentiContext`
|
|
21
|
+
- `I18nProvider`
|
|
22
|
+
- `useI18n`
|
|
23
|
+
- `t`
|
|
24
|
+
- `Trans`
|
|
25
|
+
- `Plural`
|
|
26
|
+
- `Select`
|
|
27
|
+
- `DateTime`
|
|
28
|
+
- `NumberFormat`
|
|
29
|
+
- `msg`
|
|
30
|
+
|
|
31
|
+
Types:
|
|
32
|
+
|
|
33
|
+
- `FluentiContext`
|
|
34
|
+
- `FluentiConfig`
|
|
35
|
+
- `FluentiTransProps`
|
|
36
|
+
- `FluentiPluralProps`
|
|
37
|
+
- `FluentiSelectProps`
|
|
38
|
+
|
|
39
|
+
## Context model
|
|
40
|
+
|
|
41
|
+
### `createFluentiContext(config)`
|
|
42
|
+
|
|
43
|
+
Creates an isolated reactive context backed by Solid signals. This is the factory used internally by `<I18nProvider>` and can also be used directly for advanced setups.
|
|
44
|
+
|
|
45
|
+
### `I18nProvider`
|
|
46
|
+
|
|
47
|
+
Creates and provides the nearest Solid context boundary for its subtree.
|
|
48
|
+
|
|
49
|
+
### `useI18n()`
|
|
50
|
+
|
|
51
|
+
Returns the context from the nearest `<I18nProvider>`. Throws if no provider is found.
|
|
52
|
+
|
|
53
|
+
This is the public runtime API for translations, locale switching, and formatting.
|
|
54
|
+
|
|
55
|
+
## Example
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
import { render } from 'solid-js/web'
|
|
59
|
+
import { I18nProvider, useI18n, t } from '@fluenti/solid'
|
|
60
|
+
|
|
61
|
+
function Greeting() {
|
|
62
|
+
const name = 'Fluenti'
|
|
63
|
+
const headline = t`Hello ${name}`
|
|
64
|
+
const { setLocale, preloadLocale } = useI18n()
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<>
|
|
68
|
+
<h1>{headline}</h1>
|
|
69
|
+
<button onMouseEnter={() => preloadLocale('ja')} onClick={() => void setLocale('ja')}>
|
|
70
|
+
日本語
|
|
71
|
+
</button>
|
|
72
|
+
</>
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
render(() => (
|
|
77
|
+
<I18nProvider locale="en" messages={{ en, ja }}>
|
|
78
|
+
<Greeting />
|
|
79
|
+
</I18nProvider>
|
|
80
|
+
), document.getElementById('root')!)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## `I18nConfig`
|
|
84
|
+
|
|
85
|
+
`I18nConfig` extends the core config with Solid-specific lazy-loading support:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
{
|
|
89
|
+
locale: 'en',
|
|
90
|
+
messages: { en },
|
|
91
|
+
fallbackLocale: 'en',
|
|
92
|
+
fallbackChain: { ja: ['en'] },
|
|
93
|
+
lazyLocaleLoading: true,
|
|
94
|
+
chunkLoader: (locale) => import(`./locales/compiled/${locale}.js`),
|
|
95
|
+
dateFormats: { short: { dateStyle: 'medium' } },
|
|
96
|
+
numberFormats: { currency: { style: 'currency', currency: 'USD' } },
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Fields added on top of the core runtime:
|
|
101
|
+
|
|
102
|
+
- `lazyLocaleLoading?: boolean`
|
|
103
|
+
- `chunkLoader?: (locale) => Promise<Messages | { default: Messages }>`
|
|
104
|
+
- `fallbackChain?`
|
|
105
|
+
- `dateFormats?`
|
|
106
|
+
- `numberFormats?`
|
|
107
|
+
|
|
108
|
+
## `useI18n()` return shape
|
|
109
|
+
|
|
110
|
+
- `locale(): string`
|
|
111
|
+
- `setLocale(locale): Promise<void>`
|
|
112
|
+
- `t(idOrDescriptor, values?)`
|
|
113
|
+
- tagged-template `t\`\``
|
|
114
|
+
- `d(value, style?)`
|
|
115
|
+
- `n(value, style?)`
|
|
116
|
+
- `format(message, values?)`
|
|
117
|
+
- `loadMessages(locale, messages)`
|
|
118
|
+
- `getLocales()`
|
|
119
|
+
- `isLoading()`
|
|
120
|
+
- `loadedLocales()`
|
|
121
|
+
- `te(key, locale?)`
|
|
122
|
+
- `tm(key, locale?)`
|
|
123
|
+
- `preloadLocale(locale)`
|
|
124
|
+
|
|
125
|
+
Any reactive computation that reads `t()` re-runs when `locale()` changes.
|
|
126
|
+
|
|
127
|
+
## Compile-time `t`
|
|
128
|
+
|
|
129
|
+
Imported `t` is compile-time only:
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import { t } from '@fluenti/solid'
|
|
133
|
+
|
|
134
|
+
const title = t`Hello ${name}` // ✅ Preferred
|
|
135
|
+
const label = t({ message: 'Hello {name}', context: 'home.hero' }, { name }) // ✅ Preferred
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Use `useI18n().t()` for runtime lookup by ID or other imperative scenarios.
|
|
139
|
+
|
|
140
|
+
If imported `t` runs at runtime without the build plugin, it throws a clear error.
|
|
141
|
+
|
|
142
|
+
## Runtime-capable components
|
|
143
|
+
|
|
144
|
+
These components continue to work without the build plugin:
|
|
145
|
+
|
|
146
|
+
- `Trans`
|
|
147
|
+
- `Plural`
|
|
148
|
+
- `Select`
|
|
149
|
+
- `DateTime`
|
|
150
|
+
- `NumberFormat`
|
|
151
|
+
|
|
152
|
+
Cross-framework contract highlights:
|
|
153
|
+
|
|
154
|
+
- `Plural` supports `id`, `context`, `comment`, and `offset`
|
|
155
|
+
- `zero` maps to exact `=0`
|
|
156
|
+
- `#` uses the adjusted count
|
|
157
|
+
- `Select` supports `options`, which take precedence over direct case props
|
|
158
|
+
|
|
159
|
+
## Lazy locale loading
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
<I18nProvider
|
|
163
|
+
locale="en"
|
|
164
|
+
messages={{ en }}
|
|
165
|
+
lazyLocaleLoading={true}
|
|
166
|
+
chunkLoader={(locale) => import(`./locales/compiled/${locale}.js`)}
|
|
167
|
+
>
|
|
168
|
+
<App />
|
|
169
|
+
</I18nProvider>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Behavior:
|
|
173
|
+
|
|
174
|
+
- default locale can be loaded eagerly
|
|
175
|
+
- additional locales load on demand
|
|
176
|
+
- `setLocale()` becomes async when a chunk must be fetched
|
|
177
|
+
- `preloadLocale()` fetches a locale without switching
|
|
178
|
+
|
|
179
|
+
## Build plugin relationship
|
|
180
|
+
|
|
181
|
+
`@fluenti/solid` is the runtime layer. `@fluenti/vite-plugin` provides compile-time transforms for:
|
|
182
|
+
|
|
183
|
+
- direct-import `t`
|
|
184
|
+
- JSX component optimizations
|
|
185
|
+
|
|
186
|
+
The component layer remains runtime-correct without the plugin.
|