Next.js Интернационализация (i18n) с next-intl и Intlayer
Обе библиотеки next-intl и Intlayer являются открытыми фреймворками интернационализации (i18n), разработанными для приложений на Next.js. Они широко используются для управления переводами, локализацией и переключением языков в программных проектах.
Они делят три основных понятия:
Декларация содержимого: Метод определения переводимого содержимого вашего приложения.
- Называется content declaration file в Intlayer, что может быть JSON, JS или TS файлом, экспортирующим структурированные данные. Смотрите документацию Intlayer для получения дополнительной информации.
- Называется messages или locale messages в next-intl, обычно в JSON-файлах. Смотрите документацию next-intl для получения дополнительной информации.
Утилиты: Инструменты для создания и интерпретации деклараций содержимого в приложении, такие как useIntlayer() или useLocale() для Intlayer и useTranslations() для next-intl.
Плагины и промежуточные программные обеспечения: Функции для управления перенаправлением URL, оптимизацией пакетов и многое другое — например, intlayerMiddleware для Intlayer или createMiddleware для next-intl.
Intlayer против next-intl: Ключевые различия
Для более глубокого анализа того, как Intlayer сравнивается с другими библиотеками i18n для Next.js (такими как next-intl), ознакомьтесь с статьей в блоге next-i18next vs. next-intl vs. Intlayer.
Как генерировать сообщения next-intl с Intlayer
Почему использовать Intlayer с next-intl?
Файлы декларации содержимого Intlayer, как правило, предлагают лучший опыт разработчика. Они более гибкие и удобные в обслуживании благодаря двум основным преимуществам:
Гибкое размещение: Вы можете разместить файл декларации содержимого Intlayer где угодно в файловой структуре вашего приложения. Это облегчает переименование или удаление компонентов без оставления неиспользуемых или висячих файлов сообщений.
Пример структуры файлов:
bash.└── src └── components └── MyComponent ├── index.content.ts # Файл декларации содержимого └── index.tsx
Централизованные переводы: Intlayer хранит все переводы в одной декларации содержимого, что гарантирует отсутствие пропущенных переводов. В проектах на TypeScript пропущенные переводы автоматически помечаются как ошибки типов, обеспечивая немедленную обратную связь разработчикам.
Установка
Чтобы использовать Intlayer и next-intl вместе, установите обе библиотеки:
npm install intlayer next-intl
Конфигурация Intlayer для экспорта сообщений next-intl
Примечание: Экспорт сообщений из Intlayer для next-intl может ввести небольшие различия в структуре. Если возможно, сохраняйте поток только Intlayer или только next-intl для упрощения интеграции. Если вам действительно нужно сгенерировать сообщения next-intl из Intlayer, следуйте приведенным ниже шагам.
Создайте или обновите файл intlayer.config.ts (или .mjs / .cjs) в корне вашего проекта:
import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = { internationalization: { locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH], defaultLocale: Locales.ENGLISH, }, content: { dictionaryOutput: ["next-intl"], // Используйте вывод next-intl nextIntlMessagesDir: "./intl/messages", // Куда сохранять сообщения next-intl },};export default config;
Декларация содержимого
Ниже приведены примеры файлов декларации содержимого в нескольких форматах. Intlayer собирает их в файлы сообщений, которые может использовать next-intl.
import { t, type DeclarationContent } from "intlayer";const content = { key: "my-component", content: { helloWorld: t({ en: "Hello World", fr: "Bonjour le monde", es: "Hola Mundo", }), },} satisfies DeclarationContent;export default content;
Создание сообщений для next-intl
Чтобы создать файлы сообщений для next-intl, выполните:
npx intlayer build
Это создаст ресурсы в директории ./intl/messages (как указано в intlayer.config.*). Ожидаемый вывод:
.└── intl └── messages └── ru └── my-content.json └── fr └── my-content.json └── es └── my-content.json
Каждый файл включает собранные сообщения из всех деклараций содержимого Intlayer. Ключи верхнего уровня обычно соответствуют вашим полям content.key.
Использование next-intl в вашем приложении на Next.js
Для получения более подробной информации смотрите официальные документы по использованию next-intl.
Создать промежуточное ПО (по желанию):
Если вы хотите управлять автоматическим определением локали или перенаправлением, используйте createMiddleware от next-intl.middleware.tsimport createMiddleware from "next-intl/middleware";import { NextResponse } from "next/server";export default createMiddleware({ locales: ["en", "fr", "es"], defaultLocale: "en",});export const config = { matcher: ["/((?!api|_next|.*\\..*).*)"],};
Создать layout.tsx или _app.tsx для загрузки сообщений:
Если вы используете App Router (Next.js 13+), создайте макет:app/[locale]/layout.tsximport { NextIntlClientProvider } from 'next-intl';import { notFound } from 'next/navigation';import React, { ReactNode } from 'react';export const dynamic = 'force-dynamic';export default async function RootLayout({ children, params}: { children: ReactNode; params: { locale: string };}) { let messages; try { messages = (await import(`../../intl/messages/${params.locale}.json`)).default; } catch (error) { notFound(); } return ( <html lang={params.locale}> <body> <NextIntlClientProvider locale={params.locale} messages={messages}> {children} </NextIntlClientProvider> </body> </html> );}
Если вы используете Pages Router (Next.js 12 или ниже), загружайте сообщения в _app.tsx:
pages/_app.tsximport type { AppProps } from 'next/app';import { NextIntlProvider } from 'next-intl';function MyApp({ Component, pageProps }: AppProps) { return ( <NextIntlProvider locale={pageProps.locale} messages={pageProps.messages}> <Component {...pageProps} /> </NextIntlProvider> );}export default MyApp;
Получение сообщений на стороне сервера (пример Pages Router):
pages/index.tsximport { GetServerSideProps } from "next";import HomePage from "../components/HomePage";export default HomePage;export const getServerSideProps: GetServerSideProps = async ({ locale }) => { const messages = (await import(`../intl/messages/${locale}.json`)).default; return { props: { locale, messages, }, };};
Использование содержимого в компонентах Next.js
После загрузки сообщений в next-intl вы можете использовать их в своих компонентах с помощью хука useTranslations():
import type { FC } from "react";import { useTranslations } from 'next-intl';const MyComponent: FC = () => { const t = useTranslations('my-component'); // 'my-component' соответствует ключу содержимого в Intlayer return ( <div> <h1>{t('helloWorld')}</h1> </div> );};export default MyComponent;
Вот и всё! Каждый раз, когда вы обновляете или добавляете новые файлы декларации содержимого Intlayer, повторно выполните команду intlayer build, чтобы сгенерировать ваши JSON-сообщения next-intl. next-intl автоматически подберет обновленное содержимое.
Если у вас есть идея по улучшению этой документации, не стесняйтесь внести свой вклад, подав запрос на вытягивание на GitHub.
Ссылка на блог GitHub