next.js
next.js copied to clipboard
307 redirect loop when using locale together with middleware in 13.5.1
Link to the code that reproduces this issue
https://github.com/c0per/307-loop-i18n-middleware
To Reproduce
- set
defaultLocale
to something different thanpreferredLocale
(from headeraccept-language
) - npm run dev
- access
http://localhost:3000/en
orhttp://localhost:3000/fr
orhttp://localhost:3000
or with trailing slash
Current vs. Expected behavior
Currently, Next.js 13.5.1 will stuck in 307 loop if:
- turn on
localeDetection
(which is enabled by default) - set
defaultLocale
different from user'spreferredLocale
- use a middleware
Expected behavior:
It doesn't stuck.
Verify canary release
- [X] I verified that the issue exists in the latest Next.js canary release
Provide environment information
Operating System:
Platform: darwin
Arch: x64
Version: Darwin Kernel Version 22.6.0: Wed Jul 5 22:21:56 PDT 2023; root:xnu-8796.141.3~6/RELEASE_X86_64
Binaries:
Node: 18.16.0
npm: 9.5.1
Yarn: 1.22.19
pnpm: N/A
Relevant Packages:
next: 13.5.1
eslint-config-next: 13.5.1
react: 18.2.0
react-dom: 18.2.0
typescript: 5.2.2
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Internationalization (i18n)
Additional context
No response
I tried to track down this bug.
(I'm not sure about the following investigation)
- When accessing
localhost:3000/en
, nextjs do a "internal" redirect to/
with locale set toen
. Won't send redirect request to browser - Then nextjs will handle
/
request.
Now detectedLocale
becomes preferredLocale
(accept-language
, in this case en
). (No pathLocale
, no domainLocale
, no locale from cookie)
Since detectedLocale (en) !== defaultLocale
(fr
in the example), nextjs will send a redirect request to localhost:3000/en
.
Thus it's stuck.
The bug first appears in version 13.4.20-canary.24
, 13.4.20-canary.23
is fine.
Yup, I was waiting for the default locale fix (since it broke after 13.4.12) and now in 13.5.1 the documented default locale prefixing is broken resulting in an infinite loop. Mentioned this here as well. https://github.com/vercel/next.js/issues/54217#issuecomment-1727466409
Similar issue https://github.com/vercel/next.js/issues/54495
Same issue here, upgrading > 13.4.19 breaks the app with the 307 redirect loop.
Same issue here. 307 redirect loops on /en after upgrading Next.js.
same here
Same issue here. I'm getting a redirect loop as well
We are having the same issue, but after testing the Canary releases, I saw the issue started on:
https://github.com/vercel/next.js/releases/tag/v13.4.20-canary.24
23 works as expected https://github.com/vercel/next.js/releases/tag/v13.4.20-canary.23
Same issue. My guess is that this PR broke it: https://github.com/vercel/next.js/pull/54813/files
An easy workaround would be turning off detectLocale
.
Accessing /page
will go to /${default locale}/page
instead of /${accept-language header in user request}/page
.
Client-side routing is also broken with localization when middleware file is present. The locale always becomes the default locale when clicking on a <Link />
that routes to something such as https://page.com/de - it returns 404. If I do a refresh on that route (server-side routing) then it works.
An easy workaround would be turning off
detectLocale
.Accessing
/page
will go to/${default locale}/page
instead of/${accept-language header in user request}/page
.
this doesn't work
Does the Next team even acknowledge this issue?
Seems to only affect the index route for me.
Confirming that:
- having i18n
- having middleware
- having the not default language set in the browser preferences
- up to date next version
breaks the homepage view. Removing one of them fixes the issue (not a fix at all...). Removing locale detection breaks Link components (goes to default language on a page change).
Based on how things are done in Nextjs App router, I don't really see a fix coming any time soon (almost feels like we're being pushed to the App router). I think the best way forward is to handle i18n manually, without having Nextjs do it magically.
That means you could follow the strategy on how it's being done in the App router:
- Create segment for languages, e.g.
/pages/[language]/...
- Create page level context that stores the locale, so that you could do something like
const { locale } = usePageContext()
instead of usinguseRouter
- (optional) Use middleware to detect locale and URL re-write/redirect based on that.
Just ran into this as well. No fix yet, not even an acknowledgement.
Having to deal with these kinds of issues with every patch- or minor-level Next.js upgrade is getting so frustrating and really makes me wonder if Next.js is still on the right trajectory. Putting that much energy into stuff like RSCs and leaving existing users in the dust with stuff like this will eventually come back to bite you, Vercel. Make the foundations work (middleware AND i18n in the same app is not that unusual, isn't it?), then move on to the fancy stuff.
I have the same issue on v14.0.3 with the pages router. Turning off locale detection does fix the issue.
I ended up removing all NextJS specific locales, which means I had to create a language slug for each language and do some other manual things. In the end it works better and is more bullet proof against breaking changes. This is also the way forward in the App router AFAIK.
This just goes to show that people are losing faith in Vercel and Next.js, IMHO. If we can't use the features a framework provides out of fear they might break at any time, why use a (more fully featured) framework at all? Oh, sorry, I forgot: Streaming components, form fields submitting directly to functions... Who needs working I18n and middlewares if you can have the future™️? 😄
here's something that has worked for us, maybe it will help someone too - In the i18n config, disable the nextJs locale detection, like:
{
locales: ['en', 'de', 'ja'],
defaultLocale: 'en',
defaultNS: 'common',
localeDetection: false,
}
we handle the redirecting manually in our middleware and for the locale string we use the [email protected]
I'm experiencing similar problems with middleware, next-i18next, pages router and the root URLs (i.e. /de, /sv, /en etc.). My problem is that the middleware function isn't called at all for the root URL (all other URLs not being on the root, like /en/whateverpage/ works)
Also i need to set trailingSlash: false
in my next config otherwise the startpage won't work at all when having a middleware file.
My middleware matcher looks like this so this:
{
source: '/((?!api|_next/static|_next/image|favicon.ico).*)',
missing: [
{ type: 'header', key: 'next-router-prefetch' },
{ type: 'header', key: 'purpose', value: 'prefetch' },
],
},
In my case this prevents setting CSP rules for the startpage but it works for all other pages. Tried this with latest next version 14.0.4
Hey @valleywood!
You're not alone; I'm also banging my head against the wall trying to get middlewares to play nicely with Next.js i18n… 😅
My problem is that the middleware function isn't called at all for the root URL (all other URLs not being on the root, like /en/whateverpage/ works)
I actually faced the exact same issue and was able to fix it simply by adding "/"
to the array of matchers so my config looks like this:
export const config = {
matcher: [
"/", // Required when i18n is enabled, otherwise middleware won't be executed on index route
"/((?!api/|_next/|_static/|_vercel|fonts|images/|[\\w-]+\\.\\w+).*)",
],
};
Hope that this will unblock you! 😉
Aiming to get a minimal reproducible example ready and open an issue in the coming days…
@raphaelsaunier Thank you so much! 😍
Your code together with localeDetection: false
actually solved my issue both with the middleware being called and not forcing me to use trailingSlash: false
.
Was trying something similar like this before but wasn't able to get my regExp right I guess.
Sounds great if you are able to provide a reproduction repo because is would be good to have both middleware and localeDetection working simultaneously, now it seems one have to choose. 🙏
Have a wonderful weekend!
@ijjk @timneutkens @huozhi do you guys have any ideas or thoughts about this?
Facing the same problem thanks for pointing out a possible workaround (even if loosing language detection is not that great). I still however have problems even with the workaround as I still still some really strange redirects from middleware to localhost (in production!)
Also tried next 14 but have the same problem there, and other problems as well also regarding middleware :/ Its not looking good I wonder if really using i18n is at this point a bad idea..
that would be bad since this was promoted a lot as a great feature (which it totally is) in a nextjs conf.
Same here. Have infinite redirect problem using next 14
Would love to see an update on this so we can upgrade to v14 for now we are pinned to v13.
@raphaelsaunier Thank you so much! 😍 Your code together with
localeDetection: false
actually solved my issue both with the middleware being called and not forcing me to usetrailingSlash: false
.Was trying something similar like this before but wasn't able to get my regExp right I guess.
Sounds great if you are able to provide a reproduction repo because is would be good to have both middleware and localeDetection working simultaneously, now it seems one have to choose. 🙏
Have a wonderful weekend!
Hello, is it possible to provide us a complete example for disabling localeDetection without i18n, please?
Thanks in advance!
Best Loïc
Using [email protected]
Having the same 307 loop problem when localeDetection is true and using middleware. I don't want to disable the localeDetection because it is an amazing feature, that the user is automatically redirected to the right locale url.
But if I add a middleware.ts the 307 problem occurs.
// middleware.ts
export async function middleware(req: NextRequest) {
console.log('hello')
}