Autor:
    Data utworzenia:2026-03-20Ostatnia aktualizacja:2026-05-31

    Intlayer z Storybook

    Spis treści

    Dlaczego Interlayer zamiast alternatyw?

    W porównaniu do głównych rozwiązań, takich jak „storybook-react-i18next” lub „i18next”, Intlayer jest rozwiązaniem wyposażonym w zintegrowane optymalizacje, takie jak:

    Intlayer jest zoptymalizowany do doskonałej współpracy z Storybook, oferując wielojęzyczne dekoratory historii, przełączanie ustawień regionalnych i wszystkie funkcje potrzebne do skalowania internacjonalizacji (i18n) w całym systemie projektowym.

    Zamiast ładować ogromne pliki JSON na swoje strony, ładuj tylko niezbędną treść. Intlayer pomaga zmniejszyć rozmiary bundle'a i stron nawet o 50%.

    Określanie zakresu zawartości aplikacji ułatwia konserwację aplikacji na dużą skalę. Możesz powielić lub usunąć pojedynczy folder funkcji bez obciążania psychicznego koniecznością przeglądania całej bazy kodu zawartości. Dodatkowo Inlayer jest w pełni napisany, aby zapewnić dokładność treści.

    Wspólna lokalizacja treści zmniejsza potrzebny kontekst dzięki modelom dużego języka (LLM). Intlayer zawiera także zestaw narzędzi, taki jak CLI do sprawdzania brakujących tłumaczeńLSP, MCP i agent skills, aby praca programisty (DX) była jeszcze płynniejsza dla agentów AI.

    Korzystaj z automatyzacji, aby tłumaczyć w swoim potoku CI/CD przy użyciu wybranego LLM na koszt dostawcy sztucznej inteligencji. Intlayer oferuje także kompilator do automatyzacji ekstrakcji treści, a także [platformę internetową] (/pl/doc/concept/cms), która pomaga tłumaczyć w tle.

    Łączenie ogromnych plików JSON z komponentami może prowadzić do problemów z wydajnością i reaktywnością. Inlayer optymalizuje ładowanie treści w czasie kompilacji.

    Więcej niż tylko rozwiązanie i18n, Intlayer zapewnia samodzielny edytor wizualny i pełny CMS, który pomoże Ci zarządzać wielojęzyczną treścią w w czasie rzeczywistym, dzięki czemu współpraca z tłumaczami, copywriterami i innymi członkami zespołu będzie płynna. Treść może być przechowywana lokalnie i/lub zdalnie.

    Dlaczego warto używać Intlayer z Storybook?

    Storybook to standardowe narzędzie branżowe do tworzenia i dokumentowania komponentów interfejsu użytkownika w izolacji. Połączenie go z Intlayer pozwala na:

    • Podgląd każdego języka bezpośrednio w środowisku Storybook za pomocą przełącznika na pasku narzędzi.
    • Wykrywanie brakujących tłumaczeń przed ich wdrożeniem do produkcji.
    • Dokumentowanie komponentów wielojęzycznych przy użyciu rzeczywistych, bezpiecznych pod kątem typów treści zamiast zakodowanych na sztywno ciągów znaków.

    Konfiguracja krok po kroku

    1. Instalacja zależności

      bash
      npm install intlayer react-intlayer
      npm install vite-intlayer --save-dev
      
      PakietRola
      intlayerRdzeń - konfiguracja, kompilacja treści, interfejs CLI
      react-intlayerPowiązania React - IntlayerProvider, hook useIntlayer
      vite-intlayerWtyczka Vite - monitoruje i kompiluje pliki deklaracji treści
    2. Tworzenie konfiguracji Intlayer

      Utwórz plik intlayer.config.ts w katalogu głównym projektu (lub wewnątrz pakietu systemu projektowania):

      intlayer.config.ts
      import { Locales, type IntlayerConfig } from "intlayer";
      
      const config: IntlayerConfig = {
        internationalization: {
          locales: [
            Locales.ENGLISH,
            Locales.FRENCH,
            Locales.SPANISH,
            // dodaj więcej języków w razie potrzeby
          ],
          defaultLocale: Locales.ENGLISH,
        },
        content: {
          contentDir: ["./src"], // miejsce przechowywania plików *.content.ts
        },
      };
      
      export default config;
      
      Pełną listę opcji znajdziesz w dokumentacji konfiguracji.
    3. Dodawanie wtyczki Vite do Storybook

      Hook viteFinal w Storybook pozwala na rozszerzenie wewnętrznej konfiguracji Vite. Zaimportuj i dodaj wtyczkę intlayer() w tym miejscu:

      .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",
          // …pozostałe wtyczki
        ],
        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({
                proxy: {
                  ignore: (req) => req.url?.startsWith("/api"),
                },
              }),
            ],
          }));
      
          return mergeConfig(baseConfig, viteConfig(env));
        },
      };
      
      export default config;
      

      Wtyczka intlayer() monitoruje pliki *.content.ts i automatycznie przebudowuje słowniki przy każdej zmianie podczas pracy w Storybook.

    4. Dodawanie dekoratora `IntlayerProvider` i przełącznika języków

      Plik preview w Storybook to odpowiednie miejsce, aby opakować każdą historię w IntlayerProvider i udostępnić przełącznik języków na pasku narzędzi:

      .storybook/preview.tsx
      import type { Preview, StoryContext } from "@storybook/react";
      import { IntlayerProvider } from "react-intlayer";
      
      const preview: Preview = {
        // Opakuj każdą historię w IntlayerProvider
        decorators: [
          (Story, context: StoryContext) => {
            const locale = context.globals.locale ?? "en";
            return (
              <IntlayerProvider locale={locale}>
                <Story />
              </IntlayerProvider>
            );
          },
        ],
      
        // Udostępnij przełącznik języków na pasku narzędzi Storybook
        globalTypes: {
          locale: {
            description: "Aktywny język",
            defaultValue: "en",
            toolbar: {
              title: "Język",
              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;
      
      Wartości locale muszą odpowiadać językom zadeklarowanym w intlayer.config.ts.
    1. Instalacja zależności

      bash
      npm install intlayer react-intlayer
      npm install @intlayer/webpack --save-dev
      
    2. Tworzenie konfiguracji Intlayer

      Utwórz plik intlayer.config.ts w katalogu głównym projektu:

      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"],
        },
      };
      
      export default config;
      
    3. Konfiguracja Webpack dla Storybook

      W przypadku konfiguracji Storybook opartych na Webpack (np. @storybook/react-webpack5), rozszerz konfigurację za pomocą webpackFinal, aby dodać aliasy i loader Intlayer:

      .storybook/main.ts
      import type { StorybookConfig } from "@storybook/react-webpack5";
      import { IntlayerPlugin } from "@intlayer/webpack";
      
      const config: StorybookConfig = {
        stories: ["../src/**/*.stories.@(js|jsx|ts|tsx)"],
        addons: ["@storybook/addon-essentials"],
        framework: {
          name: "@storybook/react-webpack5",
          options: {},
        },
      
        webpackFinal: async (baseConfig) => {
          baseConfig.plugins = [...(baseConfig.plugins ?? []), new IntlayerPlugin()];
          return baseConfig;
        },
      };
      
      export default config;
      
    4. Dodawanie dekoratora `IntlayerProvider` i przełącznika języków

      Podobnie jak w przypadku konfiguracji Vite - dodaj dekorator i globalny typ języka w .storybook/preview.tsx:

      .storybook/preview.tsx
      import type { Preview, StoryContext } from "@storybook/react";
      import { IntlayerProvider } from "react-intlayer";
      
      const preview: Preview = {
        decorators: [
          (Story, context: StoryContext) => {
            const locale = context.globals.locale ?? "en";
            return (
              <IntlayerProvider locale={locale}>
                <Story />
              </IntlayerProvider>
            );
          },
        ],
      
        globalTypes: {
          locale: {
            description: "Aktywny język",
            defaultValue: "en",
            toolbar: {
              title: "Język",
              icon: "globe",
              items: [
                { value: "en", title: "English" },
                { value: "fr", title: "Français" },
                { value: "es", title: "Español" },
              ],
              dynamicTitle: true,
            },
          },
        },
      };
      
      export default preview;
      

    Deklarowanie treści

    Utwórz plik *.content.ts obok każdego komponentu. Intlayer automatycznie wykryje go podczas kompilacji.

    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;
    
    Więcej informacji na temat formatów deklaracji i dostępnych funkcji znajdziesz w dokumentacji deklaracji treści.

    Używanie useIntlayer w komponencie

    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}
        >
          Kopiuj
        </button>
      );
    };
    

    useIntlayer zwraca skompilowany słownik dla bieżącego języka, dostarczanego przez najbliższy komponent IntlayerProvider. Przełączenie języka na pasku narzędzi Storybook automatycznie odświeży historię z zaktualizowanymi tłumaczeniami.

    Pisanie historii dla komponentów zinternacjonalizowanych

    Dzięki zastosowaniu dekoratora IntlayerProvider Twoje historie działają dokładnie tak, jak wcześniej. Pasek narzędzi kontroluje aktywny język dla całego obszaru roboczego:

    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>;
    
    /** Domyślna historia - przełącz język na pasku narzędzi, aby zobaczyć tłumaczenia. */
    export const Default: Story = {
      args: {
        content: "npm install intlayer react-intlayer",
      },
    };
    
    /** Renderuje przycisk wewnątrz bloku kodu, co jest częstym przypadkiem użycia w rzeczywistych projektach. */
    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",
      },
    };
    
    Każda historia dziedziczy parametr globalny locale z paska narzędzi, więc możesz zweryfikować każdy język bez modyfikacji kodu historii.

    Testowanie tłumaczeń w historiach

    Użyj funkcji play w Storybook, aby upewnić się, że renderowany jest poprawny przetłumaczony tekst dla danego języka:

    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");
    
        // Sprawdź, czy przycisk posiada niepustą nazwę dostępności (accessible name)
        await expect(button).toHaveAccessibleName();
        // Sprawdź, czy przycisk nie jest wyłączony
        await expect(button).not.toBeDisabled();
        // Sprawdź dostępność klawiatury
        await expect(button).toHaveAttribute("tabindex", "0");
      },
    };
    

    Dodatkowe zasoby