@fluenti/next 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/i18n-config.cjs +1 -2
  2. package/dist/i18n-config.js +0 -2
  3. package/dist/index.cjs +1 -2
  4. package/dist/index.js +0 -2
  5. package/dist/loader.cjs +1 -2
  6. package/dist/loader.js +0 -2
  7. package/dist/middleware.cjs +1 -2
  8. package/dist/middleware.js +0 -2
  9. package/dist/navigation.cjs +1 -2
  10. package/dist/navigation.js +0 -2
  11. package/dist/packages/next-plugin/src/client-provider.d.ts +1 -2
  12. package/dist/packages/next-plugin/src/create-navigation.d.ts +0 -1
  13. package/dist/packages/next-plugin/src/dev-runner.d.ts +0 -1
  14. package/dist/packages/next-plugin/src/dev-watcher.d.ts +0 -1
  15. package/dist/packages/next-plugin/src/generate-server-module.d.ts +0 -1
  16. package/dist/packages/next-plugin/src/i18n-config.d.ts +0 -1
  17. package/dist/packages/next-plugin/src/index.d.ts +2 -3
  18. package/dist/packages/next-plugin/src/middleware.d.ts +0 -1
  19. package/dist/packages/next-plugin/src/navigation.d.ts +0 -1
  20. package/dist/packages/next-plugin/src/provider.d.ts +0 -1
  21. package/dist/packages/next-plugin/src/read-config.d.ts +0 -1
  22. package/dist/packages/next-plugin/src/routing.d.ts +0 -1
  23. package/dist/packages/next-plugin/src/server.d.ts +0 -1
  24. package/dist/packages/next-plugin/src/types.d.ts +1 -2
  25. package/dist/packages/next-plugin/src/with-fluenti.d.ts +0 -1
  26. package/dist/packages/next-plugin/src/with-locale.d.ts +0 -1
  27. package/dist/provider.cjs +1 -2
  28. package/dist/provider.js +0 -2
  29. package/dist/routing-CRln5Gw7.js +0 -2
  30. package/dist/routing-D4p8HvMH.cjs +1 -2
  31. package/dist/server.cjs +1 -2
  32. package/dist/server.js +0 -2
  33. package/package.json +3 -3
  34. package/dist/i18n-config.cjs.map +0 -1
  35. package/dist/i18n-config.js.map +0 -1
  36. package/dist/index.cjs.map +0 -1
  37. package/dist/index.js.map +0 -1
  38. package/dist/loader.cjs.map +0 -1
  39. package/dist/loader.js.map +0 -1
  40. package/dist/middleware.cjs.map +0 -1
  41. package/dist/middleware.js.map +0 -1
  42. package/dist/navigation.cjs.map +0 -1
  43. package/dist/navigation.js.map +0 -1
  44. package/dist/packages/next-plugin/src/client-provider.d.ts.map +0 -1
  45. package/dist/packages/next-plugin/src/create-navigation.d.ts.map +0 -1
  46. package/dist/packages/next-plugin/src/dev-runner.d.ts.map +0 -1
  47. package/dist/packages/next-plugin/src/dev-watcher.d.ts.map +0 -1
  48. package/dist/packages/next-plugin/src/generate-server-module.d.ts.map +0 -1
  49. package/dist/packages/next-plugin/src/i18n-config.d.ts.map +0 -1
  50. package/dist/packages/next-plugin/src/index.d.ts.map +0 -1
  51. package/dist/packages/next-plugin/src/middleware.d.ts.map +0 -1
  52. package/dist/packages/next-plugin/src/navigation.d.ts.map +0 -1
  53. package/dist/packages/next-plugin/src/provider.d.ts.map +0 -1
  54. package/dist/packages/next-plugin/src/read-config.d.ts.map +0 -1
  55. package/dist/packages/next-plugin/src/routing.d.ts.map +0 -1
  56. package/dist/packages/next-plugin/src/server.d.ts.map +0 -1
  57. package/dist/packages/next-plugin/src/types.d.ts.map +0 -1
  58. package/dist/packages/next-plugin/src/with-fluenti.d.ts.map +0 -1
  59. package/dist/packages/next-plugin/src/with-locale.d.ts.map +0 -1
  60. package/dist/provider.cjs.map +0 -1
  61. package/dist/provider.js.map +0 -1
  62. package/dist/routing-CRln5Gw7.js.map +0 -1
  63. package/dist/routing-D4p8HvMH.cjs.map +0 -1
  64. package/dist/server.cjs.map +0 -1
  65. package/dist/server.js.map +0 -1
@@ -1,2 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=[`en`],t=`en`,n=`locale`;exports.cookieName=n,exports.locales=e,exports.sourceLocale=t;
2
- //# sourceMappingURL=i18n-config.cjs.map
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=[`en`],t=`en`,n=`locale`;exports.cookieName=n,exports.locales=e,exports.sourceLocale=t;
@@ -2,5 +2,3 @@
2
2
  var e = ["en"], t = "en", n = "locale";
3
3
  //#endregion
4
4
  export { n as cookieName, e as locales, t as sourceLocale };
5
-
6
- //# sourceMappingURL=i18n-config.js.map
package/dist/index.cjs CHANGED
@@ -206,5 +206,4 @@ export declare const cookieName: string
206
206
  pnpm add -D @fluenti/cli
207
207
  See: https://fluenti.dev/start/introduction/`;if(e.throwOnError)throw Error(n);console.warn(n),e.onError?.(Error(n))}function y(e,t=300){let n=null,r=!1,i=!1;async function a(){r=!0;try{await v(e)}finally{r=!1,i&&(i=!1,o())}}function o(){n!==null&&clearTimeout(n),n=setTimeout(()=>{n=null,r?i=!0:a()},t)}return o}var b=null;function x(e,t){if(!t||t.length===0)return[(0,i.resolve)(e,`src`)];let n=new Set;for(let e of t){let t=e.replace(/^\.\//,``).split(`*`)[0].replace(/\/+$/,``);n.add(t||`.`)}return[...n].map(t=>(0,i.resolve)(e,t))}function S(e){b&&b();let{cwd:n,compiledDir:a,delay:o=1e3,include:s,exclude:c,parallelCompile:l}=e,u=(0,i.resolve)(n,a),d=(0,r.createRequire)(typeof __filename<`u`?__filename:{}.url)(`picomatch`),f=c?.length?d(c):()=>!1,p={cwd:n};l&&(p.parallelCompile=!0);let m=y(p,o);m();let h=x(n,s).map(e=>(0,t.watch)(e,{recursive:!0},(t,n)=>{n&&/\.[jt]sx?$/.test(n)&&(n.includes(`node_modules`)||n.includes(`.next`)||(0,i.resolve)(e,n).startsWith(u)||f(n)||m())})),g=()=>{for(let e of h)e.close();b=null};return b=g,g}function C(e){if(e&&!w(e))return T({},e);let t=e??{};return function(e){return T(t,e??{})}}function w(e){return[`config`,`locales`,`serverModule`,`serverModuleOutDir`,`resolveLocale`,`cookieName`,`runtimeInterpolate`,`loaderEnforce`].some(t=>t in e)}function T(e,o){let s=process.cwd(),c=u(s,e),l=c.fluentiConfig,d=l.compileOutDir,p=(0,i.resolve)(s,d);(0,t.existsSync)(p)||(0,t.mkdirSync)(p,{recursive:!0});let m=(0,i.resolve)(s,`app`,`[locale]`),h=(0,i.resolve)(s,`src`,`app`,`[locale]`);((0,t.existsSync)(m)||(0,t.existsSync)(h))&&(`rewriteDefaultLocale`in e||(c._autoRewriteDefaultLocale=!0));let g=f(s,c),_=(0,i.resolve)(typeof __dirname<`u`?__dirname:(0,i.dirname)((0,a.fileURLToPath)({}.url)),`loader.js`),v=o.webpack,y=!1,b=Object.fromEntries([`*.ts`,`*.tsx`,`*.js`,`*.jsx`].map(e=>[e,{condition:{not:`foreign`},loaders:[`@fluenti/next/loader`]}])),x=(0,i.resolve)((0,i.dirname)(g),`i18n-config.js`),C=`./`+(0,i.relative)(s,g).split(`\\`).join(`/`),w=`./`+(0,i.relative)(s,x).split(`\\`).join(`/`),T={"@fluenti/next":C,"@fluenti/next/i18n-config":w},D=process.env.NODE_ENV===`development`||process.argv.some(e=>e===`dev`),O=l.buildAutoCompile??!0;if(!D&&O&&!y){y=!0;try{(0,n.execSync)(`node "${(0,i.resolve)((0,i.dirname)((0,r.createRequire)((0,i.resolve)(s,`noop.js`)).resolve(`@fluenti/cli`)),`cli.js`)}" compile`+(l.parallelCompile?` --parallel`:``),{cwd:s,stdio:`inherit`})}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`[fluenti] Production auto-compile failed. Run "fluenti compile" successfully before continuing the Next.js build.
208
208
  ${t}`)}}let k=l.devAutoCompile??!0;if(D&&k){let e={cwd:s,compiledDir:d,delay:l.devAutoCompileDelay??1e3};l.parallelCompile&&(e.parallelCompile=!0),l.include&&(e.include=l.include),l.exclude&&(e.exclude=l.exclude),S(e)}let A=15;try{let e=require(`next/package.json`);e.version&&(A=parseInt(e.version.split(`.`)[0],10)||15)}catch{}let j=E(A>=15?o.turbopack:o.experimental?.turbo,{rules:b,resolveAlias:T}),M=A>=15?{turbopack:j}:{experimental:{...o.experimental??{},turbo:j}};return{...o,...M,webpack(t,n){let r=e.loaderEnforce===void 0&&!(`loaderEnforce`in e)?`pre`:e.loaderEnforce;return t.module.rules.push({test:/\.[jt]sx?$/,...r?{enforce:r}:{},exclude:[/node_modules/,/\.next/],use:[{loader:_,options:{serverModulePath:g}}]}),t.resolve=t.resolve??{},t.resolve.alias=t.resolve.alias??{},t.resolve.alias[`@fluenti/next$`]=g,t.resolve.alias[`@fluenti/next/i18n-config$`]=x,v?v(t,n):t}}}function E(e,t){let n=e??{},r=n.rules??{},i=Object.keys(t.rules).filter(e=>e in r);return i.length>0&&console.warn(`[fluenti] Your turbopack.rules override Fluenti's loader for: ${i.join(`, `)}.\n Fluenti's t\`\` transform will NOT run on these file types.\n If this is intentional, you can suppress this warning with { devAutoCompile: false }.`),{...n,rules:{...t.rules,...r},resolveAlias:{...t.resolveAlias,...n.resolveAlias}}}var D=["[fluenti] `@fluenti/next` was imported before `withFluenti()` generated the server module.",`Fix this by:`," 1. Wrapping next.config.ts with `withFluenti()` from '@fluenti/next'",` 2. Restarting the Next dev server after the generated module is written`,` 3. Importing client runtime APIs from '@fluenti/react' and server APIs from '@fluenti/next'`].join(`
209
- `);function O(){throw Error(D)}var k=O,A=O,j=O;async function M(e){return O()}async function N(e){return O()}async function P(e){return O()}async function F(e){return O()}async function I(e){return O()}async function L(e){return O()}exports.DateTime=F,exports.I18nProvider=L,exports.NumberFormat=I,exports.Plural=N,exports.Select=P,exports.Trans=M,exports.defineRouting=e.t,exports.getI18n=A,Object.defineProperty(exports,`msg`,{enumerable:!0,get:function(){return l.msg}}),exports.setLocale=k,exports.t=j,exports.withFluenti=C;
210
- //# sourceMappingURL=index.cjs.map
209
+ `);function O(){throw Error(D)}var k=O,A=O,j=O;async function M(e){return O()}async function N(e){return O()}async function P(e){return O()}async function F(e){return O()}async function I(e){return O()}async function L(e){return O()}exports.DateTime=F,exports.I18nProvider=L,exports.NumberFormat=I,exports.Plural=N,exports.Select=P,exports.Trans=M,exports.defineRouting=e.t,exports.getI18n=A,Object.defineProperty(exports,`msg`,{enumerable:!0,get:function(){return l.msg}}),exports.setLocale=k,exports.t=j,exports.withFluenti=C;
package/dist/index.js CHANGED
@@ -410,5 +410,3 @@ async function G(e) {
410
410
  }
411
411
  //#endregion
412
412
  export { U as DateTime, G as I18nProvider, W as NumberFormat, V as Plural, H as Select, B as Trans, t as defineRouting, R as getI18n, _ as msg, L as setLocale, z as t, j as withFluenti };
413
-
414
- //# sourceMappingURL=index.js.map
package/dist/loader.cjs CHANGED
@@ -1,2 +1 @@
1
- let e=require(`@fluenti/core/transform`);var t=(0,e.createTransformPipeline)({framework:`react`});function n(n){if(!/\.[jt]sx?$/.test(this.resourcePath)||/node_modules|\.next/.test(this.resourcePath))return n;let r=n,i=/^\s*['"]use client['"]/.test(r);if(/\.[jt]sx$/.test(this.resourcePath)&&/<Trans[\s>]/.test(r)){let e=t.transformTrans(r);e.transformed&&(r=e.code)}if(i&&/\.[jt]sx$/.test(this.resourcePath)&&/<(Plural|Select)[\s/>]/.test(r)){let e=t.transformPluralSelect(r,`@fluenti/react/components`);e.transformed&&(r=e.code)}if(!(0,e.hasScopeTransformCandidate)(r))return r;try{let e=t.transformScope(r,{componentModuleImport:i?`@fluenti/react/components`:`@fluenti/next`,serverModuleImport:`@fluenti/next`,treatFrameworkDirectImportsAsServer:!i,rerouteServerAuthoringImports:!i,errorOnServerUseI18n:!i});if(e.transformed)return e.code}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`[fluenti] Transform failed in ${this.resourcePath}: ${t}`)}return r}module.exports=n;
2
- //# sourceMappingURL=loader.cjs.map
1
+ let e=require(`@fluenti/core/transform`);var t=(0,e.createTransformPipeline)({framework:`react`});function n(n){if(!/\.[jt]sx?$/.test(this.resourcePath)||/node_modules|\.next/.test(this.resourcePath))return n;let r=n,i=/^\s*['"]use client['"]/.test(r);if(/\.[jt]sx$/.test(this.resourcePath)&&/<Trans[\s>]/.test(r)){let e=t.transformTrans(r);e.transformed&&(r=e.code)}if(i&&/\.[jt]sx$/.test(this.resourcePath)&&/<(Plural|Select)[\s/>]/.test(r)){let e=t.transformPluralSelect(r,`@fluenti/react/components`);e.transformed&&(r=e.code)}if(!(0,e.hasScopeTransformCandidate)(r))return r;try{let e=t.transformScope(r,{componentModuleImport:i?`@fluenti/react/components`:`@fluenti/next`,serverModuleImport:`@fluenti/next`,treatFrameworkDirectImportsAsServer:!i,rerouteServerAuthoringImports:!i,errorOnServerUseI18n:!i});if(e.transformed)return e.code}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`[fluenti] Transform failed in ${this.resourcePath}: ${t}`)}return r}module.exports=n;
package/dist/loader.js CHANGED
@@ -30,5 +30,3 @@ function r(e) {
30
30
  }
31
31
  //#endregion
32
32
  export { r as default };
33
-
34
- //# sourceMappingURL=loader.js.map
@@ -1,2 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./routing-D4p8HvMH.cjs`);let t=require(`@fluenti/next/i18n-config`);var n=`x-fluenti-locale`;function r(r){let{NextResponse:l}=r,f=r.locales??t.locales,p=r.sourceLocale??t.sourceLocale,m=r.cookieName??t.cookieName,h=r.localePrefix??`as-needed`,g=r.rewriteDefaultLocale??!1,_=r.setCookie??!1,v=r.cookieOptions??{},y=r.localeDetection??!0,b=r.alternateLinks??!1,x=r.pathnames,S=r.domains,C=r.beforeResponse;function w(e,t,i,a,s){if(e.headers.set(n,i),_&&o(e,t,i,m,s,v),b||r.getAlternateLinks){let n=r.getAlternateLinks?d(r.getAlternateLinks,t,i,f):u(t,f,p,h,t.nextUrl.basePath??``,x);e.headers.set(`Link`,n)}if(C){let n=C({response:e,request:t,locale:i,type:a});if(n)return n}return e}return function(t){let o=f,u=p,{pathname:d,search:_}=t.nextUrl,v=t.nextUrl.basePath??``,b=d.split(`/`),C=b[1]??``,T=h===`never`?null:i(C,o),E;if(T)E=T;else if(!y)E=u;else{let e=r.detectLocale?.(t);E=e!==void 0&&i(e,o)!==null?i(e,o):S?s(t,S,o)??c(t,o,u,m):c(t,o,u,m)}let D=new Headers(t.headers);if(D.set(n,E),h===`never`){if(g){let e=new URL(`${v}/${E}${d}${_}`,t.url);return w(l.rewrite(e,{request:{headers:D}}),t,E,`rewrite`,null)}return w(l.next({request:{headers:D}}),t,E,`next`,null)}if(x&&T){let n=a(`/`+b.slice(2).join(`/`)),r=e.n(n,E,x);if(r){let e=new URL(`${v}/${E}${r}${_}`,t.url);return w(l.rewrite(e,{request:{headers:D}}),t,E,`rewrite`,T)}let i=e.r(n,E,x);if(i&&i!==n){let e=new URL(`${v}/${E}${i}${_}`,t.url);return w(l.redirect(e),t,E,`redirect`,T)}}if(!T&&(h===`always`||E!==u)){let n=d;if(x){let t=e.r(d,E,x);t&&(n=t)}let r=new URL(`${v}/${E}${n}${_}`,t.url);return w(l.redirect(r),t,E,`redirect`,T)}if(!T&&E===u&&g){let e=new URL(`${v}/${u}${d}${_}`,t.url);return w(l.rewrite(e,{request:{headers:D}}),t,E,`rewrite`,T)}if(h===`as-needed`&&T===u){let e=a(`/`+b.slice(2).join(`/`));if(g){let n=new URL(`${v}${e}${_}`,t.url);return w(l.redirect(n),t,E,`redirect`,T)}let n=new URL(`${v}${e}${_}`,t.url);return w(l.rewrite(n,{request:{headers:D}}),t,E,`rewrite`,T)}return w(l.next({request:{headers:D}}),t,E,`next`,T)}}function i(e,t){if(!e)return null;let n=e.toLowerCase();return t.find(e=>e.toLowerCase()===n)??null}function a(e){return e.replace(/\/+/g,`/`)||`/`}function o(e,t,n,r,i,a){if(i||t.cookies.get(r)?.value===n)return;let o=[`${r}=${encodeURIComponent(n)}`];o.push(`path=${a.path??`/`}`),o.push(`max-age=${a.maxAge??31536e3}`),o.push(`samesite=${a.sameSite??`lax`}`),a.domain&&o.push(`domain=${a.domain}`),(a.secure??t.url.startsWith(`https`))&&o.push(`secure`),e.headers.set(`set-cookie`,o.join(`;`))}function s(e,t,n){let r=e.headers.get(`host`)?.split(`:`)[0]??``;for(let e of t)if(r===e.domain||r.endsWith(`.`+e.domain)){let t=i(e.defaultLocale,e.locales??n);if(t)return t}return null}function c(e,t,n,r){let a=e.cookies.get(r)?.value;if(a){let e=i(a,t);if(e)return e}let o=e.headers.get(`accept-language`);if(o)for(let e of o.split(`,`)){let n=e.split(`;`)[0].trim(),r=i(n,t);if(r)return r;let a=n.split(`-`)[0].toLowerCase(),o=t.find(e=>{let t=e.toLowerCase();return t===a||t.startsWith(a+`-`)});if(o)return o}return n}function l(e,t){let n=e.split(`/`);return i(n[1]??``,t)?a(`/`+n.slice(2).join(`/`)):e}function u(t,n,r,a,o,s){let c=new URL(t.url).origin,u=l(t.nextUrl.pathname,n),d=t.nextUrl.pathname.split(`/`)[1]??``,f=a===`never`?r:i(d,n)??r,p=s?e.n(u,f,s)??u:u,m=n.map(t=>{let n=s?e.r(p,t,s)??p:p,i;return i=a===`never`||a===`as-needed`&&t===r?n:`/${t}${n}`,`<${c}${o}${i}>; rel="alternate"; hreflang="${t}"`}),h=s?e.r(p,r,s)??p:p,g=a===`always`?`/${r}${h}`:h;return m.push(`<${c}${o}${g}>; rel="alternate"; hreflang="x-default"`),m.join(`, `)}function d(e,t,n,r){let i=new URL(t.url).origin;return e({pathname:l(t.nextUrl.pathname,r),locale:n,locales:r,origin:i,basePath:t.nextUrl.basePath??``}).map(e=>`<${e.href}>; rel="alternate"; hreflang="${e.hreflang}"`).join(`, `)}exports.LOCALE_HEADER=n,exports.createI18nMiddleware=r;
2
- //# sourceMappingURL=middleware.cjs.map
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./routing-D4p8HvMH.cjs`);let t=require(`@fluenti/next/i18n-config`);var n=`x-fluenti-locale`;function r(r){let{NextResponse:l}=r,f=r.locales??t.locales,p=r.sourceLocale??t.sourceLocale,m=r.cookieName??t.cookieName,h=r.localePrefix??`as-needed`,g=r.rewriteDefaultLocale??!1,_=r.setCookie??!1,v=r.cookieOptions??{},y=r.localeDetection??!0,b=r.alternateLinks??!1,x=r.pathnames,S=r.domains,C=r.beforeResponse;function w(e,t,i,a,s){if(e.headers.set(n,i),_&&o(e,t,i,m,s,v),b||r.getAlternateLinks){let n=r.getAlternateLinks?d(r.getAlternateLinks,t,i,f):u(t,f,p,h,t.nextUrl.basePath??``,x);e.headers.set(`Link`,n)}if(C){let n=C({response:e,request:t,locale:i,type:a});if(n)return n}return e}return function(t){let o=f,u=p,{pathname:d,search:_}=t.nextUrl,v=t.nextUrl.basePath??``,b=d.split(`/`),C=b[1]??``,T=h===`never`?null:i(C,o),E;if(T)E=T;else if(!y)E=u;else{let e=r.detectLocale?.(t);E=e!==void 0&&i(e,o)!==null?i(e,o):S?s(t,S,o)??c(t,o,u,m):c(t,o,u,m)}let D=new Headers(t.headers);if(D.set(n,E),h===`never`){if(g){let e=new URL(`${v}/${E}${d}${_}`,t.url);return w(l.rewrite(e,{request:{headers:D}}),t,E,`rewrite`,null)}return w(l.next({request:{headers:D}}),t,E,`next`,null)}if(x&&T){let n=a(`/`+b.slice(2).join(`/`)),r=e.n(n,E,x);if(r){let e=new URL(`${v}/${E}${r}${_}`,t.url);return w(l.rewrite(e,{request:{headers:D}}),t,E,`rewrite`,T)}let i=e.r(n,E,x);if(i&&i!==n){let e=new URL(`${v}/${E}${i}${_}`,t.url);return w(l.redirect(e),t,E,`redirect`,T)}}if(!T&&(h===`always`||E!==u)){let n=d;if(x){let t=e.r(d,E,x);t&&(n=t)}let r=new URL(`${v}/${E}${n}${_}`,t.url);return w(l.redirect(r),t,E,`redirect`,T)}if(!T&&E===u&&g){let e=new URL(`${v}/${u}${d}${_}`,t.url);return w(l.rewrite(e,{request:{headers:D}}),t,E,`rewrite`,T)}if(h===`as-needed`&&T===u){let e=a(`/`+b.slice(2).join(`/`));if(g){let n=new URL(`${v}${e}${_}`,t.url);return w(l.redirect(n),t,E,`redirect`,T)}let n=new URL(`${v}${e}${_}`,t.url);return w(l.rewrite(n,{request:{headers:D}}),t,E,`rewrite`,T)}return w(l.next({request:{headers:D}}),t,E,`next`,T)}}function i(e,t){if(!e)return null;let n=e.toLowerCase();return t.find(e=>e.toLowerCase()===n)??null}function a(e){return e.replace(/\/+/g,`/`)||`/`}function o(e,t,n,r,i,a){if(i||t.cookies.get(r)?.value===n)return;let o=[`${r}=${encodeURIComponent(n)}`];o.push(`path=${a.path??`/`}`),o.push(`max-age=${a.maxAge??31536e3}`),o.push(`samesite=${a.sameSite??`lax`}`),a.domain&&o.push(`domain=${a.domain}`),(a.secure??t.url.startsWith(`https`))&&o.push(`secure`),e.headers.set(`set-cookie`,o.join(`;`))}function s(e,t,n){let r=e.headers.get(`host`)?.split(`:`)[0]??``;for(let e of t)if(r===e.domain||r.endsWith(`.`+e.domain)){let t=i(e.defaultLocale,e.locales??n);if(t)return t}return null}function c(e,t,n,r){let a=e.cookies.get(r)?.value;if(a){let e=i(a,t);if(e)return e}let o=e.headers.get(`accept-language`);if(o)for(let e of o.split(`,`)){let n=e.split(`;`)[0].trim(),r=i(n,t);if(r)return r;let a=n.split(`-`)[0].toLowerCase(),o=t.find(e=>{let t=e.toLowerCase();return t===a||t.startsWith(a+`-`)});if(o)return o}return n}function l(e,t){let n=e.split(`/`);return i(n[1]??``,t)?a(`/`+n.slice(2).join(`/`)):e}function u(t,n,r,a,o,s){let c=new URL(t.url).origin,u=l(t.nextUrl.pathname,n),d=t.nextUrl.pathname.split(`/`)[1]??``,f=a===`never`?r:i(d,n)??r,p=s?e.n(u,f,s)??u:u,m=n.map(t=>{let n=s?e.r(p,t,s)??p:p,i;return i=a===`never`||a===`as-needed`&&t===r?n:`/${t}${n}`,`<${c}${o}${i}>; rel="alternate"; hreflang="${t}"`}),h=s?e.r(p,r,s)??p:p,g=a===`always`?`/${r}${h}`:h;return m.push(`<${c}${o}${g}>; rel="alternate"; hreflang="x-default"`),m.join(`, `)}function d(e,t,n,r){let i=new URL(t.url).origin;return e({pathname:l(t.nextUrl.pathname,r),locale:n,locales:r,origin:i,basePath:t.nextUrl.basePath??``}).map(e=>`<${e.href}>; rel="alternate"; hreflang="${e.hreflang}"`).join(`, `)}exports.LOCALE_HEADER=n,exports.createI18nMiddleware=r;
@@ -135,5 +135,3 @@ function m(e, t, n, r) {
135
135
  }
136
136
  //#endregion
137
137
  export { a as LOCALE_HEADER, o as createI18nMiddleware };
138
-
139
- //# sourceMappingURL=middleware.js.map
@@ -1,3 +1,2 @@
1
1
  "use client";
2
- "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./routing-D4p8HvMH.cjs`);let t=require(`@fluenti/react`),n=require(`react`),r=require(`@fluenti/next/i18n-config`),i=require(`next/navigation`);function a(t){let{locales:r,sourceLocale:i,localePrefix:a=`as-needed`,pathnames:o}=t;function s(t,n){let r=t;if(o){let i=e.r(t,n,o);i&&(r=i)}return a===`never`||a===`as-needed`&&n===i?r:`/${n}${r}`}function c(e){if(a===`never`)return e;let t=e.split(`/`),n=(t[1]??``).toLowerCase();return r.some(e=>e.toLowerCase()===n)?`/`+t.slice(2).join(`/`)||`/`:e}let l=(0,n.forwardRef)(function({href:e,locale:t,...r},a){let o=require(`next/link`).default,c=i;try{let{useI18n:e}=require(`@fluenti/react`);c=e().locale}catch{}return(0,n.createElement)(o,{ref:a,href:s(String(e),String(t??c)),...r})});l.displayName=`I18nLink`;function u(){let{useRouter:e}=require(`next/navigation`),{useI18n:t}=require(`@fluenti/react`),n=e(),{locale:r}=t();return{push(e,t){n.push(s(String(e),String(t?.locale??r)))},replace(e,t){n.replace(s(String(e),String(t?.locale??r)))},back:()=>n.back(),forward:()=>n.forward(),refresh:()=>n.refresh(),prefetch:e=>n.prefetch(e)}}function d(e,t){let{redirect:n}=require(`next/navigation`);return n(s(String(e),String(t??i)))}function f(){let{usePathname:e}=require(`next/navigation`);return c(e())}function p(e,t){return s(String(e),String(t))}return{Link:l,useRouter:u,redirect:d,usePathname:f,getPathname:p}}function o(e,t,n){let r=n?.sourceLocale??`en`,i=n?.localePrefix??`as-needed`,a=e.split(`/`),o=a[1]??``,s=n?.locales&&n.locales.some(e=>e.toLowerCase()===o.toLowerCase())?`/`+a.slice(2).join(`/`):e;return i===`never`||i!==`always`&&t===r?s||`/`:`/${t}${s}`}function s(e){let n=(0,i.useRouter)(),a=(0,i.usePathname)(),{locale:s,setLocale:c,getLocales:l}=(0,t.useI18n)(),u=l(),d=e?.sourceLocale??u[0]??`en`,f=e?.cookieName??r.cookieName,p=e?.localePrefix??`as-needed`;return{switchLocale:e=>{if(!u.includes(e)){typeof process<`u`&&process.env.NODE_ENV!==`production`&&console.warn(`[fluenti] switchLocale: invalid locale "${e}"`);return}document.cookie=`${f}=${encodeURIComponent(e)};path=/;max-age=31536000;samesite=lax`,c(e);let t=o(a,e,{sourceLocale:d,locales:u,localePrefix:p});n.push(t),n.refresh()},currentLocale:s,locales:u,sourceLocale:d}}function c(n){let{routing:r,baseUrl:a=``}=n,o=(0,i.usePathname)(),s=r.sourceLocale;try{s=(0,t.useI18n)().locale}catch{}let c=o.split(`/`),l=c[1]??``,u=r.localePrefix===`never`?null:r.locales.find(e=>e.toLowerCase()===l.toLowerCase())??null,d=u?`/`+c.slice(2).join(`/`)||`/`:o,f=u??s??r.sourceLocale,p=r.pathnames?e.n(d,f,r.pathnames)??d:d,m=r.locales.map(t=>{let n=r.pathnames?e.r(p,t,r.pathnames)??p:p,i;return i=r.localePrefix===`never`||r.localePrefix!==`always`&&t===r.sourceLocale?`${a}${n}`:`${a}/${t}${n}`,{hreflang:t,href:i}}),h=r.pathnames?e.r(p,r.sourceLocale,r.pathnames)??p:p,g=r.localePrefix===`always`?`${a}/${r.sourceLocale}${h}`:`${a}${h}`;return m.push({hreflang:`x-default`,href:g}),m}exports.createNavigation=a,exports.defineRouting=e.t,exports.getLocalePath=o,exports.resolveLocalizedPath=e.r,exports.useAlternateLinks=c,exports.useLocaleSwitcher=s;
3
- //# sourceMappingURL=navigation.cjs.map
2
+ "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./routing-D4p8HvMH.cjs`);let t=require(`@fluenti/react`),n=require(`react`),r=require(`@fluenti/next/i18n-config`),i=require(`next/navigation`);function a(t){let{locales:r,sourceLocale:i,localePrefix:a=`as-needed`,pathnames:o}=t;function s(t,n){let r=t;if(o){let i=e.r(t,n,o);i&&(r=i)}return a===`never`||a===`as-needed`&&n===i?r:`/${n}${r}`}function c(e){if(a===`never`)return e;let t=e.split(`/`),n=(t[1]??``).toLowerCase();return r.some(e=>e.toLowerCase()===n)?`/`+t.slice(2).join(`/`)||`/`:e}let l=(0,n.forwardRef)(function({href:e,locale:t,...r},a){let o=require(`next/link`).default,c=i;try{let{useI18n:e}=require(`@fluenti/react`);c=e().locale}catch{}return(0,n.createElement)(o,{ref:a,href:s(String(e),String(t??c)),...r})});l.displayName=`I18nLink`;function u(){let{useRouter:e}=require(`next/navigation`),{useI18n:t}=require(`@fluenti/react`),n=e(),{locale:r}=t();return{push(e,t){n.push(s(String(e),String(t?.locale??r)))},replace(e,t){n.replace(s(String(e),String(t?.locale??r)))},back:()=>n.back(),forward:()=>n.forward(),refresh:()=>n.refresh(),prefetch:e=>n.prefetch(e)}}function d(e,t){let{redirect:n}=require(`next/navigation`);return n(s(String(e),String(t??i)))}function f(){let{usePathname:e}=require(`next/navigation`);return c(e())}function p(e,t){return s(String(e),String(t))}return{Link:l,useRouter:u,redirect:d,usePathname:f,getPathname:p}}function o(e,t,n){let r=n?.sourceLocale??`en`,i=n?.localePrefix??`as-needed`,a=e.split(`/`),o=a[1]??``,s=n?.locales&&n.locales.some(e=>e.toLowerCase()===o.toLowerCase())?`/`+a.slice(2).join(`/`):e;return i===`never`||i!==`always`&&t===r?s||`/`:`/${t}${s}`}function s(e){let n=(0,i.useRouter)(),a=(0,i.usePathname)(),{locale:s,setLocale:c,getLocales:l}=(0,t.useI18n)(),u=l(),d=e?.sourceLocale??u[0]??`en`,f=e?.cookieName??r.cookieName,p=e?.localePrefix??`as-needed`;return{switchLocale:e=>{if(!u.includes(e)){typeof process<`u`&&process.env.NODE_ENV!==`production`&&console.warn(`[fluenti] switchLocale: invalid locale "${e}"`);return}document.cookie=`${f}=${encodeURIComponent(e)};path=/;max-age=31536000;samesite=lax`,c(e);let t=o(a,e,{sourceLocale:d,locales:u,localePrefix:p});n.push(t),n.refresh()},currentLocale:s,locales:u,sourceLocale:d}}function c(n){let{routing:r,baseUrl:a=``}=n,o=(0,i.usePathname)(),s=r.sourceLocale;try{s=(0,t.useI18n)().locale}catch{}let c=o.split(`/`),l=c[1]??``,u=r.localePrefix===`never`?null:r.locales.find(e=>e.toLowerCase()===l.toLowerCase())??null,d=u?`/`+c.slice(2).join(`/`)||`/`:o,f=u??s??r.sourceLocale,p=r.pathnames?e.n(d,f,r.pathnames)??d:d,m=r.locales.map(t=>{let n=r.pathnames?e.r(p,t,r.pathnames)??p:p,i;return i=r.localePrefix===`never`||r.localePrefix!==`always`&&t===r.sourceLocale?`${a}${n}`:`${a}/${t}${n}`,{hreflang:t,href:i}}),h=r.pathnames?e.r(p,r.sourceLocale,r.pathnames)??p:p,g=r.localePrefix===`always`?`${a}/${r.sourceLocale}${h}`:`${a}${h}`;return m.push({hreflang:`x-default`,href:g}),m}exports.createNavigation=a,exports.defineRouting=e.t,exports.getLocalePath=o,exports.resolveLocalizedPath=e.r,exports.useAlternateLinks=c,exports.useLocaleSwitcher=s;
@@ -115,5 +115,3 @@ function p(e) {
115
115
  }
116
116
  //#endregion
117
117
  export { u as createNavigation, r as defineRouting, d as getLocalePath, n as resolveLocalizedPath, p as useAlternateLinks, f as useLocaleSwitcher };
118
-
119
- //# sourceMappingURL=navigation.js.map
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { AllMessages, DateFormatOptions, NumberFormatOptions, Locale } from '../../core/src/index.ts';
2
+ import { AllMessages, DateFormatOptions, NumberFormatOptions, Locale } from '@fluenti/core';
3
3
  export interface ClientI18nProviderProps {
4
4
  locale: string;
5
5
  fallbackLocale: string;
@@ -40,4 +40,3 @@ export interface ClientI18nProviderProps {
40
40
  * ```
41
41
  */
42
42
  export declare function ClientI18nProvider({ locale, fallbackLocale, messages, fallbackChain, dateFormats, numberFormats, children, }: ClientI18nProviderProps): import("react/jsx-runtime").JSX.Element;
43
- //# sourceMappingURL=client-provider.d.ts.map
@@ -31,4 +31,3 @@ export declare function createNavigation<const L extends string, const P extends
31
31
  usePathname: () => string;
32
32
  getPathname: (href: P | (string & Record<never, never>), locale: L) => string;
33
33
  };
34
- //# sourceMappingURL=create-navigation.d.ts.map
@@ -23,4 +23,3 @@ export declare function runExtractCompile(options: DevRunnerOptions): Promise<vo
23
23
  * - Never runs concurrently.
24
24
  */
25
25
  export declare function createDebouncedRunner(options: DevRunnerOptions, delay?: number): () => void;
26
- //# sourceMappingURL=dev-runner.d.ts.map
@@ -33,4 +33,3 @@ export declare function extractWatchDirs(cwd: string, include?: string[]): strin
33
33
  * @returns A cleanup function that stops the watcher.
34
34
  */
35
35
  export declare function startDevWatcher(options: DevWatcherOptions): () => void;
36
- //# sourceMappingURL=dev-watcher.d.ts.map
@@ -8,4 +8,3 @@ import { ResolvedFluentConfig } from './types';
8
8
  * @returns Absolute path to the generated server module.
9
9
  */
10
10
  export declare function generateServerModule(projectRoot: string, config: ResolvedFluentConfig): string;
11
- //# sourceMappingURL=generate-server-module.d.ts.map
@@ -30,4 +30,3 @@ export declare const locales: string[];
30
30
  export declare const sourceLocale: string;
31
31
  /** Cookie name for locale detection — overridden at build time from fluenti.config.ts */
32
32
  export declare const cookieName: string;
33
- //# sourceMappingURL=i18n-config.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import { ReactNode, ReactElement } from 'react';
2
- import { CompileTimeT, FluentiCoreInstanceFull } from '../../core/src/index.ts';
2
+ import { CompileTimeT, FluentiCoreInstanceFull } from '@fluenti/core';
3
3
  import { I18nProviderProps } from './types';
4
4
  /**
5
5
  * @fluenti/next — Next.js plugin for Fluenti
@@ -26,7 +26,7 @@ export { withFluenti } from './with-fluenti';
26
26
  export type { WithFluentConfig, I18nProviderProps } from './types';
27
27
  export { defineRouting } from './routing';
28
28
  export type { RoutingConfig } from './routing';
29
- export { msg } from '../../react/src/index.ts';
29
+ export { msg } from '@fluenti/react';
30
30
  interface NextTransProps {
31
31
  children: ReactNode;
32
32
  id?: string;
@@ -84,4 +84,3 @@ export declare function DateTime(_props: NextDateTimeProps): Promise<ReactElemen
84
84
  export declare function NumberFormat(_props: NextNumberFormatProps): Promise<ReactElement>;
85
85
  /** @see Generated module for the real implementation. */
86
86
  export declare function I18nProvider(_props: I18nProviderProps): Promise<ReactElement>;
87
- //# sourceMappingURL=index.d.ts.map
@@ -188,4 +188,3 @@ export declare function createI18nMiddleware<R extends NextResponseInstance = Ne
188
188
  NextResponse: NextResponseStatic<R>;
189
189
  }): (request: NextRequest) => R;
190
190
  export {};
191
- //# sourceMappingURL=middleware.d.ts.map
@@ -92,4 +92,3 @@ export declare function useAlternateLinks(options: {
92
92
  };
93
93
  baseUrl?: string;
94
94
  }): AlternateLink[];
95
- //# sourceMappingURL=navigation.d.ts.map
@@ -1,3 +1,2 @@
1
1
  export { ClientI18nProvider as I18nProvider } from './client-provider';
2
2
  export type { ClientI18nProviderProps as I18nProviderProps } from './client-provider';
3
- //# sourceMappingURL=provider.d.ts.map
@@ -5,4 +5,3 @@ import { WithFluentConfig, ResolvedFluentConfig } from './types';
5
5
  * Delegates config file loading to `@fluenti/core`'s shared `loadConfigSync()`.
6
6
  */
7
7
  export declare function resolveConfig(projectRoot: string, overrides?: WithFluentConfig): ResolvedFluentConfig;
8
- //# sourceMappingURL=read-config.d.ts.map
@@ -49,4 +49,3 @@ export declare function substituteParams(pattern: string, params: Record<string,
49
49
  export declare function resolveInternalPath(localizedPath: string, locale: string, pathnames: Record<string, Record<string, string>>): string | null;
50
50
  /** Forward lookup: internal path → localized path. */
51
51
  export declare function resolveLocalizedPath(internalPath: string, locale: string, pathnames: Record<string, Record<string, string>>): string | null;
52
- //# sourceMappingURL=routing.d.ts.map
@@ -41,4 +41,3 @@ export declare function getLocale(): Promise<string>;
41
41
  export declare function generateLocaleParams(locales: string[]): Array<{
42
42
  locale: string;
43
43
  }>;
44
- //# sourceMappingURL=server.d.ts.map
@@ -1,4 +1,4 @@
1
- import { FluentiBuildConfig } from '../../core/src/compiler.ts';
1
+ import { FluentiBuildConfig } from '@fluenti/core/compiler';
2
2
  /**
3
3
  * Configuration for `withFluenti()`.
4
4
  *
@@ -72,4 +72,3 @@ export interface I18nProviderProps {
72
72
  locale?: string;
73
73
  children: React.ReactNode;
74
74
  }
75
- //# sourceMappingURL=types.d.ts.map
@@ -21,4 +21,3 @@ type NextConfig = Record<string, any>;
21
21
  export declare function withFluenti(fluentConfig?: WithFluentConfig): (nextConfig?: NextConfig) => NextConfig;
22
22
  export declare function withFluenti(nextConfig: NextConfig): NextConfig;
23
23
  export {};
24
- //# sourceMappingURL=with-fluenti.d.ts.map
@@ -53,4 +53,3 @@ export declare function withLocale<T>(locale: string, fn: () => T | Promise<T>,
53
53
  setLocale: (l: string) => void;
54
54
  getI18n: () => Promise<unknown>;
55
55
  }): Promise<T>;
56
- //# sourceMappingURL=with-locale.d.ts.map
package/dist/provider.cjs CHANGED
@@ -1,3 +1,2 @@
1
1
  "use client";
2
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@fluenti/react`),t=require(`react/jsx-runtime`);function n({locale:n,fallbackLocale:r,messages:i,fallbackChain:a,dateFormats:o,numberFormats:s,children:c}){return(0,t.jsx)(e.I18nProvider,{locale:n,fallbackLocale:r,messages:i,...a?{fallbackChain:a}:{},...o?{dateFormats:o}:{},...s?{numberFormats:s}:{},children:c})}exports.I18nProvider=n;
3
- //# sourceMappingURL=provider.cjs.map
2
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@fluenti/react`),t=require(`react/jsx-runtime`);function n({locale:n,fallbackLocale:r,messages:i,fallbackChain:a,dateFormats:o,numberFormats:s,children:c}){return(0,t.jsx)(e.I18nProvider,{locale:n,fallbackLocale:r,messages:i,...a?{fallbackChain:a}:{},...o?{dateFormats:o}:{},...s?{numberFormats:s}:{},children:c})}exports.I18nProvider=n;
package/dist/provider.js CHANGED
@@ -15,5 +15,3 @@ function n({ locale: n, fallbackLocale: r, messages: i, fallbackChain: a, dateFo
15
15
  }
16
16
  //#endregion
17
17
  export { n as I18nProvider };
18
-
19
- //# sourceMappingURL=provider.js.map
@@ -61,5 +61,3 @@ function c(e, t, n) {
61
61
  }
62
62
  //#endregion
63
63
  export { s as n, c as r, e as t };
64
-
65
- //# sourceMappingURL=routing-CRln5Gw7.js.map
@@ -1,2 +1 @@
1
- function e(e){return e}function t(e){return e.split(`/`).filter(Boolean)}function n(e){return e?e.startsWith(`[...`)&&e.endsWith(`]`)?1:e.startsWith(`[`)&&e.endsWith(`]`)?2:3:0}function r(e,r){let i=t(e),a=t(r),o=Math.max(i.length,a.length);for(let e=0;e<o;e++){let t=n(i[e]),r=n(a[e]);if(t!==r)return r-t}return i.length===a.length?e.localeCompare(r):a.length-i.length}function i(e){return Object.entries(e).sort(([e],[t])=>r(e,t))}function a(e,t){let n=e.split(`/`).filter(Boolean),r=t.split(`/`).filter(Boolean),i={};for(let e=0;e<n.length;e++){let t=n[e];if(t.startsWith(`[...`)&&t.endsWith(`]`)){let n=t.slice(4,-1);return i[n]=r.slice(e).join(`/`),i}if(t.startsWith(`[`)&&t.endsWith(`]`)){if(e>=r.length)return null;i[t.slice(1,-1)]=r[e];continue}if(e>=r.length||t!==r[e])return null}return n.length===r.length?i:null}function o(e,t){return e.replace(/\[\.\.\.(\w+)\]|\[(\w+)\]/g,(e,n,r)=>t[n??r]??``)}function s(e,t,n){for(let[r,s]of i(n)){let n=s[t];if(!n)continue;if(n===e)return r;let i=a(n,e);if(i)return o(r,i)}return null}function c(e,t,n){for(let[r,s]of i(n)){let n=s[t];if(!n)continue;if(r===e)return n;let i=a(r,e);if(i)return o(n,i)}return null}Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return e}});
2
- //# sourceMappingURL=routing-D4p8HvMH.cjs.map
1
+ function e(e){return e}function t(e){return e.split(`/`).filter(Boolean)}function n(e){return e?e.startsWith(`[...`)&&e.endsWith(`]`)?1:e.startsWith(`[`)&&e.endsWith(`]`)?2:3:0}function r(e,r){let i=t(e),a=t(r),o=Math.max(i.length,a.length);for(let e=0;e<o;e++){let t=n(i[e]),r=n(a[e]);if(t!==r)return r-t}return i.length===a.length?e.localeCompare(r):a.length-i.length}function i(e){return Object.entries(e).sort(([e],[t])=>r(e,t))}function a(e,t){let n=e.split(`/`).filter(Boolean),r=t.split(`/`).filter(Boolean),i={};for(let e=0;e<n.length;e++){let t=n[e];if(t.startsWith(`[...`)&&t.endsWith(`]`)){let n=t.slice(4,-1);return i[n]=r.slice(e).join(`/`),i}if(t.startsWith(`[`)&&t.endsWith(`]`)){if(e>=r.length)return null;i[t.slice(1,-1)]=r[e];continue}if(e>=r.length||t!==r[e])return null}return n.length===r.length?i:null}function o(e,t){return e.replace(/\[\.\.\.(\w+)\]|\[(\w+)\]/g,(e,n,r)=>t[n??r]??``)}function s(e,t,n){for(let[r,s]of i(n)){let n=s[t];if(!n)continue;if(n===e)return r;let i=a(n,e);if(i)return o(r,i)}return null}function c(e,t,n){for(let[r,s]of i(n)){let n=s[t];if(!n)continue;if(r===e)return n;let i=a(r,e);if(i)return o(n,i)}return null}Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return e}});
package/dist/server.cjs CHANGED
@@ -1,2 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`react`);async function t(e,t,n){if(!n)throw Error(`[fluenti] withLocale requires a server module reference. Pass the generated server module as the third argument: withLocale("ja", fn, serverI18n)`);let r=(await n.getI18n()).locale;try{return n.setLocale(e),await n.getI18n(),await t()}finally{n.setLocale(r),await n.getI18n()}}var n=(0,e.cache)(()=>({locale:``}));function r(e){n().locale=e}async function i(){let e=n();if(e.locale)return e.locale;try{let{headers:e}=await import(`next/headers`),t=(await e()).get(`x-fluenti-locale`);if(t)return t}catch{}return`en`}function a(e){return e.map(e=>({locale:e}))}exports.generateLocaleParams=a,exports.getLocale=i,exports.setRequestLocale=r,exports.withLocale=t;
2
- //# sourceMappingURL=server.cjs.map
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`react`);async function t(e,t,n){if(!n)throw Error(`[fluenti] withLocale requires a server module reference. Pass the generated server module as the third argument: withLocale("ja", fn, serverI18n)`);let r=(await n.getI18n()).locale;try{return n.setLocale(e),await n.getI18n(),await t()}finally{n.setLocale(r),await n.getI18n()}}var n=(0,e.cache)(()=>({locale:``}));function r(e){n().locale=e}async function i(){let e=n();if(e.locale)return e.locale;try{let{headers:e}=await import(`next/headers`),t=(await e()).get(`x-fluenti-locale`);if(t)return t}catch{}return`en`}function a(e){return e.map(e=>({locale:e}))}exports.generateLocaleParams=a,exports.getLocale=i,exports.setRequestLocale=r,exports.withLocale=t;
package/dist/server.js CHANGED
@@ -29,5 +29,3 @@ function a(e) {
29
29
  }
30
30
  //#endregion
31
31
  export { a as generateLocaleParams, i as getLocale, r as setRequestLocale, t as withLocale };
32
-
33
- //# sourceMappingURL=server.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluenti/next",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "type": "module",
5
5
  "description": "Next.js plugin for Fluenti — withFluenti, I18nProvider, t`` transforms for App Router and Pages Router",
6
6
  "homepage": "https://fluenti.dev",
@@ -107,8 +107,8 @@
107
107
  "dependencies": {
108
108
  "jiti": "^2",
109
109
  "picomatch": "^4",
110
- "@fluenti/core": "0.6.0",
111
- "@fluenti/react": "0.6.0"
110
+ "@fluenti/core": "0.6.2",
111
+ "@fluenti/react": "0.6.2"
112
112
  },
113
113
  "devDependencies": {
114
114
  "@types/node": "^25",
@@ -1 +0,0 @@
1
- {"version":3,"file":"i18n-config.cjs","names":[],"sources":["../src/i18n-config.ts"],"sourcesContent":["/**\n * @module @fluenti/next/i18n-config\n *\n * Provides i18n config values (locales, sourceLocale, cookieName) for use in middleware.\n *\n * At build time, `withFluenti()` generates `.fluenti/i18n-config.js` with the actual\n * values from `fluenti.config.ts` and sets up a resolve alias so this module is\n * replaced by the generated version.\n *\n * If `withFluenti()` is not configured (e.g. unit tests), these fallback defaults are used.\n *\n * @example\n * ```ts\n * // middleware.ts\n * import { NextResponse } from 'next/server'\n * import { createI18nMiddleware } from '@fluenti/next/middleware'\n * import { locales, sourceLocale } from '@fluenti/next/i18n-config'\n *\n * export default createI18nMiddleware({\n * NextResponse,\n * locales,\n * sourceLocale,\n * rewriteDefaultLocale: true,\n * })\n * ```\n */\n\n/** Available locales — overridden at build time from fluenti.config.ts */\nexport const locales: string[] = ['en']\n\n/** Source/default locale — overridden at build time from fluenti.config.ts */\nexport const sourceLocale: string = 'en'\n\n/** Cookie name for locale detection — overridden at build time from fluenti.config.ts */\nexport const cookieName: string = 'locale'\n"],"mappings":"mEA4BA,IAAa,EAAoB,CAAC,KAAK,CAG1B,EAAuB,KAGvB,EAAqB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"i18n-config.js","names":[],"sources":["../src/i18n-config.ts"],"sourcesContent":["/**\n * @module @fluenti/next/i18n-config\n *\n * Provides i18n config values (locales, sourceLocale, cookieName) for use in middleware.\n *\n * At build time, `withFluenti()` generates `.fluenti/i18n-config.js` with the actual\n * values from `fluenti.config.ts` and sets up a resolve alias so this module is\n * replaced by the generated version.\n *\n * If `withFluenti()` is not configured (e.g. unit tests), these fallback defaults are used.\n *\n * @example\n * ```ts\n * // middleware.ts\n * import { NextResponse } from 'next/server'\n * import { createI18nMiddleware } from '@fluenti/next/middleware'\n * import { locales, sourceLocale } from '@fluenti/next/i18n-config'\n *\n * export default createI18nMiddleware({\n * NextResponse,\n * locales,\n * sourceLocale,\n * rewriteDefaultLocale: true,\n * })\n * ```\n */\n\n/** Available locales — overridden at build time from fluenti.config.ts */\nexport const locales: string[] = ['en']\n\n/** Source/default locale — overridden at build time from fluenti.config.ts */\nexport const sourceLocale: string = 'en'\n\n/** Cookie name for locale detection — overridden at build time from fluenti.config.ts */\nexport const cookieName: string = 'locale'\n"],"mappings":";AA4BA,IAAa,IAAoB,CAAC,KAAK,EAG1B,IAAuB,MAGvB,IAAqB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../src/read-config.ts","../src/generate-server-module.ts","../src/dev-runner.ts","../src/dev-watcher.ts","../src/with-fluenti.ts","../src/index.ts"],"sourcesContent":["import { loadConfigSync, DEFAULT_FLUENTI_CONFIG } from '@fluenti/core/config'\nimport type { FluentiBuildConfig } from '@fluenti/core/compiler'\nimport type { WithFluentConfig, ResolvedFluentConfig } from './types'\n\n/**\n * Read fluenti.config.ts and merge with withFluenti() overrides.\n *\n * Delegates config file loading to `@fluenti/core`'s shared `loadConfigSync()`.\n */\nexport function resolveConfig(\n projectRoot: string,\n overrides?: WithFluentConfig,\n): ResolvedFluentConfig {\n let fluentiConfig: FluentiBuildConfig\n\n if (overrides?.config && typeof overrides.config === 'object') {\n // Inline config — merge with defaults\n fluentiConfig = { ...DEFAULT_FLUENTI_CONFIG, ...overrides.config }\n } else if (!overrides?.config && overrides?.locales) {\n // Locales shorthand — build inline config with just locales\n fluentiConfig = { ...DEFAULT_FLUENTI_CONFIG, locales: overrides.locales }\n } else {\n // string path or auto-discover\n fluentiConfig = loadConfigSync(\n typeof overrides?.config === 'string' ? overrides.config : undefined,\n projectRoot,\n )\n }\n\n const serverModuleOutDir = overrides?.serverModuleOutDir ?? '.fluenti'\n const cookieName = overrides?.cookieName ?? 'locale'\n const runtimeInterpolate = overrides?.runtimeInterpolate ?? true\n\n const resolved: ResolvedFluentConfig = {\n fluentiConfig,\n serverModule: overrides?.serverModule ?? null,\n serverModuleOutDir,\n cookieName,\n runtimeInterpolate,\n }\n if (overrides?.resolveLocale) resolved.resolveLocale = overrides.resolveLocale\n return resolved\n}\n","import { writeFileSync, mkdirSync, existsSync } from 'node:fs'\nimport { resolve, relative } from 'node:path'\nimport { validateLocale } from '@fluenti/core'\nimport { resolveLocaleCodes } from '@fluenti/core/compiler'\nimport type { ResolvedFluentConfig } from './types'\n\n/** Wrapper around writeFileSync with a Fluenti-specific error message. */\nfunction writeSafe(path: string, content: string): void {\n try {\n writeFileSync(path, content, 'utf-8')\n } catch (err) {\n throw new Error(\n `[fluenti] Failed to write generated module at ${path}: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n}\n\n/**\n * Generate the server module that provides:\n * - setLocale / getI18n\n * - Trans / Plural / Select / DateTime / NumberFormat (server components)\n * - I18nProvider (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 locales = resolveLocaleCodes(config.fluentiConfig.locales)\n const defaultLocale = config.fluentiConfig.defaultLocale ?? config.fluentiConfig.sourceLocale\n const compiledDir = config.fluentiConfig.compileOutDir\n const fallbackChain = config.fluentiConfig.fallbackChain\n const dateFormats = config.fluentiConfig.dateFormats\n const numberFormats = config.fluentiConfig.numberFormats\n const cookieNameLiteral = toSingleQuotedJsString(config.cookieName)\n const defaultLocaleLiteral = toSingleQuotedJsString(defaultLocale)\n\n for (const locale of locales) {\n validateLocale(locale, 'next-plugin')\n }\n\n const compiledDirAbs = resolve(projectRoot, compiledDir)\n const compiledRelative = toForwardSlash(relative(outDir, compiledDirAbs))\n\n const localeImports = locales\n .map((locale) => ` case ${toSingleQuotedJsString(locale)}: return import(${toSingleQuotedJsString(`${compiledRelative}/${locale}`)})`)\n .join('\\n')\n\n const fallbackChainStr = fallbackChain\n ? JSON.stringify(fallbackChain)\n : 'undefined'\n\n const clientProviderPath = resolve(outDir, 'client-provider.js')\n const dateFormatsStr = dateFormats !== undefined ? JSON.stringify(dateFormats) : 'undefined'\n const numberFormatsStr = numberFormats !== undefined ? JSON.stringify(numberFormats) : 'undefined'\n const runtimeInterpolateImport = config.runtimeInterpolate\n ? \"import { interpolate as __interpolate } from '@fluenti/core/runtime'\\n\"\n : ''\n const runtimeInterpolateProp = config.runtimeInterpolate ? ', interpolate: __interpolate' : ''\n const runtimeInterpolateServerOption = config.runtimeInterpolate ? ' interpolate: __interpolate,\\n' : ''\n const clientProviderSource = `\"use client\";\n// Auto-generated by @fluenti/next — do not edit\n// @ts-nocheck\nimport { createElement } from 'react'\nimport { I18nProvider } from '@fluenti/react'\n${runtimeInterpolateImport}\nconst __dateFormats = ${dateFormatsStr}\nconst __numberFormats = ${numberFormatsStr}\n\nexport function ClientI18nProvider({ locale, fallbackLocale, messages, loadMessages, fallbackChain, children }) {\n return createElement(I18nProvider, { locale, fallbackLocale, messages, loadMessages, fallbackChain, dateFormats: __dateFormats, numberFormats: __numberFormats${runtimeInterpolateProp} }, children)\n}\n`\n writeSafe(clientProviderPath, clientProviderSource)\n\n const clientProviderDtsPath = resolve(outDir, 'client-provider.d.ts')\n const clientProviderDtsSource = `// Auto-generated by @fluenti/next — do not edit\nimport type { ReactNode, ReactElement } from 'react'\nimport type { AllMessages, Messages } from '@fluenti/core'\n\nexport declare function ClientI18nProvider(props: {\n locale: string\n fallbackLocale: string\n messages: AllMessages\n loadMessages: (locale: string) => Promise<Messages | { default: Messages }>\n fallbackChain?: Record<string, string[]>\n children: ReactNode\n}): ReactElement\n`\n writeSafe(clientProviderDtsPath, clientProviderDtsSource)\n\n for (const locale of locales) {\n const clientLocaleProviderPath = resolve(outDir, getClientProviderModuleName(locale))\n const initialLocales = collectInitialClientLocales(locale, defaultLocale, fallbackChain, locales)\n const staticImports = initialLocales\n .map((initialLocale) => `import ${toLocaleBindingName(initialLocale)} from ${toSingleQuotedJsString(`${compiledRelative}/${initialLocale}`)}`)\n .join('\\n')\n const initialMessageEntries = initialLocales\n .map((initialLocale) => `${toSingleQuotedJsString(initialLocale)}: ${toLocaleBindingName(initialLocale)}`)\n .join(', ')\n const loaderCases = locales\n .map((candidateLocale) => {\n const modulePath = toSingleQuotedJsString(`${compiledRelative}/${candidateLocale}`)\n if (initialLocales.includes(candidateLocale)) {\n return ` case ${toSingleQuotedJsString(candidateLocale)}: return ${toLocaleBindingName(candidateLocale)}`\n }\n return ` case ${toSingleQuotedJsString(candidateLocale)}: return import(${modulePath})`\n })\n .join('\\n')\n\n const clientLocaleProviderSource = `\"use client\";\n// Auto-generated by @fluenti/next — do not edit\n// @ts-nocheck\nimport { createElement } from 'react'\nimport { ClientI18nProvider as __FluentiClientI18nProvider } from './client-provider.js'\n${staticImports}\n\nconst __messages = { ${initialMessageEntries} }\n\nasync function __loadMessages(locale) {\n switch (locale) {\n${loaderCases}\n default: return import(${toSingleQuotedJsString(`${compiledRelative}/${defaultLocale}`)})\n }\n}\n\nexport function ClientI18nProvider({ locale, fallbackLocale, fallbackChain, children }) {\n return createElement(__FluentiClientI18nProvider, { locale, fallbackLocale, messages: __messages, loadMessages: __loadMessages, fallbackChain }, children)\n}\n`\n\n writeSafe(clientLocaleProviderPath, clientLocaleProviderSource)\n }\n\n const resolveLocaleImport = config.resolveLocale\n ? (() => {\n const absPath = resolve(projectRoot, config.resolveLocale)\n const relPath = toForwardSlash(relative(outDir, absPath))\n return `import __resolveLocale from ${toSingleQuotedJsString(relPath)}`\n })()\n : null\n\n const resolveLocaleFn = config.resolveLocale\n ? `resolveLocale: __resolveLocale,`\n : `resolveLocale: async () => {\n try {\n const { cookies, headers } = await import('next/headers')\n const [cookieStore, headerStore] = await Promise.all([cookies(), headers()])\n\n // 0. x-fluenti-locale header (set by createI18nMiddleware — most authoritative)\n const fromMiddleware = headerStore.get('x-fluenti-locale')\n if (fromMiddleware && __locales.includes(fromMiddleware)) return fromMiddleware\n\n // 1. Cookie (configurable name)\n const fromCookie = cookieStore.get(${cookieNameLiteral})?.value\n if (fromCookie && __locales.includes(fromCookie)) return fromCookie\n\n // 2. Accept-Language header\n const acceptLang = headerStore.get('accept-language')\n if (acceptLang) {\n for (const part of acceptLang.split(',')) {\n const lang = part.split(';')[0].trim()\n if (__locales.includes(lang)) return lang\n const prefix = lang.split('-')[0]\n const match = __locales.find(l => l === prefix || l.startsWith(prefix + '-'))\n if (match) return match\n }\n }\n\n return ${defaultLocaleLiteral}\n } catch {\n return ${defaultLocaleLiteral}\n }\n },`\n\n const localesArrayStr = JSON.stringify(locales)\n\n const moduleSource = `// Auto-generated by @fluenti/next — do not edit\n// @ts-nocheck\nimport { createServerI18n } from '@fluenti/react/server'\nimport { createElement } from 'react'\n${runtimeInterpolateImport}${resolveLocaleImport ? `${resolveLocaleImport}\\n` : ''}\nconst __locales = ${localesArrayStr}\n\nconst serverI18n = createServerI18n({\n${runtimeInterpolateServerOption} loadMessages: async (locale) => {\n switch (locale) {\n${localeImports}\n default: return import(${toSingleQuotedJsString(`${compiledRelative}/${defaultLocale}`)})\n }\n },\n fallbackLocale: ${defaultLocaleLiteral},\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' is a compile-time API replaced at build time.\\\\n\" +\n ' Ensure:\\\\n' +\n ' 1. \\`withFluenti()\\` is configured in next.config.ts\\\\n' +\n ' 2. The file is inside src/ (not node_modules)\\\\n' +\n \" 3. For client components, import from '@fluenti/react'\",\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 I18nProvider({ locale, children }) {\n const activeLocale = (locale && locale.trim()) ? locale : ${defaultLocaleLiteral}\n\n // 1. Initialize server-side i18n (React.cache scoped)\n serverI18n.setLocale(activeLocale)\n await serverI18n.getI18n()\n\n // 2. Import the locale-specific client provider chunk. It eagerly bundles the\n // active locale plus only the fallback locales relevant to that locale.\n const { ClientI18nProvider } = await (async () => {\n switch (activeLocale) {\n${locales\n .map((locale) => ` case ${toSingleQuotedJsString(locale)}: return import(${toSingleQuotedJsString(`./${getClientProviderModuleName(locale)}`)})`)\n .join('\\n')}\n default: return import(${toSingleQuotedJsString(`./${getClientProviderModuleName(defaultLocale)}`)})\n }\n })()\n\n return createElement(ClientI18nProvider, {\n locale: activeLocale,\n fallbackLocale: ${defaultLocaleLiteral},\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, FluentiCoreInstanceFull } from '@fluenti/core'\n\nexport declare function setLocale(locale: string): void\nexport declare function getI18n(): Promise<FluentiCoreInstanceFull & { 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 format?: string\n}): Promise<ReactElement>\n\nexport declare function NumberFormat(props: {\n value: number\n format?: string\n}): Promise<ReactElement>\n\nexport declare function I18nProvider(props: {\n locale?: string\n children: ReactNode\n}): Promise<ReactElement>\n`\n\n writeSafe(outPath, moduleSource)\n writeSafe(dtsPath, dtsSource)\n\n // Generate Edge-safe i18n config for use in middleware\n const configModulePath = resolve(outDir, 'i18n-config.js')\n const configModuleDtsPath = resolve(outDir, 'i18n-config.d.ts')\n\n const configModuleSource = `// Auto-generated by @fluenti/next — do not edit\nexport const locales = ${localesArrayStr}\nexport const sourceLocale = ${defaultLocaleLiteral}\nexport const cookieName = ${cookieNameLiteral}\n`\n writeSafe(configModulePath, configModuleSource)\n\n const configModuleDtsSource = `// Auto-generated by @fluenti/next — do not edit\nexport declare const locales: string[]\nexport declare const sourceLocale: string\nexport declare const cookieName: string\n`\n writeSafe(configModuleDtsPath, configModuleDtsSource)\n\n return outPath\n}\n\n/** Quote a string for safe embedding inside generated single-quoted JS source. */\nfunction toSingleQuotedJsString(s: string): string {\n return `'${s\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/'/g, \"\\\\'\")\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\0/g, '\\\\0')}'`\n}\n\nfunction toForwardSlash(p: string): string {\n return p.split('\\\\').join('/')\n}\n\nfunction getClientProviderModuleName(locale: string): string {\n return `client-provider-${locale.replace(/[^a-zA-Z0-9]/g, '_')}.js`\n}\n\nfunction toLocaleBindingName(locale: string): string {\n return `__messages_${locale.replace(/[^a-zA-Z0-9]/g, '_')}`\n}\n\nfunction collectInitialClientLocales(\n locale: string,\n defaultLocale: string,\n fallbackChain: Record<string, readonly string[]> | undefined,\n locales: readonly string[],\n): string[] {\n const result = new Set<string>([locale, defaultLocale])\n const localeFallbacks = fallbackChain?.[locale] ?? []\n for (const fallbackLocale of localeFallbacks) {\n if (locales.includes(fallbackLocale)) {\n result.add(fallbackLocale)\n }\n }\n return Array.from(result)\n}\n","import { join } from 'node:path'\nimport { createRequire } from 'node:module'\n\nexport interface DevRunnerOptions {\n cwd: string\n onSuccess?: () => void\n onError?: (err: Error) => void\n /** If true, reject the promise on failure instead of swallowing the error */\n throwOnError?: boolean\n /** Run only compile (skip extract). Useful for production builds where source is unchanged. */\n compileOnly?: boolean\n /** Enable parallel compilation across locales using worker threads */\n parallelCompile?: boolean\n}\n\n/**\n * Run compile in-process via `@fluenti/cli` (for compileOnly mode),\n * or extract + compile in dev mode. Requires `@fluenti/cli` to be installed\n * as a devDependency.\n */\nexport async function runExtractCompile(options: DevRunnerOptions): Promise<void> {\n if (options.compileOnly) {\n try {\n // Resolve @fluenti/cli from the project's cwd (not from this package's location)\n // using createRequire so pnpm's strict node_modules layout works correctly.\n // Use require() (not import()) to load @fluenti/cli — avoids CJS/ESM interop\n // issues when dynamic import() loads minified CJS with chunk requires.\n const projectRequire = createRequire(join(options.cwd, 'package.json'))\n const { runCompile } = projectRequire('@fluenti/cli')\n await runCompile(options.cwd)\n console.log('[fluenti] Compiling... done')\n options.onSuccess?.()\n return\n } catch (e) {\n const error = e instanceof Error ? e : new Error(String(e))\n if (options.throwOnError) throw error\n console.warn('[fluenti] Compile failed:', error.message)\n options.onError?.(error)\n return\n }\n }\n\n // Dev mode: run in-process extract + compile.\n // Step 1: load @fluenti/cli — if not installed, guide user to install it.\n // Step 2: run — errors here mean the CLI ran but failed; surface them.\n let fluentCli: { runExtract: (cwd: string) => Promise<void>; runCompile: (cwd: string, opts?: { parallel: boolean }) => Promise<void> } | null = null\n try {\n const projectRequire = createRequire(join(options.cwd, 'package.json'))\n fluentCli = projectRequire('@fluenti/cli')\n } catch {\n // @fluenti/cli not installed — will show install guide below\n }\n\n if (fluentCli) {\n try {\n await fluentCli.runExtract(options.cwd)\n if (options.parallelCompile) {\n await fluentCli.runCompile(options.cwd, { parallel: true })\n } else {\n await fluentCli.runCompile(options.cwd)\n }\n console.log('[fluenti] Extracting and compiling... done')\n options.onSuccess?.()\n return\n } catch (e) {\n const error = e instanceof Error ? e : new Error(String(e))\n if (options.throwOnError) throw error\n console.warn('[fluenti] Extract/compile failed:', error.message)\n options.onError?.(error)\n return\n }\n }\n\n const msg =\n '[fluenti] @fluenti/cli is required for auto-compile.\\n' +\n ' Install it as a devDependency:\\n' +\n ' pnpm add -D @fluenti/cli\\n' +\n ' See: https://fluenti.dev/start/introduction/'\n if (options.throwOnError) {\n throw new Error(msg)\n }\n console.warn(msg)\n options.onError?.(new Error(msg))\n}\n\n/**\n * Create a debounced runner that collapses rapid calls.\n *\n * - If called while idle, schedules a run after `delay` ms.\n * - If called while a run is in progress, marks a pending rerun.\n * - Never runs concurrently.\n */\nexport function createDebouncedRunner(\n options: DevRunnerOptions,\n delay = 300,\n): () => void {\n let timer: ReturnType<typeof setTimeout> | null = null\n let running = false\n let pendingRerun = false\n\n async function execute(): Promise<void> {\n running = true\n try {\n await runExtractCompile(options)\n } finally {\n running = false\n if (pendingRerun) {\n pendingRerun = false\n schedule()\n }\n }\n }\n\n function schedule(): void {\n if (timer !== null) {\n clearTimeout(timer)\n }\n timer = setTimeout(() => {\n timer = null\n if (running) {\n pendingRerun = true\n } else {\n execute()\n }\n }, delay)\n }\n\n return schedule\n}\n","import { watch } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { createRequire } from 'node:module'\nimport { createDebouncedRunner } from './dev-runner'\n\nexport interface DevWatcherOptions {\n cwd: string\n compiledDir: string\n delay?: number\n /** Glob patterns from fluenti.config.ts `include` field */\n include?: string[]\n /** Glob patterns from fluenti.config.ts `exclude` field */\n exclude?: string[]\n /** Enable parallel compilation across locales using worker threads */\n parallelCompile?: boolean\n}\n\nlet activeWatcher: (() => void) | null = null\n\n/**\n * Extract watch directories from include glob patterns.\n *\n * Takes the static prefix before the first glob wildcard (`*`).\n * Falls back to `src` if no include patterns are provided.\n *\n * @example\n * extractWatchDirs('/proj', ['./src/**\\/*.tsx']) → ['/proj/src']\n * extractWatchDirs('/proj', ['./app/**\\/*.ts', './lib/**\\/*.ts']) → ['/proj/app', '/proj/lib']\n * extractWatchDirs('/proj', ['./**\\/*.ts']) → ['/proj']\n */\nexport function extractWatchDirs(cwd: string, include?: string[]): string[] {\n if (!include || include.length === 0) {\n return [resolve(cwd, 'src')]\n }\n\n const dirs = new Set<string>()\n for (const pattern of include) {\n const normalized = pattern.replace(/^\\.\\//, '')\n const staticPart = normalized.split('*')[0]!.replace(/\\/+$/, '')\n dirs.add(staticPart || '.')\n }\n return [...dirs].map(d => resolve(cwd, d))\n}\n\n/**\n * Start a standalone file watcher for dev auto-compile.\n *\n * Works independently of webpack/Turbopack — watches source directories\n * (inferred from `include` patterns) for changes and triggers\n * extract+compile via the debounced runner.\n *\n * Only one watcher is active at a time (guards against multiple `applyFluenti()` calls).\n *\n * @returns A cleanup function that stops the watcher.\n */\nexport function startDevWatcher(options: DevWatcherOptions): () => void {\n // Clean up previous watcher if one exists (e.g., dev server reload)\n if (activeWatcher) {\n activeWatcher()\n }\n\n const { cwd, compiledDir, delay = 1000, include, exclude, parallelCompile } = options\n const compiledDirResolved = resolve(cwd, compiledDir)\n const _require = createRequire(\n typeof __filename !== 'undefined' ? __filename : import.meta.url,\n )\n const picomatch = _require('picomatch') as (patterns: string[]) => (str: string) => boolean\n const isExcluded = exclude?.length ? picomatch(exclude) : () => false\n const runnerOpts: Parameters<typeof createDebouncedRunner>[0] = { cwd }\n if (parallelCompile) runnerOpts.parallelCompile = true\n const debouncedRun = createDebouncedRunner(runnerOpts, delay)\n\n // Initial run\n debouncedRun()\n\n const watchDirs = extractWatchDirs(cwd, include)\n const watchers = watchDirs.map(dir =>\n watch(dir, { recursive: true }, (_event, filename) => {\n if (!filename) return\n if (!/\\.[jt]sx?$/.test(filename)) return\n if (filename.includes('node_modules') || filename.includes('.next')) return\n const full = resolve(dir, filename)\n if (full.startsWith(compiledDirResolved)) return\n if (isExcluded(filename)) return\n debouncedRun()\n }),\n )\n\n const cleanup = (): void => {\n for (const w of watchers) w.close()\n activeWatcher = null\n }\n\n activeWatcher = cleanup\n return cleanup\n}\n","import { existsSync, mkdirSync } from 'node:fs'\nimport { execSync } from 'node:child_process'\nimport { createRequire } from 'node:module'\nimport { resolve, dirname, relative } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport type { WithFluentConfig } from './types'\nimport { resolveConfig } from './read-config'\nimport { generateServerModule } from './generate-server-module'\nimport { startDevWatcher } from './dev-watcher'\n\n// Use Record<string, any> to accept both Next 15's and 16's NextConfig types\n// (Next 16 removed the index signature from NextConfig)\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype NextConfig = Record<string, any>\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 Minimal — no fluenti.config.ts needed\n * ```ts\n * import { withFluenti } from '@fluenti/next'\n * export default withFluenti({ locales: ['en', 'ja'] })({ reactStrictMode: true })\n * ```\n *\n * @example With fluenti.config.ts (advanced)\n * ```ts\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 && !isFluentConfig(configOrNext as Record<string, unknown>)) {\n // Has keys but none are fluent-specific → treat 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 isFluentConfig(obj: Record<string, unknown>): boolean {\n const fluentOnlyKeys = [\n 'config', 'locales', 'serverModule', 'serverModuleOutDir', 'resolveLocale',\n 'cookieName', 'runtimeInterpolate', 'loaderEnforce',\n ]\n return fluentOnlyKeys.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 const fluentiConfig = resolved.fluentiConfig\n const compiledDir = fluentiConfig.compileOutDir\n\n // Auto-create compiled catalogs directory if missing\n const compiledDirAbs = resolve(projectRoot, compiledDir)\n if (!existsSync(compiledDirAbs)) {\n mkdirSync(compiledDirAbs, { recursive: true })\n }\n\n // Auto-detect app/[locale]/ directory structure\n // If detected and rewriteDefaultLocale not explicitly set, enable it automatically\n const appLocaleDir = resolve(projectRoot, 'app', '[locale]')\n const srcAppLocaleDir = resolve(projectRoot, 'src', 'app', '[locale]')\n if (existsSync(appLocaleDir) || existsSync(srcAppLocaleDir)) {\n if (!('rewriteDefaultLocale' in (fluentConfig as Record<string, unknown>))) {\n // Auto-enable rewriteDefaultLocale when app/[locale]/ is detected\n (resolved as { _autoRewriteDefaultLocale?: boolean })._autoRewriteDefaultLocale = true\n }\n }\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(fileURLToPath(import.meta.url))\n const loaderPath = resolve(thisDir, 'loader.js')\n\n const existingWebpack = nextConfig['webpack'] as\n | ((config: WebpackConfig, options: WebpackOptions) => WebpackConfig)\n | undefined\n\n let buildCompileRan = false\n\n // ── Turbopack config ──────────────────────────────────────────────\n // Turbopack loader-runner supports webpack loaders via turbopack.rules.\n // Use package name (not file path) — Turbopack resolves loaders as packages,\n // file paths trigger static analysis errors (TP1006) in the loader-runner.\n const fluentTurboRules = Object.fromEntries(\n ['*.ts', '*.tsx', '*.js', '*.jsx'].map((ext) => [\n ext,\n {\n condition: { not: 'foreign' },\n loaders: ['@fluenti/next/loader'],\n },\n ]),\n )\n\n // Turbopack resolveAlias requires relative paths (absolute paths get\n // misinterpreted as \"./abs/path\"). Use \"./\" + relative-from-cwd.\n const configModulePath = resolve(dirname(serverModulePath), 'i18n-config.js')\n const relativeServerModule = './' + relative(projectRoot, serverModulePath).split('\\\\').join('/')\n const relativeConfigModule = './' + relative(projectRoot, configModulePath).split('\\\\').join('/')\n const fluentTurboAlias: Record<string, string> = {\n '@fluenti/next': relativeServerModule,\n '@fluenti/next/i18n-config': relativeConfigModule,\n }\n\n // ── Build auto-compile (bundler-agnostic — runs at config time) ──\n const isDev = process.env['NODE_ENV'] === 'development'\n || process.argv.some(a => a === 'dev')\n const buildAutoCompile = fluentiConfig.buildAutoCompile ?? true\n\n if (!isDev && buildAutoCompile && !buildCompileRan) {\n buildCompileRan = true\n try {\n // Resolve the CLI entry via Node module resolution so it works\n // in all package managers (pnpm, npm, yarn) without npx fallback\n const req = createRequire(resolve(projectRoot, 'noop.js'))\n const cliBin = resolve(dirname(req.resolve('@fluenti/cli')), 'cli.js')\n execSync(\n `node \"${cliBin}\" compile` + (fluentiConfig.parallelCompile ? ' --parallel' : ''),\n { cwd: projectRoot, stdio: 'inherit' },\n )\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error)\n throw new Error(\n `[fluenti] Production auto-compile failed. ` +\n `Run \"fluenti compile\" successfully before continuing the Next.js build.\\n` +\n ` ${detail}`,\n )\n }\n }\n\n // ── Dev auto-compile via standalone watcher (works with both webpack & Turbopack) ──\n const devAutoCompile = fluentiConfig.devAutoCompile ?? true\n\n if (isDev && devAutoCompile) {\n const watcherOpts: Parameters<typeof startDevWatcher>[0] = {\n cwd: projectRoot,\n compiledDir,\n delay: fluentiConfig.devAutoCompileDelay ?? 1000,\n }\n if (fluentiConfig.parallelCompile) watcherOpts.parallelCompile = true\n if (fluentiConfig.include) watcherOpts.include = fluentiConfig.include\n if (fluentiConfig.exclude) watcherOpts.exclude = fluentiConfig.exclude\n startDevWatcher(watcherOpts)\n }\n\n // Detect Next.js version to use correct Turbopack config key\n // Next 15+: top-level `turbopack` key\n // Next 14: `experimental.turbo` key\n let nextMajor = 15\n try {\n const nextPkg = require('next/package.json') as { version?: string }\n if (nextPkg.version) nextMajor = parseInt(nextPkg.version.split('.')[0]!, 10) || 15\n } catch { /* next not resolvable at config time */ }\n\n const turboConfig = mergeTurbopackConfig(\n (nextMajor >= 15\n ? nextConfig['turbopack']\n : (nextConfig['experimental'] as Record<string, unknown> | undefined)?.['turbo']\n ) as Record<string, unknown> | undefined,\n { rules: fluentTurboRules, resolveAlias: fluentTurboAlias },\n )\n\n const turboKey = nextMajor >= 15\n ? { turbopack: turboConfig }\n : { experimental: { ...(nextConfig['experimental'] as Record<string, unknown> ?? {}), turbo: turboConfig } }\n\n return {\n ...nextConfig,\n ...turboKey,\n webpack(config: WebpackConfig, options: WebpackOptions) {\n // Add fluenti loader\n const loaderEnforce = fluentConfig.loaderEnforce === undefined && !('loaderEnforce' in (fluentConfig as Record<string, unknown>))\n ? 'pre' as const\n : fluentConfig.loaderEnforce\n config.module.rules.push({\n test: /\\.[jt]sx?$/,\n ...(loaderEnforce ? { enforce: loaderEnforce } : {}),\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$'] = serverModulePath\n config.resolve.alias['@fluenti/next/i18n-config$'] = configModulePath\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\nfunction mergeTurbopackConfig(\n existing: Record<string, unknown> | undefined,\n fluenti: { rules: Record<string, unknown>; resolveAlias: Record<string, string> },\n): Record<string, unknown> {\n const base = existing ?? {}\n const userRules = (base['rules'] as Record<string, unknown>) ?? {}\n\n // Warn when user rules override fluenti's source-file rules\n const fluentKeys = Object.keys(fluenti.rules)\n const overlapping = fluentKeys.filter(k => k in userRules)\n if (overlapping.length > 0) {\n console.warn(\n `[fluenti] Your turbopack.rules override Fluenti's loader for: ${overlapping.join(', ')}.\\n` +\n ` Fluenti's t\\`\\` transform will NOT run on these file types.\\n` +\n ` If this is intentional, you can suppress this warning with { devAutoCompile: false }.`,\n )\n }\n\n return {\n ...base,\n rules: { ...fluenti.rules, ...userRules },\n resolveAlias: { ...fluenti.resolveAlias, ...(base['resolveAlias'] as Record<string, string>) },\n }\n}\n\n// Minimal webpack types for the config function\ninterface WebpackConfig {\n module: {\n rules: Array<Record<string, unknown>>\n }\n resolve: {\n alias?: Record<string, string>\n }\n}\n\ninterface WebpackOptions {\n isServer: boolean\n dev: boolean\n}\n","/**\n * @fluenti/next — Next.js plugin for Fluenti\n *\n * Provides:\n * - `withFluenti()` — wraps next.config.ts with t`` transform support\n * - I18nProvider — async server component (exported from generated module)\n * - Webpack loader for strict, binding-aware tagged-template optimization\n *\n * @example\n * ```ts\n * // next.config.ts\n * import { withFluenti } from '@fluenti/next'\n * export default withFluenti()({ reactStrictMode: true })\n * ```\n *\n * @example\n * ```tsx\n * // app/layout.tsx — resolved by webpack alias to the generated module\n * import { I18nProvider } from '@fluenti/next'\n * ```\n */\nexport { withFluenti } from './with-fluenti'\nexport type { WithFluentConfig, I18nProviderProps } from './types'\nexport { defineRouting } from './routing'\nexport type { RoutingConfig } from './routing'\nexport { msg } from '@fluenti/react'\n\n// ── Runtime stubs ────────────────────────────────────────────────────\n// TypeScript resolves types from this file (via package.json exports).\n// At runtime, webpack `resolve.alias` redirects `@fluenti/next$` to the\n// generated server module, so these stubs are never actually called in\n// a correctly configured project. They exist only to provide helpful\n// errors if `withFluenti()` is not configured.\n\nimport type { ReactNode, ReactElement } from 'react'\nimport type { CompileTimeT, FluentiCoreInstanceFull } from '@fluenti/core'\nimport type { I18nProviderProps } from './types'\n\ninterface NextTransProps {\n children: ReactNode\n id?: string\n context?: string\n comment?: string\n render?: (translation: ReactNode) => ReactNode\n}\n\ninterface NextPluralProps {\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}\n\ninterface NextSelectProps {\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}\n\ninterface NextDateTimeProps {\n value: Date | number\n style?: string\n}\n\ninterface NextNumberFormatProps {\n value: number\n style?: string\n}\n\nconst NOT_CONFIGURED = [\n '[fluenti] `@fluenti/next` was imported before `withFluenti()` generated the server module.',\n 'Fix this by:',\n \" 1. Wrapping next.config.ts with `withFluenti()` from '@fluenti/next'\",\n ' 2. Restarting the Next dev server after the generated module is written',\n \" 3. Importing client runtime APIs from '@fluenti/react' and server APIs from '@fluenti/next'\",\n].join('\\n')\n\nfunction throwNotConfigured(): never {\n throw new Error(NOT_CONFIGURED)\n}\n\n/** @see Generated module for the real implementation. */\nexport const setLocale: (locale: string) => void = throwNotConfigured\n/** @see Generated module for the real implementation. */\nexport const getI18n: () => Promise<FluentiCoreInstanceFull & { locale: string }> = throwNotConfigured as () => Promise<FluentiCoreInstanceFull & { locale: string }>\n/** @see Generated module for the real implementation. */\nexport const t: CompileTimeT = throwNotConfigured as unknown as CompileTimeT\n/** @see Generated module for the real implementation. */\nexport async function Trans(_props: NextTransProps): Promise<ReactElement> {\n return throwNotConfigured()\n}\n/** @see Generated module for the real implementation. */\nexport async function Plural(_props: NextPluralProps): Promise<ReactElement> {\n return throwNotConfigured()\n}\n/** @see Generated module for the real implementation. */\nexport async function Select(_props: NextSelectProps): Promise<ReactElement> {\n return throwNotConfigured()\n}\n/** @see Generated module for the real implementation. */\nexport async function DateTime(_props: NextDateTimeProps): Promise<ReactElement> {\n return throwNotConfigured()\n}\n/** @see Generated module for the real implementation. */\nexport async function NumberFormat(_props: NextNumberFormatProps): Promise<ReactElement> {\n return throwNotConfigured()\n}\n/** @see Generated module for the real implementation. */\nexport async function I18nProvider(_props: I18nProviderProps): Promise<ReactElement> {\n return throwNotConfigured()\n}\n"],"mappings":"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"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/read-config.ts","../src/generate-server-module.ts","../src/dev-runner.ts","../src/dev-watcher.ts","../src/with-fluenti.ts","../src/index.ts"],"sourcesContent":["import { loadConfigSync, DEFAULT_FLUENTI_CONFIG } from '@fluenti/core/config'\nimport type { FluentiBuildConfig } from '@fluenti/core/compiler'\nimport type { WithFluentConfig, ResolvedFluentConfig } from './types'\n\n/**\n * Read fluenti.config.ts and merge with withFluenti() overrides.\n *\n * Delegates config file loading to `@fluenti/core`'s shared `loadConfigSync()`.\n */\nexport function resolveConfig(\n projectRoot: string,\n overrides?: WithFluentConfig,\n): ResolvedFluentConfig {\n let fluentiConfig: FluentiBuildConfig\n\n if (overrides?.config && typeof overrides.config === 'object') {\n // Inline config — merge with defaults\n fluentiConfig = { ...DEFAULT_FLUENTI_CONFIG, ...overrides.config }\n } else if (!overrides?.config && overrides?.locales) {\n // Locales shorthand — build inline config with just locales\n fluentiConfig = { ...DEFAULT_FLUENTI_CONFIG, locales: overrides.locales }\n } else {\n // string path or auto-discover\n fluentiConfig = loadConfigSync(\n typeof overrides?.config === 'string' ? overrides.config : undefined,\n projectRoot,\n )\n }\n\n const serverModuleOutDir = overrides?.serverModuleOutDir ?? '.fluenti'\n const cookieName = overrides?.cookieName ?? 'locale'\n const runtimeInterpolate = overrides?.runtimeInterpolate ?? true\n\n const resolved: ResolvedFluentConfig = {\n fluentiConfig,\n serverModule: overrides?.serverModule ?? null,\n serverModuleOutDir,\n cookieName,\n runtimeInterpolate,\n }\n if (overrides?.resolveLocale) resolved.resolveLocale = overrides.resolveLocale\n return resolved\n}\n","import { writeFileSync, mkdirSync, existsSync } from 'node:fs'\nimport { resolve, relative } from 'node:path'\nimport { validateLocale } from '@fluenti/core'\nimport { resolveLocaleCodes } from '@fluenti/core/compiler'\nimport type { ResolvedFluentConfig } from './types'\n\n/** Wrapper around writeFileSync with a Fluenti-specific error message. */\nfunction writeSafe(path: string, content: string): void {\n try {\n writeFileSync(path, content, 'utf-8')\n } catch (err) {\n throw new Error(\n `[fluenti] Failed to write generated module at ${path}: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n}\n\n/**\n * Generate the server module that provides:\n * - setLocale / getI18n\n * - Trans / Plural / Select / DateTime / NumberFormat (server components)\n * - I18nProvider (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 locales = resolveLocaleCodes(config.fluentiConfig.locales)\n const defaultLocale = config.fluentiConfig.defaultLocale ?? config.fluentiConfig.sourceLocale\n const compiledDir = config.fluentiConfig.compileOutDir\n const fallbackChain = config.fluentiConfig.fallbackChain\n const dateFormats = config.fluentiConfig.dateFormats\n const numberFormats = config.fluentiConfig.numberFormats\n const cookieNameLiteral = toSingleQuotedJsString(config.cookieName)\n const defaultLocaleLiteral = toSingleQuotedJsString(defaultLocale)\n\n for (const locale of locales) {\n validateLocale(locale, 'next-plugin')\n }\n\n const compiledDirAbs = resolve(projectRoot, compiledDir)\n const compiledRelative = toForwardSlash(relative(outDir, compiledDirAbs))\n\n const localeImports = locales\n .map((locale) => ` case ${toSingleQuotedJsString(locale)}: return import(${toSingleQuotedJsString(`${compiledRelative}/${locale}`)})`)\n .join('\\n')\n\n const fallbackChainStr = fallbackChain\n ? JSON.stringify(fallbackChain)\n : 'undefined'\n\n const clientProviderPath = resolve(outDir, 'client-provider.js')\n const dateFormatsStr = dateFormats !== undefined ? JSON.stringify(dateFormats) : 'undefined'\n const numberFormatsStr = numberFormats !== undefined ? JSON.stringify(numberFormats) : 'undefined'\n const runtimeInterpolateImport = config.runtimeInterpolate\n ? \"import { interpolate as __interpolate } from '@fluenti/core/runtime'\\n\"\n : ''\n const runtimeInterpolateProp = config.runtimeInterpolate ? ', interpolate: __interpolate' : ''\n const runtimeInterpolateServerOption = config.runtimeInterpolate ? ' interpolate: __interpolate,\\n' : ''\n const clientProviderSource = `\"use client\";\n// Auto-generated by @fluenti/next — do not edit\n// @ts-nocheck\nimport { createElement } from 'react'\nimport { I18nProvider } from '@fluenti/react'\n${runtimeInterpolateImport}\nconst __dateFormats = ${dateFormatsStr}\nconst __numberFormats = ${numberFormatsStr}\n\nexport function ClientI18nProvider({ locale, fallbackLocale, messages, loadMessages, fallbackChain, children }) {\n return createElement(I18nProvider, { locale, fallbackLocale, messages, loadMessages, fallbackChain, dateFormats: __dateFormats, numberFormats: __numberFormats${runtimeInterpolateProp} }, children)\n}\n`\n writeSafe(clientProviderPath, clientProviderSource)\n\n const clientProviderDtsPath = resolve(outDir, 'client-provider.d.ts')\n const clientProviderDtsSource = `// Auto-generated by @fluenti/next — do not edit\nimport type { ReactNode, ReactElement } from 'react'\nimport type { AllMessages, Messages } from '@fluenti/core'\n\nexport declare function ClientI18nProvider(props: {\n locale: string\n fallbackLocale: string\n messages: AllMessages\n loadMessages: (locale: string) => Promise<Messages | { default: Messages }>\n fallbackChain?: Record<string, string[]>\n children: ReactNode\n}): ReactElement\n`\n writeSafe(clientProviderDtsPath, clientProviderDtsSource)\n\n for (const locale of locales) {\n const clientLocaleProviderPath = resolve(outDir, getClientProviderModuleName(locale))\n const initialLocales = collectInitialClientLocales(locale, defaultLocale, fallbackChain, locales)\n const staticImports = initialLocales\n .map((initialLocale) => `import ${toLocaleBindingName(initialLocale)} from ${toSingleQuotedJsString(`${compiledRelative}/${initialLocale}`)}`)\n .join('\\n')\n const initialMessageEntries = initialLocales\n .map((initialLocale) => `${toSingleQuotedJsString(initialLocale)}: ${toLocaleBindingName(initialLocale)}`)\n .join(', ')\n const loaderCases = locales\n .map((candidateLocale) => {\n const modulePath = toSingleQuotedJsString(`${compiledRelative}/${candidateLocale}`)\n if (initialLocales.includes(candidateLocale)) {\n return ` case ${toSingleQuotedJsString(candidateLocale)}: return ${toLocaleBindingName(candidateLocale)}`\n }\n return ` case ${toSingleQuotedJsString(candidateLocale)}: return import(${modulePath})`\n })\n .join('\\n')\n\n const clientLocaleProviderSource = `\"use client\";\n// Auto-generated by @fluenti/next — do not edit\n// @ts-nocheck\nimport { createElement } from 'react'\nimport { ClientI18nProvider as __FluentiClientI18nProvider } from './client-provider.js'\n${staticImports}\n\nconst __messages = { ${initialMessageEntries} }\n\nasync function __loadMessages(locale) {\n switch (locale) {\n${loaderCases}\n default: return import(${toSingleQuotedJsString(`${compiledRelative}/${defaultLocale}`)})\n }\n}\n\nexport function ClientI18nProvider({ locale, fallbackLocale, fallbackChain, children }) {\n return createElement(__FluentiClientI18nProvider, { locale, fallbackLocale, messages: __messages, loadMessages: __loadMessages, fallbackChain }, children)\n}\n`\n\n writeSafe(clientLocaleProviderPath, clientLocaleProviderSource)\n }\n\n const resolveLocaleImport = config.resolveLocale\n ? (() => {\n const absPath = resolve(projectRoot, config.resolveLocale)\n const relPath = toForwardSlash(relative(outDir, absPath))\n return `import __resolveLocale from ${toSingleQuotedJsString(relPath)}`\n })()\n : null\n\n const resolveLocaleFn = config.resolveLocale\n ? `resolveLocale: __resolveLocale,`\n : `resolveLocale: async () => {\n try {\n const { cookies, headers } = await import('next/headers')\n const [cookieStore, headerStore] = await Promise.all([cookies(), headers()])\n\n // 0. x-fluenti-locale header (set by createI18nMiddleware — most authoritative)\n const fromMiddleware = headerStore.get('x-fluenti-locale')\n if (fromMiddleware && __locales.includes(fromMiddleware)) return fromMiddleware\n\n // 1. Cookie (configurable name)\n const fromCookie = cookieStore.get(${cookieNameLiteral})?.value\n if (fromCookie && __locales.includes(fromCookie)) return fromCookie\n\n // 2. Accept-Language header\n const acceptLang = headerStore.get('accept-language')\n if (acceptLang) {\n for (const part of acceptLang.split(',')) {\n const lang = part.split(';')[0].trim()\n if (__locales.includes(lang)) return lang\n const prefix = lang.split('-')[0]\n const match = __locales.find(l => l === prefix || l.startsWith(prefix + '-'))\n if (match) return match\n }\n }\n\n return ${defaultLocaleLiteral}\n } catch {\n return ${defaultLocaleLiteral}\n }\n },`\n\n const localesArrayStr = JSON.stringify(locales)\n\n const moduleSource = `// Auto-generated by @fluenti/next — do not edit\n// @ts-nocheck\nimport { createServerI18n } from '@fluenti/react/server'\nimport { createElement } from 'react'\n${runtimeInterpolateImport}${resolveLocaleImport ? `${resolveLocaleImport}\\n` : ''}\nconst __locales = ${localesArrayStr}\n\nconst serverI18n = createServerI18n({\n${runtimeInterpolateServerOption} loadMessages: async (locale) => {\n switch (locale) {\n${localeImports}\n default: return import(${toSingleQuotedJsString(`${compiledRelative}/${defaultLocale}`)})\n }\n },\n fallbackLocale: ${defaultLocaleLiteral},\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' is a compile-time API replaced at build time.\\\\n\" +\n ' Ensure:\\\\n' +\n ' 1. \\`withFluenti()\\` is configured in next.config.ts\\\\n' +\n ' 2. The file is inside src/ (not node_modules)\\\\n' +\n \" 3. For client components, import from '@fluenti/react'\",\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 I18nProvider({ locale, children }) {\n const activeLocale = (locale && locale.trim()) ? locale : ${defaultLocaleLiteral}\n\n // 1. Initialize server-side i18n (React.cache scoped)\n serverI18n.setLocale(activeLocale)\n await serverI18n.getI18n()\n\n // 2. Import the locale-specific client provider chunk. It eagerly bundles the\n // active locale plus only the fallback locales relevant to that locale.\n const { ClientI18nProvider } = await (async () => {\n switch (activeLocale) {\n${locales\n .map((locale) => ` case ${toSingleQuotedJsString(locale)}: return import(${toSingleQuotedJsString(`./${getClientProviderModuleName(locale)}`)})`)\n .join('\\n')}\n default: return import(${toSingleQuotedJsString(`./${getClientProviderModuleName(defaultLocale)}`)})\n }\n })()\n\n return createElement(ClientI18nProvider, {\n locale: activeLocale,\n fallbackLocale: ${defaultLocaleLiteral},\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, FluentiCoreInstanceFull } from '@fluenti/core'\n\nexport declare function setLocale(locale: string): void\nexport declare function getI18n(): Promise<FluentiCoreInstanceFull & { 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 format?: string\n}): Promise<ReactElement>\n\nexport declare function NumberFormat(props: {\n value: number\n format?: string\n}): Promise<ReactElement>\n\nexport declare function I18nProvider(props: {\n locale?: string\n children: ReactNode\n}): Promise<ReactElement>\n`\n\n writeSafe(outPath, moduleSource)\n writeSafe(dtsPath, dtsSource)\n\n // Generate Edge-safe i18n config for use in middleware\n const configModulePath = resolve(outDir, 'i18n-config.js')\n const configModuleDtsPath = resolve(outDir, 'i18n-config.d.ts')\n\n const configModuleSource = `// Auto-generated by @fluenti/next — do not edit\nexport const locales = ${localesArrayStr}\nexport const sourceLocale = ${defaultLocaleLiteral}\nexport const cookieName = ${cookieNameLiteral}\n`\n writeSafe(configModulePath, configModuleSource)\n\n const configModuleDtsSource = `// Auto-generated by @fluenti/next — do not edit\nexport declare const locales: string[]\nexport declare const sourceLocale: string\nexport declare const cookieName: string\n`\n writeSafe(configModuleDtsPath, configModuleDtsSource)\n\n return outPath\n}\n\n/** Quote a string for safe embedding inside generated single-quoted JS source. */\nfunction toSingleQuotedJsString(s: string): string {\n return `'${s\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/'/g, \"\\\\'\")\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\0/g, '\\\\0')}'`\n}\n\nfunction toForwardSlash(p: string): string {\n return p.split('\\\\').join('/')\n}\n\nfunction getClientProviderModuleName(locale: string): string {\n return `client-provider-${locale.replace(/[^a-zA-Z0-9]/g, '_')}.js`\n}\n\nfunction toLocaleBindingName(locale: string): string {\n return `__messages_${locale.replace(/[^a-zA-Z0-9]/g, '_')}`\n}\n\nfunction collectInitialClientLocales(\n locale: string,\n defaultLocale: string,\n fallbackChain: Record<string, readonly string[]> | undefined,\n locales: readonly string[],\n): string[] {\n const result = new Set<string>([locale, defaultLocale])\n const localeFallbacks = fallbackChain?.[locale] ?? []\n for (const fallbackLocale of localeFallbacks) {\n if (locales.includes(fallbackLocale)) {\n result.add(fallbackLocale)\n }\n }\n return Array.from(result)\n}\n","import { join } from 'node:path'\nimport { createRequire } from 'node:module'\n\nexport interface DevRunnerOptions {\n cwd: string\n onSuccess?: () => void\n onError?: (err: Error) => void\n /** If true, reject the promise on failure instead of swallowing the error */\n throwOnError?: boolean\n /** Run only compile (skip extract). Useful for production builds where source is unchanged. */\n compileOnly?: boolean\n /** Enable parallel compilation across locales using worker threads */\n parallelCompile?: boolean\n}\n\n/**\n * Run compile in-process via `@fluenti/cli` (for compileOnly mode),\n * or extract + compile in dev mode. Requires `@fluenti/cli` to be installed\n * as a devDependency.\n */\nexport async function runExtractCompile(options: DevRunnerOptions): Promise<void> {\n if (options.compileOnly) {\n try {\n // Resolve @fluenti/cli from the project's cwd (not from this package's location)\n // using createRequire so pnpm's strict node_modules layout works correctly.\n // Use require() (not import()) to load @fluenti/cli — avoids CJS/ESM interop\n // issues when dynamic import() loads minified CJS with chunk requires.\n const projectRequire = createRequire(join(options.cwd, 'package.json'))\n const { runCompile } = projectRequire('@fluenti/cli')\n await runCompile(options.cwd)\n console.log('[fluenti] Compiling... done')\n options.onSuccess?.()\n return\n } catch (e) {\n const error = e instanceof Error ? e : new Error(String(e))\n if (options.throwOnError) throw error\n console.warn('[fluenti] Compile failed:', error.message)\n options.onError?.(error)\n return\n }\n }\n\n // Dev mode: run in-process extract + compile.\n // Step 1: load @fluenti/cli — if not installed, guide user to install it.\n // Step 2: run — errors here mean the CLI ran but failed; surface them.\n let fluentCli: { runExtract: (cwd: string) => Promise<void>; runCompile: (cwd: string, opts?: { parallel: boolean }) => Promise<void> } | null = null\n try {\n const projectRequire = createRequire(join(options.cwd, 'package.json'))\n fluentCli = projectRequire('@fluenti/cli')\n } catch {\n // @fluenti/cli not installed — will show install guide below\n }\n\n if (fluentCli) {\n try {\n await fluentCli.runExtract(options.cwd)\n if (options.parallelCompile) {\n await fluentCli.runCompile(options.cwd, { parallel: true })\n } else {\n await fluentCli.runCompile(options.cwd)\n }\n console.log('[fluenti] Extracting and compiling... done')\n options.onSuccess?.()\n return\n } catch (e) {\n const error = e instanceof Error ? e : new Error(String(e))\n if (options.throwOnError) throw error\n console.warn('[fluenti] Extract/compile failed:', error.message)\n options.onError?.(error)\n return\n }\n }\n\n const msg =\n '[fluenti] @fluenti/cli is required for auto-compile.\\n' +\n ' Install it as a devDependency:\\n' +\n ' pnpm add -D @fluenti/cli\\n' +\n ' See: https://fluenti.dev/start/introduction/'\n if (options.throwOnError) {\n throw new Error(msg)\n }\n console.warn(msg)\n options.onError?.(new Error(msg))\n}\n\n/**\n * Create a debounced runner that collapses rapid calls.\n *\n * - If called while idle, schedules a run after `delay` ms.\n * - If called while a run is in progress, marks a pending rerun.\n * - Never runs concurrently.\n */\nexport function createDebouncedRunner(\n options: DevRunnerOptions,\n delay = 300,\n): () => void {\n let timer: ReturnType<typeof setTimeout> | null = null\n let running = false\n let pendingRerun = false\n\n async function execute(): Promise<void> {\n running = true\n try {\n await runExtractCompile(options)\n } finally {\n running = false\n if (pendingRerun) {\n pendingRerun = false\n schedule()\n }\n }\n }\n\n function schedule(): void {\n if (timer !== null) {\n clearTimeout(timer)\n }\n timer = setTimeout(() => {\n timer = null\n if (running) {\n pendingRerun = true\n } else {\n execute()\n }\n }, delay)\n }\n\n return schedule\n}\n","import { watch } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { createRequire } from 'node:module'\nimport { createDebouncedRunner } from './dev-runner'\n\nexport interface DevWatcherOptions {\n cwd: string\n compiledDir: string\n delay?: number\n /** Glob patterns from fluenti.config.ts `include` field */\n include?: string[]\n /** Glob patterns from fluenti.config.ts `exclude` field */\n exclude?: string[]\n /** Enable parallel compilation across locales using worker threads */\n parallelCompile?: boolean\n}\n\nlet activeWatcher: (() => void) | null = null\n\n/**\n * Extract watch directories from include glob patterns.\n *\n * Takes the static prefix before the first glob wildcard (`*`).\n * Falls back to `src` if no include patterns are provided.\n *\n * @example\n * extractWatchDirs('/proj', ['./src/**\\/*.tsx']) → ['/proj/src']\n * extractWatchDirs('/proj', ['./app/**\\/*.ts', './lib/**\\/*.ts']) → ['/proj/app', '/proj/lib']\n * extractWatchDirs('/proj', ['./**\\/*.ts']) → ['/proj']\n */\nexport function extractWatchDirs(cwd: string, include?: string[]): string[] {\n if (!include || include.length === 0) {\n return [resolve(cwd, 'src')]\n }\n\n const dirs = new Set<string>()\n for (const pattern of include) {\n const normalized = pattern.replace(/^\\.\\//, '')\n const staticPart = normalized.split('*')[0]!.replace(/\\/+$/, '')\n dirs.add(staticPart || '.')\n }\n return [...dirs].map(d => resolve(cwd, d))\n}\n\n/**\n * Start a standalone file watcher for dev auto-compile.\n *\n * Works independently of webpack/Turbopack — watches source directories\n * (inferred from `include` patterns) for changes and triggers\n * extract+compile via the debounced runner.\n *\n * Only one watcher is active at a time (guards against multiple `applyFluenti()` calls).\n *\n * @returns A cleanup function that stops the watcher.\n */\nexport function startDevWatcher(options: DevWatcherOptions): () => void {\n // Clean up previous watcher if one exists (e.g., dev server reload)\n if (activeWatcher) {\n activeWatcher()\n }\n\n const { cwd, compiledDir, delay = 1000, include, exclude, parallelCompile } = options\n const compiledDirResolved = resolve(cwd, compiledDir)\n const _require = createRequire(\n typeof __filename !== 'undefined' ? __filename : import.meta.url,\n )\n const picomatch = _require('picomatch') as (patterns: string[]) => (str: string) => boolean\n const isExcluded = exclude?.length ? picomatch(exclude) : () => false\n const runnerOpts: Parameters<typeof createDebouncedRunner>[0] = { cwd }\n if (parallelCompile) runnerOpts.parallelCompile = true\n const debouncedRun = createDebouncedRunner(runnerOpts, delay)\n\n // Initial run\n debouncedRun()\n\n const watchDirs = extractWatchDirs(cwd, include)\n const watchers = watchDirs.map(dir =>\n watch(dir, { recursive: true }, (_event, filename) => {\n if (!filename) return\n if (!/\\.[jt]sx?$/.test(filename)) return\n if (filename.includes('node_modules') || filename.includes('.next')) return\n const full = resolve(dir, filename)\n if (full.startsWith(compiledDirResolved)) return\n if (isExcluded(filename)) return\n debouncedRun()\n }),\n )\n\n const cleanup = (): void => {\n for (const w of watchers) w.close()\n activeWatcher = null\n }\n\n activeWatcher = cleanup\n return cleanup\n}\n","import { existsSync, mkdirSync } from 'node:fs'\nimport { execSync } from 'node:child_process'\nimport { createRequire } from 'node:module'\nimport { resolve, dirname, relative } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport type { WithFluentConfig } from './types'\nimport { resolveConfig } from './read-config'\nimport { generateServerModule } from './generate-server-module'\nimport { startDevWatcher } from './dev-watcher'\n\n// Use Record<string, any> to accept both Next 15's and 16's NextConfig types\n// (Next 16 removed the index signature from NextConfig)\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype NextConfig = Record<string, any>\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 Minimal — no fluenti.config.ts needed\n * ```ts\n * import { withFluenti } from '@fluenti/next'\n * export default withFluenti({ locales: ['en', 'ja'] })({ reactStrictMode: true })\n * ```\n *\n * @example With fluenti.config.ts (advanced)\n * ```ts\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 && !isFluentConfig(configOrNext as Record<string, unknown>)) {\n // Has keys but none are fluent-specific → treat 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 isFluentConfig(obj: Record<string, unknown>): boolean {\n const fluentOnlyKeys = [\n 'config', 'locales', 'serverModule', 'serverModuleOutDir', 'resolveLocale',\n 'cookieName', 'runtimeInterpolate', 'loaderEnforce',\n ]\n return fluentOnlyKeys.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 const fluentiConfig = resolved.fluentiConfig\n const compiledDir = fluentiConfig.compileOutDir\n\n // Auto-create compiled catalogs directory if missing\n const compiledDirAbs = resolve(projectRoot, compiledDir)\n if (!existsSync(compiledDirAbs)) {\n mkdirSync(compiledDirAbs, { recursive: true })\n }\n\n // Auto-detect app/[locale]/ directory structure\n // If detected and rewriteDefaultLocale not explicitly set, enable it automatically\n const appLocaleDir = resolve(projectRoot, 'app', '[locale]')\n const srcAppLocaleDir = resolve(projectRoot, 'src', 'app', '[locale]')\n if (existsSync(appLocaleDir) || existsSync(srcAppLocaleDir)) {\n if (!('rewriteDefaultLocale' in (fluentConfig as Record<string, unknown>))) {\n // Auto-enable rewriteDefaultLocale when app/[locale]/ is detected\n (resolved as { _autoRewriteDefaultLocale?: boolean })._autoRewriteDefaultLocale = true\n }\n }\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(fileURLToPath(import.meta.url))\n const loaderPath = resolve(thisDir, 'loader.js')\n\n const existingWebpack = nextConfig['webpack'] as\n | ((config: WebpackConfig, options: WebpackOptions) => WebpackConfig)\n | undefined\n\n let buildCompileRan = false\n\n // ── Turbopack config ──────────────────────────────────────────────\n // Turbopack loader-runner supports webpack loaders via turbopack.rules.\n // Use package name (not file path) — Turbopack resolves loaders as packages,\n // file paths trigger static analysis errors (TP1006) in the loader-runner.\n const fluentTurboRules = Object.fromEntries(\n ['*.ts', '*.tsx', '*.js', '*.jsx'].map((ext) => [\n ext,\n {\n condition: { not: 'foreign' },\n loaders: ['@fluenti/next/loader'],\n },\n ]),\n )\n\n // Turbopack resolveAlias requires relative paths (absolute paths get\n // misinterpreted as \"./abs/path\"). Use \"./\" + relative-from-cwd.\n const configModulePath = resolve(dirname(serverModulePath), 'i18n-config.js')\n const relativeServerModule = './' + relative(projectRoot, serverModulePath).split('\\\\').join('/')\n const relativeConfigModule = './' + relative(projectRoot, configModulePath).split('\\\\').join('/')\n const fluentTurboAlias: Record<string, string> = {\n '@fluenti/next': relativeServerModule,\n '@fluenti/next/i18n-config': relativeConfigModule,\n }\n\n // ── Build auto-compile (bundler-agnostic — runs at config time) ──\n const isDev = process.env['NODE_ENV'] === 'development'\n || process.argv.some(a => a === 'dev')\n const buildAutoCompile = fluentiConfig.buildAutoCompile ?? true\n\n if (!isDev && buildAutoCompile && !buildCompileRan) {\n buildCompileRan = true\n try {\n // Resolve the CLI entry via Node module resolution so it works\n // in all package managers (pnpm, npm, yarn) without npx fallback\n const req = createRequire(resolve(projectRoot, 'noop.js'))\n const cliBin = resolve(dirname(req.resolve('@fluenti/cli')), 'cli.js')\n execSync(\n `node \"${cliBin}\" compile` + (fluentiConfig.parallelCompile ? ' --parallel' : ''),\n { cwd: projectRoot, stdio: 'inherit' },\n )\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error)\n throw new Error(\n `[fluenti] Production auto-compile failed. ` +\n `Run \"fluenti compile\" successfully before continuing the Next.js build.\\n` +\n ` ${detail}`,\n )\n }\n }\n\n // ── Dev auto-compile via standalone watcher (works with both webpack & Turbopack) ──\n const devAutoCompile = fluentiConfig.devAutoCompile ?? true\n\n if (isDev && devAutoCompile) {\n const watcherOpts: Parameters<typeof startDevWatcher>[0] = {\n cwd: projectRoot,\n compiledDir,\n delay: fluentiConfig.devAutoCompileDelay ?? 1000,\n }\n if (fluentiConfig.parallelCompile) watcherOpts.parallelCompile = true\n if (fluentiConfig.include) watcherOpts.include = fluentiConfig.include\n if (fluentiConfig.exclude) watcherOpts.exclude = fluentiConfig.exclude\n startDevWatcher(watcherOpts)\n }\n\n // Detect Next.js version to use correct Turbopack config key\n // Next 15+: top-level `turbopack` key\n // Next 14: `experimental.turbo` key\n let nextMajor = 15\n try {\n const nextPkg = require('next/package.json') as { version?: string }\n if (nextPkg.version) nextMajor = parseInt(nextPkg.version.split('.')[0]!, 10) || 15\n } catch { /* next not resolvable at config time */ }\n\n const turboConfig = mergeTurbopackConfig(\n (nextMajor >= 15\n ? nextConfig['turbopack']\n : (nextConfig['experimental'] as Record<string, unknown> | undefined)?.['turbo']\n ) as Record<string, unknown> | undefined,\n { rules: fluentTurboRules, resolveAlias: fluentTurboAlias },\n )\n\n const turboKey = nextMajor >= 15\n ? { turbopack: turboConfig }\n : { experimental: { ...(nextConfig['experimental'] as Record<string, unknown> ?? {}), turbo: turboConfig } }\n\n return {\n ...nextConfig,\n ...turboKey,\n webpack(config: WebpackConfig, options: WebpackOptions) {\n // Add fluenti loader\n const loaderEnforce = fluentConfig.loaderEnforce === undefined && !('loaderEnforce' in (fluentConfig as Record<string, unknown>))\n ? 'pre' as const\n : fluentConfig.loaderEnforce\n config.module.rules.push({\n test: /\\.[jt]sx?$/,\n ...(loaderEnforce ? { enforce: loaderEnforce } : {}),\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$'] = serverModulePath\n config.resolve.alias['@fluenti/next/i18n-config$'] = configModulePath\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\nfunction mergeTurbopackConfig(\n existing: Record<string, unknown> | undefined,\n fluenti: { rules: Record<string, unknown>; resolveAlias: Record<string, string> },\n): Record<string, unknown> {\n const base = existing ?? {}\n const userRules = (base['rules'] as Record<string, unknown>) ?? {}\n\n // Warn when user rules override fluenti's source-file rules\n const fluentKeys = Object.keys(fluenti.rules)\n const overlapping = fluentKeys.filter(k => k in userRules)\n if (overlapping.length > 0) {\n console.warn(\n `[fluenti] Your turbopack.rules override Fluenti's loader for: ${overlapping.join(', ')}.\\n` +\n ` Fluenti's t\\`\\` transform will NOT run on these file types.\\n` +\n ` If this is intentional, you can suppress this warning with { devAutoCompile: false }.`,\n )\n }\n\n return {\n ...base,\n rules: { ...fluenti.rules, ...userRules },\n resolveAlias: { ...fluenti.resolveAlias, ...(base['resolveAlias'] as Record<string, string>) },\n }\n}\n\n// Minimal webpack types for the config function\ninterface WebpackConfig {\n module: {\n rules: Array<Record<string, unknown>>\n }\n resolve: {\n alias?: Record<string, string>\n }\n}\n\ninterface WebpackOptions {\n isServer: boolean\n dev: boolean\n}\n","/**\n * @fluenti/next — Next.js plugin for Fluenti\n *\n * Provides:\n * - `withFluenti()` — wraps next.config.ts with t`` transform support\n * - I18nProvider — async server component (exported from generated module)\n * - Webpack loader for strict, binding-aware tagged-template optimization\n *\n * @example\n * ```ts\n * // next.config.ts\n * import { withFluenti } from '@fluenti/next'\n * export default withFluenti()({ reactStrictMode: true })\n * ```\n *\n * @example\n * ```tsx\n * // app/layout.tsx — resolved by webpack alias to the generated module\n * import { I18nProvider } from '@fluenti/next'\n * ```\n */\nexport { withFluenti } from './with-fluenti'\nexport type { WithFluentConfig, I18nProviderProps } from './types'\nexport { defineRouting } from './routing'\nexport type { RoutingConfig } from './routing'\nexport { msg } from '@fluenti/react'\n\n// ── Runtime stubs ────────────────────────────────────────────────────\n// TypeScript resolves types from this file (via package.json exports).\n// At runtime, webpack `resolve.alias` redirects `@fluenti/next$` to the\n// generated server module, so these stubs are never actually called in\n// a correctly configured project. They exist only to provide helpful\n// errors if `withFluenti()` is not configured.\n\nimport type { ReactNode, ReactElement } from 'react'\nimport type { CompileTimeT, FluentiCoreInstanceFull } from '@fluenti/core'\nimport type { I18nProviderProps } from './types'\n\ninterface NextTransProps {\n children: ReactNode\n id?: string\n context?: string\n comment?: string\n render?: (translation: ReactNode) => ReactNode\n}\n\ninterface NextPluralProps {\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}\n\ninterface NextSelectProps {\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}\n\ninterface NextDateTimeProps {\n value: Date | number\n style?: string\n}\n\ninterface NextNumberFormatProps {\n value: number\n style?: string\n}\n\nconst NOT_CONFIGURED = [\n '[fluenti] `@fluenti/next` was imported before `withFluenti()` generated the server module.',\n 'Fix this by:',\n \" 1. Wrapping next.config.ts with `withFluenti()` from '@fluenti/next'\",\n ' 2. Restarting the Next dev server after the generated module is written',\n \" 3. Importing client runtime APIs from '@fluenti/react' and server APIs from '@fluenti/next'\",\n].join('\\n')\n\nfunction throwNotConfigured(): never {\n throw new Error(NOT_CONFIGURED)\n}\n\n/** @see Generated module for the real implementation. */\nexport const setLocale: (locale: string) => void = throwNotConfigured\n/** @see Generated module for the real implementation. */\nexport const getI18n: () => Promise<FluentiCoreInstanceFull & { locale: string }> = throwNotConfigured as () => Promise<FluentiCoreInstanceFull & { locale: string }>\n/** @see Generated module for the real implementation. */\nexport const t: CompileTimeT = throwNotConfigured as unknown as CompileTimeT\n/** @see Generated module for the real implementation. */\nexport async function Trans(_props: NextTransProps): Promise<ReactElement> {\n return throwNotConfigured()\n}\n/** @see Generated module for the real implementation. */\nexport async function Plural(_props: NextPluralProps): Promise<ReactElement> {\n return throwNotConfigured()\n}\n/** @see Generated module for the real implementation. */\nexport async function Select(_props: NextSelectProps): Promise<ReactElement> {\n return throwNotConfigured()\n}\n/** @see Generated module for the real implementation. */\nexport async function DateTime(_props: NextDateTimeProps): Promise<ReactElement> {\n return throwNotConfigured()\n}\n/** @see Generated module for the real implementation. */\nexport async function NumberFormat(_props: NextNumberFormatProps): Promise<ReactElement> {\n return throwNotConfigured()\n}\n/** @see Generated module for the real implementation. */\nexport async function I18nProvider(_props: I18nProviderProps): Promise<ReactElement> {\n return throwNotConfigured()\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
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 if (isClientModule && /\\.[jt]sx$/.test(this.resourcePath) && /<(Plural|Select)[\\s/>]/.test(result)) {\n const componentResult = pipeline.transformPluralSelect(result, '@fluenti/react/components')\n if (componentResult.transformed) {\n result = componentResult.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 componentModuleImport: isClientModule ? '@fluenti/react/components' : '@fluenti/next',\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,MAIzB,GAAI,GAAkB,YAAY,KAAK,KAAK,aAAa,EAAI,yBAAyB,KAAK,EAAO,CAAE,CAClG,IAAM,EAAkB,EAAS,sBAAsB,EAAQ,4BAA4B,CACvF,EAAgB,cAClB,EAAS,EAAgB,MAK7B,GAAI,EAAA,EAAA,EAAA,4BAA4B,EAAO,CACrC,OAAO,EAIT,GAAI,CACF,IAAM,EAAS,EAAS,eAAe,EAAQ,CAC7C,sBAAuB,EAAiB,4BAA8B,gBACtE,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"}
@@ -1 +0,0 @@
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 if (isClientModule && /\\.[jt]sx$/.test(this.resourcePath) && /<(Plural|Select)[\\s/>]/.test(result)) {\n const componentResult = pipeline.transformPluralSelect(result, '@fluenti/react/components')\n if (componentResult.transformed) {\n result = componentResult.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 componentModuleImport: isClientModule ? '@fluenti/react/components' : '@fluenti/next',\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;;AAIzB,KAAI,KAAkB,YAAY,KAAK,KAAK,aAAa,IAAI,yBAAyB,KAAK,EAAO,EAAE;EAClG,IAAM,IAAkB,EAAS,sBAAsB,GAAQ,4BAA4B;AAC3F,EAAI,EAAgB,gBAClB,IAAS,EAAgB;;AAK7B,KAAI,CAAC,EAA2B,EAAO,CACrC,QAAO;AAIT,KAAI;EACF,IAAM,IAAS,EAAS,eAAe,GAAQ;GAC7C,uBAAuB,IAAiB,8BAA8B;GACtE,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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"middleware.cjs","names":[],"sources":["../src/middleware.ts"],"sourcesContent":["/**\n * @module @fluenti/next/middleware\n *\n * Built-in i18n middleware for Next.js App Router.\n *\n * Uses `x-fluenti-locale` request header to pass locale from middleware to\n * server components — avoids `Set-Cookie` on every request (CDN-friendly).\n *\n * @example Minimal\n * ```ts\n * import { NextResponse } from 'next/server'\n * import { createI18nMiddleware } from '@fluenti/next/middleware'\n *\n * export default createI18nMiddleware({ NextResponse })\n * ```\n *\n * @example With pathnames + alternateLinks + domains\n * ```ts\n * import { NextResponse } from 'next/server'\n * import { createI18nMiddleware } from '@fluenti/next/middleware'\n *\n * export default createI18nMiddleware({\n * NextResponse,\n * rewriteDefaultLocale: true,\n * alternateLinks: true,\n * pathnames: {\n * '/about': { fr: '/a-propos' },\n * '/blog/[slug]': { fr: '/articles/[slug]' },\n * },\n * domains: [\n * { domain: 'fr.example.com', defaultLocale: 'fr' },\n * ],\n * })\n * ```\n */\n\nimport {\n locales as _configLocales,\n sourceLocale as _configSourceLocale,\n cookieName as _configCookieName,\n} from '@fluenti/next/i18n-config'\n\n/** Header name used to pass resolved locale from middleware to RSC */\nexport const LOCALE_HEADER = 'x-fluenti-locale'\n\nexport interface CookieOptions {\n /** Cookie domain (e.g. '.example.com' for cross-subdomain) */\n domain?: string\n /** Secure flag (default: auto-detect from request URL) */\n secure?: boolean\n /** SameSite attribute (default: 'lax') */\n sameSite?: 'lax' | 'strict' | 'none'\n /** Max age in seconds (default: 31536000 = 1 year) */\n maxAge?: number\n /** Cookie path (default: '/') */\n path?: string\n}\n\nexport interface DomainConfig {\n /** Domain hostname (e.g. 'fr.example.com') */\n domain: string\n /** Default locale for this domain */\n defaultLocale: string\n /** Optional subset of locales available on this domain */\n locales?: string[]\n}\n\nexport interface AlternateLinkEntry {\n href: string\n hreflang: string\n}\n\nexport interface I18nMiddlewareConfig {\n /** Available locales. If omitted, reads from `fluenti.config.ts`. */\n locales?: string[]\n /** Source/default locale. If omitted, reads from `fluenti.config.ts`. */\n sourceLocale?: string\n /** Cookie name for reading user preference (default: 'locale') */\n cookieName?: string\n /**\n * Locale prefix strategy:\n * - `'always'`: all locales get a URL prefix\n * - `'as-needed'`: source locale has no prefix, others do\n * - `'never'`: no locale prefix in URLs; locale determined by detection chain\n *\n * Default: `'as-needed'`\n */\n localePrefix?: 'always' | 'as-needed' | 'never'\n /**\n * When true, bare paths are internally rewritten to include the locale prefix.\n * Required when using `app/[locale]/` directory structure.\n *\n * Default: `false`\n */\n rewriteDefaultLocale?: boolean\n /**\n * When true, detected locale is persisted in a cookie.\n * Disabled by default to keep responses CDN-cacheable.\n */\n setCookie?: boolean\n /** Fine-grained cookie configuration for multi-domain / secure deployments. */\n cookieOptions?: CookieOptions\n /**\n * Set to false to disable automatic locale detection.\n * Bare paths will always use `sourceLocale` instead of detecting from cookie / Accept-Language.\n *\n * Default: `true`\n */\n localeDetection?: boolean\n /**\n * Custom locale detection function. Called when no locale is present in the URL path.\n * Return a locale string to override the default chain, or `undefined` to fall through.\n */\n detectLocale?: (req: NextRequest) => string | undefined\n /**\n * Domain-based locale routing. Each domain maps to a default locale.\n * Domain matching is checked before cookie/Accept-Language detection.\n *\n * @example\n * ```ts\n * domains: [\n * { domain: 'fr.example.com', defaultLocale: 'fr' },\n * { domain: 'example.co.jp', defaultLocale: 'ja' },\n * ]\n * ```\n */\n domains?: DomainConfig[]\n /**\n * Map internal paths to localized paths per locale.\n * Supports dynamic segments: `[param]` and `[...slug]`.\n *\n * @example\n * ```ts\n * pathnames: {\n * '/about': { fr: '/a-propos' },\n * '/blog/[slug]': { fr: '/articles/[slug]' },\n * }\n * ```\n */\n pathnames?: Record<string, Record<string, string>>\n /**\n * When true, adds `Link` response headers with `rel=\"alternate\"` hreflang\n * and `rel=\"canonical\"` for SEO.\n *\n * Default: `false`\n */\n alternateLinks?: boolean\n /**\n * Custom function to build alternate link entries. Overrides default `alternateLinks` behavior.\n * Return an array of `{ href, hreflang }` entries.\n */\n getAlternateLinks?: (context: {\n pathname: string\n locale: string\n locales: string[]\n origin: string\n basePath: string\n }) => AlternateLinkEntry[]\n /**\n * Called before the middleware returns a response.\n * Modify headers, cookies, or return a replacement response.\n */\n beforeResponse?: (context: {\n response: NextResponseInstance\n request: NextRequest\n locale: string\n type: 'redirect' | 'rewrite' | 'next'\n }) => NextResponseInstance | void | undefined\n}\n\n/** Minimal request shape required by the middleware. Compatible with Next.js NextRequest. */\ntype NextRequest = {\n nextUrl: { pathname: string; search: string; basePath?: string }\n url: string\n cookies: { get(name: string): { value: string } | undefined }\n headers: Headers\n}\n\ntype NextResponseStatic<R extends NextResponseInstance = NextResponseInstance> = {\n redirect(url: URL): R\n rewrite(url: URL, init?: Record<string, unknown>): R\n next(init?: Record<string, unknown>): R\n}\n\ntype NextResponseInstance = {\n headers: { set(name: string, value: string): void }\n}\n\n/**\n * Create an i18n middleware function for Next.js.\n */\nexport function createI18nMiddleware<R extends NextResponseInstance = NextResponseInstance>(\n config: I18nMiddlewareConfig & { NextResponse: NextResponseStatic<R> },\n) {\n const { NextResponse } = config\n const resolvedLocales: string[] = config.locales ?? _configLocales\n const resolvedSourceLocale: string = config.sourceLocale ?? _configSourceLocale\n const cookieName = config.cookieName ?? _configCookieName\n const localePrefix = config.localePrefix ?? 'as-needed'\n const rewriteDefaultLocale = config.rewriteDefaultLocale ?? false\n const setCookieEnabled = config.setCookie ?? false\n const cookieOpts: CookieOptions = config.cookieOptions ?? {}\n const localeDetectionEnabled = config.localeDetection ?? true\n const alternateLinksEnabled = config.alternateLinks ?? false\n const pathnamesMap = config.pathnames\n const domainsConfig = config.domains\n const beforeResponse = config.beforeResponse\n\n function finalizeResponse(\n response: R,\n request: NextRequest,\n locale: string,\n type: 'redirect' | 'rewrite' | 'next',\n pathLocale: string | null,\n ): R {\n response.headers.set(LOCALE_HEADER, locale)\n if (setCookieEnabled) {\n maybeSetCookie(response, request, locale, cookieName, pathLocale, cookieOpts)\n }\n if (alternateLinksEnabled || config.getAlternateLinks) {\n const linkHeader = config.getAlternateLinks\n ? buildCustomAlternateLinks(config.getAlternateLinks, request, locale, resolvedLocales)\n : buildAlternateLinks(request, resolvedLocales, resolvedSourceLocale, localePrefix, request.nextUrl.basePath ?? '', pathnamesMap)\n response.headers.set('Link', linkHeader)\n }\n if (beforeResponse) {\n const replacement = beforeResponse({ response, request, locale, type })\n if (replacement) return replacement as R\n }\n return response\n }\n\n return function i18nMiddleware(request: NextRequest): R {\n const locales = resolvedLocales\n const sourceLocale = resolvedSourceLocale\n const { pathname, search } = request.nextUrl\n const basePath = request.nextUrl.basePath ?? ''\n\n // Extract locale from URL path ('never' mode skips this)\n const segments = pathname.split('/')\n const firstSegment = segments[1] ?? ''\n const pathLocale = localePrefix === 'never' ? null : findLocale(firstSegment, locales)\n\n // Determine the active locale\n let locale: string\n\n if (pathLocale) {\n locale = pathLocale\n } else if (!localeDetectionEnabled) {\n locale = sourceLocale\n } else {\n // Detection chain: custom → domains → cookie → Accept-Language → default\n const custom = config.detectLocale?.(request)\n if (custom !== undefined && findLocale(custom, locales) !== null) {\n locale = findLocale(custom, locales)!\n } else if (domainsConfig) {\n const domainLocale = detectFromDomain(request, domainsConfig, locales)\n locale = domainLocale ?? detectLocale(request, locales, sourceLocale, cookieName)\n } else {\n locale = detectLocale(request, locales, sourceLocale, cookieName)\n }\n }\n\n // Build request headers\n const requestHeaders = new Headers(request.headers)\n requestHeaders.set(LOCALE_HEADER, locale)\n\n // ── 'never' mode ──────────────────────────────────────────────────────\n if (localePrefix === 'never') {\n if (rewriteDefaultLocale) {\n const rewriteUrl = new URL(`${basePath}/${locale}${pathname}${search}`, request.url)\n return finalizeResponse(\n NextResponse.rewrite(rewriteUrl, { request: { headers: requestHeaders } }),\n request, locale, 'rewrite', null,\n )\n }\n return finalizeResponse(\n NextResponse.next({ request: { headers: requestHeaders } }),\n request, locale, 'next', null,\n )\n }\n\n // ── Pathnames mapping ─────────────────────────────────────────────────\n if (pathnamesMap && pathLocale) {\n const pathWithoutLocale = normalizeSlashes('/' + segments.slice(2).join('/'))\n const internalPath = resolveInternalPath(pathWithoutLocale, locale, pathnamesMap)\n\n if (internalPath) {\n const rewriteUrl = new URL(`${basePath}/${locale}${internalPath}${search}`, request.url)\n return finalizeResponse(\n NextResponse.rewrite(rewriteUrl, { request: { headers: requestHeaders } }),\n request, locale, 'rewrite', pathLocale,\n )\n }\n\n const localizedPath = resolveLocalizedPath(pathWithoutLocale, locale, pathnamesMap)\n if (localizedPath && localizedPath !== pathWithoutLocale) {\n const redirectUrl = new URL(`${basePath}/${locale}${localizedPath}${search}`, request.url)\n return finalizeResponse(\n NextResponse.redirect(redirectUrl),\n request, locale, 'redirect', pathLocale,\n )\n }\n }\n\n // ── Case 1: No locale in path → redirect ──────────────────────────────\n if (!pathLocale && (localePrefix === 'always' || locale !== sourceLocale)) {\n // If pathnames configured, redirect to localized path\n let targetPath = pathname\n if (pathnamesMap) {\n const localized = resolveLocalizedPath(pathname, locale, pathnamesMap)\n if (localized) targetPath = localized\n }\n const redirectUrl = new URL(`${basePath}/${locale}${targetPath}${search}`, request.url)\n return finalizeResponse(\n NextResponse.redirect(redirectUrl),\n request, locale, 'redirect', pathLocale,\n )\n }\n\n // ── Case 2: as-needed + source locale + rewriteDefaultLocale ──────────\n if (!pathLocale && locale === sourceLocale && rewriteDefaultLocale) {\n const rewriteUrl = new URL(`${basePath}/${sourceLocale}${pathname}${search}`, request.url)\n return finalizeResponse(\n NextResponse.rewrite(rewriteUrl, { request: { headers: requestHeaders } }),\n request, locale, 'rewrite', pathLocale,\n )\n }\n\n // ── Case 3: as-needed, source locale has explicit prefix → strip ──────\n if (localePrefix === 'as-needed' && pathLocale === sourceLocale) {\n const pathWithoutLocale = normalizeSlashes('/' + segments.slice(2).join('/'))\n if (rewriteDefaultLocale) {\n const redirectUrl = new URL(`${basePath}${pathWithoutLocale}${search}`, request.url)\n return finalizeResponse(\n NextResponse.redirect(redirectUrl),\n request, locale, 'redirect', pathLocale,\n )\n }\n const rewriteUrl = new URL(`${basePath}${pathWithoutLocale}${search}`, request.url)\n return finalizeResponse(\n NextResponse.rewrite(rewriteUrl, { request: { headers: requestHeaders } }),\n request, locale, 'rewrite', pathLocale,\n )\n }\n\n // ── Case 4/5: pass through ────────────────────────────────────────────\n return finalizeResponse(\n NextResponse.next({ request: { headers: requestHeaders } }),\n request, locale, 'next', pathLocale,\n )\n }\n}\n\n// ── Helpers ────────────────────────────────────────────────────────────────\n\nfunction findLocale(candidate: string, locales: string[]): string | null {\n if (!candidate) return null\n const lower = candidate.toLowerCase()\n return locales.find(l => l.toLowerCase() === lower) ?? null\n}\n\nfunction normalizeSlashes(path: string): string {\n return path.replace(/\\/+/g, '/') || '/'\n}\n\nfunction maybeSetCookie(\n response: NextResponseInstance,\n request: NextRequest,\n locale: string,\n cookieName: string,\n pathLocale: string | null,\n opts: CookieOptions,\n): void {\n if (pathLocale) return\n if (request.cookies.get(cookieName)?.value === locale) return\n\n const parts = [`${cookieName}=${encodeURIComponent(locale)}`]\n parts.push(`path=${opts.path ?? '/'}`)\n parts.push(`max-age=${opts.maxAge ?? 31536000}`)\n parts.push(`samesite=${opts.sameSite ?? 'lax'}`)\n if (opts.domain) parts.push(`domain=${opts.domain}`)\n if (opts.secure ?? request.url.startsWith('https')) parts.push('secure')\n response.headers.set('set-cookie', parts.join(';'))\n}\n\nfunction detectFromDomain(\n request: NextRequest,\n domains: DomainConfig[],\n locales: string[],\n): string | null {\n const host = request.headers.get('host')?.split(':')[0] ?? ''\n for (const d of domains) {\n if (host === d.domain || host.endsWith('.' + d.domain)) {\n const found = findLocale(d.defaultLocale, d.locales ?? locales)\n if (found) return found\n }\n }\n return null\n}\n\nfunction detectLocale(\n request: NextRequest,\n locales: string[],\n defaultLocale: string,\n cookieName: string,\n): string {\n const cookieLocale = request.cookies.get(cookieName)?.value\n if (cookieLocale) {\n const found = findLocale(cookieLocale, locales)\n if (found) return found\n }\n\n const acceptLang = request.headers.get('accept-language')\n if (acceptLang) {\n for (const part of acceptLang.split(',')) {\n const lang = part.split(';')[0]!.trim()\n const exact = findLocale(lang, locales)\n if (exact) return exact\n const prefix = lang.split('-')[0]!.toLowerCase()\n const match = locales.find(l => {\n const ll = l.toLowerCase()\n return ll === prefix || ll.startsWith(prefix + '-')\n })\n if (match) return match\n }\n }\n\n return defaultLocale\n}\n\nfunction stripLocalePrefix(pathname: string, locales: string[]): string {\n const segments = pathname.split('/')\n const first = segments[1] ?? ''\n if (findLocale(first, locales)) {\n return normalizeSlashes('/' + segments.slice(2).join('/'))\n }\n return pathname\n}\n\n// Path resolution utilities imported from shared routing module\n// (bundled by tsup, safe for Edge Runtime)\nimport { resolveInternalPath, resolveLocalizedPath } from './routing'\n\nfunction buildAlternateLinks(\n request: NextRequest,\n locales: string[],\n sourceLocale: string,\n localePrefix: 'always' | 'as-needed' | 'never',\n basePath: string,\n pathnames?: Record<string, Record<string, string>>,\n): string {\n const origin = new URL(request.url).origin\n const cleanPath = stripLocalePrefix(request.nextUrl.pathname, locales)\n const firstSegment = request.nextUrl.pathname.split('/')[1] ?? ''\n const requestLocale = localePrefix === 'never'\n ? sourceLocale\n : findLocale(firstSegment, locales) ?? sourceLocale\n const internalPath = pathnames\n ? resolveInternalPath(cleanPath, requestLocale, pathnames) ?? cleanPath\n : cleanPath\n\n const links = locales.map(loc => {\n const outwardPath = pathnames\n ? resolveLocalizedPath(internalPath, loc, pathnames) ?? internalPath\n : internalPath\n let localePath: string\n if (localePrefix === 'never') {\n localePath = outwardPath\n } else if (localePrefix === 'as-needed' && loc === sourceLocale) {\n localePath = outwardPath\n } else {\n localePath = `/${loc}${outwardPath}`\n }\n return `<${origin}${basePath}${localePath}>; rel=\"alternate\"; hreflang=\"${loc}\"`\n })\n\n // x-default\n const sourceOutwardPath = pathnames\n ? resolveLocalizedPath(internalPath, sourceLocale, pathnames) ?? internalPath\n : internalPath\n const defaultPath = localePrefix === 'always' ? `/${sourceLocale}${sourceOutwardPath}` : sourceOutwardPath\n links.push(`<${origin}${basePath}${defaultPath}>; rel=\"alternate\"; hreflang=\"x-default\"`)\n\n return links.join(', ')\n}\n\nfunction buildCustomAlternateLinks(\n getAlternateLinks: NonNullable<I18nMiddlewareConfig['getAlternateLinks']>,\n request: NextRequest,\n locale: string,\n locales: string[],\n): string {\n const origin = new URL(request.url).origin\n const cleanPath = stripLocalePrefix(request.nextUrl.pathname, locales)\n const basePath = request.nextUrl.basePath ?? ''\n const entries = getAlternateLinks({ pathname: cleanPath, locale, locales, origin, basePath })\n return entries.map(e => `<${e.href}>; rel=\"alternate\"; hreflang=\"${e.hreflang}\"`).join(', ')\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"middleware.js","names":[],"sources":["../src/middleware.ts"],"sourcesContent":["/**\n * @module @fluenti/next/middleware\n *\n * Built-in i18n middleware for Next.js App Router.\n *\n * Uses `x-fluenti-locale` request header to pass locale from middleware to\n * server components — avoids `Set-Cookie` on every request (CDN-friendly).\n *\n * @example Minimal\n * ```ts\n * import { NextResponse } from 'next/server'\n * import { createI18nMiddleware } from '@fluenti/next/middleware'\n *\n * export default createI18nMiddleware({ NextResponse })\n * ```\n *\n * @example With pathnames + alternateLinks + domains\n * ```ts\n * import { NextResponse } from 'next/server'\n * import { createI18nMiddleware } from '@fluenti/next/middleware'\n *\n * export default createI18nMiddleware({\n * NextResponse,\n * rewriteDefaultLocale: true,\n * alternateLinks: true,\n * pathnames: {\n * '/about': { fr: '/a-propos' },\n * '/blog/[slug]': { fr: '/articles/[slug]' },\n * },\n * domains: [\n * { domain: 'fr.example.com', defaultLocale: 'fr' },\n * ],\n * })\n * ```\n */\n\nimport {\n locales as _configLocales,\n sourceLocale as _configSourceLocale,\n cookieName as _configCookieName,\n} from '@fluenti/next/i18n-config'\n\n/** Header name used to pass resolved locale from middleware to RSC */\nexport const LOCALE_HEADER = 'x-fluenti-locale'\n\nexport interface CookieOptions {\n /** Cookie domain (e.g. '.example.com' for cross-subdomain) */\n domain?: string\n /** Secure flag (default: auto-detect from request URL) */\n secure?: boolean\n /** SameSite attribute (default: 'lax') */\n sameSite?: 'lax' | 'strict' | 'none'\n /** Max age in seconds (default: 31536000 = 1 year) */\n maxAge?: number\n /** Cookie path (default: '/') */\n path?: string\n}\n\nexport interface DomainConfig {\n /** Domain hostname (e.g. 'fr.example.com') */\n domain: string\n /** Default locale for this domain */\n defaultLocale: string\n /** Optional subset of locales available on this domain */\n locales?: string[]\n}\n\nexport interface AlternateLinkEntry {\n href: string\n hreflang: string\n}\n\nexport interface I18nMiddlewareConfig {\n /** Available locales. If omitted, reads from `fluenti.config.ts`. */\n locales?: string[]\n /** Source/default locale. If omitted, reads from `fluenti.config.ts`. */\n sourceLocale?: string\n /** Cookie name for reading user preference (default: 'locale') */\n cookieName?: string\n /**\n * Locale prefix strategy:\n * - `'always'`: all locales get a URL prefix\n * - `'as-needed'`: source locale has no prefix, others do\n * - `'never'`: no locale prefix in URLs; locale determined by detection chain\n *\n * Default: `'as-needed'`\n */\n localePrefix?: 'always' | 'as-needed' | 'never'\n /**\n * When true, bare paths are internally rewritten to include the locale prefix.\n * Required when using `app/[locale]/` directory structure.\n *\n * Default: `false`\n */\n rewriteDefaultLocale?: boolean\n /**\n * When true, detected locale is persisted in a cookie.\n * Disabled by default to keep responses CDN-cacheable.\n */\n setCookie?: boolean\n /** Fine-grained cookie configuration for multi-domain / secure deployments. */\n cookieOptions?: CookieOptions\n /**\n * Set to false to disable automatic locale detection.\n * Bare paths will always use `sourceLocale` instead of detecting from cookie / Accept-Language.\n *\n * Default: `true`\n */\n localeDetection?: boolean\n /**\n * Custom locale detection function. Called when no locale is present in the URL path.\n * Return a locale string to override the default chain, or `undefined` to fall through.\n */\n detectLocale?: (req: NextRequest) => string | undefined\n /**\n * Domain-based locale routing. Each domain maps to a default locale.\n * Domain matching is checked before cookie/Accept-Language detection.\n *\n * @example\n * ```ts\n * domains: [\n * { domain: 'fr.example.com', defaultLocale: 'fr' },\n * { domain: 'example.co.jp', defaultLocale: 'ja' },\n * ]\n * ```\n */\n domains?: DomainConfig[]\n /**\n * Map internal paths to localized paths per locale.\n * Supports dynamic segments: `[param]` and `[...slug]`.\n *\n * @example\n * ```ts\n * pathnames: {\n * '/about': { fr: '/a-propos' },\n * '/blog/[slug]': { fr: '/articles/[slug]' },\n * }\n * ```\n */\n pathnames?: Record<string, Record<string, string>>\n /**\n * When true, adds `Link` response headers with `rel=\"alternate\"` hreflang\n * and `rel=\"canonical\"` for SEO.\n *\n * Default: `false`\n */\n alternateLinks?: boolean\n /**\n * Custom function to build alternate link entries. Overrides default `alternateLinks` behavior.\n * Return an array of `{ href, hreflang }` entries.\n */\n getAlternateLinks?: (context: {\n pathname: string\n locale: string\n locales: string[]\n origin: string\n basePath: string\n }) => AlternateLinkEntry[]\n /**\n * Called before the middleware returns a response.\n * Modify headers, cookies, or return a replacement response.\n */\n beforeResponse?: (context: {\n response: NextResponseInstance\n request: NextRequest\n locale: string\n type: 'redirect' | 'rewrite' | 'next'\n }) => NextResponseInstance | void | undefined\n}\n\n/** Minimal request shape required by the middleware. Compatible with Next.js NextRequest. */\ntype NextRequest = {\n nextUrl: { pathname: string; search: string; basePath?: string }\n url: string\n cookies: { get(name: string): { value: string } | undefined }\n headers: Headers\n}\n\ntype NextResponseStatic<R extends NextResponseInstance = NextResponseInstance> = {\n redirect(url: URL): R\n rewrite(url: URL, init?: Record<string, unknown>): R\n next(init?: Record<string, unknown>): R\n}\n\ntype NextResponseInstance = {\n headers: { set(name: string, value: string): void }\n}\n\n/**\n * Create an i18n middleware function for Next.js.\n */\nexport function createI18nMiddleware<R extends NextResponseInstance = NextResponseInstance>(\n config: I18nMiddlewareConfig & { NextResponse: NextResponseStatic<R> },\n) {\n const { NextResponse } = config\n const resolvedLocales: string[] = config.locales ?? _configLocales\n const resolvedSourceLocale: string = config.sourceLocale ?? _configSourceLocale\n const cookieName = config.cookieName ?? _configCookieName\n const localePrefix = config.localePrefix ?? 'as-needed'\n const rewriteDefaultLocale = config.rewriteDefaultLocale ?? false\n const setCookieEnabled = config.setCookie ?? false\n const cookieOpts: CookieOptions = config.cookieOptions ?? {}\n const localeDetectionEnabled = config.localeDetection ?? true\n const alternateLinksEnabled = config.alternateLinks ?? false\n const pathnamesMap = config.pathnames\n const domainsConfig = config.domains\n const beforeResponse = config.beforeResponse\n\n function finalizeResponse(\n response: R,\n request: NextRequest,\n locale: string,\n type: 'redirect' | 'rewrite' | 'next',\n pathLocale: string | null,\n ): R {\n response.headers.set(LOCALE_HEADER, locale)\n if (setCookieEnabled) {\n maybeSetCookie(response, request, locale, cookieName, pathLocale, cookieOpts)\n }\n if (alternateLinksEnabled || config.getAlternateLinks) {\n const linkHeader = config.getAlternateLinks\n ? buildCustomAlternateLinks(config.getAlternateLinks, request, locale, resolvedLocales)\n : buildAlternateLinks(request, resolvedLocales, resolvedSourceLocale, localePrefix, request.nextUrl.basePath ?? '', pathnamesMap)\n response.headers.set('Link', linkHeader)\n }\n if (beforeResponse) {\n const replacement = beforeResponse({ response, request, locale, type })\n if (replacement) return replacement as R\n }\n return response\n }\n\n return function i18nMiddleware(request: NextRequest): R {\n const locales = resolvedLocales\n const sourceLocale = resolvedSourceLocale\n const { pathname, search } = request.nextUrl\n const basePath = request.nextUrl.basePath ?? ''\n\n // Extract locale from URL path ('never' mode skips this)\n const segments = pathname.split('/')\n const firstSegment = segments[1] ?? ''\n const pathLocale = localePrefix === 'never' ? null : findLocale(firstSegment, locales)\n\n // Determine the active locale\n let locale: string\n\n if (pathLocale) {\n locale = pathLocale\n } else if (!localeDetectionEnabled) {\n locale = sourceLocale\n } else {\n // Detection chain: custom → domains → cookie → Accept-Language → default\n const custom = config.detectLocale?.(request)\n if (custom !== undefined && findLocale(custom, locales) !== null) {\n locale = findLocale(custom, locales)!\n } else if (domainsConfig) {\n const domainLocale = detectFromDomain(request, domainsConfig, locales)\n locale = domainLocale ?? detectLocale(request, locales, sourceLocale, cookieName)\n } else {\n locale = detectLocale(request, locales, sourceLocale, cookieName)\n }\n }\n\n // Build request headers\n const requestHeaders = new Headers(request.headers)\n requestHeaders.set(LOCALE_HEADER, locale)\n\n // ── 'never' mode ──────────────────────────────────────────────────────\n if (localePrefix === 'never') {\n if (rewriteDefaultLocale) {\n const rewriteUrl = new URL(`${basePath}/${locale}${pathname}${search}`, request.url)\n return finalizeResponse(\n NextResponse.rewrite(rewriteUrl, { request: { headers: requestHeaders } }),\n request, locale, 'rewrite', null,\n )\n }\n return finalizeResponse(\n NextResponse.next({ request: { headers: requestHeaders } }),\n request, locale, 'next', null,\n )\n }\n\n // ── Pathnames mapping ─────────────────────────────────────────────────\n if (pathnamesMap && pathLocale) {\n const pathWithoutLocale = normalizeSlashes('/' + segments.slice(2).join('/'))\n const internalPath = resolveInternalPath(pathWithoutLocale, locale, pathnamesMap)\n\n if (internalPath) {\n const rewriteUrl = new URL(`${basePath}/${locale}${internalPath}${search}`, request.url)\n return finalizeResponse(\n NextResponse.rewrite(rewriteUrl, { request: { headers: requestHeaders } }),\n request, locale, 'rewrite', pathLocale,\n )\n }\n\n const localizedPath = resolveLocalizedPath(pathWithoutLocale, locale, pathnamesMap)\n if (localizedPath && localizedPath !== pathWithoutLocale) {\n const redirectUrl = new URL(`${basePath}/${locale}${localizedPath}${search}`, request.url)\n return finalizeResponse(\n NextResponse.redirect(redirectUrl),\n request, locale, 'redirect', pathLocale,\n )\n }\n }\n\n // ── Case 1: No locale in path → redirect ──────────────────────────────\n if (!pathLocale && (localePrefix === 'always' || locale !== sourceLocale)) {\n // If pathnames configured, redirect to localized path\n let targetPath = pathname\n if (pathnamesMap) {\n const localized = resolveLocalizedPath(pathname, locale, pathnamesMap)\n if (localized) targetPath = localized\n }\n const redirectUrl = new URL(`${basePath}/${locale}${targetPath}${search}`, request.url)\n return finalizeResponse(\n NextResponse.redirect(redirectUrl),\n request, locale, 'redirect', pathLocale,\n )\n }\n\n // ── Case 2: as-needed + source locale + rewriteDefaultLocale ──────────\n if (!pathLocale && locale === sourceLocale && rewriteDefaultLocale) {\n const rewriteUrl = new URL(`${basePath}/${sourceLocale}${pathname}${search}`, request.url)\n return finalizeResponse(\n NextResponse.rewrite(rewriteUrl, { request: { headers: requestHeaders } }),\n request, locale, 'rewrite', pathLocale,\n )\n }\n\n // ── Case 3: as-needed, source locale has explicit prefix → strip ──────\n if (localePrefix === 'as-needed' && pathLocale === sourceLocale) {\n const pathWithoutLocale = normalizeSlashes('/' + segments.slice(2).join('/'))\n if (rewriteDefaultLocale) {\n const redirectUrl = new URL(`${basePath}${pathWithoutLocale}${search}`, request.url)\n return finalizeResponse(\n NextResponse.redirect(redirectUrl),\n request, locale, 'redirect', pathLocale,\n )\n }\n const rewriteUrl = new URL(`${basePath}${pathWithoutLocale}${search}`, request.url)\n return finalizeResponse(\n NextResponse.rewrite(rewriteUrl, { request: { headers: requestHeaders } }),\n request, locale, 'rewrite', pathLocale,\n )\n }\n\n // ── Case 4/5: pass through ────────────────────────────────────────────\n return finalizeResponse(\n NextResponse.next({ request: { headers: requestHeaders } }),\n request, locale, 'next', pathLocale,\n )\n }\n}\n\n// ── Helpers ────────────────────────────────────────────────────────────────\n\nfunction findLocale(candidate: string, locales: string[]): string | null {\n if (!candidate) return null\n const lower = candidate.toLowerCase()\n return locales.find(l => l.toLowerCase() === lower) ?? null\n}\n\nfunction normalizeSlashes(path: string): string {\n return path.replace(/\\/+/g, '/') || '/'\n}\n\nfunction maybeSetCookie(\n response: NextResponseInstance,\n request: NextRequest,\n locale: string,\n cookieName: string,\n pathLocale: string | null,\n opts: CookieOptions,\n): void {\n if (pathLocale) return\n if (request.cookies.get(cookieName)?.value === locale) return\n\n const parts = [`${cookieName}=${encodeURIComponent(locale)}`]\n parts.push(`path=${opts.path ?? '/'}`)\n parts.push(`max-age=${opts.maxAge ?? 31536000}`)\n parts.push(`samesite=${opts.sameSite ?? 'lax'}`)\n if (opts.domain) parts.push(`domain=${opts.domain}`)\n if (opts.secure ?? request.url.startsWith('https')) parts.push('secure')\n response.headers.set('set-cookie', parts.join(';'))\n}\n\nfunction detectFromDomain(\n request: NextRequest,\n domains: DomainConfig[],\n locales: string[],\n): string | null {\n const host = request.headers.get('host')?.split(':')[0] ?? ''\n for (const d of domains) {\n if (host === d.domain || host.endsWith('.' + d.domain)) {\n const found = findLocale(d.defaultLocale, d.locales ?? locales)\n if (found) return found\n }\n }\n return null\n}\n\nfunction detectLocale(\n request: NextRequest,\n locales: string[],\n defaultLocale: string,\n cookieName: string,\n): string {\n const cookieLocale = request.cookies.get(cookieName)?.value\n if (cookieLocale) {\n const found = findLocale(cookieLocale, locales)\n if (found) return found\n }\n\n const acceptLang = request.headers.get('accept-language')\n if (acceptLang) {\n for (const part of acceptLang.split(',')) {\n const lang = part.split(';')[0]!.trim()\n const exact = findLocale(lang, locales)\n if (exact) return exact\n const prefix = lang.split('-')[0]!.toLowerCase()\n const match = locales.find(l => {\n const ll = l.toLowerCase()\n return ll === prefix || ll.startsWith(prefix + '-')\n })\n if (match) return match\n }\n }\n\n return defaultLocale\n}\n\nfunction stripLocalePrefix(pathname: string, locales: string[]): string {\n const segments = pathname.split('/')\n const first = segments[1] ?? ''\n if (findLocale(first, locales)) {\n return normalizeSlashes('/' + segments.slice(2).join('/'))\n }\n return pathname\n}\n\n// Path resolution utilities imported from shared routing module\n// (bundled by tsup, safe for Edge Runtime)\nimport { resolveInternalPath, resolveLocalizedPath } from './routing'\n\nfunction buildAlternateLinks(\n request: NextRequest,\n locales: string[],\n sourceLocale: string,\n localePrefix: 'always' | 'as-needed' | 'never',\n basePath: string,\n pathnames?: Record<string, Record<string, string>>,\n): string {\n const origin = new URL(request.url).origin\n const cleanPath = stripLocalePrefix(request.nextUrl.pathname, locales)\n const firstSegment = request.nextUrl.pathname.split('/')[1] ?? ''\n const requestLocale = localePrefix === 'never'\n ? sourceLocale\n : findLocale(firstSegment, locales) ?? sourceLocale\n const internalPath = pathnames\n ? resolveInternalPath(cleanPath, requestLocale, pathnames) ?? cleanPath\n : cleanPath\n\n const links = locales.map(loc => {\n const outwardPath = pathnames\n ? resolveLocalizedPath(internalPath, loc, pathnames) ?? internalPath\n : internalPath\n let localePath: string\n if (localePrefix === 'never') {\n localePath = outwardPath\n } else if (localePrefix === 'as-needed' && loc === sourceLocale) {\n localePath = outwardPath\n } else {\n localePath = `/${loc}${outwardPath}`\n }\n return `<${origin}${basePath}${localePath}>; rel=\"alternate\"; hreflang=\"${loc}\"`\n })\n\n // x-default\n const sourceOutwardPath = pathnames\n ? resolveLocalizedPath(internalPath, sourceLocale, pathnames) ?? internalPath\n : internalPath\n const defaultPath = localePrefix === 'always' ? `/${sourceLocale}${sourceOutwardPath}` : sourceOutwardPath\n links.push(`<${origin}${basePath}${defaultPath}>; rel=\"alternate\"; hreflang=\"x-default\"`)\n\n return links.join(', ')\n}\n\nfunction buildCustomAlternateLinks(\n getAlternateLinks: NonNullable<I18nMiddlewareConfig['getAlternateLinks']>,\n request: NextRequest,\n locale: string,\n locales: string[],\n): string {\n const origin = new URL(request.url).origin\n const cleanPath = stripLocalePrefix(request.nextUrl.pathname, locales)\n const basePath = request.nextUrl.basePath ?? ''\n const entries = getAlternateLinks({ pathname: cleanPath, locale, locales, origin, basePath })\n return entries.map(e => `<${e.href}>; rel=\"alternate\"; hreflang=\"${e.hreflang}\"`).join(', ')\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"navigation.cjs","names":[],"sources":["../src/create-navigation.tsx","../src/navigation.ts"],"sourcesContent":["/**\n * @module @fluenti/next/navigation\n *\n * Type-safe navigation factory for Next.js i18n routing.\n *\n * @example\n * ```tsx\n * // src/lib/navigation.ts\n * import { createNavigation } from '@fluenti/next/navigation'\n *\n * export const { Link, useRouter, redirect, usePathname, getPathname } = createNavigation({\n * locales: ['en', 'fr', 'ja'] as const,\n * sourceLocale: 'en',\n * localePrefix: 'as-needed',\n * pathnames: {\n * '/': { fr: '/', ja: '/' },\n * '/about': { fr: '/a-propos', ja: '/about' },\n * '/blog/[slug]': { fr: '/articles/[slug]', ja: '/blog/[slug]' },\n * },\n * })\n * ```\n */\n'use client'\n\nimport { createElement, forwardRef } from 'react'\nimport type { ReactNode } from 'react'\nimport { resolveLocalizedPath } from './routing'\nimport type { RoutingConfig } from './routing'\n\nexport type { RoutingConfig }\n\ninterface NavigationLinkProps<P extends string = string, L extends string = string> {\n href: P | (string & Record<never, never>)\n locale?: L\n children?: ReactNode\n prefetch?: boolean | null\n replace?: boolean\n scroll?: boolean\n target?: string\n className?: string\n [key: string]: unknown\n}\n\ninterface TypedRouter<P extends string = string, L extends string = string> {\n push(href: P | (string & Record<never, never>), options?: { locale?: L }): void\n replace(href: P | (string & Record<never, never>), options?: { locale?: L }): void\n back(): void\n forward(): void\n refresh(): void\n prefetch(href: string): void\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────\n\nexport function createNavigation<\n const L extends string,\n const P extends string,\n>(routing: RoutingConfig<L, P>) {\n const { locales, sourceLocale, localePrefix = 'as-needed', pathnames } = routing\n\n function resolvePath(href: string, locale: string): string {\n // Apply pathnames mapping if configured (supports [param] and [...slug])\n let resolved = href\n if (pathnames) {\n const mapped = resolveLocalizedPath(href, locale, pathnames as Record<string, Record<string, string>>)\n if (mapped) resolved = mapped\n }\n\n // Apply locale prefix\n if (localePrefix === 'never') return resolved\n if (localePrefix === 'as-needed' && locale === sourceLocale) return resolved\n return `/${locale}${resolved}`\n }\n\n function stripPrefix(pathname: string): string {\n if (localePrefix === 'never') return pathname\n const segments = pathname.split('/')\n const first = segments[1] ?? ''\n const lower = first.toLowerCase()\n const isLocale = locales.some(l => l.toLowerCase() === lower)\n if (isLocale) return '/' + segments.slice(2).join('/') || '/'\n return pathname\n }\n\n // ── Link component ────────────────────────────────────────────────────\n\n const Link = forwardRef<HTMLAnchorElement, NavigationLinkProps<P, L>>(\n function I18nLink({ href, locale: localeProp, ...rest }, ref) {\n // Dynamic imports to avoid SSR issues — these are resolved at runtime\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const NextLink = require('next/link').default\n let currentLocale = sourceLocale\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { useI18n } = require('@fluenti/react')\n const i18n = useI18n()\n currentLocale = i18n.locale\n } catch {\n // Outside I18nProvider, use sourceLocale\n }\n const locale = localeProp ?? currentLocale\n const resolvedHref = resolvePath(String(href), String(locale))\n return createElement(NextLink, { ref, href: resolvedHref, ...rest })\n },\n )\n Link.displayName = 'I18nLink'\n\n // ── useRouter hook ────────────────────────────────────────────────────\n\n function useRouter(): TypedRouter<P, L> {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { useRouter: useNextRouter } = require('next/navigation')\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { useI18n } = require('@fluenti/react')\n\n const nextRouter = useNextRouter()\n const { locale } = useI18n()\n\n return {\n push(href: P | string, options?: { locale?: L }) {\n nextRouter.push(resolvePath(String(href), String(options?.locale ?? locale)))\n },\n replace(href: P | string, options?: { locale?: L }) {\n nextRouter.replace(resolvePath(String(href), String(options?.locale ?? locale)))\n },\n back: () => nextRouter.back(),\n forward: () => nextRouter.forward(),\n refresh: () => nextRouter.refresh(),\n prefetch: (href: string) => nextRouter.prefetch(href),\n }\n }\n\n // ── redirect function (server-side) ───────────────────────────────────\n\n function redirect(href: P | (string & Record<never, never>), locale?: L): never {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { redirect: nextRedirect } = require('next/navigation') as { redirect: (url: string) => never }\n const resolvedLocale = locale ?? sourceLocale\n return nextRedirect(resolvePath(String(href), String(resolvedLocale)))\n }\n\n // ── usePathname hook ──────────────────────────────────────────────────\n\n function usePathname(): string {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { usePathname: useNextPathname } = require('next/navigation')\n const pathname = useNextPathname()\n return stripPrefix(pathname)\n }\n\n // ── getPathname utility ───────────────────────────────────────────────\n\n function getPathname(href: P | (string & Record<never, never>), locale: L): string {\n return resolvePath(String(href), String(locale))\n }\n\n return { Link, useRouter, redirect, usePathname, getPathname }\n}\n","'use client'\n\n/**\n * @module @fluenti/next/navigation\n *\n * Navigation utilities for locale-aware routing in Next.js App Router.\n *\n * @example\n * ```tsx\n * import { useLocaleSwitcher } from '@fluenti/next/navigation'\n *\n * function LanguagePicker() {\n * const { switchLocale, currentLocale, locales } = useLocaleSwitcher()\n * return (\n * <select value={currentLocale} onChange={(e) => switchLocale(e.target.value)}>\n * {locales.map((l) => <option key={l} value={l}>{l}</option>)}\n * </select>\n * )\n * }\n * ```\n */\nimport { useRouter, usePathname } from 'next/navigation'\nimport { useI18n } from '@fluenti/react'\nimport { cookieName as _configCookieName } from '@fluenti/next/i18n-config'\nimport { resolveInternalPath, resolveLocalizedPath } from './routing'\n\nexport interface GetLocalePathOptions {\n /** Source/default locale (no prefix in as-needed mode) */\n sourceLocale?: string\n /**\n * Known locale codes (e.g. ['en', 'fr', 'ja']).\n * When provided, the existing prefix is only stripped when it's an actual locale —\n * preventing false matches on generic 2-letter path segments like /my or /us.\n */\n locales?: string[]\n /**\n * Locale prefix strategy. Matches the middleware `localePrefix` setting.\n * - `'as-needed'` (default): source locale has no prefix (`/about` for en, `/fr/about` for fr)\n * - `'always'`: all locales get a prefix (`/en/about`, `/fr/about`)\n * - `'never'`: no locale prefix in URLs\n */\n localePrefix?: 'always' | 'as-needed' | 'never'\n}\n\n/**\n * Get the locale-prefixed path for a given pathname and locale.\n *\n * Pure function — works on both server and client.\n *\n * @example\n * ```ts\n * getLocalePath('/about', 'fr') // → '/fr/about'\n * getLocalePath('/about', 'en') // → '/about' (source locale, no prefix)\n * getLocalePath('/fr/about', 'en', { locales: ['en', 'fr', 'ja'] }) // → '/about'\n * getLocalePath('/fr/about', 'ja', { locales: ['en', 'fr', 'ja'] }) // → '/ja/about'\n * getLocalePath('/about', 'en', { localePrefix: 'always' }) // → '/en/about'\n * ```\n */\nexport function getLocalePath(\n pathname: string,\n locale: string,\n options?: GetLocalePathOptions,\n): string {\n const sourceLocale = options?.sourceLocale ?? 'en'\n const localePrefix = options?.localePrefix ?? 'as-needed'\n\n // Strip existing locale prefix if present\n const segments = pathname.split('/')\n const firstSegment = segments[1] ?? ''\n\n // Only strip an existing locale prefix when the caller provides the known locale list.\n const hasLocalePrefix = options?.locales\n ? options.locales.some(loc => loc.toLowerCase() === firstSegment.toLowerCase())\n : false\n const pathWithoutLocale = hasLocalePrefix\n ? '/' + segments.slice(2).join('/')\n : pathname\n\n // 'never' mode: no prefix for any locale\n if (localePrefix === 'never') {\n return pathWithoutLocale || '/'\n }\n\n // In 'as-needed' mode, source locale gets no prefix\n if (localePrefix !== 'always' && locale === sourceLocale) {\n return pathWithoutLocale || '/'\n }\n\n return `/${locale}${pathWithoutLocale}`\n}\n\n/**\n * Hook for switching locales in Next.js App Router.\n *\n * Sets a cookie to remember user preference, navigates to the new locale path,\n * and triggers a server component refresh.\n */\nexport function useLocaleSwitcher(options?: {\n /** Override the source/default locale instead of inferring from locales[0]. */\n sourceLocale?: string\n /**\n * Cookie name used by the middleware for locale preference.\n * Defaults to the value from `fluenti.config.ts` (auto-read at build time).\n * Must match the middleware `cookieName` option.\n */\n cookieName?: string\n /** Locale prefix strategy — must match the middleware `localePrefix` option. */\n localePrefix?: 'always' | 'as-needed' | 'never'\n}) {\n const router = useRouter()\n const pathname = usePathname()\n const { locale, setLocale, getLocales } = useI18n()\n\n // Read locales from I18nProvider context (works on client without fs)\n const locales = getLocales()\n const sourceLocale = options?.sourceLocale ?? locales[0] ?? 'en'\n const cookieName = options?.cookieName ?? _configCookieName\n const localePrefix = options?.localePrefix ?? 'as-needed'\n\n const switchLocale = (newLocale: string) => {\n // Validate locale against known locales to prevent cookie injection\n if (!locales.includes(newLocale)) {\n if (typeof process !== 'undefined' && process.env?.['NODE_ENV'] !== 'production') {\n console.warn(`[fluenti] switchLocale: invalid locale \"${newLocale}\"`)\n }\n return\n }\n // 1. Set cookie to remember preference (uses configured cookie name)\n document.cookie = `${cookieName}=${encodeURIComponent(newLocale)};path=/;max-age=31536000;samesite=lax`\n // 2. Update React context\n setLocale(newLocale)\n // 3. Navigate to new locale path\n const newPath = getLocalePath(pathname, newLocale, { sourceLocale, locales, localePrefix })\n router.push(newPath)\n // 4. Refresh server components\n router.refresh()\n }\n\n return {\n switchLocale,\n currentLocale: locale,\n locales,\n sourceLocale,\n }\n}\n\n// Re-export createNavigation and routing utilities\nexport { createNavigation } from './create-navigation'\nexport { defineRouting, resolveLocalizedPath } from './routing'\nexport type { RoutingConfig } from './routing'\n\n// ── useAlternateLinks ─────────────────────────────────────────────────────\n\nexport interface AlternateLink {\n hreflang: string\n href: string\n}\n\n/**\n * Generate alternate link entries for SEO `<head>` tags.\n *\n * Returns an array of `{ hreflang, href }` entries for all configured locales\n * plus `x-default`. Use in `<head>` for hreflang tags.\n *\n * @example\n * ```tsx\n * import { useAlternateLinks } from '@fluenti/next/navigation'\n * import { routing } from '@/i18n/routing'\n *\n * export function Head() {\n * const links = useAlternateLinks({ routing, baseUrl: 'https://example.com' })\n * return (\n * <head>\n * {links.map(l => (\n * <link key={l.hreflang} rel=\"alternate\" hreflang={l.hreflang} href={l.href} />\n * ))}\n * </head>\n * )\n * }\n * ```\n */\nexport function useAlternateLinks(options: {\n routing: { locales: readonly string[]; sourceLocale: string; localePrefix?: 'always' | 'as-needed' | 'never'; pathnames?: Record<string, Record<string, string>> }\n baseUrl?: string\n}): AlternateLink[] {\n const { routing: r, baseUrl = '' } = options\n const pathname = usePathname()\n let activeLocale = r.sourceLocale\n try {\n activeLocale = useI18n().locale\n } catch {\n // Outside I18nProvider, fall back to sourceLocale.\n }\n // Strip locale prefix from current path\n const segments = pathname.split('/')\n const firstSeg = segments[1] ?? ''\n const pathLocale = r.localePrefix === 'never'\n ? null\n : (r.locales as string[]).find(l => l.toLowerCase() === firstSeg.toLowerCase()) ?? null\n const cleanPath = pathLocale ? '/' + segments.slice(2).join('/') || '/' : pathname\n const requestLocale = pathLocale ?? activeLocale ?? r.sourceLocale\n const internalPath = r.pathnames\n ? resolveInternalPath(cleanPath, requestLocale, r.pathnames as Record<string, Record<string, string>>) ?? cleanPath\n : cleanPath\n\n const links: AlternateLink[] = (r.locales as string[]).map(loc => {\n const localePath = r.pathnames\n ? resolveLocalizedPath(internalPath, loc, r.pathnames as Record<string, Record<string, string>>) ?? internalPath\n : internalPath\n\n let href: string\n if (r.localePrefix === 'never') {\n href = `${baseUrl}${localePath}`\n } else if (r.localePrefix !== 'always' && loc === r.sourceLocale) {\n href = `${baseUrl}${localePath}`\n } else {\n href = `${baseUrl}/${loc}${localePath}`\n }\n\n return { hreflang: loc, href }\n })\n\n // x-default\n const sourcePath = r.pathnames\n ? resolveLocalizedPath(internalPath, r.sourceLocale, r.pathnames as Record<string, Record<string, string>>) ?? internalPath\n : internalPath\n const defaultPath = r.localePrefix === 'always'\n ? `${baseUrl}/${r.sourceLocale}${sourcePath}`\n : `${baseUrl}${sourcePath}`\n links.push({ hreflang: 'x-default', href: defaultPath })\n\n return links\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"navigation.js","names":[],"sources":["../src/create-navigation.tsx","../src/navigation.ts"],"sourcesContent":["/**\n * @module @fluenti/next/navigation\n *\n * Type-safe navigation factory for Next.js i18n routing.\n *\n * @example\n * ```tsx\n * // src/lib/navigation.ts\n * import { createNavigation } from '@fluenti/next/navigation'\n *\n * export const { Link, useRouter, redirect, usePathname, getPathname } = createNavigation({\n * locales: ['en', 'fr', 'ja'] as const,\n * sourceLocale: 'en',\n * localePrefix: 'as-needed',\n * pathnames: {\n * '/': { fr: '/', ja: '/' },\n * '/about': { fr: '/a-propos', ja: '/about' },\n * '/blog/[slug]': { fr: '/articles/[slug]', ja: '/blog/[slug]' },\n * },\n * })\n * ```\n */\n'use client'\n\nimport { createElement, forwardRef } from 'react'\nimport type { ReactNode } from 'react'\nimport { resolveLocalizedPath } from './routing'\nimport type { RoutingConfig } from './routing'\n\nexport type { RoutingConfig }\n\ninterface NavigationLinkProps<P extends string = string, L extends string = string> {\n href: P | (string & Record<never, never>)\n locale?: L\n children?: ReactNode\n prefetch?: boolean | null\n replace?: boolean\n scroll?: boolean\n target?: string\n className?: string\n [key: string]: unknown\n}\n\ninterface TypedRouter<P extends string = string, L extends string = string> {\n push(href: P | (string & Record<never, never>), options?: { locale?: L }): void\n replace(href: P | (string & Record<never, never>), options?: { locale?: L }): void\n back(): void\n forward(): void\n refresh(): void\n prefetch(href: string): void\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────\n\nexport function createNavigation<\n const L extends string,\n const P extends string,\n>(routing: RoutingConfig<L, P>) {\n const { locales, sourceLocale, localePrefix = 'as-needed', pathnames } = routing\n\n function resolvePath(href: string, locale: string): string {\n // Apply pathnames mapping if configured (supports [param] and [...slug])\n let resolved = href\n if (pathnames) {\n const mapped = resolveLocalizedPath(href, locale, pathnames as Record<string, Record<string, string>>)\n if (mapped) resolved = mapped\n }\n\n // Apply locale prefix\n if (localePrefix === 'never') return resolved\n if (localePrefix === 'as-needed' && locale === sourceLocale) return resolved\n return `/${locale}${resolved}`\n }\n\n function stripPrefix(pathname: string): string {\n if (localePrefix === 'never') return pathname\n const segments = pathname.split('/')\n const first = segments[1] ?? ''\n const lower = first.toLowerCase()\n const isLocale = locales.some(l => l.toLowerCase() === lower)\n if (isLocale) return '/' + segments.slice(2).join('/') || '/'\n return pathname\n }\n\n // ── Link component ────────────────────────────────────────────────────\n\n const Link = forwardRef<HTMLAnchorElement, NavigationLinkProps<P, L>>(\n function I18nLink({ href, locale: localeProp, ...rest }, ref) {\n // Dynamic imports to avoid SSR issues — these are resolved at runtime\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const NextLink = require('next/link').default\n let currentLocale = sourceLocale\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { useI18n } = require('@fluenti/react')\n const i18n = useI18n()\n currentLocale = i18n.locale\n } catch {\n // Outside I18nProvider, use sourceLocale\n }\n const locale = localeProp ?? currentLocale\n const resolvedHref = resolvePath(String(href), String(locale))\n return createElement(NextLink, { ref, href: resolvedHref, ...rest })\n },\n )\n Link.displayName = 'I18nLink'\n\n // ── useRouter hook ────────────────────────────────────────────────────\n\n function useRouter(): TypedRouter<P, L> {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { useRouter: useNextRouter } = require('next/navigation')\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { useI18n } = require('@fluenti/react')\n\n const nextRouter = useNextRouter()\n const { locale } = useI18n()\n\n return {\n push(href: P | string, options?: { locale?: L }) {\n nextRouter.push(resolvePath(String(href), String(options?.locale ?? locale)))\n },\n replace(href: P | string, options?: { locale?: L }) {\n nextRouter.replace(resolvePath(String(href), String(options?.locale ?? locale)))\n },\n back: () => nextRouter.back(),\n forward: () => nextRouter.forward(),\n refresh: () => nextRouter.refresh(),\n prefetch: (href: string) => nextRouter.prefetch(href),\n }\n }\n\n // ── redirect function (server-side) ───────────────────────────────────\n\n function redirect(href: P | (string & Record<never, never>), locale?: L): never {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { redirect: nextRedirect } = require('next/navigation') as { redirect: (url: string) => never }\n const resolvedLocale = locale ?? sourceLocale\n return nextRedirect(resolvePath(String(href), String(resolvedLocale)))\n }\n\n // ── usePathname hook ──────────────────────────────────────────────────\n\n function usePathname(): string {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { usePathname: useNextPathname } = require('next/navigation')\n const pathname = useNextPathname()\n return stripPrefix(pathname)\n }\n\n // ── getPathname utility ───────────────────────────────────────────────\n\n function getPathname(href: P | (string & Record<never, never>), locale: L): string {\n return resolvePath(String(href), String(locale))\n }\n\n return { Link, useRouter, redirect, usePathname, getPathname }\n}\n","'use client'\n\n/**\n * @module @fluenti/next/navigation\n *\n * Navigation utilities for locale-aware routing in Next.js App Router.\n *\n * @example\n * ```tsx\n * import { useLocaleSwitcher } from '@fluenti/next/navigation'\n *\n * function LanguagePicker() {\n * const { switchLocale, currentLocale, locales } = useLocaleSwitcher()\n * return (\n * <select value={currentLocale} onChange={(e) => switchLocale(e.target.value)}>\n * {locales.map((l) => <option key={l} value={l}>{l}</option>)}\n * </select>\n * )\n * }\n * ```\n */\nimport { useRouter, usePathname } from 'next/navigation'\nimport { useI18n } from '@fluenti/react'\nimport { cookieName as _configCookieName } from '@fluenti/next/i18n-config'\nimport { resolveInternalPath, resolveLocalizedPath } from './routing'\n\nexport interface GetLocalePathOptions {\n /** Source/default locale (no prefix in as-needed mode) */\n sourceLocale?: string\n /**\n * Known locale codes (e.g. ['en', 'fr', 'ja']).\n * When provided, the existing prefix is only stripped when it's an actual locale —\n * preventing false matches on generic 2-letter path segments like /my or /us.\n */\n locales?: string[]\n /**\n * Locale prefix strategy. Matches the middleware `localePrefix` setting.\n * - `'as-needed'` (default): source locale has no prefix (`/about` for en, `/fr/about` for fr)\n * - `'always'`: all locales get a prefix (`/en/about`, `/fr/about`)\n * - `'never'`: no locale prefix in URLs\n */\n localePrefix?: 'always' | 'as-needed' | 'never'\n}\n\n/**\n * Get the locale-prefixed path for a given pathname and locale.\n *\n * Pure function — works on both server and client.\n *\n * @example\n * ```ts\n * getLocalePath('/about', 'fr') // → '/fr/about'\n * getLocalePath('/about', 'en') // → '/about' (source locale, no prefix)\n * getLocalePath('/fr/about', 'en', { locales: ['en', 'fr', 'ja'] }) // → '/about'\n * getLocalePath('/fr/about', 'ja', { locales: ['en', 'fr', 'ja'] }) // → '/ja/about'\n * getLocalePath('/about', 'en', { localePrefix: 'always' }) // → '/en/about'\n * ```\n */\nexport function getLocalePath(\n pathname: string,\n locale: string,\n options?: GetLocalePathOptions,\n): string {\n const sourceLocale = options?.sourceLocale ?? 'en'\n const localePrefix = options?.localePrefix ?? 'as-needed'\n\n // Strip existing locale prefix if present\n const segments = pathname.split('/')\n const firstSegment = segments[1] ?? ''\n\n // Only strip an existing locale prefix when the caller provides the known locale list.\n const hasLocalePrefix = options?.locales\n ? options.locales.some(loc => loc.toLowerCase() === firstSegment.toLowerCase())\n : false\n const pathWithoutLocale = hasLocalePrefix\n ? '/' + segments.slice(2).join('/')\n : pathname\n\n // 'never' mode: no prefix for any locale\n if (localePrefix === 'never') {\n return pathWithoutLocale || '/'\n }\n\n // In 'as-needed' mode, source locale gets no prefix\n if (localePrefix !== 'always' && locale === sourceLocale) {\n return pathWithoutLocale || '/'\n }\n\n return `/${locale}${pathWithoutLocale}`\n}\n\n/**\n * Hook for switching locales in Next.js App Router.\n *\n * Sets a cookie to remember user preference, navigates to the new locale path,\n * and triggers a server component refresh.\n */\nexport function useLocaleSwitcher(options?: {\n /** Override the source/default locale instead of inferring from locales[0]. */\n sourceLocale?: string\n /**\n * Cookie name used by the middleware for locale preference.\n * Defaults to the value from `fluenti.config.ts` (auto-read at build time).\n * Must match the middleware `cookieName` option.\n */\n cookieName?: string\n /** Locale prefix strategy — must match the middleware `localePrefix` option. */\n localePrefix?: 'always' | 'as-needed' | 'never'\n}) {\n const router = useRouter()\n const pathname = usePathname()\n const { locale, setLocale, getLocales } = useI18n()\n\n // Read locales from I18nProvider context (works on client without fs)\n const locales = getLocales()\n const sourceLocale = options?.sourceLocale ?? locales[0] ?? 'en'\n const cookieName = options?.cookieName ?? _configCookieName\n const localePrefix = options?.localePrefix ?? 'as-needed'\n\n const switchLocale = (newLocale: string) => {\n // Validate locale against known locales to prevent cookie injection\n if (!locales.includes(newLocale)) {\n if (typeof process !== 'undefined' && process.env?.['NODE_ENV'] !== 'production') {\n console.warn(`[fluenti] switchLocale: invalid locale \"${newLocale}\"`)\n }\n return\n }\n // 1. Set cookie to remember preference (uses configured cookie name)\n document.cookie = `${cookieName}=${encodeURIComponent(newLocale)};path=/;max-age=31536000;samesite=lax`\n // 2. Update React context\n setLocale(newLocale)\n // 3. Navigate to new locale path\n const newPath = getLocalePath(pathname, newLocale, { sourceLocale, locales, localePrefix })\n router.push(newPath)\n // 4. Refresh server components\n router.refresh()\n }\n\n return {\n switchLocale,\n currentLocale: locale,\n locales,\n sourceLocale,\n }\n}\n\n// Re-export createNavigation and routing utilities\nexport { createNavigation } from './create-navigation'\nexport { defineRouting, resolveLocalizedPath } from './routing'\nexport type { RoutingConfig } from './routing'\n\n// ── useAlternateLinks ─────────────────────────────────────────────────────\n\nexport interface AlternateLink {\n hreflang: string\n href: string\n}\n\n/**\n * Generate alternate link entries for SEO `<head>` tags.\n *\n * Returns an array of `{ hreflang, href }` entries for all configured locales\n * plus `x-default`. Use in `<head>` for hreflang tags.\n *\n * @example\n * ```tsx\n * import { useAlternateLinks } from '@fluenti/next/navigation'\n * import { routing } from '@/i18n/routing'\n *\n * export function Head() {\n * const links = useAlternateLinks({ routing, baseUrl: 'https://example.com' })\n * return (\n * <head>\n * {links.map(l => (\n * <link key={l.hreflang} rel=\"alternate\" hreflang={l.hreflang} href={l.href} />\n * ))}\n * </head>\n * )\n * }\n * ```\n */\nexport function useAlternateLinks(options: {\n routing: { locales: readonly string[]; sourceLocale: string; localePrefix?: 'always' | 'as-needed' | 'never'; pathnames?: Record<string, Record<string, string>> }\n baseUrl?: string\n}): AlternateLink[] {\n const { routing: r, baseUrl = '' } = options\n const pathname = usePathname()\n let activeLocale = r.sourceLocale\n try {\n activeLocale = useI18n().locale\n } catch {\n // Outside I18nProvider, fall back to sourceLocale.\n }\n // Strip locale prefix from current path\n const segments = pathname.split('/')\n const firstSeg = segments[1] ?? ''\n const pathLocale = r.localePrefix === 'never'\n ? null\n : (r.locales as string[]).find(l => l.toLowerCase() === firstSeg.toLowerCase()) ?? null\n const cleanPath = pathLocale ? '/' + segments.slice(2).join('/') || '/' : pathname\n const requestLocale = pathLocale ?? activeLocale ?? r.sourceLocale\n const internalPath = r.pathnames\n ? resolveInternalPath(cleanPath, requestLocale, r.pathnames as Record<string, Record<string, string>>) ?? cleanPath\n : cleanPath\n\n const links: AlternateLink[] = (r.locales as string[]).map(loc => {\n const localePath = r.pathnames\n ? resolveLocalizedPath(internalPath, loc, r.pathnames as Record<string, Record<string, string>>) ?? internalPath\n : internalPath\n\n let href: string\n if (r.localePrefix === 'never') {\n href = `${baseUrl}${localePath}`\n } else if (r.localePrefix !== 'always' && loc === r.sourceLocale) {\n href = `${baseUrl}${localePath}`\n } else {\n href = `${baseUrl}/${loc}${localePath}`\n }\n\n return { hreflang: loc, href }\n })\n\n // x-default\n const sourcePath = r.pathnames\n ? resolveLocalizedPath(internalPath, r.sourceLocale, r.pathnames as Record<string, Record<string, string>>) ?? internalPath\n : internalPath\n const defaultPath = r.localePrefix === 'always'\n ? `${baseUrl}/${r.sourceLocale}${sourcePath}`\n : `${baseUrl}${sourcePath}`\n links.push({ hreflang: 'x-default', href: defaultPath })\n\n return links\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,cAAc,EACd,QAAQ,EACR,aAAa,EACb,WAAW,EACX,aAAa,EACb,QAAQ,GACT,EAAE,uBAAuB,2CAazB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-navigation.d.ts","sourceRoot":"","sources":["../../../../src/create-navigation.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAE9C,YAAY,EAAE,aAAa,EAAE,CAAA;AAE7B,UAAU,mBAAmB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM;IAChF,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;IACzC,MAAM,CAAC,EAAE,CAAC,CAAA;IACV,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACzB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,UAAU,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM;IACxE,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,CAAC,CAAA;KAAE,GAAG,IAAI,CAAA;IAC/E,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,CAAC,CAAA;KAAE,GAAG,IAAI,CAAA;IAClF,IAAI,IAAI,IAAI,CAAA;IACZ,OAAO,IAAI,IAAI,CAAA;IACf,OAAO,IAAI,IAAI,CAAA;IACf,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAC7B;AAID,wBAAgB,gBAAgB,CAC9B,KAAK,CAAC,CAAC,SAAS,MAAM,EACtB,KAAK,CAAC,CAAC,SAAS,MAAM,EACtB,OAAO,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC;;qBAoDN,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;qBAyBf,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,WAAW,CAAC,KAAG,KAAK;uBASvD,MAAM;wBASH,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,UAAU,CAAC,KAAG,MAAM;EAKnF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"dev-runner.d.ts","sourceRoot":"","sources":["../../../../src/dev-runner.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAA;IAC9B,6EAA6E;IAC7E,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,+FAA+F;IAC/F,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,sEAAsE;IACtE,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+DhF;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,gBAAgB,EACzB,KAAK,SAAM,GACV,MAAM,IAAI,CAiCZ"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"dev-watcher.d.ts","sourceRoot":"","sources":["../../../../src/dev-watcher.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,sEAAsE;IACtE,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAY1E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,IAAI,CAwCtE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"generate-server-module.d.ts","sourceRoot":"","sources":["../../../../src/generate-server-module.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAanD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,oBAAoB,GAC3B,MAAM,CAmTR"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"i18n-config.d.ts","sourceRoot":"","sources":["../../../../src/i18n-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,0EAA0E;AAC1E,eAAO,MAAM,OAAO,EAAE,MAAM,EAAW,CAAA;AAEvC,8EAA8E;AAC9E,eAAO,MAAM,YAAY,EAAE,MAAa,CAAA;AAExC,yFAAyF;AACzF,eAAO,MAAM,UAAU,EAAE,MAAiB,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../../../src/middleware.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../../../src/navigation.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,oBAAoB;IACnC,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAA;CAChD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,oBAAoB,GAC7B,MAAM,CA2BR;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE;IAC1C,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gFAAgF;IAChF,YAAY,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAA;CAChD;8BAWkC,MAAM;;;;EAyBxC;AAGD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAC/D,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAI9C,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,OAAO,EAAE;QAAE,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;KAAE,CAAA;IAClK,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,GAAG,aAAa,EAAE,CAgDlB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../../src/provider.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,IAAI,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACtE,YAAY,EAAE,uBAAuB,IAAI,iBAAiB,EAAE,MAAM,mBAAmB,CAAA"}
@@ -1 +0,0 @@
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,CA8BtB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../../../src/routing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAM,WAAW,aAAa,CAC5B,CAAC,SAAS,MAAM,GAAG,MAAM,EACzB,CAAC,SAAS,MAAM,GAAG,MAAM;IAEzB,OAAO,EAAE,SAAS,CAAC,EAAE,CAAA;IACrB,YAAY,EAAE,CAAC,CAAA;IACf,YAAY,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAA;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;CAClD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,KAAK,CAAC,CAAC,SAAS,MAAM,EACtB,KAAK,CAAC,CAAC,SAAS,MAAM,EACtB,MAAM,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAElD;AAyCD,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAuB7F;AAED,wCAAwC;AACxC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAKxF;AAED,sDAAsD;AACtD,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAChD,MAAM,GAAG,IAAI,CASf;AAED,sDAAsD;AACtD,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAChD,MAAM,GAAG,IAAI,CASf"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAM1C;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAErD;AAED;;;;GAIG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAcjD;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAEjF"}
@@ -1 +0,0 @@
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;IACpC;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAIlB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6DAA6D;IAC7D,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAE3B;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAE5B;;;;;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;IAClB,kBAAkB,EAAE,OAAO,CAAA;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"with-fluenti.d.ts","sourceRoot":"","sources":["../../../../src/with-fluenti.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAQ/C,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;AAErC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,YAAY,CAAC,EAAE,gBAAgB,GAAG,CAAC,UAAU,CAAC,EAAE,UAAU,KAAK,UAAU,CAAA;AACrG,wBAAgB,WAAW,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"with-locale.d.ts","sourceRoot":"","sources":["../../../../src/with-locale.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAChC,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EACxB,YAAY,CAAC,EAAE;IAAE,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,GACjF,OAAO,CAAC,CAAC,CAAC,CAwBZ"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"provider.cjs","names":[],"sources":["../src/client-provider.tsx"],"sourcesContent":["'use client'\n\nimport type { ReactNode } from 'react'\nimport { I18nProvider } from '@fluenti/react'\nimport type { AllMessages, DateFormatOptions, NumberFormatOptions, Locale } from '@fluenti/core'\n\nexport interface ClientI18nProviderProps {\n locale: string\n fallbackLocale: string\n messages: AllMessages\n fallbackChain?: Record<string, Locale[]>\n dateFormats?: DateFormatOptions\n numberFormats?: NumberFormatOptions\n children: ReactNode\n}\n\n/**\n * Client-side I18nProvider wrapper for Next.js App Router.\n *\n * Wraps `@fluenti/react`'s `I18nProvider` with the `'use client'` directive,\n * enabling hydration of client components in a Server Component tree.\n * Re-exported as `I18nProvider` from `@fluenti/next/provider`.\n *\n * @example\n * ```tsx\n * // app/layout.tsx\n * import { I18nProvider } from '@fluenti/next/provider'\n * import en from '../locales/compiled/en.js'\n *\n * export default function RootLayout({ children }: { children: React.ReactNode }) {\n * return (\n * <html>\n * <body>\n * <I18nProvider\n * locale=\"en\"\n * fallbackLocale=\"en\"\n * messages={{ en }}\n * >\n * {children}\n * </I18nProvider>\n * </body>\n * </html>\n * )\n * }\n * ```\n */\nexport function ClientI18nProvider({\n locale,\n fallbackLocale,\n messages,\n fallbackChain,\n dateFormats,\n numberFormats,\n children,\n}: ClientI18nProviderProps) {\n return (\n <I18nProvider\n locale={locale}\n fallbackLocale={fallbackLocale}\n messages={messages}\n {...(fallbackChain ? { fallbackChain } : {})}\n {...(dateFormats ? { dateFormats } : {})}\n {...(numberFormats ? { numberFormats } : {})}\n >\n {children}\n </I18nProvider>\n )\n}\n"],"mappings":"kIA8CA,SAAgB,EAAmB,CACjC,SACA,iBACA,WACA,gBACA,cACA,gBACA,YAC0B,CAC1B,OACE,EAAA,EAAA,KAAC,EAAA,aAAD,CACU,SACQ,iBACN,WACV,GAAK,EAAgB,CAAE,gBAAe,CAAG,EAAE,CAC3C,GAAK,EAAc,CAAE,cAAa,CAAG,EAAE,CACvC,GAAK,EAAgB,CAAE,gBAAe,CAAG,EAAE,CAE1C,WACY,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"provider.js","names":[],"sources":["../src/client-provider.tsx"],"sourcesContent":["'use client'\n\nimport type { ReactNode } from 'react'\nimport { I18nProvider } from '@fluenti/react'\nimport type { AllMessages, DateFormatOptions, NumberFormatOptions, Locale } from '@fluenti/core'\n\nexport interface ClientI18nProviderProps {\n locale: string\n fallbackLocale: string\n messages: AllMessages\n fallbackChain?: Record<string, Locale[]>\n dateFormats?: DateFormatOptions\n numberFormats?: NumberFormatOptions\n children: ReactNode\n}\n\n/**\n * Client-side I18nProvider wrapper for Next.js App Router.\n *\n * Wraps `@fluenti/react`'s `I18nProvider` with the `'use client'` directive,\n * enabling hydration of client components in a Server Component tree.\n * Re-exported as `I18nProvider` from `@fluenti/next/provider`.\n *\n * @example\n * ```tsx\n * // app/layout.tsx\n * import { I18nProvider } from '@fluenti/next/provider'\n * import en from '../locales/compiled/en.js'\n *\n * export default function RootLayout({ children }: { children: React.ReactNode }) {\n * return (\n * <html>\n * <body>\n * <I18nProvider\n * locale=\"en\"\n * fallbackLocale=\"en\"\n * messages={{ en }}\n * >\n * {children}\n * </I18nProvider>\n * </body>\n * </html>\n * )\n * }\n * ```\n */\nexport function ClientI18nProvider({\n locale,\n fallbackLocale,\n messages,\n fallbackChain,\n dateFormats,\n numberFormats,\n children,\n}: ClientI18nProviderProps) {\n return (\n <I18nProvider\n locale={locale}\n fallbackLocale={fallbackLocale}\n messages={messages}\n {...(fallbackChain ? { fallbackChain } : {})}\n {...(dateFormats ? { dateFormats } : {})}\n {...(numberFormats ? { numberFormats } : {})}\n >\n {children}\n </I18nProvider>\n )\n}\n"],"mappings":";;;AA8CA,SAAgB,EAAmB,EACjC,WACA,mBACA,aACA,kBACA,gBACA,kBACA,eAC0B;AAC1B,QACE,kBAAC,GAAD;EACU;EACQ;EACN;EACV,GAAK,IAAgB,EAAE,kBAAe,GAAG,EAAE;EAC3C,GAAK,IAAc,EAAE,gBAAa,GAAG,EAAE;EACvC,GAAK,IAAgB,EAAE,kBAAe,GAAG,EAAE;EAE1C;EACY,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"routing-CRln5Gw7.js","names":[],"sources":["../src/routing.ts"],"sourcesContent":["/**\n * Shared routing configuration for middleware and navigation.\n *\n * Define once, use everywhere:\n *\n * @example\n * ```ts\n * // src/i18n/routing.ts\n * import { defineRouting } from '@fluenti/next'\n *\n * export const routing = defineRouting({\n * locales: ['en', 'fr', 'ja'],\n * sourceLocale: 'en',\n * localePrefix: 'as-needed',\n * pathnames: {\n * '/about': { fr: '/a-propos' },\n * '/blog/[slug]': { fr: '/articles/[slug]' },\n * },\n * })\n * ```\n *\n * Then pass to both middleware and navigation:\n * ```ts\n * // middleware.ts\n * export default createI18nMiddleware({ NextResponse, ...routing })\n *\n * // src/i18n/navigation.ts\n * export const { Link, useRouter } = createNavigation(routing)\n * ```\n */\n\nexport interface RoutingConfig<\n L extends string = string,\n P extends string = string,\n> {\n locales: readonly L[]\n sourceLocale: L\n localePrefix?: 'always' | 'as-needed' | 'never'\n pathnames?: Record<P, Partial<Record<L, string>>>\n}\n\n/**\n * Define a routing configuration for use with both `createI18nMiddleware` and `createNavigation`.\n *\n * This is a type-only helper — it returns the input unchanged but captures\n * the literal types of locales and pathname keys for type-safe navigation.\n */\nexport function defineRouting<\n const L extends string,\n const P extends string,\n>(config: RoutingConfig<L, P>): RoutingConfig<L, P> {\n return config\n}\n\nfunction getPatternSegments(pattern: string): string[] {\n return pattern.split('/').filter(Boolean)\n}\n\nfunction getSegmentPriority(segment: string | undefined): number {\n if (!segment) return 0\n if (segment.startsWith('[...') && segment.endsWith(']')) return 1\n if (segment.startsWith('[') && segment.endsWith(']')) return 2\n return 3\n}\n\nfunction comparePatterns(a: string, b: string): number {\n const aSegments = getPatternSegments(a)\n const bSegments = getPatternSegments(b)\n const maxLength = Math.max(aSegments.length, bSegments.length)\n\n for (let i = 0; i < maxLength; i++) {\n const aPriority = getSegmentPriority(aSegments[i])\n const bPriority = getSegmentPriority(bSegments[i])\n if (aPriority !== bPriority) {\n return bPriority - aPriority\n }\n }\n\n if (aSegments.length !== bSegments.length) {\n return bSegments.length - aSegments.length\n }\n\n return a.localeCompare(b)\n}\n\nfunction getSortedPathnameEntries(\n pathnames: Record<string, Record<string, string>>,\n): Array<[string, Record<string, string>]> {\n return Object.entries(pathnames).sort(([a], [b]) => comparePatterns(a, b))\n}\n\n// ── Shared path resolution utilities ──────────────────────────────────────\n\n/** Match a pathname against a pattern with [param] and [...slug] segments. */\nexport function matchPattern(pattern: string, pathname: string): Record<string, string> | null {\n const patternParts = pattern.split('/').filter(Boolean)\n const pathParts = pathname.split('/').filter(Boolean)\n\n const params: Record<string, string> = {}\n\n for (let i = 0; i < patternParts.length; i++) {\n const pp = patternParts[i]!\n if (pp.startsWith('[...') && pp.endsWith(']')) {\n const key = pp.slice(4, -1)\n params[key] = pathParts.slice(i).join('/')\n return params\n }\n if (pp.startsWith('[') && pp.endsWith(']')) {\n if (i >= pathParts.length) return null\n params[pp.slice(1, -1)] = pathParts[i]!\n continue\n }\n if (i >= pathParts.length || pp !== pathParts[i]) return null\n }\n\n if (patternParts.length !== pathParts.length) return null\n return params\n}\n\n/** Substitute params into a pattern. */\nexport function substituteParams(pattern: string, params: Record<string, string>): string {\n return pattern.replace(/\\[\\.\\.\\.(\\w+)\\]|\\[(\\w+)\\]/g, (_, catchAll, param) => {\n const key = catchAll ?? param\n return params[key] ?? ''\n })\n}\n\n/** Reverse lookup: localized path → internal path. */\nexport function resolveInternalPath(\n localizedPath: string,\n locale: string,\n pathnames: Record<string, Record<string, string>>,\n): string | null {\n for (const [internal, mapping] of getSortedPathnameEntries(pathnames)) {\n const localized = mapping[locale]\n if (!localized) continue\n if (localized === localizedPath) return internal\n const params = matchPattern(localized, localizedPath)\n if (params) return substituteParams(internal, params)\n }\n return null\n}\n\n/** Forward lookup: internal path → localized path. */\nexport function resolveLocalizedPath(\n internalPath: string,\n locale: string,\n pathnames: Record<string, Record<string, string>>,\n): string | null {\n for (const [internal, mapping] of getSortedPathnameEntries(pathnames)) {\n const localized = mapping[locale]\n if (!localized) continue\n if (internal === internalPath) return localized\n const params = matchPattern(internal, internalPath)\n if (params) return substituteParams(localized, params)\n }\n return null\n}\n"],"mappings":";AA+CA,SAAgB,EAGd,GAAkD;AAClD,QAAO;;AAGT,SAAS,EAAmB,GAA2B;AACrD,QAAO,EAAQ,MAAM,IAAI,CAAC,OAAO,QAAQ;;AAG3C,SAAS,EAAmB,GAAqC;AAI/D,QAHK,IACD,EAAQ,WAAW,OAAO,IAAI,EAAQ,SAAS,IAAI,GAAS,IAC5D,EAAQ,WAAW,IAAI,IAAI,EAAQ,SAAS,IAAI,GAAS,IACtD,IAHc;;AAMvB,SAAS,EAAgB,GAAW,GAAmB;CACrD,IAAM,IAAY,EAAmB,EAAE,EACjC,IAAY,EAAmB,EAAE,EACjC,IAAY,KAAK,IAAI,EAAU,QAAQ,EAAU,OAAO;AAE9D,MAAK,IAAI,IAAI,GAAG,IAAI,GAAW,KAAK;EAClC,IAAM,IAAY,EAAmB,EAAU,GAAG,EAC5C,IAAY,EAAmB,EAAU,GAAG;AAClD,MAAI,MAAc,EAChB,QAAO,IAAY;;AAQvB,QAJI,EAAU,WAAW,EAAU,SAI5B,EAAE,cAAc,EAAE,GAHhB,EAAU,SAAS,EAAU;;AAMxC,SAAS,EACP,GACyC;AACzC,QAAO,OAAO,QAAQ,EAAU,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAgB,GAAG,EAAE,CAAC;;AAM5E,SAAgB,EAAa,GAAiB,GAAiD;CAC7F,IAAM,IAAe,EAAQ,MAAM,IAAI,CAAC,OAAO,QAAQ,EACjD,IAAY,EAAS,MAAM,IAAI,CAAC,OAAO,QAAQ,EAE/C,IAAiC,EAAE;AAEzC,MAAK,IAAI,IAAI,GAAG,IAAI,EAAa,QAAQ,KAAK;EAC5C,IAAM,IAAK,EAAa;AACxB,MAAI,EAAG,WAAW,OAAO,IAAI,EAAG,SAAS,IAAI,EAAE;GAC7C,IAAM,IAAM,EAAG,MAAM,GAAG,GAAG;AAE3B,UADA,EAAO,KAAO,EAAU,MAAM,EAAE,CAAC,KAAK,IAAI,EACnC;;AAET,MAAI,EAAG,WAAW,IAAI,IAAI,EAAG,SAAS,IAAI,EAAE;AAC1C,OAAI,KAAK,EAAU,OAAQ,QAAO;AAClC,KAAO,EAAG,MAAM,GAAG,GAAG,IAAI,EAAU;AACpC;;AAEF,MAAI,KAAK,EAAU,UAAU,MAAO,EAAU,GAAI,QAAO;;AAI3D,QADI,EAAa,WAAW,EAAU,SAC/B,IAD8C;;AAKvD,SAAgB,EAAiB,GAAiB,GAAwC;AACxF,QAAO,EAAQ,QAAQ,+BAA+B,GAAG,GAAU,MAE1D,EADK,KAAY,MACF,GACtB;;AAIJ,SAAgB,EACd,GACA,GACA,GACe;AACf,MAAK,IAAM,CAAC,GAAU,MAAY,EAAyB,EAAU,EAAE;EACrE,IAAM,IAAY,EAAQ;AAC1B,MAAI,CAAC,EAAW;AAChB,MAAI,MAAc,EAAe,QAAO;EACxC,IAAM,IAAS,EAAa,GAAW,EAAc;AACrD,MAAI,EAAQ,QAAO,EAAiB,GAAU,EAAO;;AAEvD,QAAO;;AAIT,SAAgB,EACd,GACA,GACA,GACe;AACf,MAAK,IAAM,CAAC,GAAU,MAAY,EAAyB,EAAU,EAAE;EACrE,IAAM,IAAY,EAAQ;AAC1B,MAAI,CAAC,EAAW;AAChB,MAAI,MAAa,EAAc,QAAO;EACtC,IAAM,IAAS,EAAa,GAAU,EAAa;AACnD,MAAI,EAAQ,QAAO,EAAiB,GAAW,EAAO;;AAExD,QAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"routing-D4p8HvMH.cjs","names":[],"sources":["../src/routing.ts"],"sourcesContent":["/**\n * Shared routing configuration for middleware and navigation.\n *\n * Define once, use everywhere:\n *\n * @example\n * ```ts\n * // src/i18n/routing.ts\n * import { defineRouting } from '@fluenti/next'\n *\n * export const routing = defineRouting({\n * locales: ['en', 'fr', 'ja'],\n * sourceLocale: 'en',\n * localePrefix: 'as-needed',\n * pathnames: {\n * '/about': { fr: '/a-propos' },\n * '/blog/[slug]': { fr: '/articles/[slug]' },\n * },\n * })\n * ```\n *\n * Then pass to both middleware and navigation:\n * ```ts\n * // middleware.ts\n * export default createI18nMiddleware({ NextResponse, ...routing })\n *\n * // src/i18n/navigation.ts\n * export const { Link, useRouter } = createNavigation(routing)\n * ```\n */\n\nexport interface RoutingConfig<\n L extends string = string,\n P extends string = string,\n> {\n locales: readonly L[]\n sourceLocale: L\n localePrefix?: 'always' | 'as-needed' | 'never'\n pathnames?: Record<P, Partial<Record<L, string>>>\n}\n\n/**\n * Define a routing configuration for use with both `createI18nMiddleware` and `createNavigation`.\n *\n * This is a type-only helper — it returns the input unchanged but captures\n * the literal types of locales and pathname keys for type-safe navigation.\n */\nexport function defineRouting<\n const L extends string,\n const P extends string,\n>(config: RoutingConfig<L, P>): RoutingConfig<L, P> {\n return config\n}\n\nfunction getPatternSegments(pattern: string): string[] {\n return pattern.split('/').filter(Boolean)\n}\n\nfunction getSegmentPriority(segment: string | undefined): number {\n if (!segment) return 0\n if (segment.startsWith('[...') && segment.endsWith(']')) return 1\n if (segment.startsWith('[') && segment.endsWith(']')) return 2\n return 3\n}\n\nfunction comparePatterns(a: string, b: string): number {\n const aSegments = getPatternSegments(a)\n const bSegments = getPatternSegments(b)\n const maxLength = Math.max(aSegments.length, bSegments.length)\n\n for (let i = 0; i < maxLength; i++) {\n const aPriority = getSegmentPriority(aSegments[i])\n const bPriority = getSegmentPriority(bSegments[i])\n if (aPriority !== bPriority) {\n return bPriority - aPriority\n }\n }\n\n if (aSegments.length !== bSegments.length) {\n return bSegments.length - aSegments.length\n }\n\n return a.localeCompare(b)\n}\n\nfunction getSortedPathnameEntries(\n pathnames: Record<string, Record<string, string>>,\n): Array<[string, Record<string, string>]> {\n return Object.entries(pathnames).sort(([a], [b]) => comparePatterns(a, b))\n}\n\n// ── Shared path resolution utilities ──────────────────────────────────────\n\n/** Match a pathname against a pattern with [param] and [...slug] segments. */\nexport function matchPattern(pattern: string, pathname: string): Record<string, string> | null {\n const patternParts = pattern.split('/').filter(Boolean)\n const pathParts = pathname.split('/').filter(Boolean)\n\n const params: Record<string, string> = {}\n\n for (let i = 0; i < patternParts.length; i++) {\n const pp = patternParts[i]!\n if (pp.startsWith('[...') && pp.endsWith(']')) {\n const key = pp.slice(4, -1)\n params[key] = pathParts.slice(i).join('/')\n return params\n }\n if (pp.startsWith('[') && pp.endsWith(']')) {\n if (i >= pathParts.length) return null\n params[pp.slice(1, -1)] = pathParts[i]!\n continue\n }\n if (i >= pathParts.length || pp !== pathParts[i]) return null\n }\n\n if (patternParts.length !== pathParts.length) return null\n return params\n}\n\n/** Substitute params into a pattern. */\nexport function substituteParams(pattern: string, params: Record<string, string>): string {\n return pattern.replace(/\\[\\.\\.\\.(\\w+)\\]|\\[(\\w+)\\]/g, (_, catchAll, param) => {\n const key = catchAll ?? param\n return params[key] ?? ''\n })\n}\n\n/** Reverse lookup: localized path → internal path. */\nexport function resolveInternalPath(\n localizedPath: string,\n locale: string,\n pathnames: Record<string, Record<string, string>>,\n): string | null {\n for (const [internal, mapping] of getSortedPathnameEntries(pathnames)) {\n const localized = mapping[locale]\n if (!localized) continue\n if (localized === localizedPath) return internal\n const params = matchPattern(localized, localizedPath)\n if (params) return substituteParams(internal, params)\n }\n return null\n}\n\n/** Forward lookup: internal path → localized path. */\nexport function resolveLocalizedPath(\n internalPath: string,\n locale: string,\n pathnames: Record<string, Record<string, string>>,\n): string | null {\n for (const [internal, mapping] of getSortedPathnameEntries(pathnames)) {\n const localized = mapping[locale]\n if (!localized) continue\n if (internal === internalPath) return localized\n const params = matchPattern(internal, internalPath)\n if (params) return substituteParams(localized, params)\n }\n return null\n}\n"],"mappings":"AA+CA,SAAgB,EAGd,EAAkD,CAClD,OAAO,EAGT,SAAS,EAAmB,EAA2B,CACrD,OAAO,EAAQ,MAAM,IAAI,CAAC,OAAO,QAAQ,CAG3C,SAAS,EAAmB,EAAqC,CAI/D,OAHK,EACD,EAAQ,WAAW,OAAO,EAAI,EAAQ,SAAS,IAAI,CAAS,EAC5D,EAAQ,WAAW,IAAI,EAAI,EAAQ,SAAS,IAAI,CAAS,EACtD,EAHc,EAMvB,SAAS,EAAgB,EAAW,EAAmB,CACrD,IAAM,EAAY,EAAmB,EAAE,CACjC,EAAY,EAAmB,EAAE,CACjC,EAAY,KAAK,IAAI,EAAU,OAAQ,EAAU,OAAO,CAE9D,IAAK,IAAI,EAAI,EAAG,EAAI,EAAW,IAAK,CAClC,IAAM,EAAY,EAAmB,EAAU,GAAG,CAC5C,EAAY,EAAmB,EAAU,GAAG,CAClD,GAAI,IAAc,EAChB,OAAO,EAAY,EAQvB,OAJI,EAAU,SAAW,EAAU,OAI5B,EAAE,cAAc,EAAE,CAHhB,EAAU,OAAS,EAAU,OAMxC,SAAS,EACP,EACyC,CACzC,OAAO,OAAO,QAAQ,EAAU,CAAC,MAAM,CAAC,GAAI,CAAC,KAAO,EAAgB,EAAG,EAAE,CAAC,CAM5E,SAAgB,EAAa,EAAiB,EAAiD,CAC7F,IAAM,EAAe,EAAQ,MAAM,IAAI,CAAC,OAAO,QAAQ,CACjD,EAAY,EAAS,MAAM,IAAI,CAAC,OAAO,QAAQ,CAE/C,EAAiC,EAAE,CAEzC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAa,OAAQ,IAAK,CAC5C,IAAM,EAAK,EAAa,GACxB,GAAI,EAAG,WAAW,OAAO,EAAI,EAAG,SAAS,IAAI,CAAE,CAC7C,IAAM,EAAM,EAAG,MAAM,EAAG,GAAG,CAE3B,MADA,GAAO,GAAO,EAAU,MAAM,EAAE,CAAC,KAAK,IAAI,CACnC,EAET,GAAI,EAAG,WAAW,IAAI,EAAI,EAAG,SAAS,IAAI,CAAE,CAC1C,GAAI,GAAK,EAAU,OAAQ,OAAO,KAClC,EAAO,EAAG,MAAM,EAAG,GAAG,EAAI,EAAU,GACpC,SAEF,GAAI,GAAK,EAAU,QAAU,IAAO,EAAU,GAAI,OAAO,KAI3D,OADI,EAAa,SAAW,EAAU,OAC/B,EAD8C,KAKvD,SAAgB,EAAiB,EAAiB,EAAwC,CACxF,OAAO,EAAQ,QAAQ,8BAA+B,EAAG,EAAU,IAE1D,EADK,GAAY,IACF,GACtB,CAIJ,SAAgB,EACd,EACA,EACA,EACe,CACf,IAAK,GAAM,CAAC,EAAU,KAAY,EAAyB,EAAU,CAAE,CACrE,IAAM,EAAY,EAAQ,GAC1B,GAAI,CAAC,EAAW,SAChB,GAAI,IAAc,EAAe,OAAO,EACxC,IAAM,EAAS,EAAa,EAAW,EAAc,CACrD,GAAI,EAAQ,OAAO,EAAiB,EAAU,EAAO,CAEvD,OAAO,KAIT,SAAgB,EACd,EACA,EACA,EACe,CACf,IAAK,GAAM,CAAC,EAAU,KAAY,EAAyB,EAAU,CAAE,CACrE,IAAM,EAAY,EAAQ,GAC1B,GAAI,CAAC,EAAW,SAChB,GAAI,IAAa,EAAc,OAAO,EACtC,IAAM,EAAS,EAAa,EAAU,EAAa,CACnD,GAAI,EAAQ,OAAO,EAAiB,EAAW,EAAO,CAExD,OAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.cjs","names":[],"sources":["../src/with-locale.ts","../src/server.ts"],"sourcesContent":["/**\n * Per-component locale isolation for RSC.\n *\n * Temporarily switches the request-scoped locale, executes a function,\n * then restores the previous locale. This allows rendering a subtree in\n * a different locale without affecting the rest of the page.\n *\n * @param locale - The locale to switch to for the duration of `fn`.\n * @param fn - The function to execute with the switched locale.\n * @param serverModule - The generated server module reference (auto-injected\n * by the webpack loader in production; only needed when calling manually).\n * @returns The return value of `fn`.\n *\n * @example Basic usage in a Server Component\n * ```tsx\n * // app/page.tsx (Server Component)\n * import { withLocale } from '@fluenti/next/server'\n *\n * export default async function Page() {\n * return (\n * <div>\n * <h1>{t`Main content`}</h1>\n * {await withLocale('ja', async () => (\n * <JapaneseWidget />\n * ))}\n * <Footer />\n * </div>\n * )\n * }\n * ```\n *\n * @example Rendering a multilingual page section\n * ```tsx\n * import { withLocale } from '@fluenti/next/server'\n *\n * export default async function MultilingualPage() {\n * const englishContent = await withLocale('en', async () => (\n * <p>{t`Welcome`}</p>\n * ))\n * const japaneseContent = await withLocale('ja', async () => (\n * <p>{t`Welcome`}</p>\n * ))\n * return (\n * <div>\n * {englishContent}\n * {japaneseContent}\n * </div>\n * )\n * }\n * ```\n */\nexport async function withLocale<T>(\n locale: string,\n fn: () => T | Promise<T>,\n serverModule?: { setLocale: (l: string) => void; getI18n: () => Promise<unknown> },\n): Promise<T> {\n if (!serverModule) {\n throw new Error(\n '[fluenti] withLocale requires a server module reference. ' +\n 'Pass the generated server module as the third argument: ' +\n 'withLocale(\"ja\", fn, serverI18n)',\n )\n }\n\n // Read current locale from the module's request store\n // We need to save/restore state. Since we can't access the store directly,\n // we use setLocale to switch and rely on the caller to restore.\n const prevInstance = await serverModule.getI18n()\n const prevLocale = (prevInstance as { locale: string }).locale\n\n try {\n serverModule.setLocale(locale)\n // Force instance recreation by calling getI18n again\n await serverModule.getI18n()\n return await fn()\n } finally {\n serverModule.setLocale(prevLocale)\n await serverModule.getI18n()\n }\n}\n","/**\n * @module @fluenti/next/server\n *\n * Server-side utilities for Next.js App Router.\n *\n * @example\n * ```tsx\n * import { getLocale, setRequestLocale } from '@fluenti/next/server'\n *\n * export default async function Page({ params }) {\n * const { locale } = await params\n * setRequestLocale(locale)\n * const currentLocale = await getLocale()\n * }\n * ```\n */\n\nimport { cache } from 'react'\n\nexport { withLocale } from './with-locale'\n\n// ── Request-scoped locale store (React.cache) ─────────────────────────────\n\nconst getRequestStore = cache(() => ({ locale: '' }))\n\n/**\n * Set the locale for the current request scope.\n *\n * Call this at the top of page/layout components to enable static rendering.\n * Required for `generateStaticParams` pages where no middleware header is available.\n */\nexport function setRequestLocale(locale: string): void {\n getRequestStore().locale = locale\n}\n\n/**\n * Get the current locale in a Server Component.\n *\n * Resolution: setRequestLocale() → x-fluenti-locale header → 'en'\n */\nexport async function getLocale(): Promise<string> {\n const store = getRequestStore()\n if (store.locale) return store.locale\n\n try {\n const { headers } = await import('next/headers')\n const h = await (headers as () => Promise<{ get(name: string): string | null }>)()\n const headerLocale = h.get('x-fluenti-locale')\n if (headerLocale) return headerLocale\n } catch {\n // headers() not available during static generation\n }\n\n return 'en'\n}\n\n/**\n * Generate static params for all configured locales.\n *\n * @example\n * ```tsx\n * export function generateStaticParams() {\n * return generateLocaleParams(['en', 'ja', 'zh-CN'])\n * }\n * ```\n */\nexport function generateLocaleParams(locales: string[]): Array<{ locale: string }> {\n return locales.map(locale => ({ locale }))\n}\n"],"mappings":"0FAmDA,eAAsB,EACpB,EACA,EACA,EACY,CACZ,GAAI,CAAC,EACH,MAAU,MACR,oJAGD,CAOH,IAAM,GADe,MAAM,EAAa,SAAS,EACO,OAExD,GAAI,CAIF,OAHA,EAAa,UAAU,EAAO,CAE9B,MAAM,EAAa,SAAS,CACrB,MAAM,GAAI,QACT,CACR,EAAa,UAAU,EAAW,CAClC,MAAM,EAAa,SAAS,ECtDhC,IAAM,GAAA,EAAA,EAAA,YAA+B,CAAE,OAAQ,GAAI,EAAE,CAQrD,SAAgB,EAAiB,EAAsB,CACrD,GAAiB,CAAC,OAAS,EAQ7B,eAAsB,GAA6B,CACjD,IAAM,EAAQ,GAAiB,CAC/B,GAAI,EAAM,OAAQ,OAAO,EAAM,OAE/B,GAAI,CACF,GAAM,CAAE,WAAY,MAAM,OAAO,gBAE3B,GADI,MAAO,GAAiE,EAC3D,IAAI,mBAAmB,CAC9C,GAAI,EAAc,OAAO,OACnB,EAIR,MAAO,KAaT,SAAgB,EAAqB,EAA8C,CACjF,OAAO,EAAQ,IAAI,IAAW,CAAE,SAAQ,EAAE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.js","names":[],"sources":["../src/with-locale.ts","../src/server.ts"],"sourcesContent":["/**\n * Per-component locale isolation for RSC.\n *\n * Temporarily switches the request-scoped locale, executes a function,\n * then restores the previous locale. This allows rendering a subtree in\n * a different locale without affecting the rest of the page.\n *\n * @param locale - The locale to switch to for the duration of `fn`.\n * @param fn - The function to execute with the switched locale.\n * @param serverModule - The generated server module reference (auto-injected\n * by the webpack loader in production; only needed when calling manually).\n * @returns The return value of `fn`.\n *\n * @example Basic usage in a Server Component\n * ```tsx\n * // app/page.tsx (Server Component)\n * import { withLocale } from '@fluenti/next/server'\n *\n * export default async function Page() {\n * return (\n * <div>\n * <h1>{t`Main content`}</h1>\n * {await withLocale('ja', async () => (\n * <JapaneseWidget />\n * ))}\n * <Footer />\n * </div>\n * )\n * }\n * ```\n *\n * @example Rendering a multilingual page section\n * ```tsx\n * import { withLocale } from '@fluenti/next/server'\n *\n * export default async function MultilingualPage() {\n * const englishContent = await withLocale('en', async () => (\n * <p>{t`Welcome`}</p>\n * ))\n * const japaneseContent = await withLocale('ja', async () => (\n * <p>{t`Welcome`}</p>\n * ))\n * return (\n * <div>\n * {englishContent}\n * {japaneseContent}\n * </div>\n * )\n * }\n * ```\n */\nexport async function withLocale<T>(\n locale: string,\n fn: () => T | Promise<T>,\n serverModule?: { setLocale: (l: string) => void; getI18n: () => Promise<unknown> },\n): Promise<T> {\n if (!serverModule) {\n throw new Error(\n '[fluenti] withLocale requires a server module reference. ' +\n 'Pass the generated server module as the third argument: ' +\n 'withLocale(\"ja\", fn, serverI18n)',\n )\n }\n\n // Read current locale from the module's request store\n // We need to save/restore state. Since we can't access the store directly,\n // we use setLocale to switch and rely on the caller to restore.\n const prevInstance = await serverModule.getI18n()\n const prevLocale = (prevInstance as { locale: string }).locale\n\n try {\n serverModule.setLocale(locale)\n // Force instance recreation by calling getI18n again\n await serverModule.getI18n()\n return await fn()\n } finally {\n serverModule.setLocale(prevLocale)\n await serverModule.getI18n()\n }\n}\n","/**\n * @module @fluenti/next/server\n *\n * Server-side utilities for Next.js App Router.\n *\n * @example\n * ```tsx\n * import { getLocale, setRequestLocale } from '@fluenti/next/server'\n *\n * export default async function Page({ params }) {\n * const { locale } = await params\n * setRequestLocale(locale)\n * const currentLocale = await getLocale()\n * }\n * ```\n */\n\nimport { cache } from 'react'\n\nexport { withLocale } from './with-locale'\n\n// ── Request-scoped locale store (React.cache) ─────────────────────────────\n\nconst getRequestStore = cache(() => ({ locale: '' }))\n\n/**\n * Set the locale for the current request scope.\n *\n * Call this at the top of page/layout components to enable static rendering.\n * Required for `generateStaticParams` pages where no middleware header is available.\n */\nexport function setRequestLocale(locale: string): void {\n getRequestStore().locale = locale\n}\n\n/**\n * Get the current locale in a Server Component.\n *\n * Resolution: setRequestLocale() → x-fluenti-locale header → 'en'\n */\nexport async function getLocale(): Promise<string> {\n const store = getRequestStore()\n if (store.locale) return store.locale\n\n try {\n const { headers } = await import('next/headers')\n const h = await (headers as () => Promise<{ get(name: string): string | null }>)()\n const headerLocale = h.get('x-fluenti-locale')\n if (headerLocale) return headerLocale\n } catch {\n // headers() not available during static generation\n }\n\n return 'en'\n}\n\n/**\n * Generate static params for all configured locales.\n *\n * @example\n * ```tsx\n * export function generateStaticParams() {\n * return generateLocaleParams(['en', 'ja', 'zh-CN'])\n * }\n * ```\n */\nexport function generateLocaleParams(locales: string[]): Array<{ locale: string }> {\n return locales.map(locale => ({ locale }))\n}\n"],"mappings":";;AAmDA,eAAsB,EACpB,GACA,GACA,GACY;AACZ,KAAI,CAAC,EACH,OAAU,MACR,sJAGD;CAOH,IAAM,KADe,MAAM,EAAa,SAAS,EACO;AAExD,KAAI;AAIF,SAHA,EAAa,UAAU,EAAO,EAE9B,MAAM,EAAa,SAAS,EACrB,MAAM,GAAI;WACT;AAER,EADA,EAAa,UAAU,EAAW,EAClC,MAAM,EAAa,SAAS;;;;;ACtDhC,IAAM,IAAkB,SAAa,EAAE,QAAQ,IAAI,EAAE;AAQrD,SAAgB,EAAiB,GAAsB;AACrD,IAAiB,CAAC,SAAS;;AAQ7B,eAAsB,IAA6B;CACjD,IAAM,IAAQ,GAAiB;AAC/B,KAAI,EAAM,OAAQ,QAAO,EAAM;AAE/B,KAAI;EACF,IAAM,EAAE,eAAY,MAAM,OAAO,iBAE3B,KADI,MAAO,GAAiE,EAC3D,IAAI,mBAAmB;AAC9C,MAAI,EAAc,QAAO;SACnB;AAIR,QAAO;;AAaT,SAAgB,EAAqB,GAA8C;AACjF,QAAO,EAAQ,KAAI,OAAW,EAAE,WAAQ,EAAE"}