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

Next.js多语言网站语言切换与路由配置问题求助

解决方案

1. 修复语言切换器

当前切换器仅跳转根路径,且未处理当前页面的路径映射。修改组件以保留当前路径并生成对应语言的链接:

'use client';
import Link from "next/link";
import { usePathname } from "next/navigation";

export default function LanguageSwitcher() {
  const pathname = usePathname();

  // 提取当前路径中的locale(如果存在)
  const currentLocale = pathname.split('/')[1];
  // 去掉路径中的locale前缀,得到基础路径
  const basePath = currentLocale && ['en', 'nl', 'fr'].includes(currentLocale) 
    ? pathname.slice(`/${currentLocale}`.length) || '/' 
    : pathname;

  return (
    <ul>
      <li><Link href={basePath} locale="en">EN</Link></li>
      <li><Link href={basePath} locale="nl">NL</Link></li>
      <li><Link href={basePath} locale="fr">FR</Link></li>
    </ul>
  );
}

同时在next.config.js中配置i18n:

/** @type {import('next').NextConfig} */
const nextConfig = {
  i18n: {
    locales: ['en', 'nl', 'fr'],
    defaultLocale: 'nl',
    localeDetection: false, // 禁用自动检测,由middleware接管
  },
};

module.exports = nextConfig;

2. 修复未知语言路径的重定向问题

原middleware未识别路径中的无效locale,导致错误追加默认前缀。修改middleware逻辑:

import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { match } from '@formatjs/intl-localematcher';
import Negotiator from 'negotiator';

const locales = ['en', 'nl', 'fr'];
const defaultLocale = 'nl';

// 从请求头获取用户偏好语言
function getLocale(request: NextRequest): string {
  const headers = { 'accept-language': request.headers.get('accept-language') || '' };
  const languages = new Negotiator({ headers }).languages();
  return match(languages, locales, defaultLocale);
}

export default function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname;
  const pathLocale = pathname.split('/')[1];

  // 处理无效locale路径(如/de/contact)
  if (pathLocale && !locales.includes(pathLocale)) {
    const validPath = pathname.slice(`/${pathLocale}`.length) || '/';
    return NextResponse.redirect(new URL(validPath, request.url));
  }

  // 处理无locale前缀的路径
  const pathnameIsMissingLocale = locales.every(
    (locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
  );

  if (pathnameIsMissingLocale) {
    const locale = getLocale(request);
    // 偏好语言为默认语言时,直接访问无前缀路径
    if (locale === defaultLocale) return NextResponse.next();
    // 非默认语言,重定向到带前缀路径
    return NextResponse.redirect(new URL(`/${locale}${pathname || '/'}`, request.url));
  }

  // 处理默认语言前缀路径(如/nl/contact),重定向到无前缀路径
  if (pathLocale === defaultLocale) {
    const newPath = pathname.slice(`/${defaultLocale}`.length) || '/';
    return NextResponse.redirect(new URL(newPath, request.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: ['/((?!_next|api|static).*)'], // 跳过内部资源和API路径
};

3. 配置默认语言无前缀路由

调整目录结构配合上述配置:

  • 将默认语言(nl)的页面放在app/根目录下(如app/page.tsx、app/contact/page.tsx)
  • 将其他语言的页面放在对应子目录中(如app/en/page.tsx、app/fr/contact/page.tsx)

最终效果:

  • site.com/、site.com/contact直接加载nl语言内容
  • site.com/nl/contact会自动重定向到site.com/contact
  • site.com/en/contact加载en语言内容

内容的提问来源于stack exchange,提问作者Alnedru

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 19:05:17