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.jsonzh.json
  • src/i18n/:用于存放语言配置及工具函数

多语言配置流程

  1. 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);
  2. 使用 TypeScript 文件(如 src/i18n/en.ts, zh.ts)代替 JSON 编写内容,提高灵活性

  3. 通过 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"];
    }
  4. 使用 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,
    });
  5. 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,
      };
    });
  6. 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 应用在多语言支持上更稳定、易维护。