Получайте уведомления о предстоящих релизах Intlayer
    Создание:2025-09-09Последнее обновление:2025-09-09

    Начало работы с интернационализацией (i18n) с Intlayer и Tanstack Start

    Это руководство демонстрирует, как интегрировать Intlayer для бесшовной интернационализации в проектах Tanstack Start с маршрутизацией, учитывающей локаль, поддержкой TypeScript и современными практиками разработки.

    Что такое Intlayer?

    Intlayer — это инновационная, открытая библиотека интернационализации (i18n), созданная для упрощения поддержки многоязычности в современных веб-приложениях.

    С помощью Intlayer вы можете:

    • Легко управлять переводами с использованием декларативных словарей на уровне компонентов.
    • Динамически локализовать метаданные, маршруты и контент.
    • Обеспечить поддержку TypeScript с помощью автогенерируемых типов, улучшая автодополнение и обнаружение ошибок.
    • Воспользоваться расширенными функциями, такими как динамическое определение и переключение локали.
    • Включите маршрутизацию с учетом локали с помощью файловой системы маршрутизации Tanstack Start.

    Пошаговое руководство по настройке Intlayer в приложении Tanstack Start

    Шаг 1: Создайте проект

    Начните с создания нового проекта TanStack Start, следуя руководству Start new project на сайте TanStack Start.

    Шаг 2: Установите пакеты Intlayer

    Установите необходимые пакеты, используя предпочитаемый менеджер пакетов:

    npm install intlayer react-intlayernpm install vite-intlayer --save-dev
    • intlayer

    • intlayer

      Основной пакет, предоставляющий инструменты интернационализации для управления конфигурацией, перевода, объявления контента, транспиляции и CLI-команд.

    • react-intlayer Пакет, который интегрирует Intlayer с приложением React. Он предоставляет провайдеры контекста и хуки для интернационализации в React.

    • vite-intlayer Включает плагин Vite для интеграции Intlayer с сборщиком Vite, а также промежуточное ПО для определения предпочтительной локали пользователя, управления куки и обработки перенаправления URL.

    Шаг 3: Конфигурация вашего проекта

    Создайте файл конфигурации для настройки языков вашего приложения:

    intlayer.config.ts
    import type { IntlayerConfig } from "intlayer";import { Locales } from "intlayer";const config: IntlayerConfig = {  internationalization: {    defaultLocale: Locales.ENGLISH, // Язык по умолчанию    locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH], // Поддерживаемые языки  },};export default config;

    С помощью этого файла конфигурации вы можете настроить локализованные URL, перенаправление через middleware, имена cookie, расположение и расширение ваших объявлений контента, отключить логи Intlayer в консоли и многое другое. Для полного списка доступных параметров обратитесь к документации по конфигурации.

    Шаг 4: Интеграция Intlayer в вашу конфигурацию Vite

    Добавьте плагин intlayer в вашу конфигурацию:

    vite.config.ts
    import { reactRouter } from "@react-router/dev/vite";import { defineConfig } from "vite";import { intlayer } from "vite-intlayer";import tsconfigPaths from "vite-tsconfig-paths";export default defineConfig({  plugins: [reactRouter(), tsconfigPaths(), intlayer()],});

    Плагин Vite intlayer() используется для интеграции Intlayer с Vite. Он обеспечивает сборку файлов деклараций контента и отслеживает их в режиме разработки. Также он определяет переменные окружения Intlayer внутри приложения Vite. Дополнительно плагин предоставляет алиасы для оптимизации производительности.

    Шаг 5: Создайте компоненты макета

    Настройте корневой макет и макеты для конкретных локалей:

    Корневой макет

    src/routes/{-$locale}/route.tsx
    import { createFileRoute, Navigate, Outlet } from "@tanstack/react-router";import { IntlayerProvider, useLocale } from "react-intlayer";import { useI18nHTMLAttributes } from "@/hooks/useI18nHTMLAttributes";export const Route = createFileRoute("/{-$locale}")({  component: LayoutComponent,});function LayoutComponent() {  const { defaultLocale } = useLocale();  const { locale } = Route.useParams();  return (    <IntlayerProvider locale={defaultLocale}>      <Outlet />    </IntlayerProvider>  );}

    Шаг 6: Объявите ваш контент

    Создавайте и управляйте объявлениями контента для хранения переводов:

    src/contents/page.content.ts
    import type { Dictionary } from "intlayer";import { t } from "intlayer";const appContent = {  content: {    links: {      about: t({        ru: "О проекте",        en: "About",        es: "Acerca de",        fr: "À propos",      }),      home: t({        ru: "Главная",        en: "Home",        es: "Inicio",        fr: "Accueil",      }),    },    meta: {      description: t({        ru: "Это пример использования Intlayer с TanStack Router",        en: "This is an example of using Intlayer with TanStack Router",        es: "Este es un ejemplo de uso de Intlayer con TanStack Router",        fr: "Ceci est un exemple d'utilisation d'Intlayer avec TanStack Router",      }),    },    title: t({      ru: "Добро пожаловать в Intlayer + TanStack Router",      en: "Welcome to Intlayer + TanStack Router",      es: "Bienvenido a Intlayer + TanStack Router",      fr: "Bienvenue à Intlayer + TanStack Router",    }),  },  key: "app",} satisfies Dictionary;export default appContent;

    Ваши объявления контента могут быть определены в любом месте вашего приложения, как только они включены в директорию contentDir (по умолчанию, ./app). И соответствуют расширению файла объявления контента (по умолчанию, .content.{json,ts,tsx,js,jsx,mjs,mjx,cjs,cjx}).

    Для получения дополнительной информации обратитесь к документации по объявлениям контента.

    Шаг 7: Создайте компоненты и хуки с поддержкой локализации

    Создайте компонент LocalizedLink для навигации с учетом локали:

    src/components/localized-link.tsx
    import type { FC } from "react";import { Link, type LinkComponentProps } from "@tanstack/react-router";import { useLocale } from "react.intlayer";export const LOCALE_ROUTE = "{-$locale}" as const;// Основная утилитаexport type RemoveLocaleParam<T> = T extends string  ? RemoveLocaleFromString<T>  : T;export type To = RemoveLocaleParam<LinkComponentProps["to"]>;type CollapseDoubleSlashes<S extends string> =  S extends `${infer H}//${infer T}` ? CollapseDoubleSlashes<`${H}/${T}`> : S;type LocalizedLinkProps = {  to?: To;} & Omit<LinkComponentProps, "to">;// Вспомогательные типыtype RemoveAll<  S extends string,  Sub extends string,> = S extends `${infer H}${Sub}${infer T}` ? RemoveAll<`${H}${T}`, Sub> : S;type RemoveLocaleFromString<S extends string> = CollapseDoubleSlashes<  RemoveAll<S, typeof LOCALE_ROUTE>>;export const LocalizedLink: FC<LocalizedLinkProps> = (props) => {  const { locale } = useLocale();  return (    <Link      {...props}      params={{        locale,        ...(typeof props?.params === "object" ? props?.params : {}),      }}      to={`/${LOCALE_ROUTE}${props.to}` as LinkComponentProps["to"]}    />  );};

    Этот компонент выполняет две задачи:

    • Удаляет ненужный префикс {-$locale} из URL.
    • Вставляет параметр локали в URL, чтобы пользователь был напрямую перенаправлен на локализованный маршрут.

    Далее мы можем создать хук useLocalizedNavigate для программной навигации:

    src/hooks/useLocalizedNavigate.tsx
    import { useLocale } from "react.intlayer";import { useNavigate } from "@tanstack/react-router";import { LOCALE_ROUTE } from "@/components/localized-link";import type { FileRouteTypes } from "@/routeTree.gen";export const useLocalizedNavigate = () => {  const navigate = useNavigate();  const { locale } = useLocale();  type StripLocalePrefix<T extends string> = T extends    | `/${typeof LOCALE_ROUTE}`    | `/${typeof LOCALE_ROUTE}/`    ? "/" // Удаляем префикс локали, оставляя корень    : T extends `/${typeof LOCALE_ROUTE}/${infer Rest}`      ? `/${Rest}` // Удаляем префикс локали, оставляя остальную часть пути      : never;  type LocalizedTo = StripLocalePrefix<FileRouteTypes["to"]>;  interface LocalizedNavigate {    (to: LocalizedTo): ReturnType<typeof navigate>;    (      opts: { to: LocalizedTo } & Record<string, unknown>    ): ReturnType<typeof navigate>;  }  const localizedNavigate: LocalizedNavigate = (args: any) => {    if (typeof args === "string") {      return navigate({ to: `/${LOCALE_ROUTE}${args}`, params: { locale } });    }    const { to, ...rest } = args;    const localedTo = `/${LOCALE_ROUTE}${to}` as any;    return navigate({ to: localedTo, params: { locale, ...rest } as any });  };  return localizedNavigate;};

    Шаг 8: Использование Intlayer на ваших страницах

    Получайте доступ к вашим словарям контента по всему приложению:

    Локализованная главная страница

    src/routes/{-$locale}/index.tsx
    import { createFileRoute } from "@tanstack/react-router";import { getIntlayer } from "intlayer";import { useIntlayer } from "react.intlayer";import LocaleSwitcher from "@/components/locale-switcher";import { LocalizedLink } from "@/components/localized-link";import { useLocalizedNavigate } from "@/hooks/useLocalizedNavigate";export const Route = createFileRoute("/{-$locale}/")({  component: RouteComponent,  head: ({ params }) => {    const { locale } = params;    const metaContent = getIntlayer("app", locale);    return {      meta: [        { title: metaContent.title },        { content: metaContent.meta.description, name: "description" },      ],    };  },});function RouteComponent() {  const content = useIntlayer("app");  const navigate = useLocalizedNavigate();  return (    <div>      <div>        {content.title}        <LocaleSwitcher />        <div>          <LocalizedLink to="/">{content.links.home}</LocalizedLink>          <LocalizedLink to="/about">{content.links.about}</LocalizedLink>        </div>        <div>          <button onClick={() => navigate({ to: "/" })}>            {content.links.home}          </button>          <button onClick={() => navigate({ to: "/about" })}>            {content.links.about}          </button>        </div>      </div>    </div>  );}

    Чтобы узнать больше о хуке useIntlayer, обратитесь к документации.

    Шаг 9: Создайте компонент переключателя локали

    Создайте компонент, который позволит пользователям менять язык:

    src/components/locale-switcher.tsx
    import type { FC } from "react";import { useLocation } from "@tanstack/react-router";import { getHTMLTextDir, getLocaleName, getPathWithoutLocale } from "intlayer";import { setLocaleCookie, useIntlayer, useLocale } from "react-intlayer";import { LocalizedLink, To } from "./localized-link";export const LocaleSwitcher: FC = () => {  const { localeSwitcherLabel } = useIntlayer("locale-switcher");  const { pathname } = useLocation();  const { availableLocales, locale } = useLocale();  const pathWithoutLocale = getPathWithoutLocale(pathname);  return (    <ol>      {availableLocales.map((localeEl) => (        <li key={localeEl}>          <LocalizedLink            aria-current={localeEl === locale ? "page" : undefined}            aria-label={`${localeSwitcherLabel.value} ${getLocaleName(localeEl)}`}            onClick={() => setLocaleCookie(localeEl)}            params={{ locale: localeEl }}            to={pathWithoutLocale as To}          >            <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>          </LocalizedLink>        </li>      ))}    </ol>  );};

    Чтобы узнать больше о хуке useLocale, обратитесь к документации.

    Шаг 10: Добавьте управление атрибутами HTML (необязательно)

    Создайте хук для управления атрибутами lang и dir в HTML:

    src/hooks/useI18nHTMLAttributes.tsx
    // src/hooks/useI18nHTMLAttributes.tsximport { getHTMLTextDir } from "intlayer";import { useEffect } from "react";import { useLocale } from "react-intlayer";export const useI18nHTMLAttributes = () => {  const { locale } = useLocale();  useEffect(() => {    document.documentElement.lang = locale; // установка атрибута lang для корневого элемента документа    document.documentElement.dir = getHTMLTextDir(locale); // установка атрибута dir для корневого элемента документа  }, [locale]);};

    Затем используйте его в вашем корневом компоненте:

    src/routes/{-$locale}/index.tsx
    import { createFileRoute, Navigate, Outlet } from "@tanstack/react-router";import { IntlayerProvider, useLocale } from "react-intlayer";import { useI18nHTMLAttributes } from "@/hooks/useI18nHTMLAttributes"; // импортируем хукexport const Route = createFileRoute("/{-$locale}")({  component: LayoutComponent,});function LayoutComponent() {  useI18nHTMLAttributes(); // добавляем эту строку  const { defaultLocale } = useLocale();  const { locale } = Route.useParams();  return (    <IntlayerProvider locale={locale ?? defaultLocale}>      <Outlet />    </IntlayerProvider>  );}

    Шаг 11: Добавление middleware (необязательно)

    Вы также можете использовать intlayerMiddleware для добавления маршрутизации на стороне сервера в ваше приложение. Этот плагин автоматически определит текущую локаль на основе URL и установит соответствующий cookie с локалью. Если локаль не указана, плагин определит наиболее подходящую локаль на основе языковых предпочтений браузера пользователя. Если локаль не будет обнаружена, произойдет перенаправление на локаль по умолчанию.

    Обратите внимание, что для использования intlayerMiddleware в продакшене необходимо переместить пакет vite-intlayer из devDependencies в dependencies.

    vite.config.ts
    import { reactRouter } from "@react-router/dev/vite";import tailwindcss from "@tailwindcss/vite";import { defineConfig } from "vite";import { intlayer, intlayerMiddleware } from "vite-intlayer";import tsconfigPaths from "vite-tsconfig-paths";export default defineConfig({  plugins: [    tailwindcss(),    reactRouter(),    tsconfigPaths(),    intlayer(),    intlayerMiddleware(),  ],});

    Шаг 12: Настройка TypeScript (необязательно)

    Intlayer использует расширение модулей (module augmentation), чтобы использовать преимущества TypeScript и сделать вашу кодовую базу более надежной.

    Убедитесь, что ваша конфигурация TypeScript включает автоматически сгенерированные типы:

    tsconfig.json
    {  // ... ваши существующие настройки  include: [    // ... ваши существующие включения    ".intlayer/**/*.ts", // Включить автоматически сгенерированные типы  ],}

    Конфигурация Git

    Рекомендуется игнорировать файлы, сгенерированные Intlayer. Это позволит избежать их коммита в ваш Git-репозиторий.

    Чтобы сделать это, вы можете добавить следующие инструкции в ваш файл .gitignore:

    .gitignore
    # Игнорировать файлы, сгенерированные Intlayer.intlayer

    Расширение VS Code

    Для улучшения вашего опыта разработки с Intlayer вы можете установить официальное расширение Intlayer для VS Code.

    Установить из VS Code Marketplace

    Это расширение предоставляет:

    • Автозаполнение ключей переводов.
    • Обнаружение ошибок в реальном времени для отсутствующих переводов.
    • Встроенный просмотр переведённого контента.
    • Быстрые действия для лёгкого создания и обновления переводов.

    Для получения дополнительной информации о том, как использовать расширение, обратитесь к документации расширения Intlayer для VS Code.


    Продвинутые возможности

    Для расширения возможностей вы можете реализовать визуальный редактор или вынести ваш контент во внешний CMS.


    Ссылки на документацию

    Это исчерпывающее руководство содержит все необходимое для интеграции Intlayer с Tanstack Start для полностью интернационализированного приложения с маршрутизацией, учитывающей локаль, и поддержкой TypeScript.

    История документации

    Версия Дата Изменения
    5.8.1 2025-09-09 Добавлено для Tanstack Start
    Получайте уведомления о предстоящих релизах Intlayer