如何在使用 App Router 的 Next.js 应用中实现国际化
通过国际化 (i18n),让你的 React 应用更具可访问性并开拓新市场。
随着世界越来越全球化,网页开发者构建能够满足来自不同国家和文化的用户需求的应用变得愈发重要。实现这一目标的关键方法之一是国际化(i18n),它允许你将应用适配到不同的语言、货币和日期格式。
在本文中,我们将探讨如何在具有服务器端渲染的 React Next.js 应用中添加国际化。 TL;DR: 在此查看完整示例。
本指南适用于使用 App Router 的 Next.js 应用。
如果您使用的是 Pages Router,请参阅此指南。
第 1 步:安装一个 i18n 库
要在你的 Next.js 应用中实现国际化,首先我们要选择一个 i18n 库。有几种流行的库可供选择,其中包括 next-intl. 在本示例中,我们将使用 TacoTranslate.
TacoTranslate 使用最先进的 AI 自动将你的字符串翻译为任何语言,免去了繁琐的 JSON 文件管理。
让我们在终端中使用 npm 来安装它:
npm install tacotranslate
第2步: 创建一个免费的 TacoTranslate 账户
既然你已经安装了该模块,现在就可以创建你的 TacoTranslate 帐户、翻译项目以及相应的 API 密钥了。在此创建帐户。 这是免费的,无需提供信用卡信息。
在 TacoTranslate 应用程序的 UI 中,创建一个项目,然后进入其 API 密钥选项卡。创建一个 read
密钥和一个 read/write
密钥。我们会将它们保存为环境变量。 read
密钥就是我们所称的 public
,而 read/write
密钥则是 secret
。例如,您可以将它们添加到项目根目录的 .env
文件中。
TACOTRANSLATE_PUBLIC_API_KEY=123456
TACOTRANSLATE_SECRET_API_KEY=789010
务必不要将秘密 read/write
API 密钥泄露到客户端的生产环境。
我们还会添加两个环境变量: TACOTRANSLATE_DEFAULT_LOCALE
和 TACOTRANSLATE_ORIGIN
.
TACOTRANSLATE_DEFAULT_LOCALE
:默认的回退区域设置代码。在此示例中,我们将其设置为en
(英语)。TACOTRANSLATE_ORIGIN
:存放字符串的“文件夹”,例如你网站的 URL。在此了解有关来源的更多信息。
TACOTRANSLATE_DEFAULT_LOCALE=en
TACOTRANSLATE_ORIGIN=your-website-url.com
第3步: 设置 TacoTranslate
要将 TacoTranslate 集成到您的应用中,您需要使用之前的 API 密钥创建一个客户端。例如,创建一个名为 /tacotranslate-client.js
的文件。
const {default: createTacoTranslateClient} = require('tacotranslate');
const tacoTranslate = createTacoTranslateClient({
apiKey:
process.env.TACOTRANSLATE_SECRET_API_KEY ??
process.env.TACOTRANSLATE_PUBLIC_API_KEY ??
process.env.TACOTRANSLATE_API_KEY,
projectLocale:
process.env.TACOTRANSLATE_IS_PRODUCTION === 'true'
? process.env.TACOTRANSLATE_PROJECT_LOCALE
: undefined,
});
module.exports = tacoTranslate;
我们将在稍后自动定义 TACOTRANSLATE_API_KEY
和 TACOTRANSLATE_PROJECT_LOCALE
。
将客户端创建在单独的文件中,便于以后重复使用。 getLocales
只是一个带有内置错误处理的实用函数。现在,创建一个名为 /app/[locale]/tacotranslate.tsx
的文件,在那里我们将实现 TacoTranslate
提供程序。
'use client';
import React, {type ReactNode} from 'react';
import {
type TranslationContextProperties,
TacoTranslate as ImportedTacoTranslate,
} from 'tacotranslate/react';
import tacoTranslateClient from '@/tacotranslate-client';
export default function TacoTranslate({
locale,
origin,
localizations,
children,
}: TranslationContextProperties & {
readonly children: ReactNode;
}) {
return (
<ImportedTacoTranslate
client={tacoTranslateClient}
locale={locale}
origin={origin}
localizations={localizations}
>
{children}
</ImportedTacoTranslate>
);
}
注意 'use client';
,这表明这是一个客户端组件。
上下文提供者准备就绪后,创建一个名为 /app/[locale]/layout.tsx
的文件,这是我们应用程序的根布局。请注意,此路径包含一个使用 Dynamic Routes 的文件夹,其中 [locale]
是动态参数。
import React, {type ReactNode} from 'react';
import {type Locale, isRightToLeftLocaleCode} from 'tacotranslate';
import './global.css';
import tacoTranslateClient from '@/tacotranslate-client';
import TacoTranslate from './tacotranslate';
export async function generateStaticParams() {
const locales = await tacoTranslateClient.getLocales();
return locales.map((locale) => ({locale}));
}
type RootLayoutParameters = {
readonly params: Promise<{locale: Locale}>;
readonly children: ReactNode;
};
export default async function RootLayout({params, children}: RootLayoutParameters) {
const {locale} = await params;
const origin = process.env.TACOTRANSLATE_ORIGIN;
const localizations = await tacoTranslateClient.getLocalizations({
locale,
origins: [origin /* , other origins to fetch */],
});
return (
<html lang={locale} dir={isRightToLeftLocaleCode(locale) ? 'rtl' : 'ltr'}>
<body>
<TacoTranslate
locale={locale}
origin={origin}
localizations={localizations}
>
{children}
</TacoTranslate>
</body>
</html>
);
}
首先需要注意的是,我们正在使用 Dynamic Route
参数 [locale]
来获取该语言的翻译。此外,generateStaticParams
确保您在项目中激活的所有语言代码都已进行预渲染。
现在,让我们构建第一个页面!创建一个名为 /app/[locale]/page.tsx
的文件。
import React from 'react';
import {Translate} from 'tacotranslate/react';
export const revalidate = 60;
export default async function Page() {
return (
<Translate string="Hello, world!" />
);
}
注意 revalidate
变量,它会告诉 Next.js 在 60 秒后重新构建页面,并使你的翻译保持最新。
第4步: 实现服务端渲染
TacoTranslate 支持服务器端渲染。这能大幅提升用户体验,直接显示已翻译的内容,而不是先短暂显示未翻译的内容。此外,我们可以在客户端跳过网络请求,因为我们已经拥有用户正在查看页面所需的翻译。
要设置服务器端渲染,请创建或修改 /next.config.js
:
const withTacoTranslate = require('tacotranslate/next/config').default;
const tacoTranslateClient = require('./tacotranslate-client');
module.exports = async () => {
const config = await withTacoTranslate(
{},
{
client: tacoTranslateClient,
isProduction:
process.env.TACOTRANSLATE_ENV === 'production' ||
process.env.VERCEL_ENV === 'production' ||
(!(process.env.TACOTRANSLATE_ENV || process.env.VERCEL_ENV) &&
process.env.NODE_ENV === 'production'),
}
);
// NOTE: Remove i18n from config when using the app router
return {...config, i18n: undefined};
};
根据你的设置修改 isProduction
检查。如果 true
,TacoTranslate 将公开公共 API 密钥。如果我们处于本地、测试或预发布环境(isProduction
is false
),我们将使用机密的 read/write
API 密钥,以确保新的字符串被发送进行翻译。
为确保路由和重定向按预期工作,我们需要创建一个名为 /middleware.ts
的文件。使用 Middleware, 我们可以将用户重定向到以其首选语言呈现的页面。
import {type NextRequest} from 'next/server';
import {middleware as tacoTranslateMiddleware} from 'tacotranslate/next';
import tacoTranslate from '@/tacotranslate-client';
export const config = {
matcher: ['/((?!api|_next|favicon.ico).*)'],
};
export async function middleware(request: NextRequest) {
return tacoTranslateMiddleware(tacoTranslate, request);
}
请确保按照 Next.js 中间件文档 的说明设置 matcher
。
在客户端,您可以修改 locale
cookie 来更改用户的首选语言。请参阅 完整示例代码 以获取如何实现的思路!
第5步: 部署并测试!
我们完成了!当你在 Translate
组件中添加任何字符串时,你的 React 应用将会自动被翻译。请注意,只有在 API 密钥上具有 read/write
权限的环境,才能创建要翻译的新字符串。我们建议设置一个封闭且安全的预发布环境(staging),在那里使用这样的 API 密钥测试你的生产应用,并在上线前添加新的字符串。这样可以防止任何人窃取你的秘密 API 密钥,并避免通过添加不相关的新字符串使你的翻译项目膨胀。
Be sure to check out the complete example over at our GitHub profile. There, you’ll also find an example of how to do this using the Pages Router! If you encounter any problems, feel free to reach out, and we’ll be more than happy to help.
TacoTranslate lets you automatically localize your React applications quickly to and from over 75 languages. Get started today!