- Documentation
- Окружающая среда
- Intlayer с Vite и React
Начало работы с интернационализацией (i18n) с Intlayer, Vite и React
Что такое Intlayer?
Intlayer — это инновационная, открытая библиотека интернационализации (i18n), предназначенная для упрощения многоязычной поддержки в современных веб-приложениях.
С помощью Intlayer вы можете:
- Легко управлять переводами, используя декларативные словари на уровне компонентов.
- Динамически локализовать метаданные, маршруты и контент.
- Обеспечить поддержку TypeScript с помощью автогенерируемых типов, что улучшает автозавершение и обнаружение ошибок.
- Воспользоваться расширенными возможностями, такими как динамическое определение и переключение локалей.
Пошаговое руководство по настройке Intlayer в приложении Vite и React
Шаг 1: Установка зависимостей
Установите необходимые пакеты с помощью npm:
1npm install intlayer react-intlayer
1yarn add intlayer react-intlayer
1pnpm add intlayer react-intlayer
Шаг 2: Конфигурация вашего проекта
Создайте файл конфигурации для настройки языков вашего приложения:
1// intlayer.config.ts
2
3import { Locales, type IntlayerConfig } from "intlayer";
4
5const config: IntlayerConfig = {
6 internationalization: {
7 locales: [
8 Locales.ENGLISH,
9 Locales.FRENCH,
10 Locales.SPANISH,
11 // Ваши другие локали
12 ],
13 defaultLocale: Locales.ENGLISH,
14 },
15};
16
17export default config;
Чтобы увидеть все доступные параметры, обратитесь к документации по конфигурации здесь.
Шаг 3: Интеграция Intlayer в вашу конфигурацию Vite
Добавьте плагин intlayer в вашу конфигурацию.
1import { defineConfig } from "vite";
2import react from "@vitejs/plugin-react-swc";
3import { intLayerPlugin } from "react-intlayer/vite";
4
5// https://vitejs.dev/config/
6export default defineConfig({
7 plugins: [react(), intLayerPlugin()],
8});
Шаг 4: Объявление вашего контента
Создайте и управляйте вашими словарями контента:
1// src/app.content.tsx
2import { t, type DeclarationContent } from "intlayer";
3import { type ReactNode } from "react";
4
5const appContent = {
6 key: "app",
7 content: {
8 viteLogo: t({
9 en: "Vite logo",
10 fr: "Logo Vite",
11 es: "Logo Vite",
12 }),
13 reactLogo: t({
14 en: "React logo",
15 fr: "Logo React",
16 es: "Logo React",
17 }),
18
19 title: "Vite + React",
20
21 count: t({
22 en: "count is ",
23 fr: "le compte est ",
24 es: "el recuento es ",
25 }),
26
27 edit: t<ReactNode>({
28 // Не забудьте импортировать React, если вы используете узел React в вашем контенте
29 en: (
30 <>
31 Edit <code>src/App.tsx</code> and save to test HMR
32 </>
33 ),
34 fr: (
35 <>
36 Éditez <code>src/App.tsx</code> et enregistrez pour tester HMR
37 </>
38 ),
39 es: (
40 <>
41 Edita <code>src/App.tsx</code> y guarda para probar HMR
42 </>
43 ),
44 }),
45
46 readTheDocs: t({
47 en: "Click on the Vite and React logos to learn more",
48 fr: "Cliquez sur les logos Vite et React pour en savoir plus",
49 es: "Haga clic en los logotipos de Vite y React para obtener más información",
50 }),
51 },
52} satisfies DeclarationContent;
53
54export default appContent;
Примечание: Если ваш файл контента включает код TSX, вам следует учитывать импорт import React from "react"; в ваш файл контента.
Смотрите, как объявить ваши файлы деклараций Intlayer.
Шаг 5: Использование Intlayer в вашем коде
Доступ к вашим словарям контента в вашем приложении:
1import { useState } from "react";
2import reactLogo from "./assets/react.svg";
3import viteLogo from "/vite.svg";
4import "./App.css";
5import { LocaleSwitcher } from "./components/LangSwitcherDropDown";
6import { IntlayerProvider, useIntlayer } from "react-intlayer";
7
8function AppContent() {
9 const [count, setCount] = useState(0);
10 const content = useIntlayer("app");
11
12 return (
13 <>
14 <div>
15 <a href="https://vitejs.dev" target="_blank">
16 <img src={viteLogo} className="logo" alt={content.viteLogo.value} />
17 </a>
18 <a href="https://react.dev" target="_blank">
19 <img
20 src={reactLogo}
21 className="logo react"
22 alt={content.reactLogo.value}
23 />
24 </a>
25 </div>
26 <h1>{content.title}</h1>
27 <div className="card">
28 <button onClick={() => setCount((count) => count + 1)}>
29 {content.count}
30 {count}
31 </button>
32 <p>{content.edit}</p>
33 </div>
34 <p className="read-the-docs">{content.readTheDocs}</p>
35 <div className="absolute bottom-5 right-5 z-50">
36 <LocaleSwitcher />
37 </div>
38 </>
39 );
40}
41
42function App() {
43 return (
44 <IntlayerProvider>
45 <AppContent />
46 </IntlayerProvider>
47 );
48}
49
50export default App;
Примечание: Если вы хотите использовать ваш контент в атрибуте string, таком как alt, title, href, aria-label и т. д., вы должны вызвать значение функции, например:
tsx1<img src={content.image.src.value} alt={content.image.value} />
(Опционально) Шаг 6: Изменение языка вашего контента
Чтобы изменить язык вашего контента, вы можете использовать функцию setLocale, предоставляемую хуком useLocale. Эта функция позволяет вам установить локаль приложения и обновить контент соответственно.
1import { Locales } from "intlayer";
2import { useLocale } from "react-intlayer";
3
4const LocaleSwitcher = () => {
5 const { setLocale } = useLocale();
6
7 return (
8 <button onClick={() => setLocale(Locales.English)}>
9 Change Language to English
10 </button>
11 );
12};
(Опционально) Шаг 7: Добавление локализованной маршрутизации в ваше приложение
Цель этого шага — создать уникальные маршруты для каждого языка. Это полезно для SEO и дружелюбных URL. Пример:
1// /dashboard
2// /es/dashboard
3// /fr/dashboard
По умолчанию маршруты не имеют префикса для локали по умолчанию. Если вы хотите префиксировать локаль по умолчанию, вы можете установить параметр middleware.prefixDefault в true в вашей конфигурации. См. документацию по конфигурации для получения дополнительной информации.
Чтобы добавить локализованную маршрутизацию в ваше приложение, вы можете создать компонент LocaleRouter, который оборачивает маршруты вашего приложения и обрабатывает маршрутизацию на основе локали. Вот пример с использованием React Router:
1// Импорт необходимых зависимостей и функций
2import { Locales, getConfiguration, getPathWithoutLocale } from "intlayer"; // Утилиты и типы из 'intlayer'
3import { FC, PropsWithChildren } from "react"; // Типы React для функциональных компонентов и пропсов
4import { IntlayerProvider } from "react-intlayer"; // Провайдер для контекста интернационализации
5import {
6 BrowserRouter,
7 Routes,
8 Route,
9 useParams,
10 Navigate,
11 useLocation,
12} from "react-router-dom"; // Компоненты роутера для управления навигацией
13
14// Деструктуризация конфигурации из Intlayer
15const { internationalization, middleware } = getConfiguration();
16const { locales, defaultLocale } = internationalization;
17
18/**
19 * Компонент, который обрабатывает локализацию и оборачивает детей в соответствующий контекст локали.
20 * Он управляет определением локали на основе URL и её валидацией.
21 */
22const AppLocalized: FC<PropsWithChildren> = ({ children }) => {
23 const path = useLocation().pathname; // Получить текущий URL
24 const { locale } = useParams<{ locale: Locales }>(); // Извлечь параметр локали из URL
25
26 // Определить текущую локаль, возвращаясь к умолчанию, если не указана
27 const currentLocale = locale ?? defaultLocale;
28
29 // Удалить префикс локали из пути для построения базового пути
30 const pathWithoutLocale = getPathWithoutLocale(
31 path // Текущий URL
32 );
33
34 /**
35 * Если middleware.prefixDefault равно true, то локаль по умолчанию всегда должна быть префиксирована.
36 */
37 if (middleware.prefixDefault) {
38 // Проверка валидности локали
39 if (!locale || !locales.includes(locale)) {
40 // Перенаправление на локаль по умолчанию с обновленным путем
41 return (
42 <Navigate
43 to={`/${defaultLocale}/${pathWithoutLocale}`}
44 replace // Заменить текущую запись истории новой
45 />
46 );
47 }
48
49 // Обернуть детей в IntlayerProvider и установить текущую локаль
50 return (
51 <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>
52 );
53 } else {
54 /**
55 * Когда middleware.prefixDefault равно false, локаль по умолчанию не префиксирована.
56 * Убедитесь, что текущая локаль валидна и не является локалью по умолчанию.
57 */
58 if (
59 currentLocale.toString() !== defaultLocale.toString() &&
60 !locales
61 .filter(
62 (locale) => locale.toString() !== defaultLocale.toString() // Исключить локаль по умолчанию
63 )
64 .includes(currentLocale) // Проверить, содержится ли текущая локаль в списке валидных локалей
65 ) {
66 // Перенаправление на путь без префикса локали
67 return <Navigate to={pathWithoutLocale} replace />;
68 }
69
70 // Обернуть детей в IntlayerProvider и установить текущую локаль
71 return (
72 <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>
73 );
74 }
75};
76
77/**
78 * Компонент роутера, который настраивает маршруты для конкретной локали.
79 * Использует React Router для управления навигацией и отображения локализованных компонентов.
80 */
81export const LocaleRouter: FC<PropsWithChildren> = ({ children }) => (
82 <BrowserRouter>
83 <Routes>
84 <Route
85 // Шаблон маршрута, чтобы захватить локаль (например, /en/, /fr/) и соответствовать всем последующим путям
86 path="/:locale/*"
87 element={<AppLocalized>{children}</AppLocalized>} // Обернуть детей в управление локалью
88 />
89
90 {
91 // Если префикса локали по умолчанию не требуется, отобразить детей непосредственно по корневому пути
92 !middleware.prefixDefault && (
93 <Route
94 path="*"
95 element={<AppLocalized>{children}</AppLocalized>} // Обернуть детей в управление локалью
96 />
97 )
98 }
99 </Routes>
100 </BrowserRouter>
101);
Параллельно вы также можете использовать плагин intLayerMiddlewarePlugin для добавления серверной маршрутизации в ваше приложение. Этот плагин автоматически определит текущую локаль на основе URL и установит соответствующий куки локали. Если локаль не указана, плагин определит наиболее подходящую локаль на основе языковых предпочтений браузера пользователя. Если локаль не найдена, будет перенаправление на локаль по умолчанию.
1import { defineConfig } from "vite";
2import react from "@vitejs/plugin-react-swc";
3import { intLayerPlugin, intLayerMiddlewarePlugin } from "react-intlayer/vite";
4
5// https://vitejs.dev/config/
6export default defineConfig({
7 plugins: [react(), intLayerPlugin(), intLayerMiddlewarePlugin()],
8});
(Опционально) Шаг 8: Изменение URL при изменении локали
Чтобы изменить URL при изменении локали, вы можете использовать свойство onLocaleChange, предоставленное хуком useLocale. Параллельно вы можете использовать хуки useLocation и useNavigate из react-router-dom, чтобы обновить путь URL.
1import { Locales, getLocalizedUrl } from "intlayer";
2import { useLocale } from "react-intlayer";
3import { useLocation, useNavigate } from "react-router-dom";
4
5const LocaleSwitcher = () => {
6 const location = useLocation(); // Получить текущий URL. Пример: /fr/about
7 const navigate = useNavigate();
8
9 const changeUrl = (locale: Locales) => {
10 // Построить URL с обновленной локалью
11 // Пример: /es/about с установленной локалью на испанский
12 const pathWithLocale = getLocalizedUrl(location.pathname, locale);
13
14 // Обновить путь URL
15 navigate(pathWithLocale);
16 };
17
18 const { setLocale } = useLocale({
19 onLocaleChange: changeUrl,
20 });
21
22 return (
23 <button onClick={() => setLocale(Locales.English)}>
24 Change Language to English
25 </button>
26 );
27};
Настройка TypeScript
Intlayer использует дополнение модуля для получения преимуществ от TypeScript и улучшения вашего кода.
Убедитесь, что ваша конфигурация TypeScript включает автогенерируемые типы.
1// tsconfig.json
2
3{
4 // ваша пользовательская конфигурация
5 include: [
6 "src",
7 "types", // <- Включите автогенерируемые типы
8 ],
9}
Конфигурация Git
Рекомендуется игнорировать файлы, генерируемые Intlayer. Это позволяет избежать их коммита в ваш репозиторий Git.
Для этого вы можете добавить следующие инструкции в ваш файл .gitignore:
1# Игнорировать файлы, генерируемые Intlayer
2.intlayer
Если у вас есть идея по улучшению этой документации, не стесняйтесь внести свой вклад, подав запрос на вытягивание на GitHub.
Ссылка на документацию GitHub