介绍
国际化是现代 Web 应用程序的基本要求。 Next.js 已将其 i18n 支持从 Pages Router 中的集成路由系统发展为 App Router 中灵活的基于中间件的方法。本文涵盖多语言 Next.js 应用程序的路由策略、区域设置检测、内容管理和 SEO 优化。
关键概念是区域设置、默认区域设置、区域设置检测以及子路径路由和域路由之间的权衡。 App Router 方法提供了更大的灵活性,但比其前身需要更多的手动设置。
路由策略——子路径与域
子路径和域路由之间的选择对 SEO 和基础设施具有重大影响。
| 标准 | 子路径 (/en/about) | 域 (en.example.com) |
|---|---|---|
| SEO权威 | 共享域权限 | 每个语言环境独立 |
| 地理定位 | 信号较弱 | 更强的信号 |
| 基础设施 | 单一部署 | 多重部署 |
| 分析 | 统一 | 分段 |
对于大多数项目,建议使用子路径路由,因为它简单且共享域权限。 App Router 中的实现使用中间件来处理区域设置前缀重写。
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
const locales = ["en", "ja", "fr"];
const defaultLocale = "en";
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
const pathnameHasLocale = locales.some(
(locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
);
if (pathnameHasLocale) return;
const locale = request.cookies.get("NEXT_LOCALE")?.value || defaultLocale;
return NextResponse.redirect(new URL(`/${locale}${pathname}`, request.url));
}
export const config = {
matcher: ["/((?!api|_next|favicon.ico).*)"],
};
区域设置检测和协商
Next.js 通过协商链确定区域设置:cookie 到 Accept-Language 标头到默认区域设置。 NEXT_LOCALE cookie 约定允许用户保留其语言首选项。
function getLocale(request: NextRequest): string {
const cookieLocale = request.cookies.get("NEXT_LOCALE")?.value;
if (cookieLocale && locales.includes(cookieLocale)) return cookieLocale;
const acceptLanguage = request.headers.get("accept-language");
if (acceptLanguage) {
const preferred = acceptLanguage
.split(",")
.map((lang) => lang.split(";")[0].trim())
.find((lang) => locales.includes(lang));
if (preferred) return preferred;
}
return defaultLocale;
}
这种协商逻辑可确保用户始终以自己喜欢的语言查看内容,同时允许手动覆盖。
使用 next-intl 进行内容管理
next-intl 是 App Router i18n 的推荐库。它提供类型安全的翻译键、命名空间分割和高效的消息加载。
// middleware.ts
import createMiddleware from "next-intl/middleware";
export default createMiddleware({ locales: ["en", "ja"], defaultLocale: "en" });
export const config = { matcher: ["/((?!api|_next).*)"] };
为了可维护性,翻译文件按命名空间组织:
{
"navigation": { "home": "Home", "about": "About" },
"home": { "title": "Welcome", "description": "This is the home page" }
}
组件使用 useTranslations 钩子消耗翻译:
import { useTranslations } from "next-intl";
function HomePage() {
const t = useTranslations("home");
return <h1>{t("title")}</h1>;
}
多语言网站的 SEO
跨语言 SEO 需要正确的 hreflang 标签和规范 URL。每个页面都应包含自引用和备用 hreflang 链接。
export async function generateMetadata({ params }: Props) {
const { locale } = await params;
return {
alternates: {
languages: {
en: "/en/about",
ja: "/ja/about",
"x-default": "/en/about",
},
},
};
}
常见的 SEO 陷阱包括跨区域设置的重复内容、缺少 hreflang 返回链接以及不一致的区域设置 URL 模式。 Google 的指南要求每种语言版本都链接回所有其他语言版本。
结论
对于大多数项目,使用 next-intl 的子路径路由可提供简单性、SEO 和开发人员体验的最佳平衡。投资适当的区域设置检测中间件,按命名空间组织翻译文件,并实现完整的 hreflang 元数据。官方 Next.js i18n 示例和 next-intl 文档是用于生产实现的优秀资源。

