next-intlayer 7.0.0-canary.3 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/cjs/client/useLocale.cjs +10 -2
  2. package/dist/cjs/client/useLocale.cjs.map +1 -1
  3. package/dist/cjs/proxy/intlayerProxy.cjs +62 -42
  4. package/dist/cjs/proxy/intlayerProxy.cjs.map +1 -1
  5. package/dist/cjs/proxy/multipleProxies.cjs +4 -4
  6. package/dist/cjs/proxy/multipleProxies.cjs.map +1 -1
  7. package/dist/esm/client/useLocale.mjs +11 -3
  8. package/dist/esm/client/useLocale.mjs.map +1 -1
  9. package/dist/esm/proxy/intlayerProxy.mjs +62 -43
  10. package/dist/esm/proxy/intlayerProxy.mjs.map +1 -1
  11. package/dist/esm/proxy/multipleProxies.mjs +4 -4
  12. package/dist/esm/proxy/multipleProxies.mjs.map +1 -1
  13. package/dist/types/client/useLocale.d.ts +4 -4
  14. package/dist/types/client/useLocale.d.ts.map +1 -1
  15. package/dist/types/client/useLocalePageRouter.d.ts +4 -4
  16. package/dist/types/generateStaticParams.d.ts +2 -2
  17. package/dist/types/generateStaticParams.d.ts.map +1 -1
  18. package/dist/types/proxy/intlayerProxy.d.ts.map +1 -1
  19. package/package.json +17 -17
  20. package/dist/cjs/middleware/index.cjs +0 -7
  21. package/dist/cjs/middleware/intlayerMiddleware.cjs +0 -227
  22. package/dist/cjs/middleware/intlayerMiddleware.cjs.map +0 -1
  23. package/dist/cjs/middleware/localeDetector.cjs +0 -21
  24. package/dist/cjs/middleware/localeDetector.cjs.map +0 -1
  25. package/dist/cjs/middleware/multipleMiddlewares.cjs +0 -58
  26. package/dist/cjs/middleware/multipleMiddlewares.cjs.map +0 -1
  27. package/dist/cjs/proxy/multipleProxy.cjs +0 -60
  28. package/dist/cjs/proxy/multipleProxy.cjs.map +0 -1
  29. package/dist/esm/middleware/index.mjs +0 -5
  30. package/dist/esm/middleware/intlayerMiddleware.mjs +0 -223
  31. package/dist/esm/middleware/intlayerMiddleware.mjs.map +0 -1
  32. package/dist/esm/middleware/localeDetector.mjs +0 -19
  33. package/dist/esm/middleware/localeDetector.mjs.map +0 -1
  34. package/dist/esm/middleware/multipleMiddlewares.mjs +0 -56
  35. package/dist/esm/middleware/multipleMiddlewares.mjs.map +0 -1
  36. package/dist/esm/proxy/multipleProxy.mjs +0 -57
  37. package/dist/esm/proxy/multipleProxy.mjs.map +0 -1
  38. package/dist/types/middleware/index.d.ts +0 -4
  39. package/dist/types/middleware/intlayerMiddleware.d.ts +0 -31
  40. package/dist/types/middleware/intlayerMiddleware.d.ts.map +0 -1
  41. package/dist/types/middleware/localeDetector.d.ts +0 -14
  42. package/dist/types/middleware/localeDetector.d.ts.map +0 -1
  43. package/dist/types/middleware/multipleMiddlewares.d.ts +0 -33
  44. package/dist/types/middleware/multipleMiddlewares.d.ts.map +0 -1
  45. package/dist/types/proxy/multipleProxy.d.ts +0 -34
  46. package/dist/types/proxy/multipleProxy.d.ts.map +0 -1
@@ -12,10 +12,18 @@ let react = require("react");
12
12
  react = require_rolldown_runtime.__toESM(react);
13
13
 
14
14
  //#region src/client/useLocale.ts
15
+ const usePathWithoutLocale = () => {
16
+ const pathname = (0, next_navigation_js.usePathname)();
17
+ const [fullPath, setFullPath] = (0, react.useState)(pathname);
18
+ (0, react.useEffect)(() => {
19
+ const search = typeof window !== "undefined" ? window.location.search : "";
20
+ setFullPath(search ? `${pathname}${search}` : pathname);
21
+ }, [pathname]);
22
+ return (0, react.useMemo)(() => (0, __intlayer_core.getPathWithoutLocale)(fullPath), [fullPath]);
23
+ };
15
24
  const useLocale = ({ onChange } = {}) => {
16
25
  const { replace, push } = (0, next_navigation_js.useRouter)();
17
- const pathname = (0, next_navigation_js.usePathname)();
18
- const pathWithoutLocale = (0, react.useMemo)(() => (0, __intlayer_core.getPathWithoutLocale)(pathname), [pathname]);
26
+ const pathWithoutLocale = usePathWithoutLocale();
19
27
  return {
20
28
  ...(0, react_intlayer.useLocale)({ onLocaleChange: (0, react.useCallback)((locale) => {
21
29
  if (!onChange) return;
@@ -1 +1 @@
1
- {"version":3,"file":"useLocale.cjs","names":[],"sources":["../../../src/client/useLocale.ts"],"sourcesContent":["'use client';\n\nimport { getLocalizedUrl, getPathWithoutLocale } from '@intlayer/core';\nimport type { LocalesValues } from '@intlayer/types';\nimport { usePathname, useRouter } from 'next/navigation.js';\nimport { useCallback, useMemo } from 'react';\nimport { useLocale as useLocaleReact } from 'react-intlayer';\n\ntype UseLocaleProps = {\n onChange?: 'replace' | 'push' | ((locale: LocalesValues) => void);\n};\n\nexport const useLocale = ({ onChange }: UseLocaleProps = {}) => {\n const { replace, push } = useRouter();\n const pathname = usePathname();\n const pathWithoutLocale = useMemo(\n () => getPathWithoutLocale(pathname),\n [pathname]\n );\n\n const redirectionFunction = useCallback(\n (locale: LocalesValues) => {\n if (!onChange) return;\n\n if (typeof onChange === 'function') {\n onChange(locale);\n return;\n }\n\n const pathWithLocale = getLocalizedUrl(pathWithoutLocale, locale);\n\n if (onChange === 'replace') {\n replace(pathWithLocale);\n }\n if (onChange === 'push') {\n push(pathWithLocale);\n }\n },\n [replace, push, pathWithoutLocale, onChange]\n );\n\n const reactLocaleHook = useLocaleReact({\n onLocaleChange: redirectionFunction,\n });\n\n return {\n ...reactLocaleHook,\n pathWithoutLocale,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;AAYA,MAAa,aAAa,EAAE,aAA6B,EAAE,KAAK;CAC9D,MAAM,EAAE,SAAS,4CAAoB;CACrC,MAAM,gDAAwB;CAC9B,MAAM,uFACuB,SAAS,EACpC,CAAC,SAAS,CACX;AA2BD,QAAO;EACL,iCALqC,EACrC,wCArBC,WAA0B;AACzB,OAAI,CAAC,SAAU;AAEf,OAAI,OAAO,aAAa,YAAY;AAClC,aAAS,OAAO;AAChB;;GAGF,MAAM,sDAAiC,mBAAmB,OAAO;AAEjE,OAAI,aAAa,UACf,SAAQ,eAAe;AAEzB,OAAI,aAAa,OACf,MAAK,eAAe;KAGxB;GAAC;GAAS;GAAM;GAAmB;GAAS,CAC7C,EAIA,CAAC;EAIA;EACD"}
1
+ {"version":3,"file":"useLocale.cjs","names":[],"sources":["../../../src/client/useLocale.ts"],"sourcesContent":["'use client';\n\nimport { getLocalizedUrl, getPathWithoutLocale } from '@intlayer/core';\nimport type { LocalesValues } from '@intlayer/types';\nimport { usePathname, useRouter } from 'next/navigation.js';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useLocale as useLocaleReact } from 'react-intlayer';\n\ntype UseLocaleProps = {\n onChange?: 'replace' | 'push' | ((locale: LocalesValues) => void);\n};\n\nconst usePathWithoutLocale = () => {\n const pathname = usePathname(); // updates on client navigations\n const [fullPath, setFullPath] = useState(pathname);\n\n useEffect(() => {\n // Runs only on client; avoids suspense.\n const search = typeof window !== 'undefined' ? window.location.search : '';\n setFullPath(search ? `${pathname}${search}` : pathname);\n }, [pathname]);\n\n // Your own helper\n return useMemo(() => getPathWithoutLocale(fullPath), [fullPath]);\n};\n\nexport const useLocale = ({ onChange }: UseLocaleProps = {}) => {\n const { replace, push } = useRouter();\n const pathWithoutLocale = usePathWithoutLocale();\n\n const redirectionFunction = useCallback(\n (locale: LocalesValues) => {\n if (!onChange) return;\n\n if (typeof onChange === 'function') {\n onChange(locale);\n return;\n }\n\n const pathWithLocale = getLocalizedUrl(pathWithoutLocale, locale);\n\n if (onChange === 'replace') {\n replace(pathWithLocale);\n }\n if (onChange === 'push') {\n push(pathWithLocale);\n }\n },\n [replace, push, pathWithoutLocale, onChange]\n );\n\n const reactLocaleHook = useLocaleReact({\n onLocaleChange: redirectionFunction,\n });\n\n return {\n ...reactLocaleHook,\n pathWithoutLocale,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;AAYA,MAAM,6BAA6B;CACjC,MAAM,gDAAwB;CAC9B,MAAM,CAAC,UAAU,mCAAwB,SAAS;AAElD,4BAAgB;EAEd,MAAM,SAAS,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS;AACxE,cAAY,SAAS,GAAG,WAAW,WAAW,SAAS;IACtD,CAAC,SAAS,CAAC;AAGd,2EAA0C,SAAS,EAAE,CAAC,SAAS,CAAC;;AAGlE,MAAa,aAAa,EAAE,aAA6B,EAAE,KAAK;CAC9D,MAAM,EAAE,SAAS,4CAAoB;CACrC,MAAM,oBAAoB,sBAAsB;AA2BhD,QAAO;EACL,iCALqC,EACrC,wCArBC,WAA0B;AACzB,OAAI,CAAC,SAAU;AAEf,OAAI,OAAO,aAAa,YAAY;AAClC,aAAS,OAAO;AAChB;;GAGF,MAAM,sDAAiC,mBAAmB,OAAO;AAEjE,OAAI,aAAa,UACf,SAAQ,eAAe;AAEzB,OAAI,aAAa,OACf,MAAK,eAAe;KAGxB;GAAC;GAAS;GAAM;GAAmB;GAAS,CAC7C,EAIA,CAAC;EAIA;EACD"}
@@ -4,15 +4,18 @@ let __intlayer_config_built = require("@intlayer/config/built");
4
4
  __intlayer_config_built = require_rolldown_runtime.__toESM(__intlayer_config_built);
5
5
  let __intlayer_core = require("@intlayer/core");
6
6
  __intlayer_core = require_rolldown_runtime.__toESM(__intlayer_core);
7
+ let __intlayer_config = require("@intlayer/config");
8
+ __intlayer_config = require_rolldown_runtime.__toESM(__intlayer_config);
7
9
  let next_server = require("next/server");
8
10
  next_server = require_rolldown_runtime.__toESM(next_server);
9
11
 
10
12
  //#region src/proxy/intlayerProxy.ts
11
13
  const { internationalization, routing } = __intlayer_config_built.default ?? {};
12
14
  const { locales, defaultLocale } = internationalization ?? {};
13
- const { headerName, basePath, detectLocaleOnPrefetchNoPrefix, mode } = routing ?? {};
14
- const noPrefix = mode === "no-prefix" || mode === "search-params";
15
- const prefixDefault = mode === "prefix-all";
15
+ const { basePath, mode } = routing ?? {};
16
+ const effectiveMode = mode ?? __intlayer_config.DefaultValues.Routing.ROUTING_MODE;
17
+ const noPrefix = effectiveMode === "no-prefix" || effectiveMode === "search-params";
18
+ const prefixDefault = effectiveMode === "prefix-all";
16
19
  /**
17
20
  * Detects if the request is a prefetch request from Next.js.
18
21
  *
@@ -35,7 +38,7 @@ const isPrefetchRequest = (request) => {
35
38
  return purpose === "prefetch" || nextRouterPrefetch === "1" || !!nextUrl || !!xNextjsData;
36
39
  };
37
40
  const appendLocaleSearchIfNeeded = (search, locale) => {
38
- if (mode !== "search-params") return search;
41
+ if (effectiveMode !== "search-params") return search;
39
42
  const params = new URLSearchParams(search ?? "");
40
43
  params.set("locale", locale);
41
44
  return `?${params.toString()}`;
@@ -65,10 +68,9 @@ const appendLocaleSearchIfNeeded = (search, locale) => {
65
68
  */
66
69
  const intlayerProxy = (request, _event, _response) => {
67
70
  const pathname = request.nextUrl.pathname;
68
- const cookieLocale = getCookieLocale(request);
69
- const basePathTrailingSlash = basePath.endsWith("/");
70
- if (noPrefix) return handleNoPrefix(request, cookieLocale, pathname, basePathTrailingSlash);
71
- return handlePrefix(request, cookieLocale, getPathLocale(pathname), pathname, basePathTrailingSlash);
71
+ const localLocale = getLocalLocale(request);
72
+ if (noPrefix) return handleNoPrefix(request, localLocale, pathname);
73
+ return handlePrefix(request, localLocale, getPathLocale(pathname), pathname);
72
74
  };
73
75
  /**
74
76
  * Retrieves the locale from the request cookies if available and valid.
@@ -76,19 +78,34 @@ const intlayerProxy = (request, _event, _response) => {
76
78
  * @param request - The incoming Next.js request object.
77
79
  * @returns - The locale found in the cookies, or undefined if not found or invalid.
78
80
  */
79
- const getCookieLocale = (request) => (0, __intlayer_core.getLocaleFromStorage)({ getCookie: (name) => request.cookies.get(name)?.value ?? null });
81
+ const getLocalLocale = (request) => (0, __intlayer_core.getLocaleFromStorage)({
82
+ getCookie: (name) => request.cookies.get(name)?.value ?? null,
83
+ getHeader: (name) => request.headers.get(name) ?? null
84
+ });
80
85
  /**
81
86
  * Handles the case where URLs do not have locale prefixes.
82
87
  *
83
88
  * @param request - The incoming Next.js request object.
84
- * @param cookieLocale - The locale from the cookie.
89
+ * @param localLocale - The locale from the cookie.
85
90
  * @param pathname - The pathname from the request URL.
86
- * @param basePathTrailingSlash - Indicates if the basePath ends with a slash.
87
91
  * @returns - The rewritten response with the locale applied.
88
92
  */
89
- const handleNoPrefix = (request, cookieLocale, pathname, basePathTrailingSlash) => {
90
- const locale = cookieLocale ?? defaultLocale;
91
- return rewriteUrl(request, constructPath(locale, pathname, basePath, basePathTrailingSlash, appendLocaleSearchIfNeeded(request.nextUrl.search, locale)), locale);
93
+ const handleNoPrefix = (request, localLocale, pathname) => {
94
+ const pathLocale = getPathLocale(pathname);
95
+ if (pathLocale) {
96
+ const pathWithoutLocale = pathname.slice(`/${pathLocale}`.length) || "/";
97
+ const search$1 = appendLocaleSearchIfNeeded(request.nextUrl.search, pathLocale);
98
+ return redirectUrl(request, search$1 ? `${pathWithoutLocale}${search$1}` : `${pathWithoutLocale}${request.nextUrl.search ?? ""}`);
99
+ }
100
+ const locale = localLocale ?? defaultLocale;
101
+ if (effectiveMode === "search-params") {
102
+ if (new URLSearchParams(request.nextUrl.search).get("locale") === locale) return rewriteUrl(request, `${`/${locale}${pathname}`}${request.nextUrl.search ?? ""}`, locale);
103
+ const search$1 = appendLocaleSearchIfNeeded(request.nextUrl.search, locale);
104
+ return redirectUrl(request, search$1 ? `${pathname}${search$1}` : `${pathname}${request.nextUrl.search ?? ""}`);
105
+ }
106
+ const internalPath = `/${locale}${pathname}`;
107
+ const search = appendLocaleSearchIfNeeded(request.nextUrl.search, locale);
108
+ return rewriteUrl(request, search ? `${internalPath}${search}` : `${internalPath}${request.nextUrl.search ?? ""}`, locale);
92
109
  };
93
110
  /**
94
111
  * Extracts the locale from the URL pathname if present.
@@ -101,47 +118,46 @@ const getPathLocale = (pathname) => locales.find((locale) => pathname.startsWith
101
118
  * Handles the case where URLs have locale prefixes.
102
119
  *
103
120
  * @param request - The incoming Next.js request object.
104
- * @param cookieLocale - The locale from the cookie.
121
+ * @param localLocale - The locale from the cookie.
105
122
  * @param pathLocale - The locale extracted from the pathname.
106
123
  * @param pathname - The pathname from the request URL.
107
124
  * @param basePathTrailingSlash - Indicates if the basePath ends with a slash.
108
125
  * @returns - The response to be returned to the client.
109
126
  */
110
- const handlePrefix = (request, cookieLocale, pathLocale, pathname, basePathTrailingSlash) => {
127
+ const handlePrefix = (request, localLocale, pathLocale, pathname) => {
111
128
  if (!pathLocale) {
112
- if (isPrefetchRequest(request) && !detectLocaleOnPrefetchNoPrefix) return handleMissingPathLocale(request, defaultLocale, pathname, basePathTrailingSlash);
113
- return handleMissingPathLocale(request, cookieLocale, pathname, basePathTrailingSlash);
129
+ if (isPrefetchRequest(request) && true) return handleMissingPathLocale(request, defaultLocale, pathname);
130
+ return handleMissingPathLocale(request, localLocale, pathname);
114
131
  }
115
- return handleExistingPathLocale(request, cookieLocale, pathLocale, pathname, basePathTrailingSlash);
132
+ return handleExistingPathLocale(request, localLocale, pathLocale, pathname);
116
133
  };
117
134
  /**
118
135
  * Handles requests where the locale is missing from the URL pathname.
119
136
  *
120
137
  * @param request - The incoming Next.js request object.
121
- * @param cookieLocale - The locale from the cookie.
138
+ * @param localLocale - The locale from the cookie.
122
139
  * @param pathname - The pathname from the request URL.
123
140
  * @param basePathTrailingSlash - Indicates if the basePath ends with a slash.
124
141
  * @returns - The response to be returned to the client.
125
142
  */
126
- const handleMissingPathLocale = (request, cookieLocale, pathname, basePathTrailingSlash) => {
127
- let locale = cookieLocale ?? require_proxy_localeDetector.localeDetector?.(request) ?? defaultLocale;
143
+ const handleMissingPathLocale = (request, localLocale, pathname) => {
144
+ let locale = localLocale ?? require_proxy_localeDetector.localeDetector?.(request) ?? defaultLocale;
128
145
  if (!locales.includes(locale)) locale = defaultLocale;
129
- const newPath = constructPath(locale, pathname, basePath, basePathTrailingSlash, appendLocaleSearchIfNeeded(request.nextUrl.search, locale));
146
+ const newPath = constructPath(locale, pathname, basePath, appendLocaleSearchIfNeeded(request.nextUrl.search, locale));
130
147
  return prefixDefault || locale !== defaultLocale ? redirectUrl(request, newPath) : rewriteUrl(request, newPath, locale);
131
148
  };
132
149
  /**
133
150
  * Handles requests where the locale exists in the URL pathname.
134
151
  *
135
152
  * @param request - The incoming Next.js request object.
136
- * @param cookieLocale - The locale from the cookie.
153
+ * @param localLocale - The locale from the cookie.
137
154
  * @param pathLocale - The locale extracted from the pathname.
138
155
  * @param pathname - The pathname from the request URL.
139
- * @param basePathTrailingSlash - Indicates if the basePath ends with a slash.
140
156
  * @returns - The response to be returned to the client.
141
157
  */
142
- const handleExistingPathLocale = (request, cookieLocale, pathLocale, pathname, basePathTrailingSlash) => {
143
- if (cookieLocale && cookieLocale !== pathLocale) return redirectUrl(request, handleCookieLocaleMismatch(request, pathname, pathLocale, cookieLocale, basePath, basePathTrailingSlash));
144
- return handleDefaultLocaleRedirect(request, pathLocale, pathname, basePathTrailingSlash);
158
+ const handleExistingPathLocale = (request, localLocale, pathLocale, pathname) => {
159
+ if (localLocale && localLocale !== pathLocale) return redirectUrl(request, handleCookieLocaleMismatch(request, pathname, pathLocale, localLocale, basePath));
160
+ return handleDefaultLocaleRedirect(request, pathLocale, pathname);
145
161
  };
146
162
  /**
147
163
  * Handles the scenario where the locale in the cookie does not match the locale in the URL pathname.
@@ -149,13 +165,12 @@ const handleExistingPathLocale = (request, cookieLocale, pathLocale, pathname, b
149
165
  * @param request - The incoming Next.js request object.
150
166
  * @param pathname - The pathname from the request URL.
151
167
  * @param pathLocale - The locale extracted from the pathname.
152
- * @param cookieLocale - The locale from the cookie.
168
+ * @param localLocale - The locale from the cookie.
153
169
  * @param basePath - The base path of the application.
154
- * @param basePathTrailingSlash - Indicates if the basePath ends with a slash.
155
170
  * @returns - The new URL path with the correct locale.
156
171
  */
157
- const handleCookieLocaleMismatch = (request, pathname, pathLocale, cookieLocale, basePath$1, basePathTrailingSlash) => {
158
- return constructPath(cookieLocale, pathname.replace(`/${pathLocale}`, `/${cookieLocale}`), basePath$1, basePathTrailingSlash, appendLocaleSearchIfNeeded(request.nextUrl.search, cookieLocale));
172
+ const handleCookieLocaleMismatch = (request, pathname, pathLocale, localLocale, basePath$1) => {
173
+ return constructPath(localLocale, pathname.replace(`/${pathLocale}`, `/${localLocale}`), basePath$1, appendLocaleSearchIfNeeded(request.nextUrl.search, localLocale));
159
174
  };
160
175
  /**
161
176
  * Handles redirection when the default locale is used and prefixing is not required.
@@ -163,13 +178,12 @@ const handleCookieLocaleMismatch = (request, pathname, pathLocale, cookieLocale,
163
178
  * @param request - The incoming Next.js request object.
164
179
  * @param pathLocale - The locale extracted from the pathname.
165
180
  * @param pathname - The pathname from the request URL.
166
- * @param basePathTrailingSlash - Indicates if the basePath ends with a slash.
167
181
  * @returns - The rewritten response without the locale prefix.
168
182
  */
169
- const handleDefaultLocaleRedirect = (request, pathLocale, pathname, basePathTrailingSlash) => {
183
+ const handleDefaultLocaleRedirect = (request, pathLocale, pathname) => {
170
184
  if (!prefixDefault && pathLocale === defaultLocale) {
171
185
  let pathWithoutLocale = pathname.slice(`/${pathLocale}`.length) ?? "/";
172
- if (basePathTrailingSlash) pathWithoutLocale = pathWithoutLocale.slice(1);
186
+ if (basePath.endsWith("/")) pathWithoutLocale = pathWithoutLocale.slice(1);
173
187
  const searchWithLocale$1 = appendLocaleSearchIfNeeded(request.nextUrl.search, pathLocale);
174
188
  if (searchWithLocale$1) pathWithoutLocale += searchWithLocale$1;
175
189
  else if (request.nextUrl.search) pathWithoutLocale += request.nextUrl.search;
@@ -184,15 +198,21 @@ const handleDefaultLocaleRedirect = (request, pathLocale, pathname, basePathTrai
184
198
  * @param locale - The locale to include in the path.
185
199
  * @param path - The original path from the request.
186
200
  * @param basePath - The base path of the application.
187
- * @param basePathTrailingSlash - Indicates if the basePath ends with a slash.
188
201
  * @param [search] - The query string from the request URL (optional).
189
202
  * @returns - The constructed new path.
190
203
  */
191
- const constructPath = (locale, path, basePath$1, basePathTrailingSlash, search) => {
192
- const pathWithLocalePrefix = mode === "search-params" ? path : path.startsWith(`/${locale}`) ? path : `${locale}${path}`;
193
- let newPath = `${basePath$1}${basePathTrailingSlash ? "" : "/"}${pathWithLocalePrefix}`;
194
- if (search) newPath += search;
195
- return newPath;
204
+ const constructPath = (locale, path, basePath$1, search) => {
205
+ const pathWithoutPrefix = path.startsWith(`/${locale}`) ? path.slice(`/${locale}`.length) || "/" : path;
206
+ if (effectiveMode === "no-prefix") {
207
+ if (search) return `${pathWithoutPrefix}?${search}`;
208
+ return pathWithoutPrefix;
209
+ }
210
+ if (effectiveMode === "search-params") {
211
+ if (search) return `${pathWithoutPrefix}?${search}`;
212
+ return pathWithoutPrefix;
213
+ }
214
+ const pathWithLocalePrefix = path.startsWith(`/${locale}`) ? path : `${locale}${path}`;
215
+ return `${basePath$1}${basePath$1.endsWith("/") ? "" : "/"}${pathWithLocalePrefix}`;
196
216
  };
197
217
  /**
198
218
  * Rewrites the URL to the new path and sets the locale header.
@@ -206,7 +226,7 @@ const rewriteUrl = (request, newPath, locale) => {
206
226
  const search = request.nextUrl.search;
207
227
  const pathWithSearch = search && !newPath.includes("?") ? `${newPath}${search}` : newPath;
208
228
  const response = next_server.NextResponse.rewrite(new URL(pathWithSearch, request.url));
209
- response.headers.set(headerName, locale);
229
+ (0, __intlayer_core.setLocaleInStorage)(locale, { setHeader: (name, value) => response.headers.set(name, value) });
210
230
  return response;
211
231
  };
212
232
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"intlayerProxy.cjs","names":["configuration","localeDetector","basePath","searchWithLocale","NextResponse"],"sources":["../../../src/proxy/intlayerProxy.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport { getLocaleFromStorage } from '@intlayer/core';\nimport type { Locale } from '@intlayer/types';\nimport {\n type NextFetchEvent,\n type NextRequest,\n NextResponse,\n} from 'next/server';\nimport { localeDetector } from './localeDetector';\n\nconst { internationalization, routing } = configuration ?? {};\nconst { locales, defaultLocale } = internationalization ?? {};\nconst { headerName, basePath, detectLocaleOnPrefetchNoPrefix, mode } =\n routing ?? {};\n// Note: cookie names are resolved inside LocaleStorage based on configuration\n\n// Derived flags from routing.mode\nconst noPrefix = mode === 'no-prefix' || mode === 'search-params';\nconst prefixDefault = mode === 'prefix-all';\n\n/**\n * Detects if the request is a prefetch request from Next.js.\n *\n * Next.js prefetch requests can be identified by several headers:\n * - purpose: 'prefetch' (standard prefetch header)\n * - next-router-prefetch: '1' (Next.js router prefetch)\n * - next-url: present (Next.js internal navigation)\n *\n * During prefetch, we should ignore cookie-based locale detection\n * to prevent unwanted redirects when users are switching locales.\n *\n * @param request - The incoming Next.js request object.\n * @returns - True if the request is a prefetch request, false otherwise.\n */\nconst isPrefetchRequest = (request: NextRequest): boolean => {\n const purpose = request.headers.get('purpose');\n const nextRouterPrefetch = request.headers.get('next-router-prefetch');\n const nextUrl = request.headers.get('next-url');\n const xNextjsData = request.headers.get('x-nextjs-data');\n\n return (\n purpose === 'prefetch' ||\n nextRouterPrefetch === '1' ||\n !!nextUrl ||\n !!xNextjsData\n );\n};\n\n// Ensure locale is reflected in search params when routing mode is 'search-params'\nconst appendLocaleSearchIfNeeded = (\n search: string | undefined,\n locale: Locale\n): string | undefined => {\n if (mode !== 'search-params') return search;\n\n const params = new URLSearchParams(search ?? '');\n\n params.set('locale', locale);\n return `?${params.toString()}`;\n};\n\n/**\n * Proxy that handles the internationalization layer\n *\n * Usage:\n *\n * ```ts\n * // ./src/proxy.ts\n *\n * export { intlayerProxy as proxy } from '@intlayer/next/proxy';\n *\n * // applies this proxy only to files in the app directory\n * export const config = {\n * matcher: '/((?!api|static|.*\\\\..*|_next).*)',\n * };\n * ```\n *\n * Main proxy function for handling internationalization.\n *\n * @param request - The incoming Next.js request object.\n * @param event - The Next.js fetch event (optional).\n * @param response - The Next.js response object (optional).\n * @returns - The response to be returned to the client.\n */\nexport const intlayerProxy = (\n request: NextRequest,\n _event?: NextFetchEvent,\n _response?: NextResponse\n): NextResponse => {\n const pathname = request.nextUrl.pathname;\n\n const cookieLocale = getCookieLocale(request);\n const basePathTrailingSlash = basePath.endsWith('/');\n\n if (\n noPrefix // If the application is configured not to use locale prefixes in URLs\n ) {\n return handleNoPrefix(\n request,\n cookieLocale,\n pathname,\n basePathTrailingSlash\n );\n }\n\n const pathLocale = getPathLocale(pathname);\n\n return handlePrefix(\n request,\n cookieLocale,\n pathLocale,\n pathname,\n basePathTrailingSlash\n );\n};\n\n/**\n * Retrieves the locale from the request cookies if available and valid.\n *\n * @param request - The incoming Next.js request object.\n * @returns - The locale found in the cookies, or undefined if not found or invalid.\n */\nconst getCookieLocale = (request: NextRequest): Locale | undefined =>\n getLocaleFromStorage({\n getCookie: (name: string) => request.cookies.get(name)?.value ?? null,\n });\n\n/**\n * Handles the case where URLs do not have locale prefixes.\n *\n * @param request - The incoming Next.js request object.\n * @param cookieLocale - The locale from the cookie.\n * @param pathname - The pathname from the request URL.\n * @param basePathTrailingSlash - Indicates if the basePath ends with a slash.\n * @returns - The rewritten response with the locale applied.\n */\nconst handleNoPrefix = (\n request: NextRequest,\n cookieLocale: Locale | undefined,\n pathname: string,\n basePathTrailingSlash: boolean\n): NextResponse => {\n const locale = cookieLocale ?? defaultLocale;\n\n const newPath = constructPath(\n locale,\n pathname,\n basePath,\n basePathTrailingSlash,\n appendLocaleSearchIfNeeded(request.nextUrl.search, locale)\n );\n return rewriteUrl(request, newPath, locale);\n};\n\n/**\n * Extracts the locale from the URL pathname if present.\n *\n * @param pathname - The pathname from the request URL.\n * @returns - The locale found in the pathname, or undefined if not found.\n */\nconst getPathLocale = (pathname: string): Locale | undefined =>\n locales.find(\n (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`\n );\n\n/**\n * Handles the case where URLs have locale prefixes.\n *\n * @param request - The incoming Next.js request object.\n * @param cookieLocale - The locale from the cookie.\n * @param pathLocale - The locale extracted from the pathname.\n * @param pathname - The pathname from the request URL.\n * @param basePathTrailingSlash - Indicates if the basePath ends with a slash.\n * @returns - The response to be returned to the client.\n */\nconst handlePrefix = (\n request: NextRequest,\n cookieLocale: Locale | undefined,\n pathLocale: Locale | undefined,\n pathname: string,\n basePathTrailingSlash: boolean\n): NextResponse => {\n if (\n !pathLocale // If the URL does not contain a locale prefix\n ) {\n const isPrefetch = isPrefetchRequest(request);\n\n if (isPrefetch && !detectLocaleOnPrefetchNoPrefix) {\n return handleMissingPathLocale(\n request,\n defaultLocale,\n pathname,\n basePathTrailingSlash\n );\n }\n\n return handleMissingPathLocale(\n request,\n cookieLocale,\n pathname,\n basePathTrailingSlash\n );\n }\n\n // If the URL contains a locale prefix\n return handleExistingPathLocale(\n request,\n cookieLocale,\n pathLocale,\n pathname,\n basePathTrailingSlash\n );\n};\n\n/**\n * Handles requests where the locale is missing from the URL pathname.\n *\n * @param request - The incoming Next.js request object.\n * @param cookieLocale - The locale from the cookie.\n * @param pathname - The pathname from the request URL.\n * @param basePathTrailingSlash - Indicates if the basePath ends with a slash.\n * @returns - The response to be returned to the client.\n */\nconst handleMissingPathLocale = (\n request: NextRequest,\n cookieLocale: Locale | undefined,\n pathname: string,\n basePathTrailingSlash: boolean\n): NextResponse => {\n let locale = (cookieLocale ??\n localeDetector?.(request) ??\n defaultLocale) as Locale;\n if (!locales.includes(locale)) {\n locale = defaultLocale;\n }\n\n const newPath = constructPath(\n locale,\n pathname,\n basePath,\n basePathTrailingSlash,\n appendLocaleSearchIfNeeded(request.nextUrl.search, locale)\n );\n\n return prefixDefault || locale !== defaultLocale\n ? redirectUrl(request, newPath)\n : rewriteUrl(request, newPath, locale);\n};\n\n/**\n * Handles requests where the locale exists in the URL pathname.\n *\n * @param request - The incoming Next.js request object.\n * @param cookieLocale - The locale from the cookie.\n * @param pathLocale - The locale extracted from the pathname.\n * @param pathname - The pathname from the request URL.\n * @param basePathTrailingSlash - Indicates if the basePath ends with a slash.\n * @returns - The response to be returned to the client.\n */\nconst handleExistingPathLocale = (\n request: NextRequest,\n cookieLocale: Locale | undefined,\n pathLocale: Locale,\n pathname: string,\n basePathTrailingSlash: boolean\n): NextResponse => {\n if (\n // If the cookie locale is set and differs from the locale in the URL\n cookieLocale &&\n cookieLocale !== pathLocale\n ) {\n const newPath = handleCookieLocaleMismatch(\n request,\n pathname,\n pathLocale,\n cookieLocale,\n basePath,\n basePathTrailingSlash\n );\n return redirectUrl(request, newPath);\n }\n\n // If the cookie locale matches the path locale, or cookie locale is not set, or serverSetCookie is 'always'\n return handleDefaultLocaleRedirect(\n request,\n pathLocale,\n pathname,\n basePathTrailingSlash\n );\n};\n\n/**\n * Handles the scenario where the locale in the cookie does not match the locale in the URL pathname.\n *\n * @param request - The incoming Next.js request object.\n * @param pathname - The pathname from the request URL.\n * @param pathLocale - The locale extracted from the pathname.\n * @param cookieLocale - The locale from the cookie.\n * @param basePath - The base path of the application.\n * @param basePathTrailingSlash - Indicates if the basePath ends with a slash.\n * @returns - The new URL path with the correct locale.\n */\nconst handleCookieLocaleMismatch = (\n request: NextRequest,\n pathname: string,\n pathLocale: Locale,\n cookieLocale: Locale,\n basePath: string,\n basePathTrailingSlash: boolean\n): string => {\n // Replace the pathLocale in the pathname with the cookieLocale\n const newPath = pathname.replace(`/${pathLocale}`, `/${cookieLocale}`);\n\n return constructPath(\n cookieLocale,\n newPath,\n basePath,\n basePathTrailingSlash,\n appendLocaleSearchIfNeeded(request.nextUrl.search, cookieLocale)\n );\n};\n\n/**\n * Handles redirection when the default locale is used and prefixing is not required.\n *\n * @param request - The incoming Next.js request object.\n * @param pathLocale - The locale extracted from the pathname.\n * @param pathname - The pathname from the request URL.\n * @param basePathTrailingSlash - Indicates if the basePath ends with a slash.\n * @returns - The rewritten response without the locale prefix.\n */\nconst handleDefaultLocaleRedirect = (\n request: NextRequest,\n pathLocale: Locale,\n pathname: string,\n basePathTrailingSlash: boolean\n): NextResponse => {\n if (\n // If default locale should not be prefixed and the pathLocale is the defaultLocale\n !prefixDefault &&\n pathLocale === defaultLocale\n ) {\n let pathWithoutLocale = pathname.slice(`/${pathLocale}`.length) ?? '/';\n\n if (basePathTrailingSlash) {\n pathWithoutLocale = pathWithoutLocale.slice(1);\n }\n\n const searchWithLocale = appendLocaleSearchIfNeeded(\n request.nextUrl.search,\n pathLocale\n );\n if (searchWithLocale) {\n pathWithoutLocale += searchWithLocale;\n } else if (request.nextUrl.search) {\n pathWithoutLocale += request.nextUrl.search;\n }\n\n return rewriteUrl(request, `${basePath}${pathWithoutLocale}`, pathLocale);\n }\n\n // If prefixing default locale is required or pathLocale is not the defaultLocale\n\n const searchWithLocale = appendLocaleSearchIfNeeded(\n request.nextUrl.search,\n pathLocale\n );\n const newPath = searchWithLocale\n ? `${pathname}${searchWithLocale}`\n : pathname;\n return rewriteUrl(request, newPath, pathLocale);\n};\n\n/**\n * Constructs a new path by combining the locale, path, basePath, and search parameters.\n *\n * @param locale - The locale to include in the path.\n * @param path - The original path from the request.\n * @param basePath - The base path of the application.\n * @param basePathTrailingSlash - Indicates if the basePath ends with a slash.\n * @param [search] - The query string from the request URL (optional).\n * @returns - The constructed new path.\n */\nconst constructPath = (\n locale: Locale,\n path: string,\n basePath: string,\n basePathTrailingSlash: boolean,\n search?: string\n): string => {\n // In 'search-params' mode, we do not prefix the path with the locale\n // If the path is already prefixed with the same locale (e.g. '/fr/...'), avoid double prefixing\n const pathWithLocalePrefix =\n mode === 'search-params'\n ? path\n : path.startsWith(`/${locale}`)\n ? path\n : `${locale}${path}`;\n\n let newPath = `${basePath}${basePathTrailingSlash ? '' : '/'}${pathWithLocalePrefix}`;\n if (search) {\n newPath += search;\n }\n return newPath;\n};\n\n/**\n * Rewrites the URL to the new path and sets the locale header.\n *\n * @param request - The incoming Next.js request object.\n * @param newPath - The new path to rewrite to.\n * @param locale - The locale to set in the response header.\n * @returns - The rewritten response.\n */\nconst rewriteUrl = (\n request: NextRequest,\n newPath: string,\n locale: Locale\n): NextResponse => {\n // Ensure we preserve the original search params if they were present and not explicitly included in newPath\n const search = request.nextUrl.search;\n const pathWithSearch =\n search && !newPath.includes('?') ? `${newPath}${search}` : newPath;\n\n const response = NextResponse.rewrite(new URL(pathWithSearch, request.url));\n response.headers.set(headerName, locale);\n return response;\n};\n\n/**\n * Redirects the request to the new path.\n *\n * @param request - The incoming Next.js request object.\n * @param newPath - The new path to redirect to.\n * @returns - The redirect response.\n */\nconst redirectUrl = (request: NextRequest, newPath: string): NextResponse => {\n // Ensure we preserve the original search params if they were present and not explicitly included in newPath\n const search = request.nextUrl.search;\n const pathWithSearch =\n search && !newPath.includes('?') ? `${newPath}${search}` : newPath;\n\n return NextResponse.redirect(new URL(pathWithSearch, request.url));\n};\n\n/**\n * Middleware that handles the internationalization layer\n *\n * Usage:\n *\n * ```ts\n * // ./src/middleware.ts\n *\n * export { intlayerMiddleware as middleware } from '@intlayer/next/middleware';\n *\n * // applies this middleware only to files in the app directory\n * export const config = {\n * matcher: '/((?!api|static|.*\\\\..*|_next).*)',\n * };\n * ```\n *\n * Main middleware function for handling internationalization.\n *\n * @param request - The incoming Next.js request object.\n * @param event - The Next.js fetch event (optional).\n * @param response - The Next.js response object (optional).\n * @returns - The response to be returned to the client.\n */\nexport const intlayerMiddleware = intlayerProxy;\n"],"mappings":";;;;;;;;;;AAUA,MAAM,EAAE,sBAAsB,YAAYA,mCAAiB,EAAE;AAC7D,MAAM,EAAE,SAAS,kBAAkB,wBAAwB,EAAE;AAC7D,MAAM,EAAE,YAAY,UAAU,gCAAgC,SAC5D,WAAW,EAAE;AAIf,MAAM,WAAW,SAAS,eAAe,SAAS;AAClD,MAAM,gBAAgB,SAAS;;;;;;;;;;;;;;;AAgB/B,MAAM,qBAAqB,YAAkC;CAC3D,MAAM,UAAU,QAAQ,QAAQ,IAAI,UAAU;CAC9C,MAAM,qBAAqB,QAAQ,QAAQ,IAAI,uBAAuB;CACtE,MAAM,UAAU,QAAQ,QAAQ,IAAI,WAAW;CAC/C,MAAM,cAAc,QAAQ,QAAQ,IAAI,gBAAgB;AAExD,QACE,YAAY,cACZ,uBAAuB,OACvB,CAAC,CAAC,WACF,CAAC,CAAC;;AAKN,MAAM,8BACJ,QACA,WACuB;AACvB,KAAI,SAAS,gBAAiB,QAAO;CAErC,MAAM,SAAS,IAAI,gBAAgB,UAAU,GAAG;AAEhD,QAAO,IAAI,UAAU,OAAO;AAC5B,QAAO,IAAI,OAAO,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;AA0B9B,MAAa,iBACX,SACA,QACA,cACiB;CACjB,MAAM,WAAW,QAAQ,QAAQ;CAEjC,MAAM,eAAe,gBAAgB,QAAQ;CAC7C,MAAM,wBAAwB,SAAS,SAAS,IAAI;AAEpD,KACE,SAEA,QAAO,eACL,SACA,cACA,UACA,sBACD;AAKH,QAAO,aACL,SACA,cAJiB,cAAc,SAAS,EAMxC,UACA,sBACD;;;;;;;;AASH,MAAM,mBAAmB,sDACF,EACnB,YAAY,SAAiB,QAAQ,QAAQ,IAAI,KAAK,EAAE,SAAS,MAClE,CAAC;;;;;;;;;;AAWJ,MAAM,kBACJ,SACA,cACA,UACA,0BACiB;CACjB,MAAM,SAAS,gBAAgB;AAS/B,QAAO,WAAW,SAPF,cACd,QACA,UACA,UACA,uBACA,2BAA2B,QAAQ,QAAQ,QAAQ,OAAO,CAC3D,EACmC,OAAO;;;;;;;;AAS7C,MAAM,iBAAiB,aACrB,QAAQ,MACL,WAAW,SAAS,WAAW,IAAI,OAAO,GAAG,IAAI,aAAa,IAAI,SACpE;;;;;;;;;;;AAYH,MAAM,gBACJ,SACA,cACA,YACA,UACA,0BACiB;AACjB,KACE,CAAC,YACD;AAGA,MAFmB,kBAAkB,QAAQ,IAE3B,CAAC,+BACjB,QAAO,wBACL,SACA,eACA,UACA,sBACD;AAGH,SAAO,wBACL,SACA,cACA,UACA,sBACD;;AAIH,QAAO,yBACL,SACA,cACA,YACA,UACA,sBACD;;;;;;;;;;;AAYH,MAAM,2BACJ,SACA,cACA,UACA,0BACiB;CACjB,IAAI,SAAU,gBACZC,8CAAiB,QAAQ,IACzB;AACF,KAAI,CAAC,QAAQ,SAAS,OAAO,CAC3B,UAAS;CAGX,MAAM,UAAU,cACd,QACA,UACA,UACA,uBACA,2BAA2B,QAAQ,QAAQ,QAAQ,OAAO,CAC3D;AAED,QAAO,iBAAiB,WAAW,gBAC/B,YAAY,SAAS,QAAQ,GAC7B,WAAW,SAAS,SAAS,OAAO;;;;;;;;;;;;AAa1C,MAAM,4BACJ,SACA,cACA,YACA,UACA,0BACiB;AACjB,KAEE,gBACA,iBAAiB,WAUjB,QAAO,YAAY,SARH,2BACd,SACA,UACA,YACA,cACA,UACA,sBACD,CACmC;AAItC,QAAO,4BACL,SACA,YACA,UACA,sBACD;;;;;;;;;;;;;AAcH,MAAM,8BACJ,SACA,UACA,YACA,cACA,YACA,0BACW;AAIX,QAAO,cACL,cAHc,SAAS,QAAQ,IAAI,cAAc,IAAI,eAAe,EAKpEC,YACA,uBACA,2BAA2B,QAAQ,QAAQ,QAAQ,aAAa,CACjE;;;;;;;;;;;AAYH,MAAM,+BACJ,SACA,YACA,UACA,0BACiB;AACjB,KAEE,CAAC,iBACD,eAAe,eACf;EACA,IAAI,oBAAoB,SAAS,MAAM,IAAI,aAAa,OAAO,IAAI;AAEnE,MAAI,sBACF,qBAAoB,kBAAkB,MAAM,EAAE;EAGhD,MAAMC,qBAAmB,2BACvB,QAAQ,QAAQ,QAChB,WACD;AACD,MAAIA,mBACF,sBAAqBA;WACZ,QAAQ,QAAQ,OACzB,sBAAqB,QAAQ,QAAQ;AAGvC,SAAO,WAAW,SAAS,GAAG,WAAW,qBAAqB,WAAW;;CAK3E,MAAM,mBAAmB,2BACvB,QAAQ,QAAQ,QAChB,WACD;AAID,QAAO,WAAW,SAHF,mBACZ,GAAG,WAAW,qBACd,UACgC,WAAW;;;;;;;;;;;;AAajD,MAAM,iBACJ,QACA,MACA,YACA,uBACA,WACW;CAGX,MAAM,uBACJ,SAAS,kBACL,OACA,KAAK,WAAW,IAAI,SAAS,GAC3B,OACA,GAAG,SAAS;CAEpB,IAAI,UAAU,GAAGD,aAAW,wBAAwB,KAAK,MAAM;AAC/D,KAAI,OACF,YAAW;AAEb,QAAO;;;;;;;;;;AAWT,MAAM,cACJ,SACA,SACA,WACiB;CAEjB,MAAM,SAAS,QAAQ,QAAQ;CAC/B,MAAM,iBACJ,UAAU,CAAC,QAAQ,SAAS,IAAI,GAAG,GAAG,UAAU,WAAW;CAE7D,MAAM,WAAWE,yBAAa,QAAQ,IAAI,IAAI,gBAAgB,QAAQ,IAAI,CAAC;AAC3E,UAAS,QAAQ,IAAI,YAAY,OAAO;AACxC,QAAO;;;;;;;;;AAUT,MAAM,eAAe,SAAsB,YAAkC;CAE3E,MAAM,SAAS,QAAQ,QAAQ;CAC/B,MAAM,iBACJ,UAAU,CAAC,QAAQ,SAAS,IAAI,GAAG,GAAG,UAAU,WAAW;AAE7D,QAAOA,yBAAa,SAAS,IAAI,IAAI,gBAAgB,QAAQ,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;AA0BpE,MAAa,qBAAqB"}
1
+ {"version":3,"file":"intlayerProxy.cjs","names":["configuration","DefaultValues","search","localeDetector","basePath","searchWithLocale","NextResponse"],"sources":["../../../src/proxy/intlayerProxy.ts"],"sourcesContent":["import { DefaultValues } from '@intlayer/config';\nimport configuration from '@intlayer/config/built';\nimport { getLocaleFromStorage, setLocaleInStorage } from '@intlayer/core';\nimport type { Locale } from '@intlayer/types';\nimport {\n type NextFetchEvent,\n type NextRequest,\n NextResponse,\n} from 'next/server';\nimport { localeDetector } from './localeDetector';\n\n/**\n * Controls whether locale detection occurs during Next.js prefetch requests\n * - true: Detect and apply locale during prefetch\n * - false: Use default locale during prefetch (recommended)\n *\n * This setting affects how Next.js handles locale prefetching:\n *\n * Example scenario:\n * - User's browser language is 'fr'\n * - Current page is /fr/about\n * - Link prefetches /about\n *\n * With `detectLocaleOnPrefetchNoPrefix:true`\n * - Prefetch detects 'fr' locale from browser\n * - Redirects prefetch to /fr/about\n *\n * With `detectLocaleOnPrefetchNoPrefix:false` (default)\n * - Prefetch uses default locale\n * - Redirects prefetch to /en/about (assuming 'en' is default)\n *\n * When to use true:\n * - Your app uses non-localized internal links (e.g. <a href=\"/about\">)\n * - You want consistent locale detection behavior between regular and prefetch requests\n *\n * When to use false (default):\n * - Your app uses locale-prefixed links (e.g. <a href=\"/fr/about\">)\n * - You want to optimize prefetching performance\n * - You want to avoid potential redirect loops\n */\nconst DEFAULT_DETECT_LOCALE_ON_PREFETCH_NO_PREFIX = false;\n\nconst { internationalization, routing } = configuration ?? {};\nconst { locales, defaultLocale } = internationalization ?? {};\nconst { basePath, mode } = routing ?? {};\n// Note: cookie names are resolved inside LocaleStorage based on configuration\n\n// Derived flags from routing.mode\nconst effectiveMode = mode ?? DefaultValues.Routing.ROUTING_MODE;\nconst noPrefix =\n effectiveMode === 'no-prefix' || effectiveMode === 'search-params';\nconst prefixDefault = effectiveMode === 'prefix-all';\n\n/**\n * Detects if the request is a prefetch request from Next.js.\n *\n * Next.js prefetch requests can be identified by several headers:\n * - purpose: 'prefetch' (standard prefetch header)\n * - next-router-prefetch: '1' (Next.js router prefetch)\n * - next-url: present (Next.js internal navigation)\n *\n * During prefetch, we should ignore cookie-based locale detection\n * to prevent unwanted redirects when users are switching locales.\n *\n * @param request - The incoming Next.js request object.\n * @returns - True if the request is a prefetch request, false otherwise.\n */\nconst isPrefetchRequest = (request: NextRequest): boolean => {\n const purpose = request.headers.get('purpose');\n const nextRouterPrefetch = request.headers.get('next-router-prefetch');\n const nextUrl = request.headers.get('next-url');\n const xNextjsData = request.headers.get('x-nextjs-data');\n\n return (\n purpose === 'prefetch' ||\n nextRouterPrefetch === '1' ||\n !!nextUrl ||\n !!xNextjsData\n );\n};\n\n// Ensure locale is reflected in search params when routing mode is 'search-params'\nconst appendLocaleSearchIfNeeded = (\n search: string | undefined,\n locale: Locale\n): string | undefined => {\n if (effectiveMode !== 'search-params') return search;\n\n const params = new URLSearchParams(search ?? '');\n\n params.set('locale', locale);\n\n return `?${params.toString()}`;\n};\n\n/**\n * Proxy that handles the internationalization layer\n *\n * Usage:\n *\n * ```ts\n * // ./src/proxy.ts\n *\n * export { intlayerProxy as proxy } from '@intlayer/next/proxy';\n *\n * // applies this proxy only to files in the app directory\n * export const config = {\n * matcher: '/((?!api|static|.*\\\\..*|_next).*)',\n * };\n * ```\n *\n * Main proxy function for handling internationalization.\n *\n * @param request - The incoming Next.js request object.\n * @param event - The Next.js fetch event (optional).\n * @param response - The Next.js response object (optional).\n * @returns - The response to be returned to the client.\n */\nexport const intlayerProxy = (\n request: NextRequest,\n _event?: NextFetchEvent,\n _response?: NextResponse\n): NextResponse => {\n const pathname = request.nextUrl.pathname;\n\n const localLocale = getLocalLocale(request);\n\n if (\n noPrefix // If the application is configured not to use locale prefixes in URLs\n ) {\n return handleNoPrefix(request, localLocale, pathname);\n }\n\n const pathLocale = getPathLocale(pathname);\n\n return handlePrefix(request, localLocale, pathLocale, pathname);\n};\n\n/**\n * Retrieves the locale from the request cookies if available and valid.\n *\n * @param request - The incoming Next.js request object.\n * @returns - The locale found in the cookies, or undefined if not found or invalid.\n */\nconst getLocalLocale = (request: NextRequest): Locale | undefined =>\n getLocaleFromStorage({\n getCookie: (name: string) => request.cookies.get(name)?.value ?? null,\n getHeader: (name: string) => request.headers.get(name) ?? null,\n });\n\n/**\n * Handles the case where URLs do not have locale prefixes.\n *\n * @param request - The incoming Next.js request object.\n * @param localLocale - The locale from the cookie.\n * @param pathname - The pathname from the request URL.\n * @returns - The rewritten response with the locale applied.\n */\nconst handleNoPrefix = (\n request: NextRequest,\n localLocale: Locale | undefined,\n pathname: string\n): NextResponse => {\n // Check if pathname has a locale prefix (even though we're in no-prefix mode)\n const pathLocale = getPathLocale(pathname);\n\n // If a locale prefix is detected in the URL, redirect to remove it\n if (pathLocale) {\n // Strip the locale prefix from the pathname\n const pathWithoutLocale = pathname.slice(`/${pathLocale}`.length) || '/';\n\n // Build redirect URL without locale prefix but with search params if needed\n const search = appendLocaleSearchIfNeeded(\n request.nextUrl.search,\n pathLocale\n );\n const redirectPath = search\n ? `${pathWithoutLocale}${search}`\n : `${pathWithoutLocale}${request.nextUrl.search ?? ''}`;\n\n // Redirect to the path without locale prefix (URL changes in browser)\n return redirectUrl(request, redirectPath);\n }\n\n // If no locale prefix in URL, determine locale and rewrite internally\n const locale = localLocale ?? defaultLocale;\n\n // In search-params mode, we need to redirect to add the locale search param\n if (effectiveMode === 'search-params') {\n // Check if locale search param already exists and matches the detected locale\n const existingSearchParams = new URLSearchParams(request.nextUrl.search);\n const existingLocale = existingSearchParams.get('locale');\n\n // If the existing locale matches the detected locale, no redirect needed\n if (existingLocale === locale) {\n // For internal routing, we need to add the locale prefix so Next.js can match [locale] param\n const internalPath = `/${locale}${pathname}`;\n const rewritePath = `${internalPath}${request.nextUrl.search ?? ''}`;\n\n // Rewrite internally (URL stays the same in browser, but Next.js routes to /[locale]/path)\n return rewriteUrl(request, rewritePath, locale);\n }\n\n const search = appendLocaleSearchIfNeeded(request.nextUrl.search, locale);\n const redirectPath = search\n ? `${pathname}${search}`\n : `${pathname}${request.nextUrl.search ?? ''}`;\n\n // Redirect to add/update the locale search param (URL changes in browser)\n return redirectUrl(request, redirectPath);\n }\n\n // For internal routing, we need to add the locale prefix so Next.js can match [locale] param\n const internalPath = `/${locale}${pathname}`;\n\n // Add search params if needed\n const search = appendLocaleSearchIfNeeded(request.nextUrl.search, locale);\n const rewritePath = search\n ? `${internalPath}${search}`\n : `${internalPath}${request.nextUrl.search ?? ''}`;\n\n // Rewrite internally (URL stays the same in browser, but Next.js routes to /[locale]/path)\n return rewriteUrl(request, rewritePath, locale);\n};\n\n/**\n * Extracts the locale from the URL pathname if present.\n *\n * @param pathname - The pathname from the request URL.\n * @returns - The locale found in the pathname, or undefined if not found.\n */\nconst getPathLocale = (pathname: string): Locale | undefined =>\n locales.find(\n (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`\n );\n\n/**\n * Handles the case where URLs have locale prefixes.\n *\n * @param request - The incoming Next.js request object.\n * @param localLocale - The locale from the cookie.\n * @param pathLocale - The locale extracted from the pathname.\n * @param pathname - The pathname from the request URL.\n * @param basePathTrailingSlash - Indicates if the basePath ends with a slash.\n * @returns - The response to be returned to the client.\n */\nconst handlePrefix = (\n request: NextRequest,\n localLocale: Locale | undefined,\n pathLocale: Locale | undefined,\n pathname: string\n): NextResponse => {\n if (\n !pathLocale // If the URL does not contain a locale prefix\n ) {\n const isPrefetch = isPrefetchRequest(request);\n\n if (isPrefetch && !DEFAULT_DETECT_LOCALE_ON_PREFETCH_NO_PREFIX) {\n return handleMissingPathLocale(request, defaultLocale, pathname);\n }\n\n return handleMissingPathLocale(request, localLocale, pathname);\n }\n\n // If the URL contains a locale prefix\n return handleExistingPathLocale(request, localLocale, pathLocale, pathname);\n};\n\n/**\n * Handles requests where the locale is missing from the URL pathname.\n *\n * @param request - The incoming Next.js request object.\n * @param localLocale - The locale from the cookie.\n * @param pathname - The pathname from the request URL.\n * @param basePathTrailingSlash - Indicates if the basePath ends with a slash.\n * @returns - The response to be returned to the client.\n */\nconst handleMissingPathLocale = (\n request: NextRequest,\n localLocale: Locale | undefined,\n pathname: string\n): NextResponse => {\n let locale = (localLocale ??\n localeDetector?.(request) ??\n defaultLocale) as Locale;\n if (!locales.includes(locale)) {\n locale = defaultLocale;\n }\n\n const newPath = constructPath(\n locale,\n pathname,\n basePath,\n appendLocaleSearchIfNeeded(request.nextUrl.search, locale)\n );\n\n return prefixDefault || locale !== defaultLocale\n ? redirectUrl(request, newPath)\n : rewriteUrl(request, newPath, locale);\n};\n\n/**\n * Handles requests where the locale exists in the URL pathname.\n *\n * @param request - The incoming Next.js request object.\n * @param localLocale - The locale from the cookie.\n * @param pathLocale - The locale extracted from the pathname.\n * @param pathname - The pathname from the request URL.\n * @returns - The response to be returned to the client.\n */\nconst handleExistingPathLocale = (\n request: NextRequest,\n localLocale: Locale | undefined,\n pathLocale: Locale,\n pathname: string\n): NextResponse => {\n if (\n // If the cookie locale is set and differs from the locale in the URL\n localLocale &&\n localLocale !== pathLocale\n ) {\n const newPath = handleCookieLocaleMismatch(\n request,\n pathname,\n pathLocale,\n localLocale,\n basePath\n );\n return redirectUrl(request, newPath);\n }\n\n // If the cookie locale matches the path locale, or cookie locale is not set, or serverSetCookie is 'always'\n return handleDefaultLocaleRedirect(request, pathLocale, pathname);\n};\n\n/**\n * Handles the scenario where the locale in the cookie does not match the locale in the URL pathname.\n *\n * @param request - The incoming Next.js request object.\n * @param pathname - The pathname from the request URL.\n * @param pathLocale - The locale extracted from the pathname.\n * @param localLocale - The locale from the cookie.\n * @param basePath - The base path of the application.\n * @returns - The new URL path with the correct locale.\n */\nconst handleCookieLocaleMismatch = (\n request: NextRequest,\n pathname: string,\n pathLocale: Locale,\n localLocale: Locale,\n basePath: string\n): string => {\n // Replace the pathLocale in the pathname with the localLocale\n const newPath = pathname.replace(`/${pathLocale}`, `/${localLocale}`);\n\n return constructPath(\n localLocale,\n newPath,\n basePath,\n appendLocaleSearchIfNeeded(request.nextUrl.search, localLocale)\n );\n};\n\n/**\n * Handles redirection when the default locale is used and prefixing is not required.\n *\n * @param request - The incoming Next.js request object.\n * @param pathLocale - The locale extracted from the pathname.\n * @param pathname - The pathname from the request URL.\n * @returns - The rewritten response without the locale prefix.\n */\nconst handleDefaultLocaleRedirect = (\n request: NextRequest,\n pathLocale: Locale,\n pathname: string\n): NextResponse => {\n if (\n // If default locale should not be prefixed and the pathLocale is the defaultLocale\n !prefixDefault &&\n pathLocale === defaultLocale\n ) {\n let pathWithoutLocale = pathname.slice(`/${pathLocale}`.length) ?? '/';\n\n const basePathTrailingSlash = basePath.endsWith('/');\n\n if (basePathTrailingSlash) {\n pathWithoutLocale = pathWithoutLocale.slice(1);\n }\n\n const searchWithLocale = appendLocaleSearchIfNeeded(\n request.nextUrl.search,\n pathLocale\n );\n if (searchWithLocale) {\n pathWithoutLocale += searchWithLocale;\n } else if (request.nextUrl.search) {\n pathWithoutLocale += request.nextUrl.search;\n }\n\n return rewriteUrl(request, `${basePath}${pathWithoutLocale}`, pathLocale);\n }\n\n // If prefixing default locale is required or pathLocale is not the defaultLocale\n\n const searchWithLocale = appendLocaleSearchIfNeeded(\n request.nextUrl.search,\n pathLocale\n );\n const newPath = searchWithLocale\n ? `${pathname}${searchWithLocale}`\n : pathname;\n return rewriteUrl(request, newPath, pathLocale);\n};\n\n/**\n * Constructs a new path by combining the locale, path, basePath, and search parameters.\n *\n * @param locale - The locale to include in the path.\n * @param path - The original path from the request.\n * @param basePath - The base path of the application.\n * @param [search] - The query string from the request URL (optional).\n * @returns - The constructed new path.\n */\nconst constructPath = (\n locale: Locale,\n path: string,\n basePath: string,\n search?: string\n): string => {\n // In 'search-params' and 'no-prefix' modes, do not prefix the path with the locale\n // Also, strip any incoming locale prefix if present\n const pathWithoutPrefix = path.startsWith(`/${locale}`)\n ? path.slice(`/${locale}`.length) || '/'\n : path;\n\n if (effectiveMode === 'no-prefix') {\n if (search) {\n return `${pathWithoutPrefix}?${search}`;\n }\n\n return pathWithoutPrefix;\n }\n\n if (effectiveMode === 'search-params') {\n if (search) {\n return `${pathWithoutPrefix}?${search}`;\n }\n\n return pathWithoutPrefix;\n }\n\n const pathWithLocalePrefix = path.startsWith(`/${locale}`)\n ? path\n : `${locale}${path}`;\n\n const basePathTrailingSlash = basePath.endsWith('/');\n\n const newPath = `${basePath}${basePathTrailingSlash ? '' : '/'}${pathWithLocalePrefix}`;\n\n return newPath;\n};\n\n/**\n * Rewrites the URL to the new path and sets the locale header.\n *\n * @param request - The incoming Next.js request object.\n * @param newPath - The new path to rewrite to.\n * @param locale - The locale to set in the response header.\n * @returns - The rewritten response.\n */\nconst rewriteUrl = (\n request: NextRequest,\n newPath: string,\n locale: Locale\n): NextResponse => {\n // Ensure we preserve the original search params if they were present and not explicitly included in newPath\n const search = request.nextUrl.search;\n const pathWithSearch =\n search && !newPath.includes('?') ? `${newPath}${search}` : newPath;\n\n const response = NextResponse.rewrite(new URL(pathWithSearch, request.url));\n\n setLocaleInStorage(locale, {\n setHeader: (name: string, value: string) =>\n response.headers.set(name, value),\n });\n\n return response;\n};\n\n/**\n * Redirects the request to the new path.\n *\n * @param request - The incoming Next.js request object.\n * @param newPath - The new path to redirect to.\n * @returns - The redirect response.\n */\nconst redirectUrl = (request: NextRequest, newPath: string): NextResponse => {\n // Ensure we preserve the original search params if they were present and not explicitly included in newPath\n const search = request.nextUrl.search;\n const pathWithSearch =\n search && !newPath.includes('?') ? `${newPath}${search}` : newPath;\n\n return NextResponse.redirect(new URL(pathWithSearch, request.url));\n};\n\n/**\n * Middleware that handles the internationalization layer\n *\n * Usage:\n *\n * ```ts\n * // ./src/middleware.ts\n *\n * export { intlayerMiddleware as middleware } from '@intlayer/next/middleware';\n *\n * // applies this middleware only to files in the app directory\n * export const config = {\n * matcher: '/((?!api|static|.*\\\\..*|_next).*)',\n * };\n * ```\n *\n * Main middleware function for handling internationalization.\n *\n * @param request - The incoming Next.js request object.\n * @param event - The Next.js fetch event (optional).\n * @param response - The Next.js response object (optional).\n * @returns - The response to be returned to the client.\n */\nexport const intlayerMiddleware = intlayerProxy;\n"],"mappings":"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"}
@@ -40,15 +40,15 @@ const multipleProxies = (proxies) => async (req, event, response) => {
40
40
  proxyHeader.forEach((header) => {
41
41
  for (const [key, value] of header.entries()) {
42
42
  mergedHeaders.append(key, value);
43
- if (key.startsWith("x-proxy-request-")) {
44
- const fixedKey = key.replace("x-proxy-request-", "");
43
+ if (key.startsWith("x-middleware-request-")) {
44
+ const fixedKey = key.replace("x-middleware-request-", "");
45
45
  transmittedHeaders.append(fixedKey, value);
46
46
  }
47
47
  }
48
48
  });
49
- const redirect = mergedHeaders.get("x-proxy-request-redirect");
49
+ const redirect = mergedHeaders.get("x-middleware-request-redirect");
50
50
  if (redirect) return next_server.NextResponse.redirect(new URL(redirect, req.url), { status: 307 });
51
- const rewrite = mergedHeaders.get("x-proxy-rewrite");
51
+ const rewrite = mergedHeaders.get("x-middleware-rewrite");
52
52
  if (rewrite) return next_server.NextResponse.rewrite(new URL(rewrite, req.url), { request: { headers: transmittedHeaders } });
53
53
  return next_server.NextResponse.next({ request: { headers: transmittedHeaders } });
54
54
  };
@@ -1 +1 @@
1
- {"version":3,"file":"multipleProxies.cjs","names":["proxyHeader: Headers[]","NextResponse"],"sources":["../../../src/proxy/multipleProxies.ts"],"sourcesContent":["import {\n type NextFetchEvent,\n type NextRequest,\n NextResponse,\n} from 'next/server';\n\n/**\n * Utility to combine multiple Next.js proxies into one.\n *\n * It executes proxies in order, merges headers, and correctly handles\n * redirects and rewrites.\n *\n * @example\n * import { multipleProxies, intlayerProxy } from \"next-intlayer/proxy\";\n * import { NextResponse } from \"next/server\";\n *\n * const authMiddleware = (req: NextRequest) => {\n * if (!req.cookies.get(\"token\")) {\n * return NextResponse.redirect(new URL(\"/login\", req.url));\n * }\n * return NextResponse.next();\n * };\n *\n * export default multipleProxies([\n * intlayerProxy,\n * authMiddleware,\n * ]);\n *\n * @param proxies - An array of proxy functions to execute in order.\n * @returns A single proxy function that runs all provided proxies.\n */\nexport const multipleProxies =\n (\n proxies: ((\n req: NextRequest,\n event?: NextFetchEvent,\n response?: NextResponse\n ) => NextResponse | Promise<NextResponse>)[]\n ) =>\n async (req: NextRequest, event?: NextFetchEvent, response?: NextResponse) => {\n // Array to store proxy headers\n const proxyHeader: Headers[] = [];\n\n // Loop through proxy functions\n for (const proxy of proxies) {\n // Execute proxy function and await the result\n const result = await proxy(req, event, response);\n\n // Check if the result is not okay and return it\n if (!result.ok) {\n return result;\n }\n\n // Push proxy headers to the array\n proxyHeader.push(result.headers);\n }\n\n // Merge all the headers to check if there is a redirection or rewrite\n const mergedHeaders = new Headers();\n\n // Merge all the custom headers added by the proxies\n const transmittedHeaders = new Headers();\n\n // Merge headers\n proxyHeader.forEach((header) => {\n for (const [key, value] of header.entries()) {\n mergedHeaders.append(key, value);\n\n // check if it's a custom header added by one of the proxies\n if (key.startsWith('x-proxy-request-')) {\n // remove the prefix to get the original key\n const fixedKey = key.replace('x-proxy-request-', '');\n\n // add the original key to the transmitted headers\n transmittedHeaders.append(fixedKey, value);\n }\n }\n });\n\n // Look for the 'x-proxy-request-redirect' header\n const redirect = mergedHeaders.get('x-proxy-request-redirect');\n\n // If a redirection is required based on the proxy headers\n if (redirect) {\n // Perform the redirection\n return NextResponse.redirect(new URL(redirect, req.url), {\n status: 307, // Temporary redirect\n });\n }\n\n // Look for the 'x-proxy-rewrite' header\n const rewrite = mergedHeaders.get('x-proxy-rewrite');\n if (rewrite) {\n // Perform the rewrite\n return NextResponse.rewrite(new URL(rewrite, req.url), {\n request: {\n headers: transmittedHeaders,\n },\n });\n }\n\n // Default: continue to next proxy\n return NextResponse.next({\n request: {\n headers: transmittedHeaders,\n },\n });\n };\n\nexport const multipleMiddlewares = multipleProxies;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,MAAa,mBAET,YAMF,OAAO,KAAkB,OAAwB,aAA4B;CAE3E,MAAMA,cAAyB,EAAE;AAGjC,MAAK,MAAM,SAAS,SAAS;EAE3B,MAAM,SAAS,MAAM,MAAM,KAAK,OAAO,SAAS;AAGhD,MAAI,CAAC,OAAO,GACV,QAAO;AAIT,cAAY,KAAK,OAAO,QAAQ;;CAIlC,MAAM,gBAAgB,IAAI,SAAS;CAGnC,MAAM,qBAAqB,IAAI,SAAS;AAGxC,aAAY,SAAS,WAAW;AAC9B,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,SAAS,EAAE;AAC3C,iBAAc,OAAO,KAAK,MAAM;AAGhC,OAAI,IAAI,WAAW,mBAAmB,EAAE;IAEtC,MAAM,WAAW,IAAI,QAAQ,oBAAoB,GAAG;AAGpD,uBAAmB,OAAO,UAAU,MAAM;;;GAG9C;CAGF,MAAM,WAAW,cAAc,IAAI,2BAA2B;AAG9D,KAAI,SAEF,QAAOC,yBAAa,SAAS,IAAI,IAAI,UAAU,IAAI,IAAI,EAAE,EACvD,QAAQ,KACT,CAAC;CAIJ,MAAM,UAAU,cAAc,IAAI,kBAAkB;AACpD,KAAI,QAEF,QAAOA,yBAAa,QAAQ,IAAI,IAAI,SAAS,IAAI,IAAI,EAAE,EACrD,SAAS,EACP,SAAS,oBACV,EACF,CAAC;AAIJ,QAAOA,yBAAa,KAAK,EACvB,SAAS,EACP,SAAS,oBACV,EACF,CAAC;;AAGN,MAAa,sBAAsB"}
1
+ {"version":3,"file":"multipleProxies.cjs","names":["proxyHeader: Headers[]","NextResponse"],"sources":["../../../src/proxy/multipleProxies.ts"],"sourcesContent":["import {\n type NextFetchEvent,\n type NextRequest,\n NextResponse,\n} from 'next/server';\n\n/**\n * Utility to combine multiple Next.js proxies into one.\n *\n * It executes proxies in order, merges headers, and correctly handles\n * redirects and rewrites.\n *\n * @example\n * import { multipleProxies, intlayerProxy } from \"next-intlayer/proxy\";\n * import { NextResponse } from \"next/server\";\n *\n * const authMiddleware = (req: NextRequest) => {\n * if (!req.cookies.get(\"token\")) {\n * return NextResponse.redirect(new URL(\"/login\", req.url));\n * }\n * return NextResponse.next();\n * };\n *\n * export default multipleProxies([\n * intlayerProxy,\n * authMiddleware,\n * ]);\n *\n * @param proxies - An array of proxy functions to execute in order.\n * @returns A single proxy function that runs all provided proxies.\n */\nexport const multipleProxies =\n (\n proxies: ((\n req: NextRequest,\n event?: NextFetchEvent,\n response?: NextResponse\n ) => NextResponse | Promise<NextResponse>)[]\n ) =>\n async (req: NextRequest, event?: NextFetchEvent, response?: NextResponse) => {\n // Array to store proxy headers\n const proxyHeader: Headers[] = [];\n\n // Loop through proxy functions\n for (const proxy of proxies) {\n // Execute proxy function and await the result\n const result = await proxy(req, event, response);\n\n // Check if the result is not okay and return it\n if (!result.ok) {\n return result;\n }\n\n // Push proxy headers to the array\n proxyHeader.push(result.headers);\n }\n\n // Merge all the headers to check if there is a redirection or rewrite\n const mergedHeaders = new Headers();\n\n // Merge all the custom headers added by the proxies\n const transmittedHeaders = new Headers();\n\n // Merge headers\n proxyHeader.forEach((header) => {\n for (const [key, value] of header.entries()) {\n mergedHeaders.append(key, value);\n\n // check if it's a custom header added by one of the proxies\n if (key.startsWith('x-middleware-request-')) {\n // remove the prefix to get the original key\n const fixedKey = key.replace('x-middleware-request-', '');\n\n // add the original key to the transmitted headers\n transmittedHeaders.append(fixedKey, value);\n }\n }\n });\n\n // Look for the 'x-middleware-request-redirect' header\n const redirect = mergedHeaders.get('x-middleware-request-redirect');\n\n // If a redirection is required based on the proxy headers\n if (redirect) {\n // Perform the redirection\n return NextResponse.redirect(new URL(redirect, req.url), {\n status: 307, // Temporary redirect\n });\n }\n\n // Look for the 'x-middleware-rewrite' header\n const rewrite = mergedHeaders.get('x-middleware-rewrite');\n if (rewrite) {\n // Perform the rewrite\n return NextResponse.rewrite(new URL(rewrite, req.url), {\n request: {\n headers: transmittedHeaders,\n },\n });\n }\n\n // Default: continue to next proxy\n return NextResponse.next({\n request: {\n headers: transmittedHeaders,\n },\n });\n };\n\nexport const multipleMiddlewares = multipleProxies;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,MAAa,mBAET,YAMF,OAAO,KAAkB,OAAwB,aAA4B;CAE3E,MAAMA,cAAyB,EAAE;AAGjC,MAAK,MAAM,SAAS,SAAS;EAE3B,MAAM,SAAS,MAAM,MAAM,KAAK,OAAO,SAAS;AAGhD,MAAI,CAAC,OAAO,GACV,QAAO;AAIT,cAAY,KAAK,OAAO,QAAQ;;CAIlC,MAAM,gBAAgB,IAAI,SAAS;CAGnC,MAAM,qBAAqB,IAAI,SAAS;AAGxC,aAAY,SAAS,WAAW;AAC9B,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,SAAS,EAAE;AAC3C,iBAAc,OAAO,KAAK,MAAM;AAGhC,OAAI,IAAI,WAAW,wBAAwB,EAAE;IAE3C,MAAM,WAAW,IAAI,QAAQ,yBAAyB,GAAG;AAGzD,uBAAmB,OAAO,UAAU,MAAM;;;GAG9C;CAGF,MAAM,WAAW,cAAc,IAAI,gCAAgC;AAGnE,KAAI,SAEF,QAAOC,yBAAa,SAAS,IAAI,IAAI,UAAU,IAAI,IAAI,EAAE,EACvD,QAAQ,KACT,CAAC;CAIJ,MAAM,UAAU,cAAc,IAAI,uBAAuB;AACzD,KAAI,QAEF,QAAOA,yBAAa,QAAQ,IAAI,IAAI,SAAS,IAAI,IAAI,EAAE,EACrD,SAAS,EACP,SAAS,oBACV,EACF,CAAC;AAIJ,QAAOA,yBAAa,KAAK,EACvB,SAAS,EACP,SAAS,oBACV,EACF,CAAC;;AAGN,MAAa,sBAAsB"}
@@ -4,13 +4,21 @@
4
4
  import { useLocale as useLocale$1 } from "react-intlayer";
5
5
  import { getLocalizedUrl, getPathWithoutLocale } from "@intlayer/core";
6
6
  import { usePathname, useRouter } from "next/navigation.js";
7
- import { useCallback, useMemo } from "react";
7
+ import { useCallback, useEffect, useMemo, useState } from "react";
8
8
 
9
9
  //#region src/client/useLocale.ts
10
+ const usePathWithoutLocale = () => {
11
+ const pathname = usePathname();
12
+ const [fullPath, setFullPath] = useState(pathname);
13
+ useEffect(() => {
14
+ const search = typeof window !== "undefined" ? window.location.search : "";
15
+ setFullPath(search ? `${pathname}${search}` : pathname);
16
+ }, [pathname]);
17
+ return useMemo(() => getPathWithoutLocale(fullPath), [fullPath]);
18
+ };
10
19
  const useLocale = ({ onChange } = {}) => {
11
20
  const { replace, push } = useRouter();
12
- const pathname = usePathname();
13
- const pathWithoutLocale = useMemo(() => getPathWithoutLocale(pathname), [pathname]);
21
+ const pathWithoutLocale = usePathWithoutLocale();
14
22
  return {
15
23
  ...useLocale$1({ onLocaleChange: useCallback((locale) => {
16
24
  if (!onChange) return;
@@ -1 +1 @@
1
- {"version":3,"file":"useLocale.mjs","names":["useLocaleReact"],"sources":["../../../src/client/useLocale.ts"],"sourcesContent":["'use client';\n\nimport { getLocalizedUrl, getPathWithoutLocale } from '@intlayer/core';\nimport type { LocalesValues } from '@intlayer/types';\nimport { usePathname, useRouter } from 'next/navigation.js';\nimport { useCallback, useMemo } from 'react';\nimport { useLocale as useLocaleReact } from 'react-intlayer';\n\ntype UseLocaleProps = {\n onChange?: 'replace' | 'push' | ((locale: LocalesValues) => void);\n};\n\nexport const useLocale = ({ onChange }: UseLocaleProps = {}) => {\n const { replace, push } = useRouter();\n const pathname = usePathname();\n const pathWithoutLocale = useMemo(\n () => getPathWithoutLocale(pathname),\n [pathname]\n );\n\n const redirectionFunction = useCallback(\n (locale: LocalesValues) => {\n if (!onChange) return;\n\n if (typeof onChange === 'function') {\n onChange(locale);\n return;\n }\n\n const pathWithLocale = getLocalizedUrl(pathWithoutLocale, locale);\n\n if (onChange === 'replace') {\n replace(pathWithLocale);\n }\n if (onChange === 'push') {\n push(pathWithLocale);\n }\n },\n [replace, push, pathWithoutLocale, onChange]\n );\n\n const reactLocaleHook = useLocaleReact({\n onLocaleChange: redirectionFunction,\n });\n\n return {\n ...reactLocaleHook,\n pathWithoutLocale,\n };\n};\n"],"mappings":";;;;;;;;;AAYA,MAAa,aAAa,EAAE,aAA6B,EAAE,KAAK;CAC9D,MAAM,EAAE,SAAS,SAAS,WAAW;CACrC,MAAM,WAAW,aAAa;CAC9B,MAAM,oBAAoB,cAClB,qBAAqB,SAAS,EACpC,CAAC,SAAS,CACX;AA2BD,QAAO;EACL,GALsBA,YAAe,EACrC,gBAtB0B,aACzB,WAA0B;AACzB,OAAI,CAAC,SAAU;AAEf,OAAI,OAAO,aAAa,YAAY;AAClC,aAAS,OAAO;AAChB;;GAGF,MAAM,iBAAiB,gBAAgB,mBAAmB,OAAO;AAEjE,OAAI,aAAa,UACf,SAAQ,eAAe;AAEzB,OAAI,aAAa,OACf,MAAK,eAAe;KAGxB;GAAC;GAAS;GAAM;GAAmB;GAAS,CAC7C,EAIA,CAAC;EAIA;EACD"}
1
+ {"version":3,"file":"useLocale.mjs","names":["useLocaleReact"],"sources":["../../../src/client/useLocale.ts"],"sourcesContent":["'use client';\n\nimport { getLocalizedUrl, getPathWithoutLocale } from '@intlayer/core';\nimport type { LocalesValues } from '@intlayer/types';\nimport { usePathname, useRouter } from 'next/navigation.js';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useLocale as useLocaleReact } from 'react-intlayer';\n\ntype UseLocaleProps = {\n onChange?: 'replace' | 'push' | ((locale: LocalesValues) => void);\n};\n\nconst usePathWithoutLocale = () => {\n const pathname = usePathname(); // updates on client navigations\n const [fullPath, setFullPath] = useState(pathname);\n\n useEffect(() => {\n // Runs only on client; avoids suspense.\n const search = typeof window !== 'undefined' ? window.location.search : '';\n setFullPath(search ? `${pathname}${search}` : pathname);\n }, [pathname]);\n\n // Your own helper\n return useMemo(() => getPathWithoutLocale(fullPath), [fullPath]);\n};\n\nexport const useLocale = ({ onChange }: UseLocaleProps = {}) => {\n const { replace, push } = useRouter();\n const pathWithoutLocale = usePathWithoutLocale();\n\n const redirectionFunction = useCallback(\n (locale: LocalesValues) => {\n if (!onChange) return;\n\n if (typeof onChange === 'function') {\n onChange(locale);\n return;\n }\n\n const pathWithLocale = getLocalizedUrl(pathWithoutLocale, locale);\n\n if (onChange === 'replace') {\n replace(pathWithLocale);\n }\n if (onChange === 'push') {\n push(pathWithLocale);\n }\n },\n [replace, push, pathWithoutLocale, onChange]\n );\n\n const reactLocaleHook = useLocaleReact({\n onLocaleChange: redirectionFunction,\n });\n\n return {\n ...reactLocaleHook,\n pathWithoutLocale,\n };\n};\n"],"mappings":";;;;;;;;;AAYA,MAAM,6BAA6B;CACjC,MAAM,WAAW,aAAa;CAC9B,MAAM,CAAC,UAAU,eAAe,SAAS,SAAS;AAElD,iBAAgB;EAEd,MAAM,SAAS,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS;AACxE,cAAY,SAAS,GAAG,WAAW,WAAW,SAAS;IACtD,CAAC,SAAS,CAAC;AAGd,QAAO,cAAc,qBAAqB,SAAS,EAAE,CAAC,SAAS,CAAC;;AAGlE,MAAa,aAAa,EAAE,aAA6B,EAAE,KAAK;CAC9D,MAAM,EAAE,SAAS,SAAS,WAAW;CACrC,MAAM,oBAAoB,sBAAsB;AA2BhD,QAAO;EACL,GALsBA,YAAe,EACrC,gBAtB0B,aACzB,WAA0B;AACzB,OAAI,CAAC,SAAU;AAEf,OAAI,OAAO,aAAa,YAAY;AAClC,aAAS,OAAO;AAChB;;GAGF,MAAM,iBAAiB,gBAAgB,mBAAmB,OAAO;AAEjE,OAAI,aAAa,UACf,SAAQ,eAAe;AAEzB,OAAI,aAAa,OACf,MAAK,eAAe;KAGxB;GAAC;GAAS;GAAM;GAAmB;GAAS,CAC7C,EAIA,CAAC;EAIA;EACD"}