ГлавнаяПесочницаВитринаПриложениеДокументБлог
    • Englishанглийский
      EN
    • русскийрусский
      RU
    • 日本語японский
      JA
    • françaisфранцузский
      FR
    • 한국어корейский
      KO
    • 中文китайский
      ZH
    • españolиспанский
      ES
    • Deutschнемецкий
      DE
    • العربيةарабский
      AR
    • italianoитальянский
      IT
    • British Englishбританский английский
      EN-GB
    • portuguêsпортугальский
      PT
    • हिन्दीхинди
      HI
    • Türkçeтурецкий
      TR
    • polskiпольский
      PL
    • Indonesiaиндонезийский
      ID
    • Tiếng Việtвьетнамский
      VI
    • українськаукраинский
      UK
    /
    Фильтровать документы по фреймворку
    Alt+←
    Почему Intlayer?
    Начать
    Концепция
    • Как работает Intlayer
    • Конфигурация
    • TestFillBuildWatchExtractLoginPushPullConfigurationListVersionEditorLiveDebugDoc ReviewDoc TranslateSDK
    • Визуальный редактор
    • CMS
    • Интеграция CI/CD
    • ПереводМножественное числоПеречислениеУсловиеПолВставкаФайлВложенностьMarkdownHTMLПолучение функции
    • Файл для каждой локали
    • Компилятор
    • Автозаполнение
    • Тестирование
    • Оптимизация пакета
    Окружающая среда
    • Next.js 14 и App Router
      Next.js 15
      Next.js без locale URL
      Next.js и Page Router
      Compiler
    • Tanstack Start Solid
    • Astro и React
      Astro и Svelte
      Astro и Vue
      Astro и Solid
      Astro и Preact
      Astro и Lit
      Astro и Vanilla JS
    • React Router v7
      React Router v7 (fs-routes)
      Compiler
    • Nuxt и Vue
    • Vite и Solid
    • SvelteKit
    • Vite и Preact
    • Vite и Vanilla JS
    • Vite и Lit
    • Angular 19 (Webpack)
      Analog
    • React CRA
    • React Native и Expo
    • Express.js
      NestJS
      Fastify
      Hono
      Adonis
    • Lynx и React
    Plugins
    • JSON
    • gettext (.po)
    Расширение VS Code
    Агент
    • Сервер MCP
    • Навики агента
    Релизы
    • v8
    • v7
    • v6
    Бенчмарк
    • Next.js
    • TanStack
    • Vue
    • Solid
    • Svelte
    Блог
    Задать вопрос
    1. Documentation
    2. Окружающая среда
    3. Tanstack Start
    4. Solid
    Создание:2025-03-25Последнее обновление:2026-05-06
    Посмотреть шаблон приложения на GitHub

    Для этой страницы доступен шаблон приложения.

    Посмотреть демонстрационное приложение

    Эта страница ведёт на живую демонстрацию шаблона.

    Посмотреть видео урок

    Для этой страницы доступен видео урок.

    Ссылайтесь на этот документ на ваш любимый ассистент AI
    ChatGPT
    Claude
    DeepSeek
    Google AI mode
    Gemini
    Perplexity
    Mistral
    Grok

    Спросите свой вопрос и получите сводку документа, используя эту страницу и выбранного вами поставщика AI

    История версий

    1. "Обновление использования API useIntlayer в Solid для прямого доступа к свойствам"
      v8.9.004.05.2026
    2. "Добавлено для Tanstack Start Solid.js"
      v8.5.125.03.2026

    Содержимое этой страницы было переведено с помощью ИИ.

    Смотреть последнюю версию оригинального контента на английском
    Изменить эту документацию

    Если у вас есть идея по улучшению этой документации, не стесняйтесь внести свой вклад, подав запрос на вытягивание на GitHub.

    Ссылка на документацию GitHub
    Копировать

    Копировать Markdown документа в буфер обмена

    Переведите ваш сайт на Tanstack Start с Solid.js, используя Intlayer | Интернационализация (i18n)

    Содержание

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

    Что такое Intlayer?

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

    С Intlayer вы можете:

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

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

    www.youtube.com
    ide.intlayer.org
    intlayer-tanstack-start-solid.vercel.app

    См. Шаблон приложения на GitHub.

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

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

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

    Установите необходимые пакеты с помощью вашего любимого менеджера пакетов:

    bash
    Копировать код

    Копировать код в буфер обмена

    npm install intlayer solid-intlayernpm install vite-intlayer --save-devnpx intlayer init
    • intlayer

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

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

    • vite-intlayer Включает плагин Vite для интеграции Intlayer с сборщиком Vite, а также промежуточное ПО (middleware) для определения предпочтительной локали пользователя, управления куки и обработки перенаправлений 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, имена куки, местоположение и расширение ваших деклараций контента, отключить логи Intlayer в консоли и многое другое. Полный список доступных параметров см. в документации по конфигурации.

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

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

    vite.config.ts
    Копировать код

    Копировать код в буфер обмена

    import { intlayer } from "vite-intlayer";import { defineConfig } from "vite";import { devtools } from "@tanstack/devtools-vite";import { tanstackStart } from "@tanstack/solid-start/plugin/vite";import solidPlugin from "vite-plugin-solid";export default defineConfig({  plugins: [    devtools(),    tanstackStart({      router: {        routeFileIgnorePattern:          ".content.(ts|tsx|js|mjs|cjs|jsx|json|jsonc|json5)$",      },    }),    solidPlugin({ ssr: true }),    intlayer(),  ],});
    Плагин Vite intlayer() используется для интеграции Intlayer с Vite. Он обеспечивает сборку файлов декларации контента и отслеживает их изменения в режиме разработки. Он определяет переменные окружения Intlayer внутри приложения Vite. Кроме того, он предоставляет псевдонимы (aliases) для оптимизации производительности.

    Шаг 5: Создание корневого макета (Root Layout)

    Настройте ваш корневой макет для поддержки интернационализации, используя useParams для определения текущей локали и устанавливая атрибуты lang и dir для тега html.

    src/routes/__root.tsx
    Копировать код

    Копировать код в буфер обмена

    import {  HeadContent,  Scripts,  createRootRouteWithContext,} from "@tanstack/solid-router";import { HydrationScript } from "solid-js/web";import { Suspense, type ParentComponent } from "solid-js";import { IntlayerProvider } from "solid-intlayer";import { defaultLocale, getHTMLTextDir } from "intlayer";import { Route as LocaleRoute } from "./{-$locale}/route";export const Route = createRootRouteWithContext()({  shellComponent: RootComponent,});const RootComponent: ParentComponent = (props) => {  const params = LocaleRoute.useParams();  const locale = params()?.locale ?? defaultLocale;  return (    <html dir={getHTMLTextDir(locale)} lang={locale}>      <head>        <HydrationScript />        <HeadContent />      </head>      <body>        <IntlayerProvider locale={locale}>          <Suspense>{props.children}</Suspense>        </IntlayerProvider>        <Scripts />      </body>    </html>  );};

    Шаг 6: Создание макета локали (необязательно)

    Создайте макет, который обрабатывает префикс локали и выполняет валидацию. Этот макет гарантирует, что будут обрабатываться только допустимые локали.

    Этот шаг является необязательным, если вам не нужно проверять префикс локали на уровне маршрута.
    src/routes/{-$locale}/route.tsx
    Копировать код

    Копировать код в буфер обмена

    import { createFileRoute, Outlet, redirect } from "@tanstack/solid-router";import { validatePrefix } from "intlayer";export const Route = createFileRoute("/{-$locale}")({  beforeLoad: ({ params }) => {    const localeParam = params.locale;    // Валидация префикса локали    const { isValid, localePrefix } = validatePrefix(localeParam);    if (!isValid) {      throw redirect({        to: "/{-$locale}/404",        params: { locale: localePrefix },        replace: true,      });    }  },  component: Outlet,});
    Здесь {-$locale} - это динамический параметр маршрута, который заменяется текущей локалью. Такая нотация делает сегмент необязательным, позволяя ему работать с такими режимами маршрутизации, как 'prefix-no-default' и т.д.

    Имейте в виду, что этот сегмент может вызвать проблемы, если вы используете несколько динамических сегментов в одном маршруте (например, /{-$locale}/other-path/$anotherDynamicPath/...). Для режима 'prefix-all' вы можете предпочесть заменить сегмент на $locale. Для режима 'no-prefix' или 'search-params' вы можете полностью удалить сегмент.

    Шаг 7: Декларация вашего контента

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

    src/contents/page.content.ts
    Копировать код

    Копировать код в буфер обмена

    import type { Dictionary } from "intlayer";import { t } from "intlayer";const appContent = {  content: {    links: {      about: t({        en: "About",        es: "Acerca de",        fr: "À propos",      }),      home: t({        en: "Home",        es: "Inicio",        fr: "Accueil",      }),    },    meta: {      title: t({        en: "Welcome to Intlayer + TanStack Router",        es: "Bienvenido a Intlayer + TanStack Router",        fr: "Bienvenue à Intlayer + TanStack Router",      }),      description: t({        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",      }),    },  },  key: "app",} satisfies Dictionary;export default appContent;
    Ваши декларации контента могут быть определены в любом месте вашего приложения, при условии, что они включены в каталог contentDir (по умолчанию ./app). И соответствуют расширению файлов декларации контента (по умолчанию .content.{json,ts,tsx,js,jsx,mjs,cjs}).
    Подробнее см. в документации по декларации контента.

    Шаг 8: Использование локально-зависимых компонентов и хуков

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

    src/components/LocalizedLink.tsx
    Копировать код

    Копировать код в буфер обмена

    import { Link, type LinkProps } from "@tanstack/solid-router";import { getPrefix } from "intlayer";import { useLocale } from "solid-intlayer";import type { JSX } from "solid-js";export const LOCALE_ROUTE = "{-$locale}" as const;export type RemoveLocaleParam<TVal> = TVal extends string  ? RemoveLocaleFromString<TVal>  : TVal;export type To = RemoveLocaleParam<LinkProps["to"]>;type CollapseDoubleSlashes<TString extends string> =  TString extends `${infer THead}//${infer TTail}`    ? CollapseDoubleSlashes<`${THead}/${TTail}`>    : TString;export type LocalizedLinkProps = Omit<LinkProps, "to"> & {  to?: To;} & JSX.AnchorHTMLAttributes<HTMLAnchorElement>;type RemoveAll<  TString extends string,  TSub extends string,> = TString extends `${infer THead}${TSub}${infer TTail}`  ? RemoveAll<`${THead}${TTail}`, TSub>  : TString;type RemoveLocaleFromString<TString extends string> = CollapseDoubleSlashes<  RemoveAll<TString, typeof LOCALE_ROUTE>>;export const LocalizedLink = (props: LocalizedLinkProps) => {  const { locale } = useLocale();  return (    <Link      {...props}      params={{        locale: getPrefix(locale()).localePrefix,        ...(typeof props.params === "object" ? props.params : {}),      }}      to={`/${LOCALE_ROUTE}${props.to ?? ""}` as LinkProps["to"]}    />  );};

    Этот компонент преследует две цели:

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

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

    src/hooks/useLocalizedNavigate.tsx
    Копировать код

    Копировать код в буфер обмена

    import { useNavigate } from "@tanstack/solid-router";import { getLocalizedUrl } from "intlayer";import { useLocale } from "solid-intlayer";export const useLocalizedNavigate = () => {  const navigate = useNavigate();  const { locale } = useLocale();  const localizedNavigate = (to: string) => {    const localizedTo = getLocalizedUrl(to, locale());    return navigate({ to: localizedTo });  };  return localizedNavigate;};

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

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

    Локализованная домашняя страница

    src/routes/{-$locale}/index.tsx
    Копировать код

    Копировать код в буфер обмена

    import { createFileRoute } from "@tanstack/solid-router";import { useIntlayer } from "solid-intlayer";import { LocalizedLink } from "@/components/LocalizedLink";export const Route = createFileRoute("/{-$locale}/")({  component: RouteComponent,});function RouteComponent() {  const content = useIntlayer("index-page");  return (    <main>      <h1>{content.heroTitle}</h1>      <p>{content.heroDesc}</p>      <div>        <LocalizedLink to="/">{content.navHome}</LocalizedLink>        <LocalizedLink to="/about">{content.navAbout}</LocalizedLink>      </div>    </main>  );}
    Если вы хотите использовать ваш контент в атрибуте типа string, таком как alt, title, href, aria-label и т.д., вы должны вызвать значение функции, например:
    html
    Копировать код

    Копировать код в буфер обмена

    <img src="{content.image.src.value}" alt="{content.image.value}" /><img src="{content.image.src.toString()}" alt="{content.image.toString()}" /><img src="{String(content.image.src)}" alt="{String(content.image)}" />

    В Solid useIntlayer возвращает реактивный контент (например, content). Вы можете обращаться к его свойствам напрямую.

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

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

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

    src/components/LocaleSwitcher.tsx
    Копировать код

    Копировать код в буфер обмена

    import { useLocation } from "@tanstack/solid-router";import { getLocaleName, getPathWithoutLocale, getPrefix } from "intlayer";import { For } from "solid-js";import { useIntlayer, useLocale } from "solid-intlayer";import { LocalizedLink, type To } from "./LocalizedLink";export const LocaleSwitcher = () => {  const content = useIntlayer("locale-switcher");  const location = useLocation();  const { availableLocales, locale, setLocale } = useLocale();  const pathWithoutLocale = () => getPathWithoutLocale(location().pathname);  return (    <div class="flex flex-row gap-2">      <For each={availableLocales}>        {(localeEl) => (          <LocalizedLink            aria-current={localeEl === locale() ? "page" : undefined}            onClick={() => setLocale(localeEl)}            params={{ locale: getPrefix(localeEl).localePrefix }}            to={pathWithoutLocale() as To}          >            {getLocaleName(localeEl)}          </LocalizedLink>        )}      </For>    </div>  );};export default LocaleSwitcher;

    В Solid locale из useLocale - это аксессор сигнала. Используйте locale() (со скобками) для реактивного чтения текущего значения.

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

    Шаг 11: Управление HTML-атрибутами

    Как показано на шаге 5, вы можете управлять атрибутами lang и dir тега html, используя useParams в вашем корневом компоненте. Это гарантирует правильную установку атрибутов как на сервере, так и на клиенте.

    src/routes/__root.tsx
    Копировать код

    Копировать код в буфер обмена

    const RootComponent: ParentComponent = (props) => {  const params = LocaleRoute.useParams();  const locale = params()?.locale ?? defaultLocale;  return (    <html dir={getHTMLTextDir(locale)} lang={locale}>      {/* ... */}    </html>  );};

    Шаг 12: Добавление промежуточного ПО (необязательно)

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

    Обратите внимание, что для использования intlayerProxy в режиме production вам необходимо перенести пакет vite-intlayer из devDependencies в dependencies.
    vite.config.ts
    Копировать код

    Копировать код в буфер обмена

    import { tanstackStart } from "@tanstack/solid-start/plugin/vite";import solid from "vite-plugin-solid";import { nitro } from "nitro/vite";import { defineConfig } from "vite";import { intlayer, intlayerProxy } from "vite-intlayer";export default defineConfig({  plugins: [    intlayerProxy(), // Прокси должен быть размещен перед сервером, если вы используете Nitro    nitro(),    intlayer(),    tanstackStart({      router: {        routeFileIgnorePattern:          ".content.(ts|tsx|js|mjs|cjs|jsx|json|jsonc|json5)$",      },    }),    solid(),  ],});

    Шаг 13: Интернационализация ваших метаданных (необязательно)

    Вы также можете использовать функцию getIntlayer для доступа к вашим словарям контента внутри загрузчика head для метаданных с учетом локали:

    src/routes/{-$locale}/index.tsx
    Копировать код

    Копировать код в буфер обмена

    import { createFileRoute } from "@tanstack/solid-router";import { getIntlayer } from "intlayer";export const Route = createFileRoute("/{-$locale}/")({  component: RouteComponent,  head: ({ params }) => {    const { locale } = params;    const path = "/"; // The path for this route    const metaContent = getIntlayer("app", locale);    return {      links: [        // Canonical link: Points to the current localized page        { rel: "canonical", href: getLocalizedUrl(path, locale) },        // Hreflang: Tell Google about all localized versions        ...localeMap(({ locale: mapLocale }) => ({          rel: "alternate",          hrefLang: mapLocale,          href: getLocalizedUrl(path, mapLocale),        })),        // x-default: For users in unmatched languages        // Define the default fallback locale (usually your primary language)        {          rel: "alternate",          hrefLang: "x-default",          href: getLocalizedUrl(path, defaultLocale),        },      ],      meta: [        { title: metaContent.title },        { name: "description", content: metaContent.meta.description },      ],    };  },});

    Шаг 13: Получение локали в ваших серверных действиях (необязательно)

    Возможно, вы захотите получить доступ к текущей локали внутри ваших серверных действий (server actions) или конечных точек API. Вы можете сделать это с помощью помощника getLocale из intlayer.

    Вот пример использования серверных функций TanStack Start:

    src/routes/{-$locale}/index.tsx
    Копировать код

    Копировать код в буфер обмена

    import { createServerFn } from "@tanstack/solid-start";import {  getRequestHeader,  getRequestHeaders,} from "@tanstack/solid-start/server";import { getCookie, getIntlayer, getLocale } from "intlayer";export const getLocaleServer = createServerFn().handler(async () => {  const locale = await getLocale({    // Получение куки из запроса (по умолчанию: 'INTLAYER_LOCALE')    getCookie: (name) => {      const cookieString = getRequestHeader("cookie");      return getCookie(name, cookieString);    },    // Получение заголовка из запроса (по умолчанию: 'x-intlayer-locale')    // Запасной вариант с использованием согласования Accept-Language    getHeader: (name) => getRequestHeader(name),  });  // Получение контента с помощью getIntlayer()  const content = getIntlayer("app", locale);  return { locale, content };});

    Шаг 14: Управление страницами 404 (необязательно)

    Когда пользователь посещает несуществующую страницу, вы можете отобразить кастомную страницу 404. Префикс локали может влиять на то, как срабатывает страница "Запрашиваемый ресурс не найден".

    Понимание обработки 404 в TanStack Router с префиксами локалей

    В TanStack Router обработка страниц 404 с локализованными маршрутами требует многоуровневого подхода:

    1. Выделенный маршрут 404: Специальный маршрут для отображения интерфейса 404.
    2. Валидация на уровне маршрута: Проверяет префиксы локалей и перенаправляет невалидные на 404.
    3. Универсальный маршрут (Catch-all): Перехватывает любые несовпадающие пути внутри сегмента локали.
    src/routes/{-$locale}/404.tsx
    Копировать код

    Копировать код в буфер обмена

    import { createFileRoute } from "@tanstack/solid-router";// Создает выделенный маршрут /[locale]/404// Используется как прямой маршрут и импортируется как компонент в другие файлыexport const Route = createFileRoute("/{-$locale}/404")({  component: NotFoundComponent,});// Экспортируется отдельно, чтобы его можно было использовать в notFoundComponent и catch-all маршрутахexport function NotFoundComponent() {  return (    <div>      <h1>404</h1>    </div>  );}
    src/routes/{-$locale}/route.tsx
    Копировать код

    Копировать код в буфер обмена

    import { createFileRoute, Outlet, redirect } from "@tanstack/solid-router";import { validatePrefix } from "intlayer";import { NotFoundComponent } from "./404";export const Route = createFileRoute("/{-$locale}")({  // beforeLoad выполняется перед рендерингом маршрута (на сервере и на клиенте)  // Это идеальное место для валидации префикса локали  beforeLoad: ({ params }) => {    const localeParam = params.locale;    // validatePrefix проверяет, валидна ли локаль согласно вашему конфигу intlayer    const { isValid, localePrefix } = validatePrefix(localeParam);    if (!isValid) {      // Невалидный префикс локали - перенаправление на страницу 404 с валидным префиксом      throw redirect({        to: "/{-$locale}/404",        params: { locale: localePrefix },      });    }  },  component: Outlet,  // notFoundComponent вызывается, когда дочерний маршрут не существует  // напр., /en/non-existent-page вызывает это внутри макета /en  notFoundComponent: NotFoundComponent,});
    src/routes/{-$locale}/$.tsx
    Копировать код

    Копировать код в буфер обмена

    import { createFileRoute } from "@tanstack/solid-router";import { NotFoundComponent } from "./404";// Маршрут $ (splat/catch-all) совпадает с любым путем, который не подошел под другие маршруты// напр., /en/some/deeply/nested/invalid/path// Это гарантирует, что ВСЕ несовпадающие пути внутри локали покажут страницу 404// Без этого глубокие несовпадающие пути могли бы показать пустую страницу или ошибкуexport const Route = createFileRoute("/{-$locale}/$")({  component: NotFoundComponent,});

    (Необязательно) Шаг 15: Извлечение контента из ваших компонентов

    Если у вас есть существующая кодовая база, трансформация тысяч файлов может занять много времени.

    Чтобы облегчить этот процесс, Intlayer предлагает компилятор / экстрактор для трансформации ваших компонентов и извлечения контента.

    Для настройки добавьте раздел compiler в ваш файл intlayer.config.ts:

    intlayer.config.ts
    Копировать код

    Копировать код в буфер обмена

    import { type IntlayerConfig } from "intlayer";
    
    const config: IntlayerConfig = {
      // ... Остальная часть конфига
      compiler: {
        /**
         * Указывает, должен ли компилятор быть включен.
         */
        enabled: true,
    
        /**
         * Определяет путь к выходным файлам
         */
        output: ({ fileName, extension }) => `./${fileName}${extension}`,
    
        /**
         * Указывает, должны ли компоненты сохраняться после трансформации.
         *
         * - Если `true`, компилятор перезапишет файл компонента на диске. Таким образом, трансформация станет постоянной, и компилятор пропустит ее при следующем запуске. Таким образом, компилятор может трансформировать приложение, а затем его можно удалить.
         *
         * - Если `false`, компилятор будет внедрять вызов функции `useIntlayer()` в код только в выходных файлах сборки, оставляя основную базу кода нетронутой. Трансформация будет выполняться только в памяти.
         */
        saveComponents: false,
    
        /**
         * Префикс ключей словаря
         */
        dictionaryKeyPrefix: "",
      },
    };
    
    export default config;

    Запустите экстрактор для трансформации ваших компонентов и извлечения контента:

    bash
    Копировать код

    Копировать код в буфер обмена

    npx intlayer extract

    Обновите ваш vite.config.ts, включив плагин intlayerCompiler:

    vite.config.ts
    Копировать код

    Копировать код в буфер обмена

    import { intlayer, intlayerCompiler } from "vite-intlayer";import { defineConfig } from "vite";import { devtools } from "@tanstack/devtools-vite";import { tanstackStart } from "@tanstack/solid-start/plugin/vite";import solidPlugin from "vite-plugin-solid";export default defineConfig({ plugins: [   devtools(),   tanstackStart({     router: {       routeFileIgnorePattern:         ".content.(ts|tsx|js|mjs|cjs|jsx|json|jsonc|json5)$",     },   }),   solidPlugin({ ssr: true }),   intlayer(),   intlayerCompiler(), ],});
    bash
    Копировать код

    Копировать код в буфер обмена

    npm run build # Или npm run dev

    Шаг 16: Генерация карты сайта (Sitemap) (опционально)

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

    Создаваемая Intlayer карта сайта поддерживает пространство имен xhtml:link (Hreflang XML Extensions). В отличие от стандартных генераторов карт сайта, которые просто перечисляют прямые URL-адреса, Intlayer автоматически создает необходимые двусторонние связи между всеми языковыми версиями страницы (например, /about, /about?lang=fr и /about?lang=es). Это гарантирует, что поисковые системы будут правильно индексировать и показывать нужную языковую версию соответствующей аудитории.

    Чтобы использовать его, вам сначала нужно настроить ваш файл vite.config.ts, чтобы включить предварительный рендеринг (pre-rendering) для ваших локализованных маршрутов и отключить генерацию карты сайта по умолчанию в TanStack Start.

    vite.config.ts
    Копировать код

    Копировать код в буфер обмена

    import { localeMap, localeFlatMap } from "intlayer";// ... другие импортыexport const pathList = ["", "/about", "/404"];const localizedPages = localeFlatMap(({ urlPrefix }) =>  pathList.map((path) => ({    path: `${urlPrefix}${path}`,    prerender: {      enabled: true,    },  })));export default defineConfig({  plugins: [    // ... другие плагины    tanstackStart({      // ... другие настройки      sitemap: {        enabled: false,      },      prerender: {        enabled: true,        crawlLinks: false,        concurrency: 10,      },      pages: localizedPages,    }),  ],});

    Затем создайте маршрут src/routes/sitemap[.]xml.ts, который использует функцию generateSitemap:

    src/routes/sitemap[.]xml.ts
    Копировать код

    Копировать код в буфер обмена

    import { createFileRoute } from "@tanstack/solid-router";import { generateSitemap } from "intlayer";const SITE_URL = "http://localhost:3000";export const Route = createFileRoute("/sitemap.xml")({  server: {    handlers: {      GET: async () => {        const sitemap = generateSitemap(          [            { path: "/", changefreq: "daily", priority: 1.0 },            { path: "/about", changefreq: "monthly", priority: 0.8 },          ],          { siteUrl: SITE_URL }        );        return new Response(sitemap, {          headers: { "Content-Type": "application/xml" },        });      },    },  },});

    Шаг 17: Настройка 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
    • Хук useIntlayer
    • Хук useLocale
    • Декларация контента
    • Конфигурация
    Tanstack Start
    Astro
    Alt+→

    На этой странице

      Обсуждения анонимны и регулярно просматриваются для решения распространённых проблем. Не стесняйтесь делиться идеями функций, отзывами о документации или чем-либо, связанным с Intlayer, мы используем эту информацию для формирования нашей дорожной карты и улучшения продукта.

      npm install intlayer solid-intlayernpm install vite-intlayer --save-devnpx intlayer init
      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;
      import { intlayer } from "vite-intlayer";import { defineConfig } from "vite";import { devtools } from "@tanstack/devtools-vite";import { tanstackStart } from "@tanstack/solid-start/plugin/vite";import solidPlugin from "vite-plugin-solid";export default defineConfig({  plugins: [    devtools(),    tanstackStart({      router: {        routeFileIgnorePattern:          ".content.(ts|tsx|js|mjs|cjs|jsx|json|jsonc|json5)$",      },    }),    solidPlugin({ ssr: true }),    intlayer(),  ],});
      import {  HeadContent,  Scripts,  createRootRouteWithContext,} from "@tanstack/solid-router";import { HydrationScript } from "solid-js/web";import { Suspense, type ParentComponent } from "solid-js";import { IntlayerProvider } from "solid-intlayer";import { defaultLocale, getHTMLTextDir } from "intlayer";import { Route as LocaleRoute } from "./{-$locale}/route";export const Route = createRootRouteWithContext()({  shellComponent: RootComponent,});const RootComponent: ParentComponent = (props) => {  const params = LocaleRoute.useParams();  const locale = params()?.locale ?? defaultLocale;  return (    <html dir={getHTMLTextDir(locale)} lang={locale}>      <head>        <HydrationScript />        <HeadContent />      </head>      <body>        <IntlayerProvider locale={locale}>          <Suspense>{props.children}</Suspense>        </IntlayerProvider>        <Scripts />      </body>    </html>  );};
      import { createFileRoute, Outlet, redirect } from "@tanstack/solid-router";import { validatePrefix } from "intlayer";export const Route = createFileRoute("/{-$locale}")({  beforeLoad: ({ params }) => {    const localeParam = params.locale;    // Валидация префикса локали    const { isValid, localePrefix } = validatePrefix(localeParam);    if (!isValid) {      throw redirect({        to: "/{-$locale}/404",        params: { locale: localePrefix },        replace: true,      });    }  },  component: Outlet,});
      import type { Dictionary } from "intlayer";import { t } from "intlayer";const appContent = {  content: {    links: {      about: t({        en: "About",        es: "Acerca de",        fr: "À propos",      }),      home: t({        en: "Home",        es: "Inicio",        fr: "Accueil",      }),    },    meta: {      title: t({        en: "Welcome to Intlayer + TanStack Router",        es: "Bienvenido a Intlayer + TanStack Router",        fr: "Bienvenue à Intlayer + TanStack Router",      }),      description: t({        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",      }),    },  },  key: "app",} satisfies Dictionary;export default appContent;
      import { Link, type LinkProps } from "@tanstack/solid-router";import { getPrefix } from "intlayer";import { useLocale } from "solid-intlayer";import type { JSX } from "solid-js";export const LOCALE_ROUTE = "{-$locale}" as const;export type RemoveLocaleParam<TVal> = TVal extends string  ? RemoveLocaleFromString<TVal>  : TVal;export type To = RemoveLocaleParam<LinkProps["to"]>;type CollapseDoubleSlashes<TString extends string> =  TString extends `${infer THead}//${infer TTail}`    ? CollapseDoubleSlashes<`${THead}/${TTail}`>    : TString;export type LocalizedLinkProps = Omit<LinkProps, "to"> & {  to?: To;} & JSX.AnchorHTMLAttributes<HTMLAnchorElement>;type RemoveAll<  TString extends string,  TSub extends string,> = TString extends `${infer THead}${TSub}${infer TTail}`  ? RemoveAll<`${THead}${TTail}`, TSub>  : TString;type RemoveLocaleFromString<TString extends string> = CollapseDoubleSlashes<  RemoveAll<TString, typeof LOCALE_ROUTE>>;export const LocalizedLink = (props: LocalizedLinkProps) => {  const { locale } = useLocale();  return (    <Link      {...props}      params={{        locale: getPrefix(locale()).localePrefix,        ...(typeof props.params === "object" ? props.params : {}),      }}      to={`/${LOCALE_ROUTE}${props.to ?? ""}` as LinkProps["to"]}    />  );};
      import { useNavigate } from "@tanstack/solid-router";import { getLocalizedUrl } from "intlayer";import { useLocale } from "solid-intlayer";export const useLocalizedNavigate = () => {  const navigate = useNavigate();  const { locale } = useLocale();  const localizedNavigate = (to: string) => {    const localizedTo = getLocalizedUrl(to, locale());    return navigate({ to: localizedTo });  };  return localizedNavigate;};
      import { createFileRoute } from "@tanstack/solid-router";import { useIntlayer } from "solid-intlayer";import { LocalizedLink } from "@/components/LocalizedLink";export const Route = createFileRoute("/{-$locale}/")({  component: RouteComponent,});function RouteComponent() {  const content = useIntlayer("index-page");  return (    <main>      <h1>{content.heroTitle}</h1>      <p>{content.heroDesc}</p>      <div>        <LocalizedLink to="/">{content.navHome}</LocalizedLink>        <LocalizedLink to="/about">{content.navAbout}</LocalizedLink>      </div>    </main>  );}
      <img src="{content.image.src.value}" alt="{content.image.value}" /><img src="{content.image.src.toString()}" alt="{content.image.toString()}" /><img src="{String(content.image.src)}" alt="{String(content.image)}" />
      import { useLocation } from "@tanstack/solid-router";import { getLocaleName, getPathWithoutLocale, getPrefix } from "intlayer";import { For } from "solid-js";import { useIntlayer, useLocale } from "solid-intlayer";import { LocalizedLink, type To } from "./LocalizedLink";export const LocaleSwitcher = () => {  const content = useIntlayer("locale-switcher");  const location = useLocation();  const { availableLocales, locale, setLocale } = useLocale();  const pathWithoutLocale = () => getPathWithoutLocale(location().pathname);  return (    <div class="flex flex-row gap-2">      <For each={availableLocales}>        {(localeEl) => (          <LocalizedLink            aria-current={localeEl === locale() ? "page" : undefined}            onClick={() => setLocale(localeEl)}            params={{ locale: getPrefix(localeEl).localePrefix }}            to={pathWithoutLocale() as To}          >            {getLocaleName(localeEl)}          </LocalizedLink>        )}      </For>    </div>  );};export default LocaleSwitcher;
      const RootComponent: ParentComponent = (props) => {  const params = LocaleRoute.useParams();  const locale = params()?.locale ?? defaultLocale;  return (    <html dir={getHTMLTextDir(locale)} lang={locale}>      {/* ... */}    </html>  );};
      import { tanstackStart } from "@tanstack/solid-start/plugin/vite";import solid from "vite-plugin-solid";import { nitro } from "nitro/vite";import { defineConfig } from "vite";import { intlayer, intlayerProxy } from "vite-intlayer";export default defineConfig({  plugins: [    intlayerProxy(), // Прокси должен быть размещен перед сервером, если вы используете Nitro    nitro(),    intlayer(),    tanstackStart({      router: {        routeFileIgnorePattern:          ".content.(ts|tsx|js|mjs|cjs|jsx|json|jsonc|json5)$",      },    }),    solid(),  ],});
      import { createFileRoute } from "@tanstack/solid-router";import { getIntlayer } from "intlayer";export const Route = createFileRoute("/{-$locale}/")({  component: RouteComponent,  head: ({ params }) => {    const { locale } = params;    const path = "/"; // The path for this route    const metaContent = getIntlayer("app", locale);    return {      links: [        // Canonical link: Points to the current localized page        { rel: "canonical", href: getLocalizedUrl(path, locale) },        // Hreflang: Tell Google about all localized versions        ...localeMap(({ locale: mapLocale }) => ({          rel: "alternate",          hrefLang: mapLocale,          href: getLocalizedUrl(path, mapLocale),        })),        // x-default: For users in unmatched languages        // Define the default fallback locale (usually your primary language)        {          rel: "alternate",          hrefLang: "x-default",          href: getLocalizedUrl(path, defaultLocale),        },      ],      meta: [        { title: metaContent.title },        { name: "description", content: metaContent.meta.description },      ],    };  },});
      import { createServerFn } from "@tanstack/solid-start";import {  getRequestHeader,  getRequestHeaders,} from "@tanstack/solid-start/server";import { getCookie, getIntlayer, getLocale } from "intlayer";export const getLocaleServer = createServerFn().handler(async () => {  const locale = await getLocale({    // Получение куки из запроса (по умолчанию: 'INTLAYER_LOCALE')    getCookie: (name) => {      const cookieString = getRequestHeader("cookie");      return getCookie(name, cookieString);    },    // Получение заголовка из запроса (по умолчанию: 'x-intlayer-locale')    // Запасной вариант с использованием согласования Accept-Language    getHeader: (name) => getRequestHeader(name),  });  // Получение контента с помощью getIntlayer()  const content = getIntlayer("app", locale);  return { locale, content };});
      import { createFileRoute } from "@tanstack/solid-router";// Создает выделенный маршрут /[locale]/404// Используется как прямой маршрут и импортируется как компонент в другие файлыexport const Route = createFileRoute("/{-$locale}/404")({  component: NotFoundComponent,});// Экспортируется отдельно, чтобы его можно было использовать в notFoundComponent и catch-all маршрутахexport function NotFoundComponent() {  return (    <div>      <h1>404</h1>    </div>  );}
      import { createFileRoute, Outlet, redirect } from "@tanstack/solid-router";import { validatePrefix } from "intlayer";import { NotFoundComponent } from "./404";export const Route = createFileRoute("/{-$locale}")({  // beforeLoad выполняется перед рендерингом маршрута (на сервере и на клиенте)  // Это идеальное место для валидации префикса локали  beforeLoad: ({ params }) => {    const localeParam = params.locale;    // validatePrefix проверяет, валидна ли локаль согласно вашему конфигу intlayer    const { isValid, localePrefix } = validatePrefix(localeParam);    if (!isValid) {      // Невалидный префикс локали - перенаправление на страницу 404 с валидным префиксом      throw redirect({        to: "/{-$locale}/404",        params: { locale: localePrefix },      });    }  },  component: Outlet,  // notFoundComponent вызывается, когда дочерний маршрут не существует  // напр., /en/non-existent-page вызывает это внутри макета /en  notFoundComponent: NotFoundComponent,});
      import { createFileRoute } from "@tanstack/solid-router";import { NotFoundComponent } from "./404";// Маршрут $ (splat/catch-all) совпадает с любым путем, который не подошел под другие маршруты// напр., /en/some/deeply/nested/invalid/path// Это гарантирует, что ВСЕ несовпадающие пути внутри локали покажут страницу 404// Без этого глубокие несовпадающие пути могли бы показать пустую страницу или ошибкуexport const Route = createFileRoute("/{-$locale}/$")({  component: NotFoundComponent,});
      npx intlayer extract
      import { intlayer, intlayerCompiler } from "vite-intlayer";import { defineConfig } from "vite";import { devtools } from "@tanstack/devtools-vite";import { tanstackStart } from "@tanstack/solid-start/plugin/vite";import solidPlugin from "vite-plugin-solid";export default defineConfig({ plugins: [   devtools(),   tanstackStart({     router: {       routeFileIgnorePattern:         ".content.(ts|tsx|js|mjs|cjs|jsx|json|jsonc|json5)$",     },   }),   solidPlugin({ ssr: true }),   intlayer(),   intlayerCompiler(), ],});
      npm run build # Или npm run dev
      import { localeMap, localeFlatMap } from "intlayer";// ... другие импортыexport const pathList = ["", "/about", "/404"];const localizedPages = localeFlatMap(({ urlPrefix }) =>  pathList.map((path) => ({    path: `${urlPrefix}${path}`,    prerender: {      enabled: true,    },  })));export default defineConfig({  plugins: [    // ... другие плагины    tanstackStart({      // ... другие настройки      sitemap: {        enabled: false,      },      prerender: {        enabled: true,        crawlLinks: false,        concurrency: 10,      },      pages: localizedPages,    }),  ],});
      import { createFileRoute } from "@tanstack/solid-router";import { generateSitemap } from "intlayer";const SITE_URL = "http://localhost:3000";export const Route = createFileRoute("/sitemap.xml")({  server: {    handlers: {      GET: async () => {        const sitemap = generateSitemap(          [            { path: "/", changefreq: "daily", priority: 1.0 },            { path: "/about", changefreq: "monthly", priority: 0.8 },          ],          { siteUrl: SITE_URL }        );        return new Response(sitemap, {          headers: { "Content-Type": "application/xml" },        });      },    },  },});
      {  // ... ваши существующие настройки  include: [    // ... ваши существующие пути    ".intlayer/**/*.ts", // Включение автоматически генерируемых типов  ],}
      # Игнорировать файлы, генерируемые Intlayer.intlayer