Creation:2026-03-20Last update:2026-05-31

    Intlayer зі Storybook

    Зміст

    Чому варто обрати Intlayer, а не альтернативи?

    Порівняно з основними рішеннями, такими як storybook-react-i18next або i18next, Intlayer — це рішення, яке має такі інтегровані оптимізації, як:

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

    Замість того, щоб завантажувати великі файли JSON на свої сторінки, завантажуйте лише необхідний вміст. Intlayer допомагає зменшити розмір бандлу і сторінок до 50%.

    Організація вмісту за окремими областями (scoping) полегшує технічне обслуговування великомасштабних програм. Ви можете скопіювати або видалити окрему папку функцій без розумового навантаження перегляду всієї кодової бази вмісту. Крім того, Intlayer повністю типізований (fully typed), щоб забезпечити точність вашого вмісту.

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

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

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

    Більше ніж просто рішення i18n, Intlayer пропонує власний візуальний редактор і повний CMS, щоб допомогти вам керувати своїм багатомовним вмістом у реальному часі, спрощуючи співпрацю з перекладачами, копірайтерами та іншими членами команди. Контент можна зберігати локально та/або віддалено.


    Чому варто використовувати Intlayer зі Storybook?

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

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

    Покрокове налаштування

    1. Встановлення залежностей

      bash
      npm install intlayer react-intlayernpm install vite-intlayer --save-dev
      Пакет Роль
      intlayer Ядро - конфігурація, компіляція вмісту, CLI
      react-intlayer Зв’язки React - IntlayerProvider, хук useIntlayer
      vite-intlayer Плагін Vite - відстежує та компілює файли декларації вмісту

    2. Створення конфігурації Intlayer

      Створіть intlayer.config.ts у корені вашого проекту (або всередині пакету вашої дизайн-системи):

      intlayer.config.ts
      import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  internationalization: {    locales: [      Locales.ENGLISH,      Locales.FRENCH,      Locales.SPANISH,      // додайте більше локалей за потреби    ],    defaultLocale: Locales.ENGLISH,  },  content: {    contentDir: ["./src"], // місцезнаходження ваших файлів *.content.ts  },};export default config;
      Повний список опцій дивіться в довіднику з конфігурації.

    3. Додавання плагіна Vite до Storybook

      Хук viteFinal у Storybook дозволяє розширити внутрішню конфігурацію Vite. Імпортуйте та додайте плагін intlayer() туди:

      .storybook/main.ts
      import type { StorybookConfig } from "@storybook/react-vite";import { defineConfig, mergeConfig } from "vite";import { intlayer } from "vite-intlayer";const config: StorybookConfig = {  stories: ["../src/**/*.stories.@(js|jsx|ts|tsx)"],  addons: [    "@storybook/addon-essentials",    // …інші аддони  ],  framework: {    name: "@storybook/react-vite",    options: {},  },  async viteFinal(baseConfig, { configType }) {    const env = {      command: configType === "DEVELOPMENT" ? "serve" : "build",      mode: configType === "DEVELOPMENT" ? "development" : "production",    } as const;    const viteConfig = defineConfig(() => ({      plugins: [intlayer()],    }));    return mergeConfig(baseConfig, viteConfig(env));  },};export default config;

      Плагін intlayer() відстежує ваші файли *.content.ts та автоматично перебудовує словники щоразу, коли вони змінюються під час розробки в Storybook.


    4. Додавання декоратора `IntlayerProvider` та панелі інструментів локалей

    5. Файл preview у Storybook - це ідеальне місце, щоб обгорнути кожну історію в IntlayerProvider та додати перемикач локалей на панель інструментів:

      .storybook/preview.tsx
      import type { Preview, StoryContext } from "@storybook/react";import { IntlayerProvider } from "react-intlayer";const preview: Preview = {  // Обгортаємо кожну історію в IntlayerProvider  decorators: [    (Story, context: StoryContext) => {      const locale = context.globals.locale ?? "en";      return (        <IntlayerProvider locale={locale}>          <Story />        </IntlayerProvider>      );    },  ],  // Додаємо перемикач локалей на панель інструментів Storybook  globalTypes: {    locale: {      description: "Активна локаль",      defaultValue: "en",      toolbar: {        title: "Локаль",        icon: "globe",        items: [          { value: "en", title: "English" },          { value: "fr", title: "Français" },          { value: "es", title: "Español" },        ],        dynamicTitle: true,      },    },  },  parameters: {    controls: {      matchers: {        color: /(background|color)$/i,        date: /Date$/i,      },    },  },};export default preview;
      Значення locale повинні відповідати локалям, оголошеним у вашому intlayer.config.ts.

      </Step>

      </Steps>

      Оголошення вмісту

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

      src/components/CopyButton/CopyButton.content.ts
      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 у компоненті

      src/components/CopyButton/index.tsx
      "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 автоматично оновить історію з актуальними перекладами.


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

      З налаштованим декоратором IntlayerProvider ваші історії працюють так само, як і раніше. Панель інструментів локалей керує активною локаллю для всього канвасу:

      src/components/CopyButton/CopyButton.stories.tsx
      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, щоб переконатися, що відображається правильний перекладений текст для певної локалі:

      src/components/CopyButton/CopyButton.stories.tsx
      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");  },};

      Додаткові ресурси