You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 21:21:04