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

Next.js国际化路由:基于用户国别自动适配URL方案问询

解决方案

1. 配置Next.js的i18n基础设置

先在next.config.js中关闭默认语言检测,仅配置需要个性化的语言大类:

module.exports = {
  i18n: {
    locales: ['en', 'fr', 'ar'], // 只保留需要做个性化的语言组
    defaultLocale: 'en',
    localeDetection: false, // 禁用Next.js自带的浏览器语言检测,改用Cookie中的国别信息
  },
};

2. 用Middleware实现国别检测与URL自动适配

借助Next.js 12+的Middleware,在请求到达页面前处理路由逻辑:读取Cloudflare的国别Cookie,自动重定向到对应语言的URL路径。

创建middleware.ts文件:

import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

// 维护国家代码到语言组的映射表,按需添加需要个性化的国家
const countryToLocale: Record<string, string> = {
  US: 'en',
  GB: 'en',
  CA: 'en',
  FR: 'fr',
  BE: 'fr',
  AE: 'ar',
  SA: 'ar',
  // 可添加更多国家映射
};

export function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl;

  // 跳过静态资源、API路径,避免无效重定向
  if (pathname.startsWith('/_next/') || pathname.startsWith('/api/') || pathname.includes('.')) {
    return NextResponse.next();
  }

  // 优先读取用户手动切换的语言Cookie,否则读取Cloudflare的国别Cookie
  const userSelectedLocale = request.cookies.get('user-locale')?.value;
  const countryCode = request.cookies.get('cf-country')?.value || '';
  const targetLocale = userSelectedLocale || countryToLocale[countryCode] || 'en';

  // 检查当前URL是否已包含正确的语言前缀
  const currentLocaleMatch = pathname.match(/^\/([a-z]{2})\//);
  if (currentLocaleMatch) {
    const currentLocale = currentLocaleMatch[1];
    if (currentLocale === targetLocale) {
      // 语言匹配,直接放行
      return NextResponse.next();
    } else {
      // 重定向到正确语言的路径
      const newPathname = pathname.replace(/^\/[a-z]{2}\//, `/${targetLocale}/`);
      return NextResponse.redirect(new URL(newPathname, request.url));
    }
  } else {
    // URL无语言前缀,重定向到带目标语言的路径
    return NextResponse.redirect(new URL(`/${targetLocale}${pathname || '/'}`, request.url));
  }
}

// 指定需要处理的路由匹配规则
export const config = {
  matcher: ['/', '/:locale*'],
};

3. 共用翻译文件

无需为每个国家单独创建翻译文件,仅为语言大类维护一份即可:

public/
└── locales/
    ├── en/
    │   └── common.json
    ├── fr/
    │   └── common.json
    └── ar/
        └── common.json

在页面组件中通过useRouter获取当前locale,直接加载对应语言的翻译:

import { useRouter } from 'next/router';
import enTranslations from '../public/locales/en/common.json';
import frTranslations from '../public/locales/fr/common.json';
import arTranslations from '../public/locales/ar/common.json';

const translations = {
  en: enTranslations,
  fr: frTranslations,
  ar: arTranslations,
};

export default function Home() {
  const router = useRouter();
  const { locale } = router;
  const t = translations[locale];

  return <h1>{t.welcome}</h1>;
}

4. 支持用户手动切换语言

如果需要允许用户手动切换语言,可添加切换按钮,点击时设置user-localeCookie并重定向:

import { useRouter } from 'next/router';
import { setCookie } from 'cookies-next';

export default function LanguageSwitcher() {
  const router = useRouter();

  const switchLanguage = (newLocale) => {
    // 设置用户语言偏好Cookie,有效期30天
    setCookie('user-locale', newLocale, { maxAge: 30 * 24 * 60 * 60 });
    // 重定向到新语言的当前页面
    router.push(router.pathname, router.asPath, { locale: newLocale });
  };

  return (
    <div>
      <button onClick={() => switchLanguage('en')}>English</button>
      <button onClick={() => switchLanguage('fr')}>Français</button>
      <button onClick={() => switchLanguage('ar')}>العربية</button>
    </div>
  );
}

这套方案实现了:

  • 自动读取Cloudflare国别Cookie,映射到对应语言组
  • URL自动适配为语言组前缀,无需配置所有国家地区
  • 同一语系国家共用一份翻译文件,减少重复维护
  • 用户手动切换语言的优先级高于国别检测

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 10:41:17