Next.js 国际化、多语言与路由策略
国际化这件事在 Next.js 里通常分成两层:
Internationalization:路由、语言、地区、格式化策略Localization:具体文案 翻译和内容落地
Next.js 主要负责前一层,也就是:
- 路由怎么带 locale
- 默认语言怎么选
- 用户访问时该落到哪个语言路径
- 多语言页面的渲染和组织怎么接起来
至于具体文案翻译,往往还要结合 i18n 库或业务侧内容系统。
先看 App Router 里的主线
当前官方 App Router 文档更推荐的理解方式是:
- 用 URL 层表示 locale
- 用
Accept-Language辅助做首次语言选择 - 在路由层组织不同 locale 的页面结构
也就是说,多语言不是“页面里切换几段文案”那么简单,它首先是一套路由策略。
最常见的一种目录结构
app/
[lang]/
layout.tsx
page.tsx
products/
page.tsx
这样可以得到:
/en/zh-CN/ja
[lang] 就是 locale 路由段。
为什么这套方式直观
因为:
- locale 直接进入 URL
- 服务端和客户端都容易识别当前语言
- metadata、导航、内容查询、缓存标签都更容易按语言拆分
首次访问时怎么决定语言
官方文档里推荐参考浏览器的 Accept-Language 头。
常见做法是:
- 定义一组支持的 locales
- 设默认 locale
- 首次访问根路径时,根据请求头判断跳到哪个 locale
例如可以在 proxy.ts 里做:
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
const locales = ['en-US', 'zh-CN'];
const defaultLocale = 'en-US';
function getLocale(request: NextRequest) {
const locale = request.headers.get('accept-language');
if (locale?.includes('zh')) return 'zh-CN';
return defaultLocale;
}
export function proxy(request: NextRequest) {
const { pathname } = request.nextUrl;
const pathnameHasLocale = locales.some(
(locale) => pathname === `/${locale}` || pathname.startsWith(`/${locale}/`)
);
if (pathnameHasLocale) {
return NextResponse.next();
}
const locale = getLocale(request);
request.nextUrl.pathname = `/${locale}${pathname}`;
return NextResponse.redirect(request.nextUrl);
}
这个例子只是说明路由思路,实际项目里通常会配合更稳的 locale 匹配库。