Next.js国际化异常:仅ar locale路由全部404,en路由正常
Next.js国际化配置异常:阿拉伯语路由返回404
- 正在开发Next.js本地化/国际化功能,需支持
ar(阿拉伯语)、en(英语)两种语言 - 页面结构:根目录
page.jsx(首页),以及test、tester两个子目录页面 - 异常现象:添加
middleware.js前,所有语言路由均可正常访问;添加后:- 根页面、
/ar/test、/ar/tester均返回404,且<html>标签无lang属性 /en下所有路由正常,lang属性识别正确
- 根页面、
- 已排除浏览器默认语言影响(切换浏览器语言后问题依旧)
目录结构
项目目录包含根目录page.jsx,以及test、tester两个子目录,每个目录下对应语言页面文件(结构参考用户提供截图)
相关配置代码
next.config.js
/** @type {import('next').NextConfig} */ const nextConfig = { i18n: { // locales: ['default',"ar", "ar-SA", "en", "en-GB"], locales: ['ar', "en-GB"], defaultLocale: 'ar', localeDetection: false }, trailingSlash: true, }; export default nextConfig;
控制台请求日志
GET /en/ 200 in 1797ms GET / 404 in 284ms GET / 404 in 280ms GET /en/tester/ 200 in 401ms GET /tester/ 404 in 284ms
middleware.js
import { NextResponse } from "next/server"; import { getLocale } from "./helpers/getLocale" const localesRegex = /^\/((?!ar\/|en\/|api|_next\/static|_next\/image|auth|favicon.ico|images).*)$/; export const middleware = (request) => { console.log("middleware.js is running"); const { pathname: url } = request.nextUrl; // is the request to the root page and doesn't have any locale attached? if(localesRegex.test(url)) { // attach the locale based on the user's preferences: const locale = getLocale(request); // rebuild the new request's pathname (url): // request.nextUrl.url = `/${locale}${url}`; // return NextResponse.redirect(request.nextUrl); return NextResponse.redirect(new URL(`/${locale}${url}`, request.nextUrl.origin).href); } return NextResponse.next(); } export const config = { matcher: ["/^\/((?!ar\/|en\/|api|_next\/static|_next\/image|auth|favicon.ico|images).*)$/"], };
getLocale函数(helpers/getLocale.js)
const supportedLocales = ["ar", "en"]; const matchedLocales = []; // const matchPattern = ["/^(?!\/(ar|en)($|\/)).*/"]; // to get the locale from the request => request.nextUrl.locale export function getLocale(request){ // 1) is there any locale ? is it supported ? return it if(request.nextUrl.locale && supportedLocales.includes(request.nextUrl.locale)) { console.log("there is", request.nextUrl.locale); return request.nextUrl.locale; } // 2) build an array of the preferred locales: const userLocals = request.headers.get("accept-language")?.split(",") || []; // 3) empty userLocales ? return the matchers and the newUrl attached with /ar (the default) if(!userLocals) return "ar"; // 4) extract the matches, the split(/[-;]/)[0] is used for locales like en-GB-oxendict;q=0.8 or en;q=0.7 userLocals.map(locale => { locale = locale.split(/[-;]/)[0]; if(supportedLocales.includes(locale) && !matchedLocales.includes(locale)) matchedLocales.push(locale); }); // 5) empty matchedLocales ? return the matchers and the newUrl attached with /ar (the default) if(!matchedLocales) return "ar"; // 6) return the first match: return matchedLocales[0]; }
问题分析与修复方案
1. Locale标识不统一
next.config.js中配置的locales是['ar', "en-GB"],但getLocale里的supportedLocales是["ar", "en"],两者不匹配。当请求匹配en-GB时,getLocale会因不识别返回默认ar,但实际有效locale是en-GB,导致跳转路由无效。
- 修复:统一locale标识,二选一:
- 将
next.config.js的locales改为['ar', 'en'] - 将
getLocale的supportedLocales改为['ar', 'en-GB']
- 将
2. Middleware正则与Matcher配置错误
config.matcher中的正则不需要包裹/ /,Next.js的matcher接受纯路径匹配字符串- 当前正则会错误拦截带
ar/的路由,或导致跳转逻辑异常 - 修复:调整正则与matcher:
// middleware.js中修改 const localesRegex = /^\/((?!ar|en|api|_next\/static|_next\/image|auth|favicon.ico|images).*)$/; export const config = { matcher: ['/((?!ar|en|api|_next/static|_next/image|auth|favicon.ico|images).*)'], };
3. getLocale数组判断逻辑错误
if(!matchedLocales)永远为false,因为空数组[]的布尔值为true,应该判断数组长度。
- 修复:修改getLocale中的判断:
// getLocale.js中替换对应行 if(matchedLocales.length === 0) return "ar";
4. 重定向URL拼接错误
当url为根路径/时,会拼接成/ar//,导致无效路由。
- 修复:处理根路径拼接:
// middleware.js中替换重定向代码 const targetUrl = url === '/' ? `/${locale}` : `/${locale}${url}`; return NextResponse.redirect(new URL(targetUrl, request.nextUrl.origin));
5. 确保lang属性正确设置
修复上述问题后,Next.js会自动根据路由locale设置<html>的lang属性,若仍不生效,可在根布局手动配置:
// app/layout.jsx export default function RootLayout({ children, params: { locale } }) { return ( <html lang={locale}> <body>{children}</body> </html> ); }
内容的提问来源于stack exchange,提问作者Marya
相关产品推荐
相关产品推荐

