diff --git a/.changeset/violet-otters-destroy.md b/.changeset/violet-otters-destroy.md new file mode 100644 index 0000000..5c16a25 --- /dev/null +++ b/.changeset/violet-otters-destroy.md @@ -0,0 +1,5 @@ +--- +"@labdigital/next-intl-custom-paths": minor +--- + +Fix double redirect bug when path has no locale diff --git a/src/middleware.test.ts b/src/middleware.test.ts index 58269e9..de074aa 100644 --- a/src/middleware.test.ts +++ b/src/middleware.test.ts @@ -18,6 +18,7 @@ describe("rewrite request for ", () => { const result = processRequest(request, { defaultLocale: "en-US", + localePrefix: "as-needed", localePrefixForRoot: "as-needed", pathToLocaleMapping: { en: "en-US", @@ -33,6 +34,7 @@ describe("rewrite request for ", () => { it.each([ ["http://example.org/", "/en"], + ["http://example.org/foobar", "/en/foobar"], ["http://example.org/en-US", "/en"], ["http://example.org/en-US/", "/en"], ["http://example.org/en-US/foobar", "/en/foobar"], @@ -43,6 +45,7 @@ describe("rewrite request for ", () => { const result = processRequest(request, { defaultLocale: "en-US", + localePrefix: "always", localePrefixForRoot: "always", pathToLocaleMapping: { en: "en-US", diff --git a/src/middleware.ts b/src/middleware.ts index 8d84a49..97ed84b 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -36,6 +36,7 @@ export function createNextIntlCustomPathMiddleware({ const info = processRequest(request, { defaultLocale, + localePrefix: nextIntlMiddlewareOptions.localePrefix, localePrefixForRoot, pathToLocaleMapping, }); @@ -61,6 +62,7 @@ type processRequestResult = { type processRequestArgs = { defaultLocale: Locales[number]; + localePrefix?: "always" | "as-needed" | "never"; localePrefixForRoot?: "always" | "as-needed"; pathToLocaleMapping: Record; }; @@ -69,6 +71,7 @@ export const processRequest = ( request: NextRequest, { defaultLocale, + localePrefix, localePrefixForRoot, pathToLocaleMapping, }: processRequestArgs @@ -132,8 +135,22 @@ export const processRequest = ( targetURL: request.nextUrl, }; } + + // if pathLocale is not a path locale or locale (e.g. /foo) then the + // next-intl will redirect to the default locale (/nl-NL). However we want + // to intercept that and redirect to the localePath (/nl) instead. OTherwise + // we get a double redirect (e.g. /foo -> /nl-NL/foo -> /nl/foo) const locale = pathToLocale(pathLocale, pathToLocaleMapping); + if (pathLocale && locale === undefined && localePrefix === "always") { + request.nextUrl.pathname = `/${defaultLocalePath}` + request.nextUrl.pathname; + return { + statusCode: 308, + targetURL: request.nextUrl, + }; + } + // If there is a locale in the path and we have mapped that to a locale path + // then just update the url to the locale path if (pathLocale && locale && request.nextUrl.pathname !== "/") { request.nextUrl.pathname = request.nextUrl.pathname.replace( new RegExp(`^/${pathLocale}`, "i"),