Начало работы с интернационализацией (i18n) с Intlayer и Next.js, используя Page Router
Что такое Intlayer?
Intlayer — это инновационная, открытая библиотека интернационализации (i18n), разработанная для упрощения поддержки многоязычности в современных веб-приложениях. Intlayer бесшовно интегрируется с последней версией фреймворка Next.js, включая его традиционный Page Router.
С помощью Intlayer вы можете:
- Легко управлять переводами с использованием декларативных словарей на уровне компонентов.
- Динамически локализовать метаданные, маршруты и контент.
- Обеспечить поддержку TypeScript с автогенерацией типов, улучшая автодополнение и обнаружение ошибок.
- Использовать расширенные функции, такие как динамическое определение и переключение локали.
Intlayer совместим с Next.js 12, 13, 14 и 15. Если вы используете Next.js App Router, обратитесь к руководству по App Router. Для Next.js 15 следуйте этому руководству.
Пошаговое руководство по настройке Intlayer в приложении Next.js с использованием Page Router
Шаг 1: Установите зависимости
Установите необходимые пакеты, используя предпочитаемый менеджер пакетов:
npm install intlayer next-intlayer
intlayer
Основной пакет, предоставляющий инструменты интернационализации для управления конфигурацией, переводами, декларацией контента, транспиляцией и CLI-командами.
next-intlayer
Пакет, интегрирующий Intlayer с Next.js. Он предоставляет провайдеры контекста и хуки для интернационализации в Next.js. Кроме того, он включает плагин Next.js для интеграции Intlayer с Webpack или Turbopack, а также middleware для определения предпочтительной локали пользователя, управления cookies и обработки перенаправлений 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, перенаправления middleware, имена cookies, расположение и расширение ваших деклараций контента, отключить логи Intlayer в консоли и многое другое. Для полного списка доступных параметров обратитесь к документации по конфигурации.
Шаг 3: Интеграция Intlayer с конфигурацией Next.js
Измените конфигурацию Next.js для включения Intlayer:
import { withIntlayer } from "next-intlayer/server";/** @type {import('next').NextConfig} */const nextConfig = { // Ваша существующая конфигурация Next.js};export default withIntlayer(nextConfig);
Плагин withIntlayer() для Next.js используется для интеграции Intlayer с Next.js. Он обеспечивает построение файлов декларации контента и их мониторинг в режиме разработки. Он определяет переменные окружения Intlayer в средах Webpack или Turbopack. Кроме того, он предоставляет алиасы для оптимизации производительности и гарантирует совместимость с серверными компонентами.
Шаг 4: Настройка Middleware для определения локали
Настройте middleware для автоматического определения и обработки предпочтительной локали пользователя:
export { intlayerMiddleware as middleware } from "next-intlayer/middleware";export const config = { matcher: "/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\..*|_next).*)",};
Настройте параметр matcher для соответствия маршрутам вашего приложения. Для получения дополнительной информации обратитесь к документации Next.js по настройке matcher.
Шаг 5: Определение динамических маршрутов локали
Реализуйте динамическую маршрутизацию для предоставления локализованного контента на основе локали пользователя.
Создайте страницы для конкретных локалей:
Переименуйте основной файл страницы, чтобы включить динамический сегмент [locale].
bashmv src/pages/index.tsx src/pages/[locale]/index.tsx
Обновите _app.tsx для обработки локализации:
Измените ваш _app.tsx, чтобы включить провайдеры Intlayer.
src/pages/_app.tsximport type { FC } from "react";import type { AppProps } from "next/app";import { IntlayerClientProvider } from "next-intlayer";const App = FC<AppProps>({ Component, pageProps }) => { const { locale } = pageProps; return ( <IntlayerClientProvider locale={locale}> <Component {...pageProps} /> </IntlayerClientProvider> );}export default MyApp;
Настройте getStaticPaths и getStaticProps:
В вашем [locale]/index.tsx определите пути и свойства для обработки различных локалей.
src/pages/[locale]/index.tsximport type { FC } from "react";import type { GetStaticPaths, GetStaticProps } from "next";import { type Locales, getConfiguration } from "intlayer";
const HomePage: FC = () =>
getStaticPaths и getStaticProps обеспечивают предварительную сборку необходимых страниц для всех локалей в маршрутизаторе страниц Next.js. Этот подход снижает вычисления во время выполнения и улучшает пользовательский опыт. Для получения дополнительной информации обратитесь к документации Next.js по getStaticPaths и getStaticProps.
Шаг 6: Объявите ваш контент
Создайте и управляйте объявлениями контента для хранения переводов.
import { t, type Dictionary } from "intlayer";const homeContent = { key: "home", content: { title: t({ ru: "Добро пожаловать на мой сайт", en: "Welcome to My Website", fr: "Bienvenue sur mon site Web", es: "Bienvenido a mi sitio web", }), description: t({ ru: "Начните с редактирования этой страницы.", en: "Get started by editing this page.", fr: "Commencez par éditer cette page.", es: "Comience por editar esta página.", }), },} satisfies Dictionary;export default homeContent;
Для получения дополнительной информации об объявлении контента обратитесь к руководству по объявлению контента.
Шаг 7: Используйте контент в вашем коде
Получите доступ к словарям контента в вашем приложении для отображения переведенного контента.
import type { FC } from "react";import { useIntlayer } from "next-intlayer";import { ComponentExample } from "@components/ComponentExample";const HomePage: FC = () => { const content = useIntlayer("home"); return ( <div> <h1>{content.title}</h1> <p>{content.description}</p> <ComponentExample /> {/* Дополнительные компоненты */} </div> );};// ... Остальная часть кода, включая getStaticPaths и getStaticPropsexport default HomePage;
import type { FC } from "react";import { useIntlayer } from "next-intlayer";export const ComponentExample: FC = () => { const content = useIntlayer("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: Интернационализация метаданных
Для интернационализации метаданных, таких как заголовки страниц и описания, используйте функцию getStaticProps в сочетании с функцией getTranslation из Intlayer.
import { GetStaticPaths, GetStaticProps } from "next";import { type IConfigLocales, getTranslation, Locales } from "intlayer";import { useIntlayer } from "next-intlayer";interface HomePageProps { locale: string; metadata: Metadata;}const HomePage = ({ metadata }: HomePageProps) => { // Метаданные могут использоваться в head или других компонентах по мере необходимости return ( <div> <Head> <title>{metadata.title}</title> <meta name="description" content={metadata.description} /> </Head> {/* Дополнительный контент */} </div> );};export const getStaticProps: GetStaticProps = async ({ params }) => { const locale = params?.locale as string; const t = <T,>(content: IConfigLocales<T>) => getTranslation(content, locale); const metadata = { title: t({ ru: "Мой Вебсайт", en: "My Website", fr: "Mon Site Web", es: "Mi Sitio Web", }), description: t({ ru: "Добро пожаловать на мой вебсайт.", en: "Welcome to my website.", fr: "Bienvenue sur mon site Web.", es: "Bienvenido a mi sitio web.", }), }; return { props: { locale, metadata, }, };};export default HomePage;// ... Остальная часть кода, включая getStaticPaths
(Необязательно) Шаг 9: Изменение языка вашего контента
Чтобы позволить пользователям динамически переключать языки, используйте функцию setLocale, предоставляемую хуком useLocale.
import { Locales, getHTMLTextDir, getLocaleName, getLocalizedUrl,} from "intlayer";import { useLocalePageRouter } from "next-intlayer";import { type FC } from "react";import Link from "next/link";const LocaleSwitcher: FC = () => { const { locale, pathWithoutLocale, availableLocales, setLocale } = useLocalePageRouter(); return ( <div> <button popoverTarget="localePopover">{getLocaleName(locale)}</button> <div id="localePopover" popover="auto"> {availableLocales.map((localeItem) => ( <Link href={getLocalizedUrl(pathWithoutLocale, localeItem)} hrefLang={localeItem} key={localeItem} aria-current={locale === localeItem ? "page" : undefined} onClick={(e) => { e.preventDefault(); setLocale(localeItem); }} > <span> {/* Локаль - например, FR */} {localeItem} </span> <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> </Link> ))} </div> </div> );};
API useLocalePageRouter идентичен useLocale. Чтобы узнать больше о хуке useLocale, обратитесь к документации.
Ссылки на документацию:
(Опционально) Шаг 10: Создание локализованного компонента ссылки
Чтобы обеспечить соблюдение текущей локали при навигации в вашем приложении, вы можете создать пользовательский компонент Link. Этот компонент автоматически добавляет префикс к внутренним URL-адресам с текущим языком. Например, когда пользователь, говорящий на французском, нажимает на ссылку на страницу "О нас", он перенаправляется на /ru/about вместо /about.
Это поведение полезно по нескольким причинам:
- SEO и пользовательский опыт: Локализованные URL-адреса помогают поисковым системам корректно индексировать страницы на определенных языках и предоставляют пользователям контент на их предпочтительном языке.
- Согласованность: Используя локализованную ссылку по всему приложению, вы гарантируете, что навигация остается в рамках текущей локали, предотвращая неожиданные переключения языка.
- Поддерживаемость: Централизация логики локализации в одном компоненте упрощает управление URL-адресами, делая ваш код более удобным для поддержки и расширения по мере роста приложения.
Ниже приведена реализация локализованного компонента Link на TypeScript:
"use client";import { getLocalizedUrl } from "intlayer";import NextLink, { type LinkProps as NextLinkProps } from "next/link";import { useLocale } from "next-intlayer";import { forwardRef, PropsWithChildren, type ForwardedRef } from "react";/** * Утилита для проверки, является ли данный URL внешним. * Если URL начинается с http:// или https://, он считается внешним. */export const checkIsExternalLink = (href?: string): boolean => /^https?:///.test(href ?? "");/** * Пользовательский компонент Link, который адаптирует атрибут href в зависимости от текущей локали. * Для внутренних ссылок используется `getLocalizedUrl` для добавления префикса URL с локалью (например, /fr/about). * Это гарантирует, что навигация остается в рамках текущей локали. */export const Link = forwardRef< HTMLAnchorElement, PropsWithChildren<NextLinkProps>>(({ href, children, ...props }, ref: ForwardedRef<HTMLAnchorElement>) => { const { locale } = useLocale(); const isExternalLink = checkIsExternalLink(href.toString()); // Если ссылка внутренняя и предоставлен допустимый href, получить локализованный URL. const hrefI18n: NextLinkProps["href"] = href && !isExternalLink ? getLocalizedUrl(href.toString(), locale) : href; return ( <NextLink href={hrefI18n} ref={ref} {...props}> {children} </NextLink> );});Link.displayName = "Link";
Как это работает
Определение внешних ссылок:
Вспомогательная функция checkIsExternalLink определяет, является ли URL внешним. Внешние ссылки остаются неизменными, так как они не требуют локализации.Получение текущей локали:
Хук useLocale предоставляет текущую локаль (например, fr для французского).Локализация URL:
Для внутренних ссылок (т.е. не внешних) используется getLocalizedUrl, чтобы автоматически добавлять префикс URL с текущей локалью. Это означает, что если пользователь находится на французском языке, передача /about в качестве href преобразуется в /fr/about.Возврат ссылки:
Компонент возвращает элемент <a> с локализованным URL, обеспечивая согласованность навигации с локалью.
Настройка TypeScript
Intlayer использует расширение модулей для получения преимуществ TypeScript и укрепления вашей кодовой базы.
Убедитесь, что ваша конфигурация TypeScript включает автоматически сгенерированные типы.
{ // ... Ваши существующие конфигурации TypeScript "include": [ // ... Ваши существующие конфигурации TypeScript ".intlayer/**/*.ts", // Включите автоматически сгенерированные типы ],}
Конфигурация Git
Чтобы сохранить ваш репозиторий чистым и избежать коммита сгенерированных файлов, рекомендуется игнорировать файлы, созданные Intlayer.
Добавьте следующие строки в ваш файл .gitignore:
# Игнорировать файлы, созданные Intlayer.intlayer
Дополнительные ресурсы
- Документация Intlayer: Репозиторий GitHub
- Руководство по словарю: Словарь
- Документация по конфигурации: Руководство по конфигурации
Следуя этому руководству, вы сможете эффективно интегрировать Intlayer в ваше приложение Next.js, используя Page Router, что обеспечит надежную и масштабируемую поддержку интернационализации для ваших веб-проектов.
Дальнейшие шаги
Чтобы пойти дальше, вы можете внедрить визуальный редактор или вынести ваш контент с помощью CMS.
Если у вас есть идея по улучшению этой документации, не стесняйтесь внести свой вклад, подав запрос на вытягивание на GitHub.
Ссылка на документацию GitHub