Autor:
    Data utworzenia:2025-12-07Ostatnia aktualizacja:2026-05-31

    Przetłumacz swoją stronę React Router v7 (File-System Routes) za pomocą Intlayer | Internacjonalizacja (i18n)

    Ten przewodnik pokazuje, jak zintegrować Intlayer dla płynnej internacjonalizacji w projektach React Router v7 używając routingu opartego na systemie plików (@react-router/fs-routes) z routingiem uwzględniającym lokalizację, wsparciem TypeScript oraz nowoczesnymi praktykami programistycznymi.

    W przypadku routingu po stronie klienta, zapoznaj się z przewodnikiem Intlayer z React Router v7.

    Table of Contents

    Dlaczego Interlayer zamiast alternatyw?

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

    Pełny zasięg routera React

    Intlayer jest zoptymalizowany do doskonałej współpracy z React Router, oferując routing uwzględniający ustawienia lokalne, oprogramowanie pośredniczące do wykrywania ustawień regionalnych i wszystkie funkcje potrzebne do skalowania internacjonalizacji (i18n).

    </Accordion>

    Rozmiar bundle'a

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

    </Accordion>

    Łatwość konserwacji

    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.

    Agent AI

    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.

    Automatyzacja

    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.

    Wydajność

    Łą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.

    Skalowanie bez użycia dewelopera

    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.

    </Accordion>


    Przewodnik krok po kroku dotyczący konfiguracji Intlayer w aplikacji React Router v7 z trasami opartymi na systemie plików

    www.youtube.com
    ide.intlayer.org
    intlayer-react-router-v7-fs-routes.vercel.app

    See Application Template on GitHub.

    1. Zainstaluj zależności

      Zainstaluj niezbędne pakiety, używając preferowanego menedżera pakietów:

      bash
      npm install intlayer react-intlayer
      npm install vite-intlayer --save-dev
      npm install @react-router/fs-routes --save-dev
      npx intlayer init
      
      • intlayer

        Główny pakiet, który dostarcza narzędzia do internacjonalizacji, zarządzania konfiguracją, tłumaczeń, deklaracji treści, transpilecji oraz poleceń CLI.

      • react-intlayer Pakiet integrujący Intlayer z aplikacją React. Zapewnia dostawców kontekstu oraz hooki do internacjonalizacji w React.

      • vite-intlayer Zawiera wtyczkę Vite do integracji Intlayer z bundlerem Vite, a także middleware do wykrywania preferowanego języka użytkownika, zarządzania ciasteczkami oraz obsługi przekierowań URL.

      • @react-router/fs-routes Pakiet, który umożliwia routing oparty na systemie plików dla React Router v7.

    2. Konfiguracja Twojego projektu

      Utwórz plik konfiguracyjny, aby skonfigurować języki swojej aplikacji:

      intlayer.config.ts
      import { type IntlayerConfig, Locales } from "intlayer";
      
      const config: IntlayerConfig = {
        internationalization: {
          defaultLocale: Locales.ENGLISH,
          locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
        },
      };
      
      export default config;
      
      Za pomocą tego pliku konfiguracyjnego możesz ustawić lokalizowane adresy URL, przekierowania w middleware, nazwy ciasteczek, lokalizację i rozszerzenie deklaracji zawartości, wyłączyć logi Intlayer w konsoli i wiele więcej. Pełną listę dostępnych parametrów znajdziesz w dokumentacji konfiguracyjnej.
    3. Integracja Intlayer w konfiguracji Vite

      Dodaj wtyczkę intlayer do swojej konfiguracji:

      vite.config.ts
      import { reactRouter } from "@react-router/dev/vite";
      import { defineConfig } from "vite";
      import { intlayer } from "vite-intlayer";
      
      export default defineConfig({
        plugins: [reactRouter(), intlayer()],
      });
      
      Wtyczka Vite intlayer() służy do integracji Intlayer z Vite. Zapewnia budowanie plików deklaracji zawartości i monitoruje je w trybie deweloperskim. Definiuje zmienne środowiskowe Intlayer w aplikacji Vite. Dodatkowo dostarcza aliasy w celu optymalizacji wydajności.
    4. Konfiguracja tras opartych na systemie plików React Router v7

      Skonfiguruj routing, aby używać tras opartych na systemie plików z flatRoutes:

      app/routes.ts
      import type { RouteConfig } from "@react-router/dev/routes";
      import { flatRoutes } from "@react-router/fs-routes";
      import { configuration } from "intlayer";
      
      const routes: RouteConfig = flatRoutes({
        // Ignoruj pliki deklaracji treści, aby nie były traktowane jako trasy
        ignoredRouteFiles: configuration.content.fileExtensions.map(
          (fileExtension) => `**/*${fileExtension}`
        ),
      });
      
      export default routes;
      
      Funkcja flatRoutes z @react-router/fs-routes umożliwia routing oparty na systemie plików, gdzie struktura plików w katalogu routes/ określa trasy Twojej aplikacji. Opcja ignoredRouteFiles zapewnia, że pliki deklaracji treści Intlayer (.content.ts, itp.) nie są traktowane jako pliki tras.
    5. Utwórz pliki tras z konwencjami systemu plików

      Przy routingu opartym na systemie plików używasz płaskiej konwencji nazewnictwa, gdzie kropki (.) reprezentują segmenty ścieżki, a nawiasy () oznaczają opcjonalne segmenty.

      Utwórz następujące pliki w katalogu app/routes/:

      Struktura plików

      bash
      app/
      ├── root.tsx                         # Opakowanie layoutu dla tras lokalizacji
      └──routes/
          ├── ($locale)._index.tsx         # Strona główna (/, /es, itd.)
          ├── ($locale)._index.content.ts  # Zawartość strony głównej
          ├── ($locale).about.tsx          # Strona O nas (/about, /es/about, itd.)
          └── ($locale).about.content.ts   # Zawartość strony O nas
      

      Konwencje nazewnictwa:

      • ($locale) - Opcjonalny dynamiczny segment dla parametru lokalizacji
      • _layout - Trasa layoutu, która opakowuje trasy potomne
      • _index - Trasa indeksowa (renderuje się na ścieżce nadrzędnej)
      • . (kropka) - Oddziela segmenty ścieżki (np. ($locale).about/:locale?/about)

      Komponent Layoutu

      app/root.tsx
      import { getLocaleFromPath } from "intlayer";
      import { IntlayerProvider } from "react-intlayer";
      import {
        isRouteErrorResponse,
        Meta,
        Outlet,
        Scripts,
        ScrollRestoration,
        useLoaderData,
      } from "react-router";
      
      import type { Route } from "./+types/root";
      
      import "./app.css";
      
      // links and ErrorBoundary code
      
      export async function loader({ request }: Route.LoaderArgs) {
        const locale = getLocaleFromPath(request.url);
      
        return { locale };
      }
      
      export function Layout({
        children,
      }: { children: React.ReactNode } & Route.ComponentProps) {
        const data = useLoaderData<typeof loader>();
        const { locale } = data ?? {};
      
        return (
          <html lang={locale}>
            <head>
              <meta charSet="utf-8" />
              <meta content="width=device-width, initial-scale=1" name="viewport" />
              <Meta />
              <Links />
            </head>
            <body>
              <IntlayerProvider locale={locale}>{children}</IntlayerProvider>
              <ScrollRestoration />
              <Scripts />
            </body>
          </html>
        );
      }
      

      Strona indeksowa

      app/routes/($locale)._index.tsx
      import { getIntlayer, validatePrefix } from "intlayer";
      import { useIntlayer } from "react-intlayer";
      import { data } from "react-router";
      
      import { LocaleSwitcher } from "~/components/locale-switcher";
      import { Navbar } from "~/components/navbar";
      
      import type { Route } from "./+types/($locale)._index";
      
      export const loader = ({ params }: Route.LoaderArgs) => {
        const { locale } = params;
      
        const { isValid } = validatePrefix(locale);
      
        if (!isValid) {
          throw data("Locale not supported", { status: 404 });
        }
      };
      
      export const meta: Route.MetaFunction = ({ params }) => {
        const content = getIntlayer("page", params.locale);
      
        return [
          { title: content.title },
          { content: content.description, name: "description" },
        ];
      };
      
      export default function Page() {
        const { title, description, aboutLink } = useIntlayer("page");
      
        return (
          <div>
            <h1>{title}</h1>
            <p>{description}</p>
            <nav>
              <LocalizedLink to="/about">{aboutLink}</LocalizedLink>
            </nav>
          </div>
        );
      }
      

      Strona O nas

      app/routes/($locale).about.tsx
      import { getIntlayer, validatePrefix } from "intlayer";
      import { useIntlayer } from "react-intlayer";
      import { data } from "react-router";
      
      import { LocaleSwitcher } from "~/components/locale-switcher";
      import { Navbar } from "~/components/navbar";
      
      import type { Route } from "./+types/($locale).about";
      
      export const loader = ({ params }: Route.LoaderArgs) => {
        const { locale } = params;
      
        const { isValid } = validatePrefix(locale);
      
        if (!isValid) {
          throw data("Locale not supported", { status: 404 });
        }
      };
      
      export const meta: Route.MetaFunction = ({ params }) => {
        const content = getIntlayer("about", params.locale);
      
        return [
          { title: content.title },
          { content: content.description, name: "description" },
        ];
      };
      
      export default function AboutPage() {
        const { title, content, homeLink } = useIntlayer("about");
      
        return (
          <div>
            <h1>{title}</h1>
            <p>{content}</p>
            <nav>
              <LocalizedLink to="/">{homeLink}</LocalizedLink>
            </nav>
          </div>
        );
      }
      
    6. Zadeklaruj swoją zawartość

      Utwórz i zarządzaj deklaracjami zawartości, aby przechowywać tłumaczenia. Umieść pliki zawartości obok plików tras:

      app/routes/($locale)._index.content.ts
      import { t, type Dictionary } from "intlayer";
      
      const pageContent = {
        key: "page",
        content: {
          title: t({
            en: "Welcome to React Router v7 + Intlayer",
            es: "Bienvenido a React Router v7 + Intlayer",
            fr: "Bienvenue sur React Router v7 + Intlayer",
          }),
          description: t({
            en: "Build multilingual applications with ease using React Router v7 and Intlayer.",
            pl: "Twórz wielojęzyczne aplikacje z łatwością, korzystając z React Router v7 i Intlayer.",
            es: "Cree aplicaciones multilingües fácilmente usando React Router v7 y Intlayer.",
            fr: "Créez des applications multilingues facilement avec React Router v7 et Intlayer.",
          }),
          aboutLink: t({
            en: "Learn About Us",
            es: "Aprender Sobre Nosotros",
            fr: "En savoir plus sur nous",
          }),
        },
      } satisfies Dictionary;
      
      export default pageContent;
      
      app/routes/($locale).about.content.ts
      import { t, type Dictionary } from "intlayer";
      
      const aboutContent = {
        key: "about",
        content: {
          title: t({
            en: "About Us",
            es: "Sobre Nosotros",
            fr: "À propos de nous",
          }),
          content: t({
            en: "This is the about page content.",
            es: "Este es el contenido de la página de información.",
            fr: "Ceci est le contenu de la page à propos.",
          }),
          homeLink: t({
            en: "Home",
            es: "Inicio",
            fr: "Accueil",
          }),
        },
      } satisfies Dictionary;
      
      export default aboutContent;
      
      Twoje deklaracje treści mogą być zdefiniowane w dowolnym miejscu w aplikacji, pod warunkiem, że zostaną umieszczone w katalogu contentDir (domyślnie ./app). I muszą odpowiadać rozszerzeniu pliku deklaracji treści (domyślnie .content.{json,ts,tsx,js,jsx,mjs,cjs,md,mdx,yaml,yml}).
      Po więcej szczegółów odsyłamy do dokumentacji deklaracji treści.
      Jeśli Twoja aplikacja już istnieje, możesz użyć Intlayer Compiler, a także polecenia extract, aby transformować tysiące komponentów w sekundę.
    7. Tworzenie komponentów uwzględniających lokalizację

      Utwórz komponent LocalizedLink do nawigacji uwzględniającej lokalizację:

      app/components/localized-link.tsx
      import type { FC } from "react";
      
      import { getLocalizedUrl, type LocalesValues } from "intlayer";
      import { useLocale } from "react-intlayer";
      import { Link, type LinkProps, type To } from "react-router";
      
      const isExternalLink = (to: string) => /^(https?:)?\/\//.test(to);
      
      // Funkcja lokalizująca ścieżkę na podstawie podanego locale
      export const locacalizeTo = (to: To, locale: LocalesValues): To => {
        if (typeof to === "string") {
          if (isExternalLink(to)) {
            return to; // Zwraca link zewnętrzny bez zmian
          }
      
          return getLocalizedUrl(to, locale); // Zwraca lokalizowany URL
        }
      
        if (isExternalLink(to.pathname ?? "")) {
          return to; // Zwraca link zewnętrzny bez zmian
        }
      
        return {
          ...to,
          pathname: getLocalizedUrl(to.pathname ?? "", locale), // Lokalizuje pathname
        };
      };
      
      // Komponent linku lokalizowanego
      export const LocalizedLink: FC<LinkProps> = (props) => {
        const { locale } = useLocale();
      
        return <Link {...props} to={locacalizeTo(props.to, locale)} />;
      };
      

      W przypadku, gdy chcesz nawigować do lokalizowanych tras, możesz użyć hooka useLocalizedNavigate:

      app/hooks/useLocalizedNavigate.ts
      import { useLocale } from "react-intlayer";
      import { type NavigateOptions, type To, useNavigate } from "react-router";
      
      import { locacalizeTo } from "~/components/localized-link";
      
      export const useLocalizedNavigate = () => {
        const navigate = useNavigate();
        const { locale } = useLocale();
      
        const localizedNavigate = (to: To, options?: NavigateOptions) => {
          const localedTo = locacalizeTo(to, locale);
      
          navigate(localedTo, options);
        };
      
        return localizedNavigate;
      };
      
    8. Utwórz komponent przełącznika języka

      Utwórz komponent, który pozwoli użytkownikom zmieniać języki:

      app/components/locale-switcher.tsx
      import type { FC } from "react";
      
      import {
        getHTMLTextDir,
        getLocaleName,
        getLocalizedUrl,
        getPathWithoutLocale,
        Locales,
      } from "intlayer";
      import { useIntlayer, useLocale } from "react-intlayer";
      import { Link, useLocation } from "react-router";
      
      export const LocaleSwitcher: FC = () => {
        const { localeSwitcherLabel } = useIntlayer("locale-switcher");
        const { pathname } = useLocation();
      
        const { availableLocales, locale } = useLocale();
      
        const pathWithoutLocale = getPathWithoutLocale(pathname);
      
        return (
          <ol>
            {availableLocales.map((localeItem) => (
              <li key={localeItem}>
                <Link
                  aria-current={localeItem === locale ? "page" : undefined}
                  aria-label={`${localeSwitcherLabel.value} ${getLocaleName(localeItem)}`}
                  reloadDocument // Przeładuj stronę, aby zastosować nową lokalizację
                  to={getLocalizedUrl(pathWithoutLocale, localeItem)}
                >
                  <span>
                    {/* Lokalizacja - np. FR */}
                    {localeItem}
                  </span>
                  <span>
                    {/* Język w jego własnej lokalizacji - np. Français */}
                    {getLocaleName(localeItem, locale)}
                  </span>
                  <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
                    {/* Język w bieżącej lokalizacji - np. Francés przy ustawionej lokalizacji Locales.SPANISH */}
                    {getLocaleName(localeItem)}
                  </span>
                  <span dir="ltr" lang={Locales.ENGLISH}>
                    {/* Język po angielsku - np. French */}
                    {getLocaleName(localeItem, Locales.ENGLISH)}
                  </span>
                </Link>
              </li>
            ))}
          </ol>
        );
      };
      
      Aby dowiedzieć się więcej o hooku useLocale, zapoznaj się z dokumentacją.
    9. Dodaj zarządzanie atrybutami HTML

      Utwórz hook do zarządzania atrybutami lang i dir w HTML:

      app/hooks/useI18nHTMLAttributes.tsx
      import { getHTMLTextDir } from "intlayer";
      import { useEffect } from "react";
      import { useLocale } from "react-intlayer";
      
      export const useI18nHTMLAttributes = () => {
        const { locale } = useLocale();
      
        useEffect(() => {
          document.documentElement.lang = locale;
          document.documentElement.dir = getHTMLTextDir(locale);
        }, [locale]);
      };
      

      Ten hook jest już używany w komponencie layout (($locale)._layout.tsx) pokazanym w Kroku 5.

    10. Następnie użyj go w swoim komponencie root:

      Możesz również użyć intlayerProxy do dodania routingu po stronie serwera do twojej aplikacji. Ten plugin automatycznie wykryje bieżącą lokalizację na podstawie adresu URL i ustawi odpowiednią plik cookie lokalizacji. Jeśli nie określono lokalizacji, plugin określi najbardziej odpowiednią lokalizację na podstawie preferencji języka przeglądarki użytkownika. Jeśli nie wykryto żadnej lokalizacji, będzie przekierowywać do lokalizacji domyślnej.

      Pamiętaj, że aby używać intlayerProxy w produkcji, musisz przenieść pakiet vite-intlayer z devDependencies do dependencies.
      Od wersji Intlayer v9, intlayerProxy() jest dołączony bezpośrednio do wtyczki intlayer() i domyślnie włączony za pomocą opcji routing.enableProxy (true domyślnie). Rejestrowanie go osobno, jak pokazano poniżej, jest teraz opcjonalne — jest zachowywane dla wstecznej kompatybilności i dla konfiguracji, które muszą kontrolować kolejność wtyczek. Ustaw routing.enableProxy: false, aby zrezygnować. Zobacz notatki wydania v9.
      app/routes/layout.tsx
      import { Outlet } from "react-router";
      import { IntlayerProvider } from "react-intlayer";
      
      import { useI18nHTMLAttributes } from "app/hooks/useI18nHTMLAttributes"; // importuj hook
      
      export default function RootLayout() {
        useI18nHTMLAttributes(); // wywołaj hook
      
        return (
          <IntlayerProvider>
            <Outlet />
          </IntlayerProvider>
        );
      }
      

      </Step>

    11. Wyodrębnij zawartość swoich komponentów

      Opcjonalne

      Jeśli masz istniejącą bazę kodu, transformacja tysięcy plików może być czasochłonna.

      Aby ułatwić ten proces, Intlayer proponuje kompilator / ekstraktor, aby przetransformować komponenty i wyodrębnić zawartość.

      Aby go skonfigurować, możesz dodać sekcję compiler w pliku intlayer.config.ts:

      intlayer.config.ts
      import { type IntlayerConfig } from "intlayer";
      
      const config: IntlayerConfig = {
        // ... Reszta Twojej konfiguracji
        compiler: {
          /**
           * Wskazuje, czy kompilator powinien być włączony.
           */
          enabled: true,
      
          /**
           * Definiuje ścieżkę plików wyjściowych
           */
          output: ({ fileName, extension }) => `./${fileName}${extension}`,
      
          /**
           * Wskazuje, czy komponenty powinny zostać zapisane po transformacji. W ten sposób kompilator można uruchomić tylko raz, aby przetransformować aplikację, a następnie go usunąć.
           */
          saveComponents: false,
      
          /**
           * Prefiks klucza słownika
           */
          dictionaryKeyPrefix: "",
        },
      };
      
      export default config;
      

      Uruchom ekstraktor, aby przetransformować komponenty i wyodrębnić zawartość

      bash
      npx intlayer extract
      
      Since v9, the intlayerCompiler is included in the intlayer plugin. So you don't need to add it manually.

      Zaktualizuj vite.config.ts, aby dołączyć wtyczkę intlayerCompiler:

      vite.config.ts
      import { defineConfig } from "vite";
      import { intlayer, intlayerCompiler } from "vite-intlayer";
      
      export default defineConfig({
        plugins: [
          intlayer(),
          intlayerCompiler(), // Adds the compiler plugin
        ],
      });
      
      bash
      npm run build # Lub npm run dev
      

    Configure TypeScript

    Intlayer uses module augmentation to get benefits of TypeScript and make your codebase stronger.

    Ensure your TypeScript configuration includes the autogenerated types:

    tsconfig.json
    {
      // ... your existing configurations
      include: [
        // ... your existing includes
        ".intlayer/**/*.ts", // Include the auto-generated types
      ],
    }
    

    Git Configuration

    It is recommended to ignore the files generated by Intlayer. This allows you to avoid committing them to your Git repository.

    To do this, you can add the following instructions to your .gitignore file:

    .gitignore
    # Ignore the files generated by Intlayer
    .intlayer
    

    VS Code Extension

    To improve your development experience with Intlayer, you can install the official Intlayer VS Code Extension.

    Install from the VS Code Marketplace

    This extension provides:

    • Autocompletion for translation keys.
    • Real-time error detection for missing translations.
    • Inline previews of translated content.
    • Quick actions to easily create and update translations.

    For more details on how to use the extension, refer to the Intlayer VS Code Extension documentation.


    Go Further

    To go further, you can implement the visual editor or externalize your content using the CMS.


    Odnośniki do dokumentacji

    Ten kompleksowy przewodnik zawiera wszystko, co potrzebne do integracji Intlayer z React Router v7 używając routingu opartego na systemie plików, aby uzyskać w pełni zinternacjonalizowaną aplikację z trasowaniem uwzględniającym lokalizację oraz wsparciem dla TypeScript.