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
相关产品推荐
相关产品推荐

