@fluenti/next 0.1.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Fluenti Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,325 @@
1
+ # @fluenti/next
2
+
3
+ [![npm](https://img.shields.io/npm/v/@fluenti/next?color=4f46e5&label=npm)](https://www.npmjs.com/package/@fluenti/next)
4
+ [![bundle size](https://img.shields.io/bundlephobia/minzip/@fluenti/next?color=22c55e&label=size)](https://bundlephobia.com/package/@fluenti/next)
5
+ [![license](https://img.shields.io/npm/l/@fluenti/next?color=gray)](https://github.com/usefluenti/fluenti/blob/main/LICENSE)
6
+
7
+ **Compile-time i18n for Next.js.** App Router native. RSC + streaming + server actions out of the box.
8
+
9
+ ```tsx
10
+ // Server Component — zero client JS
11
+ import { t } from '@fluenti/react'
12
+
13
+ export default async function Page() {
14
+ return <h1>{t`Welcome, ${user.name}!`}</h1>
15
+ }
16
+ ```
17
+
18
+ ```tsx
19
+ // Client Component — same syntax
20
+ 'use client'
21
+ import { t } from '@fluenti/react'
22
+
23
+ export default function Counter() {
24
+ return <p>{t`You have ${count} items in your cart.`}</p>
25
+ }
26
+ ```
27
+
28
+ No runtime parsing. No bundle bloat. Messages are compiled at build time and tree-shaken per locale.
29
+
30
+ ## Features
31
+
32
+ - **App Router native** — first-class RSC, streaming SSR, and server actions support
33
+ - **Next.js 14 & 15** compatible (`next >= 14.0.0`)
34
+ - **`t\`\`` tagged templates** — write messages inline, extract them with the CLI
35
+ - **Binding-aware transforms** — the webpack loader rewrites tagged templates only for proven Fluenti bindings
36
+ - **`FluentProvider`** — async server component that sets up both server and client i18n in one place
37
+ - **`withLocale()`** — per-component locale isolation in RSC
38
+ - **ICU MessageFormat** — plurals, selects, nested arguments, custom formatters
39
+ - **Code splitting** — messages split per locale, loaded on demand
40
+ - **Cookie-based locale detection** — reads `locale` cookie in server components by default
41
+
42
+ ## Quick Start
43
+
44
+ ### 1. Install
45
+
46
+ ```bash
47
+ pnpm add @fluenti/next @fluenti/core @fluenti/react
48
+ pnpm add -D @fluenti/cli
49
+ ```
50
+
51
+ ### 2. Configure `next.config.ts`
52
+
53
+ ```ts
54
+ import type { NextConfig } from 'next'
55
+ import { withFluenti } from '@fluenti/next'
56
+
57
+ const nextConfig: NextConfig = {
58
+ reactStrictMode: true,
59
+ }
60
+
61
+ export default withFluenti()(nextConfig)
62
+ ```
63
+
64
+ `withFluenti()` adds a webpack loader that rewrites direct-import authoring APIs in supported client/server scopes and generates a server module for RSC i18n. It reads your `fluenti.config.ts` automatically.
65
+
66
+ You can pass overrides directly:
67
+
68
+ ```ts
69
+ export default withFluenti({
70
+ locales: ['en', 'ja', 'zh-CN'],
71
+ defaultLocale: 'en',
72
+ })(nextConfig)
73
+ ```
74
+
75
+ ### 3. Set up `FluentProvider` in your root layout
76
+
77
+ ```tsx
78
+ // app/layout.tsx
79
+ import { cookies } from 'next/headers'
80
+ import { FluentProvider } from '@fluenti/next/__generated'
81
+
82
+ export default async function RootLayout({ children }: { children: React.ReactNode }) {
83
+ const cookieStore = await cookies()
84
+ const locale = cookieStore.get('locale')?.value ?? 'en'
85
+
86
+ return (
87
+ <html lang={locale}>
88
+ <body>
89
+ <FluentProvider locale={locale}>
90
+ {children}
91
+ </FluentProvider>
92
+ </body>
93
+ </html>
94
+ )
95
+ }
96
+ ```
97
+
98
+ `FluentProvider` is an async server component. It initializes the server-side i18n instance (via `React.cache`) and wraps children in a client-side `I18nProvider` for hydration.
99
+
100
+ ### 4. Use `t\`\`` in your pages
101
+
102
+ **Server Component** (default in `app/`):
103
+
104
+ ```tsx
105
+ // app/rsc/page.tsx
106
+ import { t } from '@fluenti/react'
107
+
108
+ export default async function RSCPage() {
109
+ return (
110
+ <div>
111
+ <h1>{t`Server rendered`}</h1>
112
+ <p>{t`This page is a React Server Component.`}</p>
113
+ </div>
114
+ )
115
+ }
116
+ ```
117
+
118
+ **Client Component**:
119
+
120
+ ```tsx
121
+ // app/page.tsx
122
+ 'use client'
123
+ import { t, useI18n } from '@fluenti/react'
124
+
125
+ export default function Home() {
126
+ const { setLocale, preloadLocale } = useI18n()
127
+ const name = 'World'
128
+ return <h1>{t`Hello, ${name}!`}</h1>
129
+ }
130
+ ```
131
+
132
+ `import { t }` is the primary compile-time API. It supports tagged templates and descriptor calls, but not `t('message.id')` lookup. In Next apps using `withFluenti()`, ordinary authoring imports come from `@fluenti/react` on both the client and the server. For runtime lookup or full imperative access, use `await getI18n()` on the server or `useI18n()` on the client.
133
+
134
+ ### 5. Extract and compile messages
135
+
136
+ ```bash
137
+ # Extract messages from source files
138
+ pnpm fluenti extract
139
+
140
+ # Translate your PO files, then compile
141
+ pnpm fluenti compile
142
+ ```
143
+
144
+ ## Next.js-Specific Features
145
+
146
+ ### React Server Components
147
+
148
+ Server components use `t\`\`` with zero client-side JavaScript. The loader detects server context automatically (files in `app/` without `'use client'`).
149
+
150
+ For direct access to the i18n instance in RSC:
151
+
152
+ ```tsx
153
+ import { setLocale, getI18n } from '@fluenti/next/__generated'
154
+
155
+ export default async function Page({ searchParams }) {
156
+ const params = await searchParams
157
+ if (params.lang) setLocale(params.lang)
158
+
159
+ const { t, locale } = await getI18n()
160
+ return <p>{t`Current server locale: ${locale}`}</p>
161
+ }
162
+ ```
163
+
164
+ ### Streaming SSR
165
+
166
+ Works with `Suspense` boundaries — streamed content is translated on the server:
167
+
168
+ ```tsx
169
+ import { Suspense } from 'react'
170
+
171
+ async function SlowContent() {
172
+ const { getI18n } = await import('@fluenti/next/__generated')
173
+ const { t } = await getI18n()
174
+ await fetchData()
175
+ return <p>{t`Streamed content loaded!`}</p>
176
+ }
177
+
178
+ export default async function StreamingPage() {
179
+ return (
180
+ <Suspense fallback={<p>Loading...</p>}>
181
+ <SlowContent />
182
+ </Suspense>
183
+ )
184
+ }
185
+ ```
186
+
187
+ ### Server Actions
188
+
189
+ Direct-import `t` works in `'use server'` functions:
190
+
191
+ ```ts
192
+ 'use server'
193
+
194
+ import { t } from '@fluenti/react'
195
+
196
+ export async function greetAction(): Promise<string> {
197
+ return t`Hello from server action`
198
+ }
199
+ ```
200
+
201
+ ### Metadata i18n
202
+
203
+ Translate Next.js metadata using the server i18n instance:
204
+
205
+ ```tsx
206
+ import { getI18n } from '@fluenti/next/__generated'
207
+
208
+ export async function generateMetadata() {
209
+ const i18n = await getI18n()
210
+ return {
211
+ title: i18n.t('My App — Internationalized'),
212
+ description: i18n.t('A fully localized Next.js application'),
213
+ }
214
+ }
215
+ ```
216
+
217
+ ### Middleware Locale Detection
218
+
219
+ Detect locale from headers, cookies, or URL and set it via cookie:
220
+
221
+ ```ts
222
+ // middleware.ts
223
+ import { NextResponse } from 'next/server'
224
+ import type { NextRequest } from 'next/server'
225
+
226
+ const SUPPORTED_LOCALES = ['en', 'ja', 'zh-CN']
227
+ const DEFAULT_LOCALE = 'en'
228
+
229
+ export function middleware(request: NextRequest) {
230
+ const response = NextResponse.next()
231
+
232
+ // Already has a locale cookie
233
+ if (request.cookies.get('locale')?.value) {
234
+ return response
235
+ }
236
+
237
+ // Detect from Accept-Language header
238
+ const acceptLang = request.headers.get('accept-language') ?? ''
239
+ const detected = acceptLang
240
+ .split(',')
241
+ .map((s) => s.split(';')[0]!.trim())
242
+ .find((lang) => SUPPORTED_LOCALES.includes(lang))
243
+
244
+ response.cookies.set('locale', detected ?? DEFAULT_LOCALE)
245
+ return response
246
+ }
247
+ ```
248
+
249
+ ### Per-Component Locale Isolation
250
+
251
+ Render a subtree in a different locale using `withLocale()`:
252
+
253
+ ```tsx
254
+ import { withLocale } from '@fluenti/next/server'
255
+
256
+ export default async function Page() {
257
+ return (
258
+ <div>
259
+ <h1>{t`Main content`}</h1>
260
+ {await withLocale('ja', async () => (
261
+ <JapaneseWidget />
262
+ ))}
263
+ </div>
264
+ )
265
+ }
266
+ ```
267
+
268
+ ## API Reference
269
+
270
+ ### `withFluenti(config?)`
271
+
272
+ Wraps your Next.js config with Fluenti support. Accepts an optional `WithFluentConfig`:
273
+
274
+ | Option | Type | Description |
275
+ |--------|------|-------------|
276
+ | `locales` | `string[]` | Override locales from `fluenti.config.ts` |
277
+ | `defaultLocale` | `string` | Override source locale |
278
+ | `compiledDir` | `string` | Override compiled messages directory |
279
+ | `serverModule` | `string` | Custom server module path (skip auto-generation) |
280
+ | `resolveLocale` | `() => string \| Promise<string>` | Custom locale resolver for server actions |
281
+ | `dateFormats` | `DateFormatOptions` | Custom date format styles |
282
+ | `numberFormats` | `NumberFormatOptions` | Custom number format styles |
283
+ | `fallbackChain` | `Record<string, Locale[]>` | Fallback chain per locale |
284
+
285
+ ### `FluentProvider`
286
+
287
+ Async server component (imported from `@fluenti/next/__generated`). Place in your root layout.
288
+
289
+ | Prop | Type | Description |
290
+ |------|------|-------------|
291
+ | `locale` | `string?` | Active locale. Defaults to `defaultLocale` from config. |
292
+ | `children` | `ReactNode` | Application tree |
293
+
294
+ ### `withLocale(locale, fn)`
295
+
296
+ Server utility (imported from `@fluenti/next/server`). Executes `fn` with a temporarily switched locale.
297
+
298
+ ### Generated Server Module
299
+
300
+ `@fluenti/next/__generated` exports:
301
+
302
+ | Export | Description |
303
+ |--------|-------------|
304
+ | `FluentProvider` | Async server component for layouts |
305
+ | `setLocale(locale)` | Set the request-scoped locale |
306
+ | `getI18n()` | Get the i18n instance (async) |
307
+ | `t` | Compile-time translation API, preserved for advanced/server-specific imports |
308
+ | `Trans` | Server component for rich text |
309
+ | `Plural` | Server component for plurals |
310
+ | `Select` | Server component for categorical selection |
311
+ | `DateTime` | Server component for date formatting |
312
+ | `NumberFormat` | Server component for number formatting |
313
+
314
+ ## Documentation
315
+
316
+ Full docs at [fluenti.dev](https://fluenti.dev).
317
+
318
+ - [Next.js Quick Start](https://fluenti.dev/start/quick-start-nextjs/)
319
+ - [Next.js Guide](https://fluenti.dev/frameworks/react/nextjs/)
320
+ - [Server Components](https://fluenti.dev/frameworks/react/server-components/)
321
+ - [API Reference](https://fluenti.dev/api/next/)
322
+
323
+ ## License
324
+
325
+ [MIT](https://github.com/usefluenti/fluenti/blob/main/LICENSE)
package/client.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Global tagged template function transformed by @fluenti/next webpack loader.
3
+ * Transforms `t`message`` into compiled i18n calls at build time.
4
+ *
5
+ * @deprecated Prefer `const { t } = useI18n()` which provides the same
6
+ * tagged template support without a magic global. The plugin will optimize
7
+ * tagged templates via AST scope analysis when `t` comes from `useI18n()`.
8
+ */
9
+ declare function t(strings: TemplateStringsArray, ...values: unknown[]): string
@@ -0,0 +1,17 @@
1
+ import { ReactNode } from 'react';
2
+ import { AllMessages, DateFormatOptions, NumberFormatOptions, Locale } from '@fluenti/core';
3
+ export interface ClientI18nProviderProps {
4
+ locale: string;
5
+ fallbackLocale: string;
6
+ messages: AllMessages;
7
+ fallbackChain?: Record<string, Locale[]>;
8
+ dateFormats?: DateFormatOptions;
9
+ numberFormats?: NumberFormatOptions;
10
+ children: ReactNode;
11
+ }
12
+ /**
13
+ * Client-side I18nProvider wrapper.
14
+ * Used internally by FluentProvider to hydrate client components.
15
+ */
16
+ export declare function ClientI18nProvider({ locale, fallbackLocale, messages, fallbackChain, dateFormats, numberFormats, children, }: ClientI18nProviderProps): import("react/jsx-runtime").JSX.Element;
17
+ //# sourceMappingURL=client-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-provider.d.ts","sourceRoot":"","sources":["../src/client-provider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAEhG,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAE,WAAW,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IACxC,WAAW,CAAC,EAAE,iBAAiB,CAAA;IAC/B,aAAa,CAAC,EAAE,mBAAmB,CAAA;IACnC,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,cAAc,EACd,QAAQ,EACR,aAAa,EACb,WAAW,EACX,aAAa,EACb,QAAQ,GACT,EAAE,uBAAuB,2CAazB"}
@@ -0,0 +1,11 @@
1
+ import { ResolvedFluentConfig } from './types';
2
+ /**
3
+ * Generate the server module that provides:
4
+ * - setLocale / getI18n
5
+ * - Trans / Plural / Select / DateTime / NumberFormat (server components)
6
+ * - FluentProvider (async server component for layouts)
7
+ *
8
+ * @returns Absolute path to the generated server module.
9
+ */
10
+ export declare function generateServerModule(projectRoot: string, config: ResolvedFluentConfig): string;
11
+ //# sourceMappingURL=generate-server-module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-server-module.d.ts","sourceRoot":"","sources":["../src/generate-server-module.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAEnD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,oBAAoB,GAC3B,MAAM,CAyLR"}
package/dist/index.cjs ADDED
@@ -0,0 +1,128 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`node:path`),t=require(`node:fs`),n=require(`node:module`);var r=typeof __filename==`string`?__filename:{}.url,{createJiti:i}=(0,n.createRequire)(r)(`jiti`);function a(t,n){let r=o(t),i=n?.defaultLocale??r?.sourceLocale??`en`,a=n?.locales??r?.locales??[i],s=n?.compiledDir??r?.compileOutDir??`./src/locales/compiled`,c=n?.serverModuleOutDir??(0,e.join)(`node_modules`,`.fluenti`),l={locales:a,defaultLocale:i,compiledDir:s,serverModule:n?.serverModule??null,serverModuleOutDir:c};return n?.resolveLocale&&(l.resolveLocale=n.resolveLocale),n?.dateFormats&&(l.dateFormats=n.dateFormats),n?.numberFormats&&(l.numberFormats=n.numberFormats),n?.fallbackChain&&(l.fallbackChain=n.fallbackChain),l}function o(n){let a=i(r,{moduleCache:!1,interopDefault:!0});for(let r of[`fluenti.config.ts`,`fluenti.config.js`,`fluenti.config.mjs`]){let i=(0,e.resolve)(n,r);if((0,t.existsSync)(i))try{return c(a(i))}catch{return s(i,a)||null}}return null}function s(n,r){let i=(0,t.readFileSync)(n,`utf8`),a=i.match(/import\s*\{\s*defineConfig(?:\s+as\s+([A-Za-z_$][\w$]*))?\s*\}\s*from\s*['"]@fluenti\/cli['"]\s*;?/);if(!a)return null;let o=a[1]??`defineConfig`,s=i.replace(a[0],``),l=(0,e.join)((0,e.dirname)(n),`.${(0,e.basename)(n,(0,e.extname)(n))}.next-plugin-read-config${(0,e.extname)(n)||`.ts`}`);(0,t.writeFileSync)(l,`const ${o} = (config) => config\n${s}`,`utf8`);try{return c(r(l))}catch{return null}finally{(0,t.rmSync)(l,{force:!0})}}function c(e){return typeof e==`object`&&e&&`default`in e?e.default??{}:e}function l(n,r){if(r.serverModule)return(0,e.resolve)(n,r.serverModule);let i=(0,e.resolve)(n,r.serverModuleOutDir),a=(0,e.resolve)(i,`server.js`),o=(0,e.resolve)(i,`server.d.ts`);(0,t.existsSync)(i)||(0,t.mkdirSync)(i,{recursive:!0});let s=u((0,e.relative)(i,(0,e.resolve)(n,r.compiledDir))),c=r.locales.map(e=>` case '${e}': return import('${s}/${e}')`).join(`
2
+ `),l=r.fallbackChain?JSON.stringify(r.fallbackChain):`undefined`;(0,t.writeFileSync)((0,e.resolve)(i,`client-provider.js`),`"use client";
3
+ // Auto-generated by @fluenti/next — do not edit
4
+ import { createElement } from 'react'
5
+ import { I18nProvider } from '@fluenti/react'
6
+ ${r.locales.map(e=>`import ${e.replace(/[^a-zA-Z0-9]/g,`_`)} from '${s}/${e}'`).join(`
7
+ `)}
8
+
9
+ const __allMessages = { ${r.locales.map(e=>`'${e}': ${e.replace(/[^a-zA-Z0-9]/g,`_`)}`).join(`, `)} }
10
+
11
+ export function ClientI18nProvider({ locale, fallbackLocale, fallbackChain, children }) {
12
+ return createElement(I18nProvider, { locale, fallbackLocale, messages: __allMessages, fallbackChain }, children)
13
+ }
14
+ `,`utf-8`);let d=r.resolveLocale?`import __resolveLocale from '${r.resolveLocale}'`:null,f=r.resolveLocale?`resolveLocale: __resolveLocale,`:`resolveLocale: async () => {
15
+ try {
16
+ const { cookies } = await import('next/headers')
17
+ return (await cookies()).get('locale')?.value ?? '${r.defaultLocale}'
18
+ } catch {
19
+ return '${r.defaultLocale}'
20
+ }
21
+ },`,p=`// Auto-generated by @fluenti/next — do not edit
22
+ import { createServerI18n } from '@fluenti/react/server'
23
+ import { createElement } from 'react'
24
+ ${d?`${d}\n`:``}
25
+ const serverI18n = createServerI18n({
26
+ loadMessages: async (locale) => {
27
+ switch (locale) {
28
+ ${c}
29
+ default: return import('${s}/${r.defaultLocale}')
30
+ }
31
+ },
32
+ fallbackLocale: '${r.defaultLocale}',
33
+ fallbackChain: ${l},
34
+ ${f}
35
+ })
36
+
37
+ export const setLocale = serverI18n.setLocale
38
+ export const getI18n = serverI18n.getI18n
39
+ export const t = (..._args) => {
40
+ throw new Error(
41
+ "[fluenti] \`t\` imported from '@fluenti/next/__generated' is a compile-time API. " +
42
+ 'Use it only with the Fluenti loader inside an async server scope.',
43
+ )
44
+ }
45
+ export const Trans = serverI18n.Trans
46
+ export const Plural = serverI18n.Plural
47
+ export const Select = serverI18n.Select
48
+ export const DateTime = serverI18n.DateTime
49
+ export const NumberFormat = serverI18n.NumberFormat
50
+
51
+ /**
52
+ * Async server component for root layouts.
53
+ *
54
+ * Sets up both server-side (React.cache) and client-side (I18nProvider) i18n.
55
+ */
56
+ export async function FluentProvider({ locale, children }) {
57
+ const activeLocale = locale ?? '${r.defaultLocale}'
58
+
59
+ // 1. Initialize server-side i18n (React.cache scoped)
60
+ serverI18n.setLocale(activeLocale)
61
+ await serverI18n.getI18n()
62
+
63
+ // 2. Import the local 'use client' provider that has messages statically bundled.
64
+ // Messages contain functions (interpolation) which can't be serialized across the RSC boundary.
65
+ const { ClientI18nProvider } = await import('./client-provider.js')
66
+
67
+ return createElement(ClientI18nProvider, {
68
+ locale: activeLocale,
69
+ fallbackLocale: '${r.defaultLocale}',
70
+ fallbackChain: ${l},
71
+ }, children)
72
+ }
73
+ `;return(0,t.writeFileSync)(a,p,`utf-8`),(0,t.writeFileSync)(o,`// Auto-generated by @fluenti/next — do not edit
74
+ import type { ReactNode, ReactElement } from 'react'
75
+ import type { CompileTimeT, FluentInstanceExtended } from '@fluenti/core'
76
+
77
+ export declare function setLocale(locale: string): void
78
+ export declare function getI18n(): Promise<FluentInstanceExtended & { locale: string }>
79
+ export declare const t: CompileTimeT
80
+
81
+ export declare function Trans(props: {
82
+ children: ReactNode
83
+ id?: string
84
+ context?: string
85
+ comment?: string
86
+ render?: (translation: ReactNode) => ReactNode
87
+ }): Promise<ReactElement>
88
+
89
+ export declare function Plural(props: {
90
+ value: number
91
+ id?: string
92
+ context?: string
93
+ comment?: string
94
+ zero?: ReactNode
95
+ one?: ReactNode
96
+ two?: ReactNode
97
+ few?: ReactNode
98
+ many?: ReactNode
99
+ other: ReactNode
100
+ offset?: number
101
+ }): Promise<ReactElement>
102
+
103
+ export declare function Select(props: {
104
+ value: string
105
+ id?: string
106
+ context?: string
107
+ comment?: string
108
+ other: ReactNode
109
+ options?: Record<string, ReactNode>
110
+ [key: string]: ReactNode | Record<string, ReactNode> | string | undefined
111
+ }): Promise<ReactElement>
112
+
113
+ export declare function DateTime(props: {
114
+ value: Date | number
115
+ style?: string
116
+ }): Promise<ReactElement>
117
+
118
+ export declare function NumberFormat(props: {
119
+ value: number
120
+ style?: string
121
+ }): Promise<ReactElement>
122
+
123
+ export declare function FluentProvider(props: {
124
+ locale?: string
125
+ children: ReactNode
126
+ }): Promise<ReactElement>
127
+ `,`utf-8`),a}function u(e){return e.split(`\\`).join(`/`)}function d(e){if(e&&f(e))return p({},e);let t=e??{};return function(e){return p(t,e??{})}}function f(e){return[`reactStrictMode`,`experimental`,`images`,`env`,`webpack`,`rewrites`,`redirects`,`headers`,`pageExtensions`,`output`,`basePath`,`i18n`,`trailingSlash`,`compiler`,`transpilePackages`].some(t=>t in e)}function p(t,n){let r=process.cwd(),i=l(r,a(r,t)),o=(0,e.resolve)(typeof __dirname<`u`?__dirname:(0,e.dirname)(new URL({}.url).pathname),`loader.js`),s=n.webpack;return{...n,webpack(e,t){return e.module.rules.push({test:/\.[jt]sx?$/,enforce:`pre`,exclude:[/node_modules/,/\.next/],use:[{loader:o,options:{serverModulePath:i}}]}),e.resolve=e.resolve??{},e.resolve.alias=e.resolve.alias??{},e.resolve.alias[`@fluenti/next/__generated`]=i,s?s(e,t):e}}}exports.withFluenti=d;
128
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/read-config.ts","../src/generate-server-module.ts","../src/with-fluenti.ts"],"sourcesContent":["import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { basename, dirname, extname, join, resolve } from 'node:path'\nimport type { FluentiConfig } from '@fluenti/core'\nimport type { WithFluentConfig, ResolvedFluentConfig } from './types'\n\nconst runtimeModulePath = typeof __filename === 'string'\n ? __filename\n : import.meta.url\nconst require = createRequire(runtimeModulePath)\nconst { createJiti } = require('jiti') as {\n createJiti: (\n url: string,\n options?: { moduleCache?: boolean; interopDefault?: boolean },\n ) => (path: string) => unknown\n}\n\n/**\n * Read fluenti.config.ts and merge with withFluenti() overrides.\n */\nexport function resolveConfig(\n projectRoot: string,\n overrides?: WithFluentConfig,\n): ResolvedFluentConfig {\n const fileConfig = readFluentConfigSync(projectRoot)\n\n const defaultLocale = overrides?.defaultLocale\n ?? fileConfig?.sourceLocale\n ?? 'en'\n\n const locales = overrides?.locales\n ?? fileConfig?.locales\n ?? [defaultLocale]\n\n const compiledDir = overrides?.compiledDir\n ?? fileConfig?.compileOutDir\n ?? './src/locales/compiled'\n\n const serverModuleOutDir = overrides?.serverModuleOutDir\n ?? join('node_modules', '.fluenti')\n\n const resolved: ResolvedFluentConfig = {\n locales,\n defaultLocale,\n compiledDir,\n serverModule: overrides?.serverModule ?? null,\n serverModuleOutDir,\n }\n if (overrides?.resolveLocale) resolved.resolveLocale = overrides.resolveLocale\n if (overrides?.dateFormats) resolved.dateFormats = overrides.dateFormats\n if (overrides?.numberFormats) resolved.numberFormats = overrides.numberFormats\n if (overrides?.fallbackChain) resolved.fallbackChain = overrides.fallbackChain\n return resolved\n}\n\n/**\n * Attempt to read fluenti.config.ts synchronously.\n * Returns null if file doesn't exist or can't be parsed.\n */\nfunction readFluentConfigSync(projectRoot: string): FluentiConfig | null {\n const jiti = createJiti(runtimeModulePath, {\n moduleCache: false,\n interopDefault: true,\n })\n const candidates = [\n 'fluenti.config.ts',\n 'fluenti.config.js',\n 'fluenti.config.mjs',\n ]\n\n for (const name of candidates) {\n const configPath = resolve(projectRoot, name)\n if (existsSync(configPath)) {\n try {\n return normalizeLoadedConfig(jiti(configPath) as FluentiConfig | { default?: FluentiConfig })\n } catch {\n const rewritten = tryLoadConfigViaDefineConfigShim(configPath, jiti)\n if (rewritten) {\n return rewritten\n }\n return null\n }\n }\n }\n\n return null\n}\n\nfunction tryLoadConfigViaDefineConfigShim(\n configPath: string,\n jiti: (path: string) => unknown,\n): FluentiConfig | null {\n const source = readFileSync(configPath, 'utf8')\n const importMatch = source.match(\n /import\\s*\\{\\s*defineConfig(?:\\s+as\\s+([A-Za-z_$][\\w$]*))?\\s*\\}\\s*from\\s*['\"]@fluenti\\/cli['\"]\\s*;?/,\n )\n if (!importMatch) {\n return null\n }\n\n const helperName = importMatch[1] ?? 'defineConfig'\n const rewrittenSource = source.replace(importMatch[0], '')\n const tempPath = join(\n dirname(configPath),\n `.${basename(configPath, extname(configPath))}.next-plugin-read-config${extname(configPath) || '.ts'}`,\n )\n\n writeFileSync(tempPath, `const ${helperName} = (config) => config\\n${rewrittenSource}`, 'utf8')\n\n try {\n return normalizeLoadedConfig(jiti(tempPath) as FluentiConfig | { default?: FluentiConfig })\n } catch {\n return null\n } finally {\n rmSync(tempPath, { force: true })\n }\n}\n\nfunction normalizeLoadedConfig(\n mod: FluentiConfig | { default?: FluentiConfig },\n): FluentiConfig {\n return typeof mod === 'object' && mod !== null && 'default' in mod\n ? (mod.default ?? {}) as FluentiConfig\n : mod as FluentiConfig\n}\n","import { writeFileSync, mkdirSync, existsSync } from 'node:fs'\nimport { resolve, relative } from 'node:path'\nimport type { ResolvedFluentConfig } from './types'\n\n/**\n * Generate the server module that provides:\n * - setLocale / getI18n\n * - Trans / Plural / Select / DateTime / NumberFormat (server components)\n * - FluentProvider (async server component for layouts)\n *\n * @returns Absolute path to the generated server module.\n */\nexport function generateServerModule(\n projectRoot: string,\n config: ResolvedFluentConfig,\n): string {\n if (config.serverModule) {\n return resolve(projectRoot, config.serverModule)\n }\n\n const outDir = resolve(projectRoot, config.serverModuleOutDir)\n const outPath = resolve(outDir, 'server.js')\n const dtsPath = resolve(outDir, 'server.d.ts')\n\n if (!existsSync(outDir)) {\n mkdirSync(outDir, { recursive: true })\n }\n\n const compiledDirAbs = resolve(projectRoot, config.compiledDir)\n const compiledRelative = toForwardSlash(relative(outDir, compiledDirAbs))\n\n const localeImports = config.locales\n .map((locale) => ` case '${locale}': return import('${compiledRelative}/${locale}')`)\n .join('\\n')\n\n const fallbackChainStr = config.fallbackChain\n ? JSON.stringify(config.fallbackChain)\n : 'undefined'\n\n // Generate a 'use client' provider that imports messages statically.\n // Messages contain functions (interpolation) which can't cross the RSC boundary.\n const clientProviderPath = resolve(outDir, 'client-provider.js')\n\n const clientStaticImports = config.locales\n .map((locale) => {\n const safe = locale.replace(/[^a-zA-Z0-9]/g, '_')\n return `import ${safe} from '${compiledRelative}/${locale}'`\n })\n .join('\\n')\n\n const clientAllMessagesEntries = config.locales\n .map((locale) => {\n const safe = locale.replace(/[^a-zA-Z0-9]/g, '_')\n return `'${locale}': ${safe}`\n })\n .join(', ')\n\n const clientProviderSource = `\"use client\";\n// Auto-generated by @fluenti/next — do not edit\nimport { createElement } from 'react'\nimport { I18nProvider } from '@fluenti/react'\n${clientStaticImports}\n\nconst __allMessages = { ${clientAllMessagesEntries} }\n\nexport function ClientI18nProvider({ locale, fallbackLocale, fallbackChain, children }) {\n return createElement(I18nProvider, { locale, fallbackLocale, messages: __allMessages, fallbackChain }, children)\n}\n`\n writeFileSync(clientProviderPath, clientProviderSource, 'utf-8')\n\n const resolveLocaleImport = config.resolveLocale\n ? `import __resolveLocale from '${config.resolveLocale}'`\n : null\n\n const resolveLocaleFn = config.resolveLocale\n ? `resolveLocale: __resolveLocale,`\n : `resolveLocale: async () => {\n try {\n const { cookies } = await import('next/headers')\n return (await cookies()).get('locale')?.value ?? '${config.defaultLocale}'\n } catch {\n return '${config.defaultLocale}'\n }\n },`\n\n const moduleSource = `// Auto-generated by @fluenti/next — do not edit\nimport { createServerI18n } from '@fluenti/react/server'\nimport { createElement } from 'react'\n${resolveLocaleImport ? `${resolveLocaleImport}\\n` : ''}\nconst serverI18n = createServerI18n({\n loadMessages: async (locale) => {\n switch (locale) {\n${localeImports}\n default: return import('${compiledRelative}/${config.defaultLocale}')\n }\n },\n fallbackLocale: '${config.defaultLocale}',\n fallbackChain: ${fallbackChainStr},\n ${resolveLocaleFn}\n})\n\nexport const setLocale = serverI18n.setLocale\nexport const getI18n = serverI18n.getI18n\nexport const t = (..._args) => {\n throw new Error(\n \"[fluenti] \\`t\\` imported from '@fluenti/next/__generated' is a compile-time API. \" +\n 'Use it only with the Fluenti loader inside an async server scope.',\n )\n}\nexport const Trans = serverI18n.Trans\nexport const Plural = serverI18n.Plural\nexport const Select = serverI18n.Select\nexport const DateTime = serverI18n.DateTime\nexport const NumberFormat = serverI18n.NumberFormat\n\n/**\n * Async server component for root layouts.\n *\n * Sets up both server-side (React.cache) and client-side (I18nProvider) i18n.\n */\nexport async function FluentProvider({ locale, children }) {\n const activeLocale = locale ?? '${config.defaultLocale}'\n\n // 1. Initialize server-side i18n (React.cache scoped)\n serverI18n.setLocale(activeLocale)\n await serverI18n.getI18n()\n\n // 2. Import the local 'use client' provider that has messages statically bundled.\n // Messages contain functions (interpolation) which can't be serialized across the RSC boundary.\n const { ClientI18nProvider } = await import('./client-provider.js')\n\n return createElement(ClientI18nProvider, {\n locale: activeLocale,\n fallbackLocale: '${config.defaultLocale}',\n fallbackChain: ${fallbackChainStr},\n }, children)\n}\n`\n\n const dtsSource = `// Auto-generated by @fluenti/next — do not edit\nimport type { ReactNode, ReactElement } from 'react'\nimport type { CompileTimeT, FluentInstanceExtended } from '@fluenti/core'\n\nexport declare function setLocale(locale: string): void\nexport declare function getI18n(): Promise<FluentInstanceExtended & { locale: string }>\nexport declare const t: CompileTimeT\n\nexport declare function Trans(props: {\n children: ReactNode\n id?: string\n context?: string\n comment?: string\n render?: (translation: ReactNode) => ReactNode\n}): Promise<ReactElement>\n\nexport declare function Plural(props: {\n value: number\n id?: string\n context?: string\n comment?: string\n zero?: ReactNode\n one?: ReactNode\n two?: ReactNode\n few?: ReactNode\n many?: ReactNode\n other: ReactNode\n offset?: number\n}): Promise<ReactElement>\n\nexport declare function Select(props: {\n value: string\n id?: string\n context?: string\n comment?: string\n other: ReactNode\n options?: Record<string, ReactNode>\n [key: string]: ReactNode | Record<string, ReactNode> | string | undefined\n}): Promise<ReactElement>\n\nexport declare function DateTime(props: {\n value: Date | number\n style?: string\n}): Promise<ReactElement>\n\nexport declare function NumberFormat(props: {\n value: number\n style?: string\n}): Promise<ReactElement>\n\nexport declare function FluentProvider(props: {\n locale?: string\n children: ReactNode\n}): Promise<ReactElement>\n`\n\n writeFileSync(outPath, moduleSource, 'utf-8')\n writeFileSync(dtsPath, dtsSource, 'utf-8')\n\n return outPath\n}\n\nfunction toForwardSlash(p: string): string {\n return p.split('\\\\').join('/')\n}\n","import { resolve, dirname } from 'node:path'\nimport type { WithFluentConfig } from './types'\nimport { resolveConfig } from './read-config'\nimport { generateServerModule } from './generate-server-module'\n\ntype NextConfig = Record<string, unknown>\n\n/**\n * Wrap your Next.js config with Fluenti support.\n *\n * Adds a webpack loader that transforms `t\\`\\`` and `t()` calls,\n * and generates a server module for RSC i18n.\n *\n * @example\n * ```ts\n * // next.config.ts — function style (recommended)\n * import { withFluenti } from '@fluenti/next'\n * export default withFluenti()({ reactStrictMode: true })\n * ```\n *\n * @example\n * ```ts\n * // next.config.ts — direct style\n * import { withFluenti } from '@fluenti/next'\n * export default withFluenti({ reactStrictMode: true })\n * ```\n */\nexport function withFluenti(fluentConfig?: WithFluentConfig): (nextConfig?: NextConfig) => NextConfig\nexport function withFluenti(nextConfig: NextConfig): NextConfig\nexport function withFluenti(\n configOrNext?: WithFluentConfig | NextConfig,\n): NextConfig | ((nextConfig?: NextConfig) => NextConfig) {\n if (configOrNext && isNextConfig(configOrNext as NextConfig)) {\n return applyFluenti({}, configOrNext as NextConfig)\n }\n\n const fluentConfig = (configOrNext ?? {}) as WithFluentConfig\n return function wrappedConfig(nextConfig?: NextConfig): NextConfig {\n return applyFluenti(fluentConfig, nextConfig ?? {})\n }\n}\n\nfunction isNextConfig(obj: NextConfig): boolean {\n const nextKeys = [\n 'reactStrictMode', 'experimental', 'images', 'env', 'webpack',\n 'rewrites', 'redirects', 'headers', 'pageExtensions', 'output',\n 'basePath', 'i18n', 'trailingSlash', 'compiler', 'transpilePackages',\n ]\n return nextKeys.some((key) => key in obj)\n}\n\nfunction applyFluenti(\n fluentConfig: WithFluentConfig,\n nextConfig: NextConfig,\n): NextConfig {\n const projectRoot = process.cwd()\n const resolved = resolveConfig(projectRoot, fluentConfig)\n\n // Generate server module for RSC\n const serverModulePath = generateServerModule(projectRoot, resolved)\n\n // Resolve the loader path — use import.meta.url for ESM compatibility\n const thisDir = typeof __dirname !== 'undefined'\n ? __dirname\n : dirname(new URL(import.meta.url).pathname)\n const loaderPath = resolve(thisDir, 'loader.js')\n\n const existingWebpack = nextConfig['webpack'] as\n | ((config: WebpackConfig, options: WebpackOptions) => WebpackConfig)\n | undefined\n\n return {\n ...nextConfig,\n webpack(config: WebpackConfig, options: WebpackOptions) {\n // Add fluenti loader (enforce: pre — runs before other loaders)\n config.module.rules.push({\n test: /\\.[jt]sx?$/,\n enforce: 'pre' as const,\n exclude: [/node_modules/, /\\.next/],\n use: [\n {\n loader: loaderPath,\n options: {\n serverModulePath,\n },\n },\n ],\n })\n\n // Add resolve alias so loader can import from generated server module\n config.resolve = config.resolve ?? {} as WebpackConfig['resolve']\n config.resolve.alias = config.resolve.alias ?? {}\n config.resolve.alias['@fluenti/next/__generated'] = serverModulePath\n\n // Call user's webpack config if provided\n if (existingWebpack) {\n return existingWebpack(config, options)\n }\n\n return config\n },\n }\n}\n\n// Minimal webpack types for the config function\ninterface WebpackConfig {\n module: {\n rules: Array<{\n test: RegExp\n enforce?: 'pre' | 'post'\n exclude?: Array<RegExp>\n use: Array<{ loader: string; options: Record<string, unknown> }>\n }>\n }\n resolve: {\n alias?: Record<string, string>\n }\n}\n\ninterface WebpackOptions {\n isServer: boolean\n dev: boolean\n}\n"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @fluenti/next — Next.js plugin for Fluenti
3
+ *
4
+ * Provides:
5
+ * - `withFluenti()` — wraps next.config.ts with t`` transform support
6
+ * - FluentProvider — async server component (exported from generated module)
7
+ * - Webpack loader for strict, binding-aware tagged-template optimization
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * // next.config.ts
12
+ * import { withFluenti } from '@fluenti/next'
13
+ * export default withFluenti()({ reactStrictMode: true })
14
+ * ```
15
+ */
16
+ export { withFluenti } from './with-fluenti';
17
+ export type { WithFluentConfig, FluentProviderProps } from './types';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAA"}