ГоловнаПісочницяВітринаДодатокДокументаціяБлог
    • 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
    Дата створення:2025-09-09Останнє оновлення:2026-05-06
    Переглянути шаблон додатку на GitHub

    На цій сторінці доступний шаблон додатку.

    Переглянути демонстраційний додаток

    Ця сторінка веде на живу демонстрацію шаблону.

    Переглянути відеоурок

    На цій сторінці доступний відеоурок.

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

    Задайте питання та отримайте підсумок документа, вказавши цю сторінку та обраного вами постачальника штучного інтелекту

    Історія версій

    1. "Оновлення використання API useIntlayer у Solid для прямого доступу до властивостей"
      v8.9.004.05.2026
    2. "Додано команду init"
      v7.5.930.12.2025
    3. "Представлено validatePrefix та додано крок 14: Обробка сторінок 404 з локалізованими маршрутами."
      v7.4.011.12.2025
    4. "Додано крок 13: Отримання локалі у server actions (необов'язково)"
      v7.3.905.12.2025
    5. "Додано крок 13: Адаптувати Nitro"
      v7.2.318.11.2025
    6. "Виправлено значення префікса за замовчуванням, додавши функцію getPrefix, useLocalizedNavigate, LocaleSwitcher та LocalizedLink."
      v7.1.017.11.2025
    7. "Оновлено документацію"
      v6.5.203.10.2025
    8. "Додано для Tanstack Start"
      v5.8.109.09.2025

    Вміст цієї сторінки перекладено за допомогою штучного інтелекту.

    Переглянути останню версію оригінального вмісту англійською
    Редагувати цей документ

    Якщо у вас є ідея щодо покращення цієї документації, будь ласка, долучіться, надіславши pull request на GitHub.

    Посилання на документацію на GitHub
    Копіювати

    Скопіювати документацію у форматі Markdown в буфер обміну

    Перекладіть ваш вебсайт Tanstack Start за допомогою Intlayer | Інтернаціоналізація (i18n)

    Зміст

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

    Що таке Intlayer?

    Intlayer, інноваційна open-source бібліотека для інтернаціоналізації (i18n), призначена для спрощення підтримки кількох мов у сучасних вебзастосунках.

    За допомогою Intlayer ви можете:

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

    Покроковий посібник з налаштування Intlayer у застосунку Tanstack Start

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

    Перегляньте Шаблон додатка на GitHub.

    Крок 1: Створіть проект

    Почніть зі створення нового проєкту TanStack Start, дотримуючись інструкції Створення нового проєкту на сайті TanStack Start.

    Крок 2: Встановіть пакети Intlayer

    Встановіть необхідні пакети, використовуючи обраний менеджер пакетів:

    bash
    Копіювати код

    Скопіюйте код у буфер обміну

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

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

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

    • vite-intlayer Містить плагін Vite для інтеграції Intlayer з бандлером Vite, а також middleware для визначення пріоритетної локалі користувача, керування cookie та обробки перенаправлень 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 { tanstackStart } from "@tanstack/react-start/plugin/vite";import viteReact from "@vitejs/plugin-react";import { nitro } from "nitro/vite";import { defineConfig } from "vite";import { intlayer } from "vite-intlayer";const config = defineConfig({  plugins: [    nitro(),    intlayer(),    tanstackStart({      router: {        routeFileIgnorePattern:          ".content.(ts|tsx|js|mjs|cjs|jsx|json|jsonc|json5)$",      },    }),    viteReact(),  ],});export default config;
    Плагін Vite intlayer() використовується для інтеграції Intlayer з Vite. Він забезпечує побудову файлів декларацій контенту та відстежує їх у режимі розробки. Він визначає змінні середовища Intlayer у Vite-застосунку. Додатково він надає аліаси для оптимізації продуктивності.

    Крок 5: Створіть кореневий Layout

    Налаштуйте кореневий layout для підтримки інтернаціоналізації, використовуючи useParams для визначення поточної локалі та встановлення атрибутів lang і dir на тезі html.

    src/routes/__root.tsx
    Копіювати код

    Скопіюйте код у буфер обміну

    import {  createRootRouteWithContext,  HeadContent,  Scripts,} from "@tanstack/react-router";import { defaultLocale, getHTMLTextDir } from "intlayer";import { type ReactNode } from "react";import { IntlayerProvider } from "react-intlayer";import { Route as LocaleRoute } from "./{-$locale}/route";export const Route = createRootRouteWithContext<{}>()({  head: () => ({    meta: [      {        charSet: "utf-8",      },      {        content: "width=device-width, initial-scale=1",        name: "viewport",      },      {        title: "TanStack Start Starter",      },    ],  }),  shellComponent: RootDocument,});function RootDocument({ children }: { children: ReactNode }) {  const params = LocaleRoute.useParams();  const locale = params?.locale ?? defaultLocale;  return (    <html dir={getHTMLTextDir(locale)} lang={locale}>      <head>        <HeadContent />      </head>      <body>        <IntlayerProvider locale={locale}>{children}</IntlayerProvider>        <Scripts />      </body>    </html>  );}
    Якщо ви хочете використовувати свій вміст в атрибуті типу 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)}" />

    Крок 6: Створіть Locale Layout

    Створіть layout, який обробляє префікс локалі та виконує валідацію.

    src/routes/{-$locale}/route.tsx
    Копіювати код

    Скопіюйте код у буфер обміну

    import { createFileRoute, Outlet, redirect } from "@tanstack/react-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 },      });    }  },  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/localized-link.tsx
    Копіювати код

    Скопіюйте код у буфер обміну

    import type { FC } from "react";import { Link, type LinkComponentProps } from "@tanstack/react-router";import { useLocale } from "react-intlayer";import { getPrefix } from "intlayer";export const LOCALE_ROUTE = "{-$locale}" as const;export type To = StripLocalePrefix<LinkComponentProps["to"]>;export type StripLocalePrefix<T extends string | undefined> = T extends  | `/${typeof LOCALE_ROUTE}/`  | `/${typeof LOCALE_ROUTE}`  ? "/"  : T extends `/${typeof LOCALE_ROUTE}/${infer Rest}`    ? `/${Rest}`    : T;type LocalizedLinkProps = {  to?: To;} & Omit<LinkComponentProps, "to">;export const LocalizedLink: FC<LocalizedLinkProps> = (props) => {  const { locale } = useLocale();  const { localePrefix } = getPrefix(locale);  return (    <Link      {...props}      params={{        locale: localePrefix,        ...(typeof props?.params === "object" ? props?.params : {}),      }}      to={`/${LOCALE_ROUTE}${props.to}` as LinkComponentProps["to"]}    />  );};

    Цей компонент має дві цілі:

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

    Потім ми можемо створити хук useLocalizedNavigate для програмної навігації:

    src/hooks/useLocalizedNavigate.tsx
    Копіювати код

    Скопіюйте код у буфер обміну

    import { useNavigate } from "@tanstack/react-router";import { getPrefix } from "intlayer";import { useLocale } from "react-intlayer";import type { StripLocalePrefix } from "@/components/localized-link";import type { FileRouteTypes } from "@/routeTree.gen";type NavigateFn = ReturnType<typeof useNavigate>;type BaseNavigateOptions = Parameters<NavigateFn>[0];type LocalizedTo = StripLocalePrefix<FileRouteTypes["to"]>;export type LocalizedNavigateOptions = Omit<  BaseNavigateOptions,  "to" | "params"> & {  to: LocalizedTo;  params?: Omit<NonNullable<BaseNavigateOptions["params"]>, "locale">;};type LocalizedNavigate = (  options: LocalizedNavigateOptions) => ReturnType<NavigateFn>;export const useLocalizedNavigate = () => {  const navigate = useNavigate();  const { locale } = useLocale();  const localizedNavigate: LocalizedNavigate = (args: any) => {    const { localePrefix } = getPrefix(locale);    if (typeof args === "string") {      return navigate({        to: `/${LOCALE_ROUTE}${args}`,        params: { locale: localePrefix },      });    }    const { to, ...rest } = args;    const localizedTo = `/${LOCALE_ROUTE}${to}` as any;    return navigate({      to: localizedTo,      params: { locale: localePrefix, ...rest } as any,    });  };  return localizedNavigate;};

    Крок 9: Використовуйте 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,});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, зверніться до документації.

    Крок 10: Створіть компонент перемикача локалі

    Створіть компонент, щоб дозволити користувачам змінювати мову:

    src/components/locale-switcher.tsx
    Копіювати код

    Скопіюйте код у буфер обміну

    import { useLocation } from "@tanstack/react-router";import {  getHTMLTextDir,  getLocaleName,  getPathWithoutLocale,  getPrefix,  Locales,} from "intlayer";import type { FC } from "react";import { useLocale } from "react-intlayer";import { LocalizedLink, type To } from "./localized-link";export const LocaleSwitcher: FC = () => {  const { pathname } = useLocation();  const { availableLocales, locale, setLocale } = useLocale();  const pathWithoutLocale = getPathWithoutLocale(pathname);  return (    <ol>      {availableLocales.map((localeEl) => (        <li key={localeEl}>          <LocalizedLink            aria-current={localeEl === locale ? "page" : undefined}            onClick={() => setLocale(localeEl)}            params={{ locale: getPrefix(localeEl).localePrefix }}            to={pathWithoutLocale as To}          >            <span>              {/* Локаль, наприклад FR */}              {localeEl}            </span>            <span>              {/* Назва мови у власній локалі, наприклад Français */}              {getLocaleName(localeEl, locale)}            </span>            <span dir={getHTMLTextDir(localeEl)} lang={localeEl}>              {/* Мова в поточній локалі, наприклад «Francés», коли поточна локаль встановлена як Locales.SPANISH */}              {getLocaleName(localeEl)}            </span>            <span dir="ltr" lang={Locales.ENGLISH}>              {/* Мова англійською, наприклад «French» */}              {getLocaleName(localeEl, Locales.ENGLISH)}            </span>          </LocalizedLink>        </li>      ))}    </ol>  );};
    Щоб дізнатися більше про хук useLocale, зверніться до документації.

    Крок 11: Керування атрибутами HTML

    Як показано в Кроці 5, ви можете керувати атрибутами lang і dir тега html, використовуючи useParams у вашому кореневому компоненті. Це забезпечує правильне встановлення атрибутів на сервері та клієнті.

    src/routes/__root.tsx
    Копіювати код

    Скопіюйте код у буфер обміну

    function RootDocument({ children }: { children: ReactNode }) {  const params = LocaleRoute.useParams();  const locale = params?.locale ?? defaultLocale;  return (    <html dir={getHTMLTextDir(locale)} lang={locale}>      {/* ... */}    </html>  );}

    Крок 12: Додати middleware (необов'язково)

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

    Зверніть увагу, що щоб використовувати intlayerProxy у production, потрібно перемістити пакет vite-intlayer з devDependencies до dependencies.
    vite.config.ts
    Копіювати код

    Скопіюйте код у буфер обміну

    import { tanstackStart } from "@tanstack/react-start/plugin/vite";import viteReact from "@vitejs/plugin-react";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)$",      },    }),    viteReact(),  ],});

    Крок 13: Інтернаціоналізуйте свої метадані (необов'язково)

    Ви також можете використовувати хук getIntlayer, щоб отримувати ваші словники контенту по всьому застосунку:

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

    Скопіюйте код у буфер обміну

    import { createFileRoute } from "@tanstack/react-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 },      ],    };  },});

    Крок 14: Отримання локалі у серверних діях (Необов'язково)

    Можливо, ви захочете отримувати поточну локаль всередині серверних дій або API-ендпоїнтів. Ви можете зробити це за допомогою хелпера getLocale з intlayer.

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

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

    Скопіюйте код у буфер обміну

    import { createServerFn } from "@tanstack/react-start";import {  getRequestHeader,  getRequestHeaders,} from "@tanstack/react-start/server";import { getCookie, getIntlayer, getLocale } from "intlayer";export const getLocaleServer = createServerFn().handler(async () => {  const locale = await getLocale({    // Отримати cookie з запиту (за замовчуванням: '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 };});

    Крок 15: Керування сторінками «Не знайдено» (необов'язково)

    Коли користувач переходить на неіснуючу сторінку, ви можете відобразити власну сторінку «не знайдено», і префікс локалі може впливати на те, як ця сторінка викликається.

    Розуміння обробки 404 у TanStack Router з префіксами локалі

    У TanStack Router обробка сторінок 404 для локалізованих маршрутів вимагає багаторівневого підходу:

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

    Скопіюйте код у буфер обміну

    import { createFileRoute } from "@tanstack/react-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/react-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 спричиняє це в межах layout для /en  notFoundComponent: NotFoundComponent,});
    src/routes/{-$locale}/$.tsx
    Копіювати код

    Скопіюйте код у буфер обміну

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

    Крок 16: Налаштування TypeScript (необов'язково)

    Intlayer використовує module augmentation, щоб отримати переваги TypeScript і зміцнити ваш codebase.

    Переконайтеся, що ваша конфігурація TypeScript включає автогенеровані типи:

    tsconfig.json
    Копіювати код

    Скопіюйте код у буфер обміну

    {  // ... ваші наявні конфігурації  include: [    // ... ваші наявні includes    ".intlayer/**/*.ts", // Включає автогенеровані типи  ],}

    (Необов'язково) Крок 1 : Витягніть вміст ваших компонентів

    Якщо у вас є існуюча кодова база, перетворення тисяч файлів може зайняти багато часу.

    Щоб спростити цей процес, Intlayer пропонує компілятор / екстрактор для перетворення ваших компонентів і витягування вмісту.

    Щоб налаштувати його, ви можете додати розділ compiler у свій файл intlayer.config.ts:

    intlayer.config.ts
    Копіювати код

    Скопіюйте код у буфер обміну

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

    Запустіть екстрактор для перетворення компонентів і витягування вмісту

    bash
    Копіювати код

    Скопіюйте код у буфер обміну

    npx intlayer extract

    Оновіть свій vite.config.ts, щоб включити плагін intlayerCompiler:

    vite.config.ts
    Копіювати код

    Скопіюйте код у буфер обміну

    import { defineConfig } from "vite";import { intlayer, intlayerCompiler } from "vite-intlayer";export default defineConfig({ plugins: [   intlayer(),   intlayerCompiler(), // Додає плагін компілятора ],});
    bash
    Копіювати код

    Скопіюйте код у буфер обміну

    npm run build # Або npm run dev

    Налаштування Git

    Рекомендується ігнорувати файли, згенеровані Intlayer. Це дозволить уникнути їх коміту в ваш Git-репозиторій.

    Для цього ви можете додати наступні інструкції до файлу .gitignore:

    .gitignore
    Копіювати код

    Скопіюйте код у буфер обміну

    # Ігнорувати файли, згенеровані Intlayer.intlayer

    Розширення VS Code

    Щоб покращити досвід розробки з Intlayer, ви можете встановити офіційне Intlayer VS Code Extension.

    Встановити з VS Code Marketplace

    Це розширення надає:

    • Автозаповнення для ключів перекладу.
    • Виявлення помилок у реальному часі для відсутніх перекладів.
    • Вбудовані попередні перегляди перекладеного вмісту.
    • Швидкі дії для простого створення та оновлення перекладів.

    Для детальнішої інформації про використання розширення зверніться до документації Intlayer VS Code Extension.


    Рухатися далі

    Щоб піти далі, ви можете реалізувати візуальний редактор або винести свій вміст у зовнішню систему, використовуючи CMS.


    Посилання на документацію

    • Документація Intlayer
    • Документація Tanstack Start
    • Хук useIntlayer
    • Хук useLocale
    • Оголошення контенту
    • Конфігурація
    Compiler
    Tanstack Start Solid
    Alt+→

    На цій сторінці

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

      npm install intlayer react-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 { tanstackStart } from "@tanstack/react-start/plugin/vite";import viteReact from "@vitejs/plugin-react";import { nitro } from "nitro/vite";import { defineConfig } from "vite";import { intlayer } from "vite-intlayer";const config = defineConfig({  plugins: [    nitro(),    intlayer(),    tanstackStart({      router: {        routeFileIgnorePattern:          ".content.(ts|tsx|js|mjs|cjs|jsx|json|jsonc|json5)$",      },    }),    viteReact(),  ],});export default config;
      import {  createRootRouteWithContext,  HeadContent,  Scripts,} from "@tanstack/react-router";import { defaultLocale, getHTMLTextDir } from "intlayer";import { type ReactNode } from "react";import { IntlayerProvider } from "react-intlayer";import { Route as LocaleRoute } from "./{-$locale}/route";export const Route = createRootRouteWithContext<{}>()({  head: () => ({    meta: [      {        charSet: "utf-8",      },      {        content: "width=device-width, initial-scale=1",        name: "viewport",      },      {        title: "TanStack Start Starter",      },    ],  }),  shellComponent: RootDocument,});function RootDocument({ children }: { children: ReactNode }) {  const params = LocaleRoute.useParams();  const locale = params?.locale ?? defaultLocale;  return (    <html dir={getHTMLTextDir(locale)} lang={locale}>      <head>        <HeadContent />      </head>      <body>        <IntlayerProvider locale={locale}>{children}</IntlayerProvider>        <Scripts />      </body>    </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)}" />
      import { createFileRoute, Outlet, redirect } from "@tanstack/react-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 },      });    }  },  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 type { FC } from "react";import { Link, type LinkComponentProps } from "@tanstack/react-router";import { useLocale } from "react-intlayer";import { getPrefix } from "intlayer";export const LOCALE_ROUTE = "{-$locale}" as const;export type To = StripLocalePrefix<LinkComponentProps["to"]>;export type StripLocalePrefix<T extends string | undefined> = T extends  | `/${typeof LOCALE_ROUTE}/`  | `/${typeof LOCALE_ROUTE}`  ? "/"  : T extends `/${typeof LOCALE_ROUTE}/${infer Rest}`    ? `/${Rest}`    : T;type LocalizedLinkProps = {  to?: To;} & Omit<LinkComponentProps, "to">;export const LocalizedLink: FC<LocalizedLinkProps> = (props) => {  const { locale } = useLocale();  const { localePrefix } = getPrefix(locale);  return (    <Link      {...props}      params={{        locale: localePrefix,        ...(typeof props?.params === "object" ? props?.params : {}),      }}      to={`/${LOCALE_ROUTE}${props.to}` as LinkComponentProps["to"]}    />  );};
      import { useNavigate } from "@tanstack/react-router";import { getPrefix } from "intlayer";import { useLocale } from "react-intlayer";import type { StripLocalePrefix } from "@/components/localized-link";import type { FileRouteTypes } from "@/routeTree.gen";type NavigateFn = ReturnType<typeof useNavigate>;type BaseNavigateOptions = Parameters<NavigateFn>[0];type LocalizedTo = StripLocalePrefix<FileRouteTypes["to"]>;export type LocalizedNavigateOptions = Omit<  BaseNavigateOptions,  "to" | "params"> & {  to: LocalizedTo;  params?: Omit<NonNullable<BaseNavigateOptions["params"]>, "locale">;};type LocalizedNavigate = (  options: LocalizedNavigateOptions) => ReturnType<NavigateFn>;export const useLocalizedNavigate = () => {  const navigate = useNavigate();  const { locale } = useLocale();  const localizedNavigate: LocalizedNavigate = (args: any) => {    const { localePrefix } = getPrefix(locale);    if (typeof args === "string") {      return navigate({        to: `/${LOCALE_ROUTE}${args}`,        params: { locale: localePrefix },      });    }    const { to, ...rest } = args;    const localizedTo = `/${LOCALE_ROUTE}${to}` as any;    return navigate({      to: localizedTo,      params: { locale: localePrefix, ...rest } as any,    });  };  return localizedNavigate;};
      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,});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>  );}
      import { useLocation } from "@tanstack/react-router";import {  getHTMLTextDir,  getLocaleName,  getPathWithoutLocale,  getPrefix,  Locales,} from "intlayer";import type { FC } from "react";import { useLocale } from "react-intlayer";import { LocalizedLink, type To } from "./localized-link";export const LocaleSwitcher: FC = () => {  const { pathname } = useLocation();  const { availableLocales, locale, setLocale } = useLocale();  const pathWithoutLocale = getPathWithoutLocale(pathname);  return (    <ol>      {availableLocales.map((localeEl) => (        <li key={localeEl}>          <LocalizedLink            aria-current={localeEl === locale ? "page" : undefined}            onClick={() => setLocale(localeEl)}            params={{ locale: getPrefix(localeEl).localePrefix }}            to={pathWithoutLocale as To}          >            <span>              {/* Локаль, наприклад FR */}              {localeEl}            </span>            <span>              {/* Назва мови у власній локалі, наприклад Français */}              {getLocaleName(localeEl, locale)}            </span>            <span dir={getHTMLTextDir(localeEl)} lang={localeEl}>              {/* Мова в поточній локалі, наприклад «Francés», коли поточна локаль встановлена як Locales.SPANISH */}              {getLocaleName(localeEl)}            </span>            <span dir="ltr" lang={Locales.ENGLISH}>              {/* Мова англійською, наприклад «French» */}              {getLocaleName(localeEl, Locales.ENGLISH)}            </span>          </LocalizedLink>        </li>      ))}    </ol>  );};
      function RootDocument({ children }: { children: ReactNode }) {  const params = LocaleRoute.useParams();  const locale = params?.locale ?? defaultLocale;  return (    <html dir={getHTMLTextDir(locale)} lang={locale}>      {/* ... */}    </html>  );}
      import { tanstackStart } from "@tanstack/react-start/plugin/vite";import viteReact from "@vitejs/plugin-react";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)$",      },    }),    viteReact(),  ],});
      import { createFileRoute } from "@tanstack/react-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/react-start";import {  getRequestHeader,  getRequestHeaders,} from "@tanstack/react-start/server";import { getCookie, getIntlayer, getLocale } from "intlayer";export const getLocaleServer = createServerFn().handler(async () => {  const locale = await getLocale({    // Отримати cookie з запиту (за замовчуванням: '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/react-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/react-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 спричиняє це в межах layout для /en  notFoundComponent: NotFoundComponent,});
      import { createFileRoute } from "@tanstack/react-router";import { NotFoundComponent } from "./404";// Маркер $ (splat/catch-all) маршрут відповідає будь-якому шляху, який не відповідає іншим маршрутам// наприклад, /en/some/deeply/nested/invalid/path// Це гарантує, що ВСІ невідповідні шляхи всередині локалі показуватимуть сторінку 404// Без цього, невідповідні глибокі шляхи можуть показувати порожню сторінку або викликати помилкуexport const Route = createFileRoute("/{-$locale}/$")({  component: NotFoundComponent,});
      {  // ... ваші наявні конфігурації  include: [    // ... ваші наявні includes    ".intlayer/**/*.ts", // Включає автогенеровані типи  ],}
      npx intlayer extract
      import { defineConfig } from "vite";import { intlayer, intlayerCompiler } from "vite-intlayer";export default defineConfig({ plugins: [   intlayer(),   intlayerCompiler(), // Додає плагін компілятора ],});
      npm run build # Або npm run dev
      # Ігнорувати файли, згенеровані Intlayer.intlayer