Next.jsnext-intli18n
在 Next.js 中使用 next-intl 实现多语言支持
介绍如何在 Next.js App Router 中使用 next-intl 实现高效的多语言支持,包括目录结构、路由处理、语言切换等最佳实践。
RaytonX
5 min read
next-intl
是专为 Next.js App Router 设计的国际化库,具备轻量、易用、与 App Router 深度集成等优势。
1. 安装依赖
使用 pnpm
安装 next-intl
。
2. 配置 next-intl
目录结构建议
messages/
:用于存放翻译文件,例如en.json
和zh.json
src/i18n/
:用于存放语言配置及工具函数
多语言配置流程
-
在
next.config.js
中集成next-intl
插件import type { NextConfig } from "next"; import createNextIntlPlugin from "next-intl/plugin"; const nextConfig: NextConfig = {}; const withNextIntl = createNextIntlPlugin(); export default withNextIntl(nextConfig);
-
使用 TypeScript 文件(如
src/i18n/en.ts
,zh.ts
)代替 JSON 编写内容,提高灵活性 -
通过
getI18n
方法按需加载翻译对象// src/i18n/index.ts import { en } from "./en"; import { zh } from "./zh"; const locales = { zh, en }; export function getI18n(locale: string) { return locales[locale as keyof typeof locales] || locales["en"]; }
-
使用
routing.ts
配置多语言路由参数(locales、默认语言、是否自动检测)// src/i18n/routing.ts import { defineRouting } from "next-intl/routing"; export const routing = defineRouting({ // A list of all locales that are supported locales: ["en", "zh"], // Used when no locale matches defaultLocale: "en", localeDetection: false, });
-
在
request.ts
中配置消息加载逻辑(按请求语言加载相应 JSON 文件)// src/i18n/request.ts import { hasLocale } from "next-intl"; import { getRequestConfig } from "next-intl/server"; import { routing } from "./routing"; export default getRequestConfig(async ({ requestLocale }) => { // Typically corresponds to the `[locale]` segment const requested = await requestLocale; const locale = hasLocale(routing.locales, requested) ? requested : routing.defaultLocale; return { locale, messages: (await import(`../../messages/${locale}.json`)).default, }; });
-
navigation.ts
封装 Link 等导航方法,自动处理语言切换// src/i18n/navigation.ts import { createNavigation } from "next-intl/navigation"; import { routing } from "./routing"; // Lightweight wrappers around Next.js' navigation // APIs that consider the routing configuration export const { Link, redirect, usePathname, useRouter, getPathname } = createNavigation(routing);
布局文件支持
在 src/app/[locale]/layout.tsx
中,根据当前语言设置 <html lang="xx">
,并引入 NextIntlClientProvider
。
// src/app/[locale]/layout.tsx
import { routing } from "@/i18n/routing";
import { NextIntlClientProvider, hasLocale } from "next-intl";
import { notFound } from "next/navigation";
export default async function LocaleLayout({
children,
params,
}: {
children: React.ReactNode;
params: Promise<{ locale: string }>;
}) {
const { locale } = await params;
if (!hasLocale(routing.locales, locale)) {
notFound();
}
return (
<html lang={locale}>
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
<NextIntlClientProvider>{children}</NextIntlClientProvider>
</body>
</html>
);
}
3. 使用多语言内容
-
页面中通过
useTranslations
获取字符串内容import {useTranslations} from 'next-intl'; function About() { const t = useTranslations('About'); return <h1>{t('title')}</h1>; }
-
若使用对象形式加载,可通过
getI18n(locale)
访问更复杂的结构import { useLocale } from "next-intl"; export default function Header() { const locale = useLocale(); const t = getI18n(locale); } return ( <div> {t.services.items.map((service, index) => ( <Card key={index}> {service.description} </Card> ))} </div> )
-
使用封装后的
Link
自动处理路由语言切换,无需手动拼接语言前缀import { Link } from "@/i18n/navigation"; <Link href={posts[0].url} className="inline-flex items-center px-6 py-3 rounded-lg bg-blue-600 text-white font-medium hover:bg-blue-700 transition-colors" > Read More → </Link>
通过以上结构,next-intl
提供了清晰的组织方式与 API 接口,使 Next.js 应用在多语言支持上更稳定、易维护。