Создание:2026-03-20Последнее обновление:2026-05-31

    Intlayer со Storybook

    Содержание

    Почему Intlayer лучше альтернатив?

    По сравнению с основными решениями, такими как «storybook-react-i18next» или «i18next», Intlayer — это решение со встроенными оптимизациями, такими как:

    Intlayer оптимизирован для идеальной работы с Storybook, предлагая многоязычные декораторы историй, переключение языковых стандартов и все функции, необходимые для масштабирования интернационализации (i18n) в вашей дизайн-системе.

    Вместо загрузки огромных файлов JSON на свои страницы загружайте только необходимый контент. Intlayer помогает уменьшить размер бандла и страниц до 50 %.

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

    Совместное размещение контента уменьшает контекст, необходимый для моделей большого языка (LLM). Intlayer также поставляется с набором инструментов, таких как CLI для проверки отсутствия переводов,LSP, MCP, и навыки агента, чтобы сделать работу разработчика (DX) еще более удобной для агентов ИИ.

    Используйте автоматизацию для перевода в своем конвейере CI/CD, используя LLM по вашему выбору за счет вашего поставщика ИИ. Intlayer также предлагает компилятор для автоматизации извлечения контента, а также веб-платформу, которая помогает переводить в фоновом режиме.

    Подключение больших файлов JSON к компонентам может привести к проблемам с производительностью и реактивностью. Intlayer оптимизирует загрузку контента во время сборки (build time).

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


    Зачем использовать Intlayer со Storybook?

    Storybook - это отраслевой стандарт для разработки и документирования компонентов пользовательского интерфейса в изоляции. Совмещение его с Intlayer позволяет:

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

    Пошаговая настройка


    </Step>

    </Steps>

    Объявление контента

    Создайте файл *.content.ts рядом с каждым компонентом. Intlayer автоматически подхватит его во время компиляции.

    import { type Dictionary, t } from "intlayer";
    
    const copyButtonContent = {
      key: "copy-button",
      content: {
        label: t({
          en: "Copy content",
          fr: "Copier le contenu",
          es: "Copiar contenido",
        }),
      },
    } satisfies Dictionary;
    
    export default copyButtonContent;
    Более подробную информацию о форматах объявлений контента и функциях см. в документации по объявлению контента.

    Использование useIntlayer в компоненте

    "use client";
    
    import { type FC } from "react";
    import { useIntlayer } from "react-intlayer";
    
    type CopyButtonProps = {
      content: string;
    };
    
    export const CopyButton: FC<CopyButtonProps> = ({ content }) => {
      const { label } = useIntlayer("copy-button");
    
      return (
        <button
          onClick={() => navigator.clipboard.writeText(content)}
          aria-label={label.value}
          title={label.value}
        >
          Копировать
        </button>
      );
    };

    useIntlayer возвращает скомпилированный словарь для текущего языка, предоставленного ближайшим IntlayerProvider. Переключение языка в панели инструментов Storybook автоматически перерисовывает историю с обновленными переводами.


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

    С настроенным декоратором IntlayerProvider ваши истории работают так же, как и раньше. Панель инструментов управляет активным языком для всего холста:

    import type { Meta, StoryObj } from "@storybook/react";
    import { CopyButton } from ".";
    
    const meta: Meta<typeof CopyButton> = {
      title: "Components/CopyButton",
      component: CopyButton,
      tags: ["autodocs"],
      argTypes: {
        content: { control: "text" },
      },
    };
    
    export default meta;
    type Story = StoryObj<typeof CopyButton>;
    
    /** История по умолчанию - переключите язык в панели инструментов, чтобы просмотреть переводы. */
    export const Default: Story = {
      args: {
        content: "npm install intlayer react-intlayer",
      },
    };
    
    /** Отрисовывает кнопку внутри блока кода - распространенный случай использования. */
    export const InsideCodeBlock: Story = {
      render: (args) => (
        <div style={{ position: "relative", display: "inline-block" }}>
          <pre style={{ background: "#1e1e1e", color: "#fff", padding: "1rem" }}>
            <code>{args.content}</code>
          </pre>
          <CopyButton
            content={args.content}
            style={{ position: "absolute", top: 8, right: 8 }}
          />
        </div>
      ),
      args: {
        content: "npx intlayer init",
      },
    };
    Каждая история наследует глобальный параметр locale из панели инструментов, поэтому вы можете проверить каждый язык без изменения кода самой истории.

    Тестирование переводов в историях

    Используйте функции play в Storybook, чтобы подтвердить правильность отображения переведенного текста для заданного языка:

    import type { Meta, StoryObj } from "@storybook/react";
    import { expect, within } from "@storybook/test";
    import { CopyButton } from ".";
    
    const meta: Meta<typeof CopyButton> = {
      title: "Components/CopyButton",
      component: CopyButton,
      tags: ["autodocs"],
    };
    
    export default meta;
    type Story = StoryObj<typeof CopyButton>;
    
    export const AccessibleLabel: Story = {
      args: { content: "Hello World" },
      play: async ({ canvasElement }) => {
        const canvas = within(canvasElement);
        const button = canvas.getByRole("button");
    
        // Проверяем, что у кнопки есть непустое доступное имя
        await expect(button).toHaveAccessibleName();
        // Проверяем, что кнопка не отключена
        await expect(button).not.toBeDisabled();
        // Проверяем доступность клавиатуры
        await expect(button).toHaveAttribute("tabindex", "0");
      },
    };

    Дополнительные ресурсы