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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 04:35:45