Next.js 13 Beta语言切换时非首页跳转到首页问题求助
Next.js 13 Beta 多语言切换非首页重定向问题修复
我在Next.js 13 Beta版本中用i18n实现语言切换功能,正常使用没问题,但遇到一个问题:在/news这类非首页页面切换语言时,会被强制重定向到首页/。尝试修改middleware.js解决,结果直接触发无限重定向错误,页面显示“This page isn’t working”和“ERR_TOO_MANY_REDIRECTS”。
原middleware.js代码
import { NextResponse } from "next/server"; import acceptLanguage from "accept-language"; import { fallbackLng, languages } from "@/app/i18n/settings"; acceptLanguage.languages(languages); export const config = { matcher: "/:lng*", }; const cookieName = "i18next"; export function middleware(req) { let lng; if (req.cookies.has(cookieName)) lng = acceptLanguage.get(req.cookies.get(cookieName).value); if (!lng) lng = acceptLanguage.get(req.headers.get("Accept-Language")); if (!lng) lng = fallbackLng; if (req.nextUrl.pathname === "/") { return NextResponse.redirect(new URL(`/${lng}`, req.url)); } if (req.headers.has("referer")) { const refererUrl = new URL(req.headers.get("referer")); const lngInReferer = languages.find((l) => refererUrl.pathname.startsWith(`/${l}`) ); const response = NextResponse.next(); if (lngInReferer) response.cookies.set(cookieName, lngInReferer); return response; } return NextResponse.next(); }
出错的修改代码
if (req.nextUrl.pathname !== '/') { const newPathname = `/${lng}${req.nextUrl.pathname.replace(/^\/[a-z]{2}\b/, '')}` return NextResponse.redirect(new URL(newPathname, req.url)) }
问题原因
这段修改的代码没有判断当前路径是否已经包含合法的语言前缀,导致每次请求都会被强制添加语言前缀,陷入无限重定向循环。比如当前路径是/en/news,代码处理后还是/en/news,但因为没有判断前缀存在,会再次触发重定向,反复循环直到浏览器报错。
修正后的完整middleware.js代码
import { NextResponse } from "next/server"; import acceptLanguage from "accept-language"; import { fallbackLng, languages } from "@/app/i18n/settings"; acceptLanguage.languages(languages); export const config = { matcher: "/:lng*", }; const cookieName = "i18next"; export function middleware(req) { let lng; if (req.cookies.has(cookieName)) lng = acceptLanguage.get(req.cookies.get(cookieName).value); if (!lng) lng = acceptLanguage.get(req.headers.get("Accept-Language")); if (!lng) lng = fallbackLng; // 检查当前路径是否已包含合法语言前缀 const hasValidLngPrefix = languages.some(lang => req.nextUrl.pathname.startsWith(`/${lang}/`) || req.nextUrl.pathname === `/${lang}` ); // 首页无语言前缀时,重定向到带lng的首页 if (req.nextUrl.pathname === "/") { return NextResponse.redirect(new URL(`/${lng}`, req.url)); } // 非首页且无合法语言前缀时,重定向到带lng的对应页面 if (!hasValidLngPrefix) { const newPathname = `/${lng}${req.nextUrl.pathname}`; return NextResponse.redirect(new URL(newPathname, req.url)); } // 从referer获取语言并更新cookie if (req.headers.has("referer")) { const refererUrl = new URL(req.headers.get("referer")); const lngInReferer = languages.find((l) => refererUrl.pathname.startsWith(`/${l}`) ); const response = NextResponse.next(); if (lngInReferer) response.cookies.set(cookieName, lngInReferer); return response; } return NextResponse.next(); }
关键修改说明
- 新增
hasValidLngPrefix判断:检查当前路径是否已经包含我们支持的语言前缀,避免重复添加导致无限重定向 - 非首页重定向逻辑:只有当路径没有合法语言前缀时才触发,保留原页面路径,切换语言时就能跳转到对应语言的同页面(比如
/news→/en/news) - 保留原有referer处理逻辑:确保cookie能正确记录用户选择的语言,后续请求自动使用该语言
内容的提问来源于stack exchange,提问作者Rahil Əliyev
相关产品推荐
相关产品推荐

