Начало работы с интернационализацией (i18n) с Intlayer и Next.js 14 с маршрутизатором App
Что такое Intlayer?
Intlayer — это инновационная библиотека для интернационализации (i18n) с открытым исходным кодом, разработанная для упрощения поддержки многоязычности в современных веб-приложениях. Intlayer seamlessly integrates with the latest Next.js 14 framework, including its powerful App Router. Он оптимизирован для работы с Server Components для эффективного рендеринга и полностью совместим с Turbopack (с Next.js >= 15).
С помощью Intlayer вы можете:
- Легко управлять переводами, используя декларативные словари на уровне компонентов.
- Динамически локализовать метаданные, маршруты и содержимое.
- Получать доступ к переводам как в компонентах на стороне клиента, так и на стороне сервера.
- Обеспечить поддержку TypeScript с автогенерируемыми типами, улучшая автозаполнение и обнаружение ошибок.
- Воспользоваться расширенными функциями, такими как динамическое определение и переключение локали.
Intlayer совместим с Next.js 12, 13, 14 и 15. Если вы используете маршрутизатор страниц Next.js, вы можете обратиться к этому руководству. Для Next.js 15 с или без turbopack обратитесь к этому руководству.
Пошаговое руководство по настройке Intlayer в приложении Next.js
Шаг 1: Установка зависимостей
Установите необходимые пакеты с помощью npm:
npm install intlayer next-intlayer
intlayer
Основной пакет, который предоставляет инструменты интернационализации для управления конфигурацией, переводом, декларацией контента, трансалиацией и CLI командами.
next-intlayer
Пакет, который интегрирует Intlayer с Next.js. Он предоставляет контекстные провайдеры и хуки для интернационализации Next.js. Кроме того, он включает плагин Next.js для интеграции Intlayer с Webpack или Turbopack, а также промежуточное ПО для определения предпочтительной локали пользователя, управления куками и обработки перенаправления URL.
Шаг 2: Настройте ваш проект
Создайте конфигурационный файл для настройки языков вашего приложения:
import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = { internationalization: { locales: [ Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH, // Ваши другие локали ], defaultLocale: Locales.ENGLISH, },};export default config;
С помощью этого конфигурационного файла вы можете настроить локализованные URL, промежуточные перенаправления, имена куки, местоположение и расширение ваших деклараций контента, отключить логи Intlayer в консоли и многое другое. Для полного списка доступных параметров смотрите документацию по конфигурации.
Шаг 3: Интегрируйте Intlayer в вашу конфигурацию Next.js
Настройте вашу установку Next.js для использования Intlayer:
import { withIntlayer } from "next-intlayer/server";/** @type {import('next').NextConfig} */const nextConfig = {};export default withIntlayer(nextConfig);
Плагин withIntlayer() используется для интеграции Intlayer с Next.js. Он обеспечивает сборку файлов декларации контента и их мониторинг в режиме разработки. Он определяет переменные окружения Intlayer в средах Webpack или Turbopack. Кроме того, он предоставляет псевдонимы для оптимизации производительности и обеспечивает совместимость с серверными компонентами.
Шаг 4: Настройте промежуточное программное обеспечение для определения локали
Настройте промежуточное ПО для определения предпочтительной локали пользователя:
export { intlayerMiddleware as middleware } from "next-intlayer/middleware";export const config = { matcher: "/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",};
intlayerMiddleware используется для определения предпочтительной локали пользователя и перенаправления его на соответствующий URL, как указано в конфигурации. Кроме того, он позволяет сохранить предпочтительную локаль пользователя в куке.
Настройте параметр matcher, чтобы он соответствовал маршрутам вашего приложения. Для получения дополнительных подробностей смотрите документацию Next.js по настройке matcher.
Шаг 5: Определите динамические маршруты локали
Удалите все из RootLayout и замените его следующим кодом:
import type { PropsWithChildren, FC } from "react";import "./globals.css";const RootLayout: FC<PropsWithChildren> = ({ children }) => children;export default RootLayout;
Оставляя компонент RootLayout пустым, вы можете установить атрибуты lang и dir для тега <html>.
Для реализации динамической маршрутизации укажите путь для локали, добавив новую разметку в вашем каталоге [locale]:
import type { Next14LayoutIntlayer } from "next-intlayer";import { Inter } from "next/font/google";import { getHTMLTextDir } from "intlayer";const inter = Inter({ subsets: ["latin"] });const LocaleLayout: Next14LayoutIntlayer = ({ children, params: { locale },}) => ( <html lang={locale} dir={getHTMLTextDir(locale)}> <body className={inter.className}>{children}</body> </html>);export default LocaleLayout;
Путь [locale] используется для определения локали. Пример: /en-US/about будет относиться к en-US, а /fr/about к fr.
Затем реализуйте функцию generateStaticParams в разметке вашего приложения.
export { generateStaticParams } from "next-intlayer"; // Строка для вставкиconst LocaleLayout: Next14LayoutIntlayer = ({ children, params: { locale },}) => { /*... Остальная часть кода */};export default LocaleLayout;
generateStaticParams гарантирует, что ваше приложение предварительно генерирует необходимые страницы для всех локалей, уменьшая вычисления во время выполнения и улучшая пользовательский опыт. Для получения дополнительных сведений смотрите документацию Next.js по generateStaticParams.
Шаг 6: Объявите ваш контент
Создайте и управляйте вашими декларациями контента, чтобы сохранить переводы:
import { t, type DeclarationContent } from "intlayer";const pageContent = { key: "page", content: { getStarted: { main: t({ en: "Get started by editing", fr: "Commencez par éditer", es: "Comience por editar", }), pageLink: "src/app/page.tsx", }, },} satisfies DeclarationContent;export default pageContent;
Ваши декларации контента могут быть определены в любом месте вашего приложения, как только они включены в каталог contentDir (по умолчанию ./src). И совпадают с расширением файла декларации контента (по умолчанию .content.{ts,tsx,js,jsx,mjs,cjs}). Для получения дополнительных сведений смотрите документацию по декларации контента.
Шаг 7: Используйте контент в вашем коде
Получите доступ к вашим словарям контента по всему вашему приложению:
import { ClientComponentExample } from "@components/ClientComponentExample";import { ServerComponentExample } from "@components/ServerComponentExample";import { type Next14PageIntlayer, IntlayerClientProvider } from "next-intlayer";import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server";const Page: Next14PageIntlayer = ({ params: { locale } }) => { const content = useIntlayer("page", locale); return ( <> <p> {content.getStarted.main} <code>{content.getStarted.pageLink}</code> </p> <IntlayerServerProvider locale={locale}> <IntlayerClientProvider locale={locale}> <ServerComponentExample /> <ClientComponentExample /> </IntlayerClientProvider> </IntlayerServerProvider> </> );};export default Page;
- IntlayerClientProvider используется для предоставления локали компонентам на стороне клиента. Его можно разместить в любом родительском компоненте, включая разметку. Однако рекомендуется размещать его в разметке, потому что Next.js делит код разметки между страницами, что делает его более эффективным. Используя IntlayerClientProvider в разметке, вы избегаете повторной инициализации его для каждой страницы, что улучшает производительность и поддерживает постоянный контекст локализации по всему вашему приложению.
IntlayerServerProvider используется для предоставления локали дочерним элементам сервера. Его нельзя установить в разметке.
Разметка и страница не могут разделять общий контекст сервера, поскольку система контекста сервера основана на хранилище данных на основе каждой заявки (с помощью механизма кэша React), что приводит к воссозданию каждого "контекста" для разных сегментов приложения. Размещение провайдера в общей разметке нарушило бы эту изоляцию, предотвращая правильное распространение значений контекста сервера к вашим серверным компонентам.
"use client";import type { FC } from "react";import { useIntlayer } from "next-intlayer";const ClientComponentExample: FC = () => { const content = useIntlayer("client-component-example"); // Создайте соответствующую декларацию контента return ( <div> <h2>{content.title} </h2> <p>{content.content}</p> </div> );};
import type { FC } from "react";import { useIntlayer } from "next-intlayer/server";const ServerComponentExample: FC = () => { const content = useIntlayer("server-component-example"); // Создайте соответствующую декларацию контента return ( <div> <h2>{content.title} </h2> <p>{content.content}</p> </div> );};
Если вы хотите использовать ваш контент в атрибуте string, таком как alt, title, href, aria-label и т. д., вы должны вызвать значение функции, например:
jsx<img src={content.image.src.value} alt={content.image.value} />
Чтобы узнать больше о хуке useIntlayer, смотрите документацию.
(Опционально) Шаг 8: Интернационализация ваших метаданных
В случае, если вы хотите интернационализировать ваши метаданные, такие как заголовок вашей страницы, вы можете использовать функцию generateMetadata, предоставляемую Next.js. Внутри функции используйте функцию getTranslationContent, чтобы перевести ваши метаданные.
import { type IConfigLocales, getTranslationContent, getMultilingualUrls,} from "intlayer";import type { Metadata } from "next";import type { LocalParams } from "next-intlayer";export const generateMetadata = ({ params: { locale },}: LocalParams): Metadata => { const t = <T>(content: IConfigLocales<T>) => getTranslationContent(content, locale); /** * Генерирует объект, содержащий все URL для каждой локали. * * Пример: * ```ts * getMultilingualUrls('/about'); * * // Возвращает * // { * // en: '/about', * // fr: '/fr/about', * // es: '/es/about', * // } * ``` */ const multilingualUrls = getMultilingualUrls("/"); return { title: t<string>({ en: "My title", fr: "Mon titre", es: "Mi título", }), description: t({ en: "My description", fr: "Ma description", es: "Mi descripción", }), alternates: { canonical: "/", languages: { ...multilingualUrls, "x-default": "/" }, }, openGraph: { url: multilingualUrls[locale], }, };};// ... Остальная часть кода
Узнайте больше о оптимизации метаданных в официальной документации Next.js.
(Опционально) Шаг 9: Интернационализация вашего sitemap.xml и robots.txt
Чтобы интернационализировать ваш sitemap.xml и robots.txt, вы можете использовать функцию getMultilingualUrls, предоставляемую Intlayer. Эта функция позволяет вам генерировать многоязычные URL для вашей карты сайта.
import { getMultilingualUrls } from "intlayer";import type { MetadataRoute } from "next";const sitemap = (): MetadataRoute.Sitemap => [ { url: "https://example.com", alternates: { languages: getMultilingualUrls("https://example.com"), }, }, { url: "https://example.com/login", alternates: { languages: getMultilingualUrls("https://example.com/login"), }, }, { url: "https://example.com/register", alternates: { languages: getMultilingualUrls("https://example.com/register"), }, },];export default sitemap;
import type { MetadataRoute } from "next";import { getMultilingualUrls } from "intlayer";const getAllMultilingualUrls = (urls: string[]) => urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);const robots = (): MetadataRoute.Robots => ({ rules: { userAgent: "*", allow: ["/"], disallow: getAllMultilingualUrls(["/login", "/register"]), }, host: "https://example.com", sitemap: `https://example.com/sitemap.xml`,});export default robots;
Узнайте больше об оптимизации карты сайта в официальной документации Next.js. Узнайте больше об оптимизации robots.txt в официальной документации Next.js.
(Опционально) Шаг 10: Измените язык вашего контента
Чтобы изменить язык вашего контента, вы можете использовать функцию setLocale, предоставляемую хуком useLocale. Эта функция позволяет вам установить локаль приложения и соответственно обновить контент.
"use client";import { Locales, getHTMLTextDir, getLocaleName, getLocalizedUrl,} from "intlayer";import { useLocale } from "next-intlayer";import { type FC } from "react";const LocaleSwitcher: FC = () => { const { locale, pathWithoutLocale, availableLocales, setLocale } = useLocale(); return ( <ol> {availableLocales.map((localeItem) => ( <li key={localeItem}> <a href={getLocalizedUrl(pathWithoutLocale, localeItem)} hrefLang={localeItem} aria-current={locale === localeItem ? "page" : undefined} onClick={(e) => { e.preventDefault(); setLocale(localeItem); }} > <span> {/* Язык на своём локале - например, Français */} {getLocaleName(localeItem, locale)} </span> <span dir={getHTMLTextDir(localeItem)} lang={localeItem}> {/* Язык на текущем локале - например, Francés при текущем локале, установленном на Locales.SPANISH */} {getLocaleName(localeItem)} </span> <span dir="ltr" lang={Locales.ENGLISH}> {/* Язык на английском - например, French */} {getLocaleName(localeItem, Locales.ENGLISH)} </span> <span> {/* Язык на своём локале - например, FR */} {localeItem} </span> </a> </li> ))} </ol> );};
Справочные документы:
Настройка TypeScript
Intlayer использует расширение модулей для получения преимуществ TypeScript и повышения устойчивости вашей кодовой базы.
Убедитесь, что ваша конфигурация TypeScript включает авто-сгенерированные типы.
{ // ... Ваша существующая конфигурация TypeScript "include": [ // ... Ваша существующая конфигурация TypeScript "types", // Включите авто-сгенерированные типы ],}
Конфигурация Git
Рекомендуется игнорировать файлы, сгенерированные Intlayer. Это позволяет избежать их коммита в ваш репозиторий Git.
Для этого вы можете добавить следующие инструкции в ваш файл .gitignore:
# Игнорировать файлы, сгенерированные Intlayer.intlayer
Если у вас есть идея по улучшению этой документации, не стесняйтесь внести свой вклад, подав запрос на вытягивание на GitHub.
Ссылка на документацию GitHub