React Internationalization (i18n) с react-intl и Intlayer
Этот гид показывает, как интегрировать Intlayer с react-intl для управления переводами в приложении React. Вы будете объявлять ваши переводимые данные с помощью Intlayer, а затем использовать эти сообщения с react-intl, популярной библиотекой из экосистемы FormatJS.
Обзор
- Intlayer позволяет хранить переводы в файлах декларации контента уровня компонента (JSON, JS, TS и т.д.) внутри вашего проекта.
- react-intl предоставляет компоненты React и хуки (такие как <FormattedMessage> и useIntl()) для отображения локализованных строк.
Настраивая Intlayer на экспорт переводов в формат, совместимый с react-intl, вы можете автоматически генерировать и обновлять файлы сообщений, которые требуется <IntlProvider> (из react-intl).
Почему использовать Intlayer с react-intl?
Декларации контента на уровне компонента
Файлы декларации контента Intlayer могут находиться рядом с вашими компонентами React, предотвращая «сиротские» переводы, если компоненты перемещаются или удаляются. Например:bash.└── src └── components └── MyComponent ├── index.content.ts # Декларация контента Intlayer └── index.tsx # Компонент React
Централизованные переводы
Каждый файл декларации контента собирает все переводы, необходимые для компонента. Это особенно полезно в проектах TypeScript: отсутствующие переводы можно выявить во время компиляции.Автоматическая сборка и регенерация
Каждый раз, когда вы добавляете или обновляете переводы, Intlayer регенерирует файлы сообщений JSON. Затем вы можете передать их в <IntlProvider> от react-intl.
Установка
В типичном проекте React установите следующее:
# с npmnpm install intlayer react-intl# с yarnyarn add intlayer react-intl# с pnpmpnpm add intlayer react-intl
Почему эти пакеты?
- intlayer: Основная CLI и библиотека, которая сканирует декларации контента, объединяет их и создает выходные словари.
- react-intl: Основная библиотека от FormatJS, которая предоставляет <IntlProvider>, <FormattedMessage>, useIntl() и другие примитивы интернационализации.
Если у вас еще не установлен React, вам тоже нужно это сделать (react и react-dom).
Настройка Intlayer для экспорта сообщений react-intl
В корне вашего проекта создайте intlayer.config.ts (или .js, .mjs, .cjs) следующим образом:
import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = { internationalization: { // Добавьте столько локалей, сколько хотите locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH], defaultLocale: Locales.ENGLISH, }, content: { // Указывает Intlayer на генерацию файлов сообщений для react-intl dictionaryOutput: ["react-intl"], // Директория, в которую Intlayer будет записывать ваши файлы JSON сообщений reactIntlMessagesDir: "./react-intl/messages", },};export default config;
Примечание: Для других расширений файлов (.mjs, .cjs, .js) смотрите документацию Intlayer для получения деталей использования.
Создание деклараций контента Intlayer
Intlayer сканирует вашу кодовую базу (по умолчанию, в ./src) на наличие файлов, соответствующих *.content.{ts,tsx,js,jsx,mjs,cjs,json}.
Вот пример на TypeScript:
import { t, type DeclarationContent } from "intlayer";const content = { // "key" становится ключом верхнего уровня сообщения в вашем файле JSON react-intl key: "my-component", content: { // Каждый вызов t() объявляет переводимое поле helloWorld: t({ en: "Hello World", fr: "Bonjour le monde", es: "Hola Mundo", }), description: t({ en: "This is a description", fr: "Ceci est une description", es: "Esta es una descripción", }), },} satisfies DeclarationContent;export default content;
Если вы предпочитаете JSON или разные варианты JS (.cjs, .mjs), структура в значительной степени такая же — смотрите документацию Intlayer по декларациям контента.
Сборка сообщений для react-intl
Чтобы сгенерировать фактические файлы JSON сообщений для react-intl, выполните:
# с npmnpx intlayer build# с yarnyarn intlayer build# с pnpmpnpm intlayer build
Это сканирует все файлы *.content.*, компилирует их и записывает результаты в директорию, указанную в вашем intlayer.config.ts — в этом примере, ./react-intl/messages.
Типичный вывод может выглядеть так:
.└── react-intl └── messages ├── en.json ├── fr.json └── es.json
Каждый файл является объектом JSON, верхние ключи которого соответствуют каждому content.key из ваших деклараций. Подключи (например, helloWorld) отражают переводы, объявленные в этом элементе контента.
Например, en.json может выглядеть так:
{ "helloWorld": "Hello World", "description": "This is a description"}
Инициализация react-intl в вашем приложении React
1. Загрузка сгенерированных сообщений
Где вы настраиваете корневой компонент вашего приложения (например, src/main.tsx или src/index.tsx), вам нужно:
- Импортировать сгенерированные файлы сообщений (статически или динамически).
- Передать их в <IntlProvider> от react-intl.
Простой подход — импортировать их статически:
import React from "react";import ReactDOM from "react-dom/client";import { IntlProvider } from "react-intl";import App from "./App";// Импортировать JSON файлы из выходных данных сборки.// Альтернатива: вы можете импортировать динамически в зависимости от выбранной локали пользователем.import en from "../react-intl/messages/en.json";import fr from "../react-intl/messages/fr.json";import es from "../react-intl/messages/es.json";// Если у вас есть механизм для определения языка пользователя, установите его здесь.// Для простоты давайте выберем английский.const locale = "en";// Соберите сообщения в объекте (или выберите их динамически)const messagesRecord: Record<string, Record<string, any>> = { en, fr, es,};ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( <React.StrictMode> <IntlProvider locale={locale} messages={messagesRecord[locale]}> <App /> </IntlProvider> </React.StrictMode>);
Совет: Для реальных проектов вы можете:
- Динамически загружать сообщения JSON во время выполнения.
- Использовать основанную на окружении, браузере или учетной записи пользователя детекцию локали.
2. Используйте <FormattedMessage> или useIntl()
Как только ваши сообщения загружены в <IntlProvider>, любой дочерний компонент может использовать react-intl для доступа к локализованным строкам. Есть два основных подхода:
- <FormattedMessage> компонент
- useIntl() хук
Использование переводов в компонентах React
Подход A: <FormattedMessage>
Для быстрого использования в пределах строки:
import React from "react";import { FormattedMessage } from "react-intl";export default function MyComponent() { return ( <div> <h1> {/* “my-component.helloWorld” ссылается на ключ из en.json, fr.json и т.д. */} <FormattedMessage id="my-component.helloWorld" /> </h1> <p> <FormattedMessage id="my-component.description" /> </p> </div> );}
Проп в id в <FormattedMessage> должен соответствовать ключу верхнего уровня (my-component) плюс любым под-ключам (helloWorld).
Подход B: useIntl()
Для более динамичного использования:
import React from "react";import { useIntl } from "react-intl";export default function MyComponent() { const intl = useIntl(); return ( <div> <h1>{intl.formatMessage({ id: "my-component.helloWorld" })}</h1> <p>{intl.formatMessage({ id: "my-component.description" })}</p> </div> );}
Оба подхода допустимы — выбирайте тот стиль, который лучше подходит вашему приложению.
Обновление или добавление новых переводов
- Добавьте или измените контент в любом файле *.content.*.
- Повторно выполните intlayer build, чтобы регенерировать файлы JSON в ./react-intl/messages.
- React (и react-intl) будут подбирать обновления в следующий раз, когда вы пересоберете или перезагрузите ваше приложение.
Интеграция TypeScript (по желанию)
Если вы используете TypeScript, Intlayer может генерировать определения типов для ваших переводов.
- Убедитесь, что tsconfig.json включает вашу папку types (или любую другую выходную папку, которую генерирует Intlayer) в массиве "include".
{ "compilerOptions": { // ... }, "include": ["src", "types"],}
Сгенерированные типы могут помочь выявлять отсутствующие переводы или недействительные ключи в ваших компонентах React на этапе компиляции.
Конфигурация Git
Обычно исключаются внутренние артефакты сборки Intlayer из контроля версий. В вашем .gitignore добавьте:
# Игнорировать артефакты сборки intlayer.intlayerreact-intl
В зависимости от вашего рабочего процесса, вы также можете захотеть игнорировать или коммитить окончательные словари в ./react-intl/messages. Если ваш CI/CDipeline регенерирует их, их можно безопасно игнорировать; в противном случае коммитите их, если они вам нужны для оберток в производства.
Если у вас есть идея по улучшению этой документации, не стесняйтесь внести свой вклад, подав запрос на вытягивание на GitHub.
Ссылка на блог GitHub