@fluenti/next 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/dist/dev-runner.d.ts +2 -0
- package/dist/dev-runner.d.ts.map +1 -1
- package/dist/dev-watcher.d.ts +36 -0
- package/dist/dev-watcher.d.ts.map +1 -0
- package/dist/generate-server-module.d.ts.map +1 -1
- package/dist/index.cjs +25 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +175 -140
- package/dist/index.js.map +1 -1
- package/dist/loader.cjs +1 -1
- package/dist/loader.cjs.map +1 -1
- package/dist/loader.js +16 -22
- package/dist/loader.js.map +1 -1
- package/dist/middleware.d.ts +109 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/navigation.d.ts +40 -0
- package/dist/navigation.d.ts.map +1 -0
- package/dist/read-config.d.ts +2 -0
- package/dist/read-config.d.ts.map +1 -1
- package/dist/types.d.ts +14 -27
- package/dist/types.d.ts.map +1 -1
- package/llms-full.txt +122 -0
- package/llms-migration.txt +262 -0
- package/llms.txt +55 -0
- package/package.json +7 -5
- package/dist/scope-transform.d.ts +0 -3
- package/dist/scope-transform.d.ts.map +0 -1
- package/dist/trans-transform.d.ts +0 -3
- package/dist/trans-transform.d.ts.map +0 -1
package/dist/loader.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.cjs","names":[],"sources":["../src/loader.ts"],"sourcesContent":["/**\n * Webpack loader for t`` and t() transforms in Next.js.\n *\n * Runs as enforce: 'pre' to transform source before other loaders.\n * Only statically provable `t` bindings are optimized; runtime `t()` calls\n * continue to work without injected proxy globals.\n */\nimport {
|
|
1
|
+
{"version":3,"file":"loader.cjs","names":[],"sources":["../src/loader.ts"],"sourcesContent":["/**\n * Webpack loader for t`` and t() transforms in Next.js.\n *\n * Runs as enforce: 'pre' to transform source before other loaders.\n * Only statically provable `t` bindings are optimized; runtime `t()` calls\n * continue to work without injected proxy globals.\n */\nimport { createTransformPipeline, hasScopeTransformCandidate } from '@fluenti/core/transform'\n\nconst pipeline = createTransformPipeline({ framework: 'react' })\n\n/**\n * Webpack loader function.\n * `this` is the webpack LoaderContext.\n */\nexport default function fluentLoader(this: LoaderContext, source: string): string {\n // Only process .tsx, .ts, .jsx, .js files\n if (!/\\.[jt]sx?$/.test(this.resourcePath)) {\n return source\n }\n\n // Skip node_modules and .next directory\n if (/node_modules|\\.next/.test(this.resourcePath)) {\n return source\n }\n\n let result = source\n const isClientModule = /^\\s*['\"]use client['\"]/.test(result)\n\n // ── <Trans> compile-time optimization (JSX/TSX only) ──────────────\n if (/\\.[jt]sx$/.test(this.resourcePath) && /<Trans[\\s>]/.test(result)) {\n const transResult = pipeline.transformTrans(result)\n if (transResult.transformed) {\n result = transResult.code\n }\n }\n\n // Quick check: does this file contain any Fluenti patterns?\n if (!hasScopeTransformCandidate(result)) {\n return result\n }\n\n // Try scope-aware transform (AST-based, zero false positives)\n try {\n const scoped = pipeline.transformScope(result, {\n serverModuleImport: '@fluenti/next',\n treatFrameworkDirectImportsAsServer: !isClientModule,\n rerouteServerAuthoringImports: !isClientModule,\n errorOnServerUseI18n: !isClientModule,\n })\n if (scoped.transformed) {\n return scoped.code\n }\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error)\n throw new Error(`[fluenti] Transform failed in ${this.resourcePath}: ${msg}`)\n }\n\n return result\n}\n\ninterface LoaderContext {\n resourcePath: string\n getOptions(): Record<string, unknown>\n}\n"],"mappings":"yCASA,IAAM,GAAA,EAAA,EAAA,yBAAmC,CAAE,UAAW,QAAS,CAAC,CAMhE,SAAwB,EAAkC,EAAwB,CAOhF,GALI,CAAC,aAAa,KAAK,KAAK,aAAa,EAKrC,sBAAsB,KAAK,KAAK,aAAa,CAC/C,OAAO,EAGT,IAAI,EAAS,EACP,EAAiB,yBAAyB,KAAK,EAAO,CAG5D,GAAI,YAAY,KAAK,KAAK,aAAa,EAAI,cAAc,KAAK,EAAO,CAAE,CACrE,IAAM,EAAc,EAAS,eAAe,EAAO,CAC/C,EAAY,cACd,EAAS,EAAY,MAKzB,GAAI,EAAA,EAAA,EAAA,4BAA4B,EAAO,CACrC,OAAO,EAIT,GAAI,CACF,IAAM,EAAS,EAAS,eAAe,EAAQ,CAC7C,mBAAoB,gBACpB,oCAAqC,CAAC,EACtC,8BAA+B,CAAC,EAChC,qBAAsB,CAAC,EACxB,CAAC,CACF,GAAI,EAAO,YACT,OAAO,EAAO,WAET,EAAgB,CACvB,IAAM,EAAM,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAClE,MAAU,MAAM,iCAAiC,KAAK,aAAa,IAAI,IAAM,CAG/E,OAAO"}
|
package/dist/loader.js
CHANGED
|
@@ -1,35 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createTransformPipeline as e, hasScopeTransformCandidate as t } from "@fluenti/core/transform";
|
|
2
2
|
//#region src/loader.ts
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
e
|
|
3
|
+
var n = e({ framework: "react" });
|
|
4
|
+
function r(e) {
|
|
5
|
+
if (!/\.[jt]sx?$/.test(this.resourcePath) || /node_modules|\.next/.test(this.resourcePath)) return e;
|
|
6
|
+
let r = e, i = /^\s*['"]use client['"]/.test(r);
|
|
7
|
+
if (/\.[jt]sx$/.test(this.resourcePath) && /<Trans[\s>]/.test(r)) {
|
|
8
|
+
let e = n.transformTrans(r);
|
|
9
|
+
e.transformed && (r = e.code);
|
|
9
10
|
}
|
|
10
|
-
if (!
|
|
11
|
+
if (!t(r)) return r;
|
|
11
12
|
try {
|
|
12
|
-
let
|
|
13
|
-
framework: "react",
|
|
13
|
+
let e = n.transformScope(r, {
|
|
14
14
|
serverModuleImport: "@fluenti/next",
|
|
15
|
-
treatFrameworkDirectImportsAsServer: !
|
|
16
|
-
rerouteServerAuthoringImports: !
|
|
17
|
-
errorOnServerUseI18n: !
|
|
15
|
+
treatFrameworkDirectImportsAsServer: !i,
|
|
16
|
+
rerouteServerAuthoringImports: !i,
|
|
17
|
+
errorOnServerUseI18n: !i
|
|
18
18
|
});
|
|
19
|
-
if (
|
|
19
|
+
if (e.transformed) return e.code;
|
|
20
20
|
} catch (e) {
|
|
21
21
|
let t = e instanceof Error ? e.message : String(e);
|
|
22
22
|
throw Error(`[fluenti] Transform failed in ${this.resourcePath}: ${t}`);
|
|
23
23
|
}
|
|
24
|
-
return
|
|
25
|
-
}
|
|
26
|
-
function r(e) {
|
|
27
|
-
return /(?<![.\w$])t\(\s*['"]/.test(e) || /[A-Za-z_$][\w$]*\(\s*\{/.test(e) || /[A-Za-z_$][\w$]*`/.test(e) && (e.includes("useI18n") || e.includes("getI18n")) ? !0 : /import\s*\{\s*t(?:\s+as\s+[A-Za-z_$][\w$]*)?[\s,}]/.test(e) && (e.includes("@fluenti/react") || e.includes("@fluenti/next"));
|
|
28
|
-
}
|
|
29
|
-
function i(e, t) {
|
|
30
|
-
return t || !e.includes("@fluenti/react") && !e.includes("@fluenti/next") ? !1 : /\b(useI18n|Trans|Plural|Select|DateTime|NumberFormat|t)\b/.test(e);
|
|
24
|
+
return r;
|
|
31
25
|
}
|
|
32
26
|
//#endregion
|
|
33
|
-
export {
|
|
27
|
+
export { r as default };
|
|
34
28
|
|
|
35
29
|
//# sourceMappingURL=loader.js.map
|
package/dist/loader.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","names":[],"sources":["../src/loader.ts"],"sourcesContent":["/**\n * Webpack loader for t`` and t() transforms in Next.js.\n *\n * Runs as enforce: 'pre' to transform source before other loaders.\n * Only statically provable `t` bindings are optimized; runtime `t()` calls\n * continue to work without injected proxy globals.\n */\nimport {
|
|
1
|
+
{"version":3,"file":"loader.js","names":[],"sources":["../src/loader.ts"],"sourcesContent":["/**\n * Webpack loader for t`` and t() transforms in Next.js.\n *\n * Runs as enforce: 'pre' to transform source before other loaders.\n * Only statically provable `t` bindings are optimized; runtime `t()` calls\n * continue to work without injected proxy globals.\n */\nimport { createTransformPipeline, hasScopeTransformCandidate } from '@fluenti/core/transform'\n\nconst pipeline = createTransformPipeline({ framework: 'react' })\n\n/**\n * Webpack loader function.\n * `this` is the webpack LoaderContext.\n */\nexport default function fluentLoader(this: LoaderContext, source: string): string {\n // Only process .tsx, .ts, .jsx, .js files\n if (!/\\.[jt]sx?$/.test(this.resourcePath)) {\n return source\n }\n\n // Skip node_modules and .next directory\n if (/node_modules|\\.next/.test(this.resourcePath)) {\n return source\n }\n\n let result = source\n const isClientModule = /^\\s*['\"]use client['\"]/.test(result)\n\n // ── <Trans> compile-time optimization (JSX/TSX only) ──────────────\n if (/\\.[jt]sx$/.test(this.resourcePath) && /<Trans[\\s>]/.test(result)) {\n const transResult = pipeline.transformTrans(result)\n if (transResult.transformed) {\n result = transResult.code\n }\n }\n\n // Quick check: does this file contain any Fluenti patterns?\n if (!hasScopeTransformCandidate(result)) {\n return result\n }\n\n // Try scope-aware transform (AST-based, zero false positives)\n try {\n const scoped = pipeline.transformScope(result, {\n serverModuleImport: '@fluenti/next',\n treatFrameworkDirectImportsAsServer: !isClientModule,\n rerouteServerAuthoringImports: !isClientModule,\n errorOnServerUseI18n: !isClientModule,\n })\n if (scoped.transformed) {\n return scoped.code\n }\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error)\n throw new Error(`[fluenti] Transform failed in ${this.resourcePath}: ${msg}`)\n }\n\n return result\n}\n\ninterface LoaderContext {\n resourcePath: string\n getOptions(): Record<string, unknown>\n}\n"],"mappings":";;AASA,IAAM,IAAW,EAAwB,EAAE,WAAW,SAAS,CAAC;AAMhE,SAAwB,EAAkC,GAAwB;AAOhF,KALI,CAAC,aAAa,KAAK,KAAK,aAAa,IAKrC,sBAAsB,KAAK,KAAK,aAAa,CAC/C,QAAO;CAGT,IAAI,IAAS,GACP,IAAiB,yBAAyB,KAAK,EAAO;AAG5D,KAAI,YAAY,KAAK,KAAK,aAAa,IAAI,cAAc,KAAK,EAAO,EAAE;EACrE,IAAM,IAAc,EAAS,eAAe,EAAO;AACnD,EAAI,EAAY,gBACd,IAAS,EAAY;;AAKzB,KAAI,CAAC,EAA2B,EAAO,CACrC,QAAO;AAIT,KAAI;EACF,IAAM,IAAS,EAAS,eAAe,GAAQ;GAC7C,oBAAoB;GACpB,qCAAqC,CAAC;GACtC,+BAA+B,CAAC;GAChC,sBAAsB,CAAC;GACxB,CAAC;AACF,MAAI,EAAO,YACT,QAAO,EAAO;UAET,GAAgB;EACvB,IAAM,IAAM,aAAiB,QAAQ,EAAM,UAAU,OAAO,EAAM;AAClE,QAAU,MAAM,iCAAiC,KAAK,aAAa,IAAI,IAAM;;AAG/E,QAAO"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @fluenti/next/middleware
|
|
3
|
+
*
|
|
4
|
+
* Built-in i18n middleware for Next.js App Router.
|
|
5
|
+
*
|
|
6
|
+
* Uses `x-fluenti-locale` request header to pass locale from middleware to
|
|
7
|
+
* server components — avoids `Set-Cookie` on every request (CDN-friendly).
|
|
8
|
+
*
|
|
9
|
+
* Cookie is only used to remember user preference (set by LocaleSwitcher).
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* // src/middleware.ts
|
|
14
|
+
* import { NextResponse } from 'next/server'
|
|
15
|
+
* import { createI18nMiddleware } from '@fluenti/next/middleware'
|
|
16
|
+
*
|
|
17
|
+
* export default createI18nMiddleware({ NextResponse })
|
|
18
|
+
*
|
|
19
|
+
* export const config = {
|
|
20
|
+
* matcher: ['/((?!_next|api|favicon).*)'],
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @example Composing with Clerk
|
|
25
|
+
* ```ts
|
|
26
|
+
* import { NextResponse } from 'next/server'
|
|
27
|
+
* import { clerkMiddleware } from '@clerk/nextjs/server'
|
|
28
|
+
* import { createI18nMiddleware } from '@fluenti/next/middleware'
|
|
29
|
+
*
|
|
30
|
+
* const i18nMiddleware = createI18nMiddleware({ NextResponse })
|
|
31
|
+
*
|
|
32
|
+
* export default clerkMiddleware(async (auth, req) => {
|
|
33
|
+
* await auth.protect()
|
|
34
|
+
* return i18nMiddleware(req)
|
|
35
|
+
* })
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
/** Header name used to pass resolved locale from middleware to RSC */
|
|
39
|
+
export declare const LOCALE_HEADER = "x-fluenti-locale";
|
|
40
|
+
export interface I18nMiddlewareConfig {
|
|
41
|
+
/** Available locales. If omitted, reads from `fluenti.config.ts`. */
|
|
42
|
+
locales?: string[];
|
|
43
|
+
/** Source/default locale. If omitted, reads from `fluenti.config.ts`. */
|
|
44
|
+
sourceLocale?: string;
|
|
45
|
+
/** Cookie name for reading user preference (default: 'locale') */
|
|
46
|
+
cookieName?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Locale prefix strategy:
|
|
49
|
+
* - `'always'`: all locales get a URL prefix (e.g. `/en/about`, `/fr/about`)
|
|
50
|
+
* - `'as-needed'`: source locale has no prefix, others do (e.g. `/about`, `/fr/about`)
|
|
51
|
+
*
|
|
52
|
+
* Default: `'as-needed'`
|
|
53
|
+
*/
|
|
54
|
+
localePrefix?: 'always' | 'as-needed';
|
|
55
|
+
}
|
|
56
|
+
type NextRequest = {
|
|
57
|
+
nextUrl: {
|
|
58
|
+
pathname: string;
|
|
59
|
+
search: string;
|
|
60
|
+
};
|
|
61
|
+
url: string;
|
|
62
|
+
cookies: {
|
|
63
|
+
get(name: string): {
|
|
64
|
+
value: string;
|
|
65
|
+
} | undefined;
|
|
66
|
+
};
|
|
67
|
+
headers: Headers;
|
|
68
|
+
};
|
|
69
|
+
type NextResponseStatic = {
|
|
70
|
+
redirect(url: URL): NextResponseInstance;
|
|
71
|
+
rewrite(url: URL, init?: Record<string, unknown>): NextResponseInstance;
|
|
72
|
+
next(init?: Record<string, unknown>): NextResponseInstance;
|
|
73
|
+
};
|
|
74
|
+
type NextResponseInstance = {
|
|
75
|
+
headers: {
|
|
76
|
+
set(name: string, value: string): void;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Create an i18n middleware function for Next.js.
|
|
81
|
+
*
|
|
82
|
+
* Requires `NextResponse` to be passed in because the middleware module runs
|
|
83
|
+
* in Next.js Edge Runtime where `require('next/server')` is not available.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* import { NextResponse } from 'next/server'
|
|
88
|
+
* import { createI18nMiddleware } from '@fluenti/next/middleware'
|
|
89
|
+
*
|
|
90
|
+
* export default createI18nMiddleware({ NextResponse })
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @example With explicit locales
|
|
94
|
+
* ```ts
|
|
95
|
+
* import { NextResponse } from 'next/server'
|
|
96
|
+
* import { createI18nMiddleware } from '@fluenti/next/middleware'
|
|
97
|
+
*
|
|
98
|
+
* export default createI18nMiddleware({
|
|
99
|
+
* NextResponse,
|
|
100
|
+
* locales: ['en', 'ja', 'zh-CN'],
|
|
101
|
+
* sourceLocale: 'en',
|
|
102
|
+
* })
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
export declare function createI18nMiddleware(config: I18nMiddlewareConfig & {
|
|
106
|
+
NextResponse: NextResponseStatic;
|
|
107
|
+
}): (request: NextRequest) => NextResponseInstance;
|
|
108
|
+
export {};
|
|
109
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,sEAAsE;AACtE,eAAO,MAAM,aAAa,qBAAqB,CAAA;AAE/C,MAAM,WAAW,oBAAoB;IACnC,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAA;CACtC;AAED,KAAK,WAAW,GAAG;IACjB,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAA;KAAE,CAAA;IAC7D,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,KAAK,kBAAkB,GAAG;IACxB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,oBAAoB,CAAA;IACxC,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,oBAAoB,CAAA;IACvE,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,oBAAoB,CAAA;CAC3D,CAAA;AAED,KAAK,oBAAoB,GAAG;IAC1B,OAAO,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CACpD,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG;IAAE,YAAY,EAAE,kBAAkB,CAAA;CAAE,IAOvE,SAAS,WAAW,0BA6DpD"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface GetLocalePathOptions {
|
|
2
|
+
/** Source/default locale (no prefix in as-needed mode) */
|
|
3
|
+
sourceLocale?: string;
|
|
4
|
+
/**
|
|
5
|
+
* Known locale codes (e.g. ['en', 'fr', 'ja']).
|
|
6
|
+
* When provided, the existing prefix is only stripped when it's an actual locale —
|
|
7
|
+
* preventing false matches on generic 2-letter path segments like /my or /us.
|
|
8
|
+
*/
|
|
9
|
+
locales?: string[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Get the locale-prefixed path for a given pathname and locale.
|
|
13
|
+
*
|
|
14
|
+
* Pure function — works on both server and client.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* getLocalePath('/about', 'fr') // → '/fr/about'
|
|
19
|
+
* getLocalePath('/about', 'en') // → '/about' (source locale, no prefix)
|
|
20
|
+
* getLocalePath('/fr/about', 'en') // → '/about'
|
|
21
|
+
* getLocalePath('/fr/about', 'ja') // → '/ja/about'
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function getLocalePath(pathname: string, locale: string, options?: GetLocalePathOptions): string;
|
|
25
|
+
/**
|
|
26
|
+
* Hook for switching locales in Next.js App Router.
|
|
27
|
+
*
|
|
28
|
+
* Sets a cookie to remember user preference, navigates to the new locale path,
|
|
29
|
+
* and triggers a server component refresh.
|
|
30
|
+
*/
|
|
31
|
+
export declare function useLocaleSwitcher(options?: {
|
|
32
|
+
/** Override the source/default locale instead of inferring from locales[0]. */
|
|
33
|
+
sourceLocale?: string;
|
|
34
|
+
}): {
|
|
35
|
+
switchLocale: (newLocale: string) => void;
|
|
36
|
+
currentLocale: string;
|
|
37
|
+
locales: string[];
|
|
38
|
+
sourceLocale: string;
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=navigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../src/navigation.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,oBAAoB;IACnC,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CACnB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,oBAAoB,GAC7B,MAAM,CAwBR;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE;IAC1C,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;8BASkC,MAAM;;;;EAkBxC"}
|
package/dist/read-config.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { WithFluentConfig, ResolvedFluentConfig } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* Read fluenti.config.ts and merge with withFluenti() overrides.
|
|
4
|
+
*
|
|
5
|
+
* Delegates config file loading to `@fluenti/core`'s shared `loadConfigSync()`.
|
|
4
6
|
*/
|
|
5
7
|
export declare function resolveConfig(projectRoot: string, overrides?: WithFluentConfig): ResolvedFluentConfig;
|
|
6
8
|
//# sourceMappingURL=read-config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read-config.d.ts","sourceRoot":"","sources":["../src/read-config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"read-config.d.ts","sourceRoot":"","sources":["../src/read-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAErE;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,gBAAgB,GAC3B,oBAAoB,CAyBtB"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FluentiBuildConfig } from '@fluenti/core/internal';
|
|
2
2
|
/**
|
|
3
3
|
* Configuration for `withFluenti()`.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* All i18n config (locales, sourceLocale, splitting, etc.) lives in `fluenti.config.ts`.
|
|
6
|
+
* Only Next.js-specific options are set here.
|
|
7
7
|
*/
|
|
8
8
|
export interface WithFluentConfig {
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
-
/** Override `fluenti.config.ts` sourceLocale (used as defaultLocale) */
|
|
12
|
-
defaultLocale?: string;
|
|
13
|
-
/** Override `fluenti.config.ts` compileOutDir */
|
|
14
|
-
compiledDir?: string;
|
|
9
|
+
/** fluenti.config.ts path or inline config */
|
|
10
|
+
config?: string | FluentiBuildConfig;
|
|
15
11
|
/** Custom serverModule path (skip auto-generation) */
|
|
16
12
|
serverModule?: string;
|
|
17
13
|
/** Where to generate the serverModule (default: node_modules/.fluenti) */
|
|
@@ -29,33 +25,24 @@ export interface WithFluentConfig {
|
|
|
29
25
|
resolveLocale?: string;
|
|
30
26
|
/** Cookie name used for locale detection (default: 'locale') */
|
|
31
27
|
cookieName?: string;
|
|
32
|
-
/**
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
devAutoCompile?: boolean;
|
|
40
|
-
/** Debounce delay in ms for dev auto-compile (default: 1000). Increase if you see excessive recompilation. */
|
|
41
|
-
devAutoCompileDelay?: number;
|
|
42
|
-
/** Auto extract+compile before production build (default: true) */
|
|
43
|
-
buildAutoCompile?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Webpack loader enforce mode (default: 'pre').
|
|
30
|
+
*
|
|
31
|
+
* Set to `undefined` to let webpack determine ordering, or `'post'` to run after other loaders.
|
|
32
|
+
* This can be useful when other loaders need to process files before Fluenti's transform.
|
|
33
|
+
*/
|
|
34
|
+
loaderEnforce?: 'pre' | 'post' | undefined;
|
|
44
35
|
}
|
|
45
36
|
/**
|
|
46
37
|
* Resolved config after merging fluenti.config.ts + withFluenti() overrides.
|
|
47
38
|
*/
|
|
48
39
|
export interface ResolvedFluentConfig {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
compiledDir: string;
|
|
40
|
+
/** The fully resolved FluentiBuildConfig */
|
|
41
|
+
fluentiConfig: FluentiBuildConfig;
|
|
52
42
|
serverModule: string | null;
|
|
53
43
|
serverModuleOutDir: string;
|
|
54
44
|
resolveLocale?: string;
|
|
55
45
|
cookieName: string;
|
|
56
|
-
dateFormats?: DateFormatOptions;
|
|
57
|
-
numberFormats?: NumberFormatOptions;
|
|
58
|
-
fallbackChain?: Record<string, Locale[]>;
|
|
59
46
|
}
|
|
60
47
|
/**
|
|
61
48
|
* Props for the I18nProvider server component.
|
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,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAEhE;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAAA;IAIpC,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0EAA0E;IAC1E,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAE3B;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,CAAA;CAC3C;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,4CAA4C;IAC5C,aAAa,EAAE,kBAAkB,CAAA;IACjC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,kBAAkB,EAAE,MAAM,CAAA;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B"}
|
package/llms-full.txt
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# @fluenti/next
|
|
2
|
+
|
|
3
|
+
> Next.js integration for Fluenti — `withFluenti()`, strict compile-time transforms, and generated server runtime helpers.
|
|
4
|
+
|
|
5
|
+
@fluenti/next integrates Fluenti into Next.js projects. Its job is to:
|
|
6
|
+
|
|
7
|
+
- wrap `next.config` with `withFluenti()`
|
|
8
|
+
- install the Fluenti loader
|
|
9
|
+
- generate the internal server runtime module consumed as `@fluenti/next`
|
|
10
|
+
- keep Next authoring aligned with the main React authoring surface
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm add @fluenti/core @fluenti/react @fluenti/next
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Main public entry
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { withFluenti } from '@fluenti/next'
|
|
22
|
+
|
|
23
|
+
export default withFluenti()({
|
|
24
|
+
reactStrictMode: true,
|
|
25
|
+
})
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### `withFluenti(config?)`
|
|
29
|
+
|
|
30
|
+
Supports:
|
|
31
|
+
|
|
32
|
+
- `withFluenti(fluentiConfig?)(nextConfig)`
|
|
33
|
+
- `withFluenti(nextConfig)`
|
|
34
|
+
|
|
35
|
+
Public config fields:
|
|
36
|
+
|
|
37
|
+
- `locales`
|
|
38
|
+
- `defaultLocale`
|
|
39
|
+
- `compiledDir`
|
|
40
|
+
- `serverModule`
|
|
41
|
+
- `serverModuleOutDir`
|
|
42
|
+
- `resolveLocale`
|
|
43
|
+
- `dateFormats`
|
|
44
|
+
- `numberFormats`
|
|
45
|
+
- `fallbackChain`
|
|
46
|
+
|
|
47
|
+
## Authoring model in Next
|
|
48
|
+
|
|
49
|
+
In a `withFluenti()` project, the recommended authoring surface is:
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
// ✅ Preferred: compile-time authoring surface
|
|
53
|
+
import { t, Trans, Plural, Select, DateTime, NumberFormat } from '@fluenti/react'
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
This applies to both client and server authoring.
|
|
57
|
+
|
|
58
|
+
For runtime and integration concerns, use the generated module:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { I18nProvider, getI18n, setLocale } from '@fluenti/next'
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Important boundaries
|
|
65
|
+
|
|
66
|
+
- imported `t` is compile-time only — ✅ this is the preferred API
|
|
67
|
+
- client and server authoring should stay on `@fluenti/react`
|
|
68
|
+
- server runtime access should use `await getI18n()` — ⚠️ runtime fallback for dynamic keys
|
|
69
|
+
- direct-import server `t` requires an async server scope
|
|
70
|
+
|
|
71
|
+
## What `withFluenti()` does
|
|
72
|
+
|
|
73
|
+
1. resolves Fluenti config from `fluenti.config.ts` and explicit overrides
|
|
74
|
+
2. generates a server module under the configured output directory
|
|
75
|
+
3. aliases that generated module as `@fluenti/next`
|
|
76
|
+
4. runs the loader on app code so official authoring APIs are transformed correctly
|
|
77
|
+
|
|
78
|
+
## Generated runtime module
|
|
79
|
+
|
|
80
|
+
`@fluenti/next` is not a hand-authored package entry. It is a generated module created by `withFluenti()`.
|
|
81
|
+
|
|
82
|
+
It provides:
|
|
83
|
+
|
|
84
|
+
- `I18nProvider`
|
|
85
|
+
- `setLocale`
|
|
86
|
+
- `getI18n`
|
|
87
|
+
- compile-time `t` stub
|
|
88
|
+
- server-side `Trans`
|
|
89
|
+
- server-side `Plural`
|
|
90
|
+
- server-side `Select`
|
|
91
|
+
- server-side `DateTime`
|
|
92
|
+
- server-side `NumberFormat`
|
|
93
|
+
|
|
94
|
+
### `I18nProvider`
|
|
95
|
+
|
|
96
|
+
Use in root layouts to initialize server and client runtime state.
|
|
97
|
+
|
|
98
|
+
### `getI18n()`
|
|
99
|
+
|
|
100
|
+
Use in server components, route handlers, metadata functions, and server actions when you need the full runtime API.
|
|
101
|
+
|
|
102
|
+
### `setLocale()`
|
|
103
|
+
|
|
104
|
+
Sets the request locale for the generated server runtime.
|
|
105
|
+
|
|
106
|
+
## Public package subpaths
|
|
107
|
+
|
|
108
|
+
- `@fluenti/next` — config wrapper and types
|
|
109
|
+
- `@fluenti/next/server` — server-side helpers exported by the package itself
|
|
110
|
+
- `@fluenti/next/provider` — provider-related types/helpers
|
|
111
|
+
- `@fluenti/next/client` — client-side type declarations
|
|
112
|
+
|
|
113
|
+
`@fluenti/next` is created per project by `withFluenti()`.
|
|
114
|
+
|
|
115
|
+
## Relationship to `@fluenti/react`
|
|
116
|
+
|
|
117
|
+
`@fluenti/next` builds on `@fluenti/react`.
|
|
118
|
+
|
|
119
|
+
- authoring surface: `@fluenti/react`
|
|
120
|
+
- Next-specific runtime integration: `@fluenti/next` + generated module
|
|
121
|
+
|
|
122
|
+
This keeps the main mental model aligned across React SPA, Vite, and Next.
|