如何让Next.js自定义重定向中间件优先于next-intl生效?
如何让自定义语言重定向优先于next-intl的路由中间件生效?
你遇到的问题是自定义重定向中间件被next-intl的路由逻辑覆盖,核心原因是链式中间件没有在返回重定向后终止后续流程,导致next-intl仍会处理请求并触发它自己的重定向。以下是两种可行的解决方法:
方法一:手动控制中间件执行流程(替代链式调用)
放弃使用@nimpl/middleware-chain,手动按顺序执行中间件,确保自定义重定向生效后直接返回响应,跳过后续逻辑:
修改middleware.ts:
import { NextRequest } from 'next/server'; import { pagesWhiteListMiddleware } from './middlewares/pagesWhiteList'; import handleI18nRouting from './middlewares/handleI18nRouting'; import handleLocaleRedirect from './middlewares/handleLocaleRedirect'; export default async function middleware(request: NextRequest) { // 先执行自定义重定向逻辑 const redirectResp = await handleLocaleRedirect(request); if (redirectResp) { // 如果返回了重定向响应,直接返回,不执行后续中间件 return redirectResp; } // 执行next-intl路由中间件 const i18nResp = await handleI18nRouting(request); // 执行白名单中间件(根据实际需求调整传递参数) const finalResp = await pagesWhiteListMiddleware(request, i18nResp); return finalResp || i18nResp; } export const config = { matcher: [ '/((?!api|_next/static|_next/image|next-assets|favicon.ico|sw.js|site.webmanifest).*)', ], };
同时修改handleLocaleRedirect.ts,确保只有需要重定向时才返回响应,否则返回undefined:
import { NextRequest, NextResponse } from 'next/server'; export default async function handler(request: NextRequest) { // 从Cookie获取目标语言(替换成你的Cookie键名) const targetLocale = request.cookies.get('your-locale-cookie')?.value; // 从当前URL解析出当前语言(实现你自己的解析逻辑) const currentLocale = request.nextUrl.pathname.split('/')[1]; // 定义支持的语言列表 const supportedLocales = ['en', 'zh']; if (targetLocale && supportedLocales.includes(targetLocale) && targetLocale !== currentLocale) { // 构造新的URL,保留查询参数 const newPathname = `/${targetLocale}${request.nextUrl.pathname.replace(/^\/[a-z]{2}/, '')}`; const newUrl = new URL(newPathname, request.nextUrl.origin); newUrl.search = request.nextUrl.search; return NextResponse.redirect(newUrl); } // 不需要重定向时返回undefined,让后续中间件处理 return undefined; }
方法二:扩展next-intl的语言检测逻辑(更优雅)
直接利用next-intl自身的detectLocale配置,优先读取项目原有Cookie,不需要额外写重定向中间件:
修改i18n/routing.ts:
import { defineRouting } from 'next-intl/routing'; export const routing = defineRouting({ locales: ['en', 'zh'], // 替换成你的支持语言列表 defaultLocale: 'en', // 自定义语言检测逻辑,优先从Cookie读取 async detectLocale(request) { // 从Cookie获取语言 const cookieLocale = request.cookies.get('your-locale-cookie')?.value; if (cookieLocale && ['en', 'zh'].includes(cookieLocale)) { return cookieLocale; } // fallback到默认的Accept-Language头检测 const acceptLang = request.headers.get('accept-language'); if (acceptLang) { const primaryLang = acceptLang.split(',')[0].split('-')[0]; if (['en', 'zh'].includes(primaryLang)) { return primaryLang; } } // 最终fallback到默认语言 return 'en'; } });
然后修改handleI18nRouting.ts,去掉多余的逻辑(如果不需要处理link头可以简化):
import { routing } from '../i18n/routing'; import createMiddleware from 'next-intl/middleware'; export default createMiddleware(routing);
这种方法让next-intl直接使用你的Cookie语言,避免了自定义重定向和next-intl逻辑冲突的问题,是更符合next-intl设计的方案。
内容的提问来源于stack exchange,提问作者Alex Buznik
相关产品推荐
相关产品推荐

