Как реализовать интернационализацию в приложении Next.js, использующем App Router
Сделайте ваше React-приложение более доступным и выйдите на новые рынки с помощью интернационализации (i18n).
По мере того как мир становится все более глобализованным, для веб-разработчиков становится все важнее создавать приложения, которые могут обслуживать пользователей из разных стран и культур. Один из ключевых способов добиться этого — международная адаптация (i18n), которая позволяет адаптировать ваше приложение под разные языки, валюты и форматы дат.
В этой статье мы рассмотрим, как добавить международную адаптацию в ваше React-приложение на Next.js с поддержкой серверного рендеринга. TL;DR: Полный пример смотрите здесь.
Это руководство предназначено для приложений Next.js, которые используют App Router.
Если вы используете Pages Router, смотрите это руководство.
Шаг 1: Установите библиотеку i18n
Чтобы внедрить интернационализацию в ваше приложение Next.js, сначала выберем библиотеку i18n. Существует несколько популярных библиотек, включая next-intl. В этом примере, однако, мы будем использовать TacoTranslate.
TacoTranslate автоматически переводит ваши строки на любой язык с помощью передового ИИ и избавляет вас от утомительного управления JSON-файлами.
Давайте установим его с помощью npm в вашем терминале:
npm install tacotranslate
Шаг 2: Создайте бесплатную учетную запись TacoTranslate
Теперь, когда модуль установлен, пришло время создать вашу учетную запись TacoTranslate, проект перевода и связанные с ним API-ключи. Создайте учетную запись здесь. Это бесплатно и не требует добавления кредитной карты.
В пользовательском интерфейсе приложения TacoTranslate создайте проект и перейдите на вкладку с 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
), мы будем использовать секретный API-ключ с правами read/write
, чтобы новые строки отправлялись на перевод.
Чтобы обеспечить правильную работу маршрутизации и переадресации, нам нужно создать файл с именем /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);
}
Обязательно настройте matcher
в соответствии с документацией Next.js по Middleware.
На клиенте вы можете изменить куки locale
, чтобы изменить предпочитаемый пользователем язык. Пожалуйста, смотрите полный пример кода для идей о том, как это сделать!
Шаг 5: Разверните и протестируйте!
Мы закончили! Ваше React-приложение теперь будет автоматически переводиться, когда вы добавляете любые строки в компонент Translate
. Обратите внимание, что только среды с разрешениями read/write
на ключ API смогут создавать новые строки для перевода. Мы рекомендуем иметь закрытую и защищённую среду тестирования, где вы можете проверить ваше производственное приложение с таким ключом 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!