配置 Nextjs 的多语言支持

힘센캥거루
2025년 10월 18일(수정됨)
9
nextjs
配置 Nextjs 的多语言支持-1

为了增加我的博客的访问量,我考虑尝试设置多语言。

找到了多种方法,首先的一步是为语言设置不同的路由。

决定使用 next-intl 来实现。

1. 安装

yarn add next-intl

2. 应用

应用稍显复杂。

大致按以下步骤进行。

  1. 将 app 内部的所有路由文件放到 [locale] 文件夹中。

  2. 创建 i18n 文件夹,并在其中设置 config.ts、request.ts、ko.json、en.json 文件

  3. 在 middleware.ts 和 next.config.ts 中进行设置

  4. 在布局中通过 params 和 provider 包装子组件

  5. 在组件中加载消息

3. 运行

1) [locale] 文件夹

配置 Nextjs 的多语言支持-2

我的 app 内部文件结构如上图所示。 

我打算将 app 下所有除 api 和 uploads 外的文件夹都放在 [locale] 中。

由于 .next 存在时移动文件夹会出现权限错误,因此需通过 sudo rm -r .next 删除后再移动文件夹。

需注意,因文件结构改变,若存在使用相对路径的调用需修改

配置 Nextjs 的多语言支持-3

2) 创建 i18n 文件夹

如有 src 文件夹的用户,在 src 下创建即可;仅使用 app 的用户可直接在根目录创建。

我在 i18n 文件夹内创建了 config.ts 和 request.ts,并在 message 文件夹内创建了 ko.json 和 en.json。

配置 Nextjs 的多语言支持-4

config.ts 文件设置如下。

我将空路径 "/" 设置为韩语。

export const locales = ['ko', 'en'] as const;
export type Locale = (typeof locales)[number];

export const defaultLocale: Locale = 'ko'; // 将默认路径设置为韩语

export const pathnames = {
  '/': '/',
  '/about': {
    ko: '/about',
    en: '/about',
  },
  '/post/[slug]': {
    ko: '/post/[slug]',
    en: '/post/[slug]',
  },
} as const;

request.ts 文件的设置如下。

调用 locale 信息并返回给服务器。

import { getRequestConfig } from 'next-intl/server';
import { defaultLocale } from './config';

export default getRequestConfig(async ({ requestLocale }: { requestLocale: Promise<string | undefined> }) => {
  const locale = await requestLocale || defaultLocale;

  return {
    locale,
    messages: (await import(`./message/${locale}.json`)).default,
  };
});

3) 设置 middleware.ts 和 next.config.ts

首先,middleware.ts 设置如下。

简单来说就是在上方用 export 添加 createMiddleware。

import createMiddleware from 'next-intl/middleware';
import { locales, defaultLocale } from './i18n/config';

export createMiddleware({
  locales,
  defaultLocale,
  localePrefix: 'as-needed', // 默认(ko)路径无前缀
});
//...现有设置...//
export default withAuth(
	  function middleware(req) {
		//...现有设置...//
	});

然后在 next.config.ts 中创建 createNextIntlPlugin,并将现有设置包裹起来。

import type { NextConfig } from "next";
import createNextIntlPlugin from 'next-intl/plugin';

const withNextIntl = createNextIntlPlugin()

const withNextIntlConfig: NextConfig = withNextIntl({
	现有 next.config 设置...
});

export default withNextIntlConfig;

4) 包装布局

在布局中,通过 getMessage 获取 locale 并用 provider 包裹,以便于下级组件使用。

import { NextIntlClientProvider } from "next-intl";
import { getMessages, getLocale } from "next-intl/server";

export default async function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  const messages = await getMessages();
  const locale = await getLocale();

  return (
    <html
      lang={locale}
    >
      <NextIntlClientProvider locale={locale} messages={messages}>
        <body>
		{children}
        </body>
      </NextIntlClientProvider>
    </html>
  );
}

5) 试用消息

服务器渲染和客户端渲染时函数名不同。

import {useTranslations, useLocale, useFormatter} from 'next-intl'; // 在 'use client' 组件中调用
import {getTranslations, getLocale, getFormatter} from 'next-intl/server'; // 在服务器组件中调用

分类

客户端组件

服务器组件 / 服务器函数

说明

Translations

useTranslations(namespace?)

getTranslations(namespace?)

获取ko.jsonen.json 等翻译消息,并以 t('key') 形式使用

Locale

useLocale()

getLocale()

返回当前激活的语言(/en, /ko, …)为字符串

Formatter

useFormatter()

getFormatter()

格式化日期、时间、数字以适应语言环境

Messages

getMessages()

获取当前请求的完整翻译消息对象(通常用于布局中的 Provider)

Request Locale 设置

unstable_setRequestLocale(locale)

在 SSG·SSR 缓存时用于保证语言一致性时在布局中使用

我决定先尝试修改 /about。

当前我的 /about 组件如下面硬编码状态一样,因此易于修改。

import {
  HeroSection,
  JourneySection,
  ProjectsSection,
} from "@/components/about";


const baseUrl = process.env.NEXT_PUBLIC_URL||"";

export default function AboutPage() {
	...
  const heroData = {
	...
  };

  const journeyData = {
    title: "My Journey",
    items: [
	.....
	]
  };

  const projectsData = {
    title: "Featured Projects",
    projects: [
      {
        title: "大入统计分析",
		...
      },
	...
    ],
  };

  return (
    <div className="min-h-screen bg-gray-900 ">
      <main className="rounded-lg container relative mx-auto scroll-my-12 overflow-auto">
        {/* Language Selector */}
        <HeroSection {...heroData} />
        <JourneySection {...journeyData} />
        <ProjectsSection {...projectsData} />
      </main>
    </div>
  );
}

现在设置 ko.json 和 en.json 后,可以通过 getTranslations 将文本插入组件。

配置 Nextjs 的多语言支持-5

然而,用 getTranslations 调用的信息仅为字符串结构。

试图像下方这样进行更改时出了错误。

export default async function AboutPage() {
	...
  const t = await getTranslations("about");
  const heroData = JSON.parse(JSON.stringify(t("hero")));
  const journeyData = JSON.parse(JSON.stringify(t("journey")));
  const projectsData = JSON.parse(JSON.stringify(t("projects")));
	...
}

于是十分麻烦,寻求了光标(cursor)导航的帮助。

配置 Nextjs 的多语言支持-6

这样逐个将参数传递给下级组件。

之后用 en 进行访问,确认是否生效。

配置 Nextjs 的多语言支持-7

可以看到应用得很好。

4. 结论

直到现在我还以为需要手动翻译所有英语博客,但如今有了 AI 和许多自动化工具,这将变得更为简单。

剩下的工作是将博客中的所有文章翻译,并存入数据库。

然后在数据库中添加 locale,通过 locale 搜索返回 post。

我打算不久后试一下。

댓글을 불러오는 중...