Strona głównaPiaskownicaPrezentacjaAplikacjaDokumentacjaBlog
    • Englishangielski
      EN
    • русскийrosyjski
      RU
    • 日本語japoński
      JA
    • françaisfrancuski
      FR
    • 한국어koreański
      KO
    • 中文chiński
      ZH
    • españolhiszpański
      ES
    • Deutschniemiecki
      DE
    • العربيةarabski
      AR
    • italianowłoski
      IT
    • British Englishangielski brytyjski
      EN-GB
    • portuguêsportugalski
      PT
    • हिन्दीhindi
      HI
    • Türkçeturecki
      TR
    • polskipolski
      PL
    • Indonesiaindonezyjski
      ID
    • Tiếng Việtwietnamski
      VI
    • українськаukraiński
      UK
    /
    Filtruj dokumenty według frameworka
    Alt+←
    Dlaczego Intlayer?
    Zacząć
    Koncepcja
    • Jak działa Intlayer
    • Konfiguracja
    • TestFillBuildWatchExtractLoginPushPullConfigurationListVersionEditorLiveDebugDoc ReviewDoc TranslateSDK
    • Edytor wizualny
    • CMS
    • Integracja CI/CD
    • TłumaczenieLiczba mnogaWyliczenieWarunekPłećWstawieniePlikZagnieżdżanieMarkdownHTMLPobieranie funkcji
    • Plik dla każdej lokalizacji
    • Kompilator
    • Automatyczne wypełnianie
    • Testowanie
    • Optymalizacja pakietu
    Środowisko
    • Next.js 14 i App Router
      Next.js 15
      Next.js bez locale URL
      Next.js dan Page Router
      Kompilator
    • Tanstack Start Solid
    • Astro dan React
      Astro dan Svelte
      Astro dan Vue
      Astro dan Solid
      Astro dan Preact
      Astro dan Lit
      Astro dan Vanilla JS
    • React Router v7
      React Router v7 (fs-routes)
      Compiler
    • Nuxt dan Vue
    • Vite dan Solid
    • SvelteKit
    • Vite dan Preact
    • Vite dan Vanilla JS
    • Vite dan Lit
    • Angular 19 (Webpack)
      Analog
    • React CRA
    • React Native dan Expo
    • Express.js
      NestJS
      Fastify
      Hono
      Adonis
    • Lynx dan React
    Plugins
    • JSON
    • gettext (.po)
    Rozszerzenie VS Code
    Agent
    • Serwer MCP
    • Umiejętności agenta
    Wersje
    • v8
    • v7
    • v6
    Benchmark
    • Next.js
    • TanStack
    • Vue
    • Solid
    • Svelte
    Blog
    Zadaj pytanie
    1. Documentation
    2. Środowisko
    3. Tanstack Start
    Data utworzenia:2025-09-09Ostatnia aktualizacja:2026-05-06
    Zobacz szablon aplikacji na GitHubie

    Na tej stronie dostępny jest szablon aplikacji.

    Zobacz aplikację pokazową

    Ta strona prowadzi do działającej demonstracji szablonu.

    Obejrzyj samouczek wideo

    Na tej stronie dostępny jest samouczek wideo.

    Prześlij ten dokument do swojego ulubionego asystenta AI
    ChatGPT
    Claude
    DeepSeek
    Google AI mode
    Gemini
    Perplexity
    Mistral
    Grok

    Zadaj pytanie i otrzymaj streszczenie dokumentu, odwołując się do tej strony i wybranego dostawcy AI

    Historia wersji

    1. "Aktualizacja użycia API useIntlayer w Solid do bezpośredniego dostępu do właściwości"
      v8.9.04.05.2026
    2. "Dodaj polecenie init"
      v7.5.930.12.2025
    3. "Wprowadzenie validatePrefix oraz dodanie kroku 14: Obsługa stron 404 z lokalizowanymi trasami."
      v7.4.011.12.2025
    4. "Dodany krok 13: Pobieranie lokalizacji w akcjach serwerowych (Opcjonalnie)"
      v7.3.95.12.2025
    5. "Dodaj krok 13: Adaptacja Nitro"
      v7.2.318.11.2025
    6. "Naprawienie domyślnego prefiksu poprzez dodanie funkcji getPrefix useLocalizedNavigate, LocaleSwitcher i LocalizedLink."
      v7.1.017.11.2025
    7. "Aktualizacja dokumentacji"
      v6.5.23.10.2025
    8. "Dodano dla Tanstack Start"
      v5.8.19.09.2025

    Treść tej strony została przetłumaczona przy użyciu sztucznej inteligencji.

    Zobacz ostatnią wersję oryginalnej treści w języku angielskim
    Edytuj tę dokumentację

    Jeśli masz pomysł na ulepszenie tej dokumentacji, zachęcamy do przesłania pull requesta na GitHubie.

    Link do dokumentacji na GitHubie
    Kopiuj

    Kopiuj dokument Markdown do schowka

    Przetłumacz swoją stronę Tanstack Start za pomocą Intlayer | Internacjonalizacja (i18n)

    Spis treści

    Ten przewodnik pokazuje, jak zintegrować Intlayer dla płynnej internacjonalizacji w projektach Tanstack Start z routingiem uwzględniającym lokalizację, wsparciem TypeScript oraz nowoczesnymi praktykami programistycznymi.

    Czym jest Intlayer?

    Intlayer to innowacyjna, open-source'owa biblioteka do internacjonalizacji (i18n), zaprojektowana, aby uprościć wsparcie wielojęzyczne w nowoczesnych aplikacjach webowych.

    Dzięki Intlayer możesz:

    • Łatwo zarządzać tłumaczeniami za pomocą deklaratywnych słowników na poziomie komponentów.
    • Dynamicznie lokalizować metadane, trasy i zawartość.
    • Zapewnić wsparcie TypeScript dzięki automatycznie generowanym typom, co poprawia autouzupełnianie i wykrywanie błędów.
    • Korzystać z zaawansowanych funkcji, takich jak dynamiczne wykrywanie i przełączanie lokalizacji.
    • Włączyć routing uwzględniający lokalizację za pomocą systemu routingu opartego na plikach Tanstack Start.

    Przewodnik krok po kroku, jak skonfigurować Intlayer w aplikacji Tanstack Start

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

    Zobacz Szablon aplikacji na GitHub.

    Krok 1: Utwórz projekt

    Rozpocznij od utworzenia nowego projektu TanStack Start, postępując zgodnie z przewodnikiem Start new project na stronie TanStack Start.

    Krok 2: Zainstaluj pakiety Intlayer

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

    bash
    Kopiuj kod

    Skopiuj kod do schowka

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

      Podstawowy pakiet, który dostarcza narzędzia do internacjonalizacji dla zarządzania konfiguracją, tłumaczeń, deklaracji treści, transpiliacji 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.

    Krok 3: Konfiguracja projektu

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

    intlayer.config.ts
    Kopiuj kod

    Skopiuj kod do schowka

    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;
    Za pomocą tego pliku konfiguracyjnego możesz ustawić lokalizowane adresy URL, przekierowania w middleware, nazwy ciasteczek, lokalizację i rozszerzenie deklaracji treści, wyłączyć logi Intlayer w konsoli i wiele więcej. Pełną listę dostępnych parametrów znajdziesz w dokumentacji konfiguracji.

    Krok 4: Integracja Intlayer w konfiguracji Vite

    Dodaj wtyczkę intlayer do swojej konfiguracji:

    vite.config.ts
    Kopiuj kod

    Skopiuj kod do schowka

    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;
    Wtyczka intlayer() dla Vite służy do integracji Intlayer z Vite. Zapewnia budowanie plików deklaracji treści oraz monitorowanie ich w trybie deweloperskim. Definiuje zmienne środowiskowe Intlayer w aplikacji Vite. Dodatkowo dostarcza aliasy optymalizujące wydajność.

    Krok 5: Utwórz układ główny (Root Layout)

    Skonfiguruj swój główny układ, aby wspierać internacjonalizację, używając useParams do wykrywania aktualnej lokalizacji i ustawiając atrybuty lang i dir w tagu html.

    src/routes/__root.tsx
    Kopiuj kod

    Skopiuj kod do schowka

    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>  );}
    Jeśli chcesz użyć swojej zawartości w atrybucie typu string, takim jak alt, title, href, aria-label itp., musisz wywołać wartość funkcji, na przykład:
    html
    Kopiuj kod

    Skopiuj kod do schowka

    <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)}" />

    Krok 6: Utwórz układ lokalizacji

    Utwórz układ, który obsługuje prefiks lokalizacji i wykonuje walidację.

    src/routes/{-$locale}/route.tsx
    Kopiuj kod

    Skopiuj kod do schowka

    import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";import { validatePrefix } from "intlayer";export const Route = createFileRoute("/{-$locale}")({  beforeLoad: ({ params }) => {    const localeParam = params.locale;    // Walidacja prefiksu lokalizacji    const { isValid, localePrefix } = validatePrefix(localeParam);    if (!isValid) {      throw redirect({        to: "/{-$locale}/404",        params: { locale: localePrefix },      });    }  },  component: Outlet,});
    Tutaj {-$locale} jest dynamicznym parametrem trasy, który zostaje zastąpiony aktualną lokalizacją. Ta notacja sprawia, że slot jest opcjonalny, co pozwala na współpracę z trybami routingu takimi jak 'prefix-no-default' itp.

    Pamiętaj, że ten slot może powodować problemy, jeśli używasz wielu dynamicznych segmentów w tej samej trasie (np. /{-$locale}/other-path/$anotherDynamicPath/...). W trybie 'prefix-all' możesz woleć zmienić slot na $locale. W trybach 'no-prefix' lub 'search-params' możesz całkowicie usunąć ten slot.

    Krok 7: Zadeklaruj swoją treść

    Twórz i zarządzaj deklaracjami treści, aby przechowywać tłumaczenia:

    src/contents/page.content.ts
    Kopiuj kod

    Skopiuj kod do schowka

    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;
    Twoje deklaracje zawartości mogą być definiowane w dowolnym miejscu w Twojej aplikacji, pod warunkiem, że zostaną umieszczone w katalogu contentDir (domyślnie ./app). I będą miały rozszerzenie pliku deklaracji zawartości (domyślnie .content.{json,ts,tsx,js,jsx,mjs,cjs}).
    Po więcej szczegółów odsyłamy do dokumentacji deklaracji zawartości.

    Krok 8: Tworzenie komponentów i hooków uwzględniających lokalizację

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

    src/components/localized-link.tsx
    Kopiuj kod

    Skopiuj kod do schowka

    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"]}    />  );};

    Ten komponent ma dwa cele:

    • Usunięcie niepotrzebnego prefiksu {-$locale} z URL.
    • Wstrzyknięcie parametru locale do URL, aby zapewnić użytkownikowi bezpośrednie przekierowanie do zlokalizowanej ścieżki.

    Następnie możemy stworzyć hook useLocalizedNavigate do nawigacji programowej:

    src/hooks/useLocalizedNavigate.tsx
    Kopiuj kod

    Skopiuj kod do schowka

    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;};

    Krok 9: Wykorzystaj Intlayer na swoich stronach

    Uzyskaj dostęp do swoich słowników treści w całej aplikacji:

    Lokalizowana strona główna

    src/routes/{-$locale}/index.tsx
    Kopiuj kod

    Skopiuj kod do schowka

    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>  );}
    Aby dowiedzieć się więcej o hooku useIntlayer, zapoznaj się z dokumentacją.

    Krok 10: Utwórz komponent przełącznika języka (Locale Switcher)

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

    src/components/locale-switcher.tsx
    Kopiuj kod

    Skopiuj kod do schowka

    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>              {/* Lokalizacja - np. FR */}              {localeEl}            </span>            <span>              {/* Język w swojej własnej lokalizacji - np. Français */}              {getLocaleName(localeEl, locale)}            </span>            <span dir={getHTMLTextDir(localeEl)} lang={localeEl}>              {/* Język w bieżącej lokalizacji - np. Francés przy ustawionej lokalizacji Locales.SPANISH */}              {getLocaleName(localeEl)}            </span>            <span dir="ltr" lang={Locales.ENGLISH}>              {/* Język po angielsku - np. French */}              {getLocaleName(localeEl, Locales.ENGLISH)}            </span>          </LocalizedLink>        </li>      ))}    </ol>  );};
    Aby dowiedzieć się więcej o hooku useLocale, zapoznaj się z dokumentacją.

    Krok 11: Zarządzanie atrybutami HTML

    Jak pokazano w Kroku 5, możesz zarządzać atrybutami lang i dir tagu html za pomocą useParams w swoim komponencie głównym. Zapewnia to, że poprawne atrybuty są ustawione zarówno na serwerze, jak i kliencie.

    src/routes/__root.tsx
    Kopiuj kod

    Skopiuj kod do schowka

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

    Krok 12: Dodaj middleware (Opcjonalnie)

    Możesz również użyć intlayerProxy, aby dodać routing po stronie serwera do swojej aplikacji. Ten plugin automatycznie wykryje aktualną lokalizację na podstawie URL i ustawi odpowiednie ciasteczko lokalizacji. Jeśli nie zostanie określona żadna lokalizacja, plugin wybierze najbardziej odpowiednią na podstawie preferencji językowych przeglądarki użytkownika. Jeśli nie zostanie wykryta żadna lokalizacja, nastąpi przekierowanie do domyślnej.

    Uwaga: aby używać intlayerProxy w produkcji, musisz przenieść pakiet vite-intlayer z devDependencies do dependencies.
    vite.config.ts
    Kopiuj kod

    Skopiuj kod do schowka

    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(), // Proxy powinno być umieszczone przed serwerem, jeśli używasz Nitro    nitro(),    intlayer(),    tanstackStart({      router: {        routeFileIgnorePattern:          ".content.(ts|tsx|js|mjs|cjs|jsx|json|jsonc|json5)$",      },    }),    viteReact(),  ],});

    Krok 13: Internacjonalizacja metadanych (Opcjonalnie)

    Możesz również użyć hooka getIntlayer, aby uzyskać dostęp do słowników treści w całej aplikacji:

    src/routes/{-$locale}/index.tsx
    Kopiuj kod

    Skopiuj kod do schowka

    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 },      ],    };  },});

    Krok 14: Pobieranie lokalizacji w akcjach serwerowych (Opcjonalnie)

    Możesz chcieć uzyskać dostęp do aktualnej lokalizacji wewnątrz swoich akcji serwerowych lub punktów końcowych API. Możesz to zrobić za pomocą pomocnika getLocale z intlayer.

    Oto przykład użycia funkcji serwerowych TanStack Start:

    src/routes/{-$locale}/index.tsx
    Kopiuj kod

    Skopiuj kod do schowka

    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({    // Pobierz ciasteczko z żądania (domyślnie: 'INTLAYER_LOCALE')    getCookie: (name) => {      const cookieString = getRequestHeader("cookie");      return getCookie(name, cookieString);    },    // Pobierz nagłówek z żądania (domyślnie: 'x-intlayer-locale')    // Rezerwowe rozwiązanie przy użyciu negocjacji Accept-Language    getHeader: (name) => getRequestHeader(name),  });  // Pobierz treść za pomocą getIntlayer()  const content = getIntlayer("app", locale);  return { locale, content };});

    Krok 15: Zarządzanie stronami "nie znaleziono" (Opcjonalnie)

    Gdy użytkownik odwiedza nieistniejącą stronę, możesz wyświetlić niestandardową stronę "nie znaleziono", a prefiks lokalizacji może wpływać na sposób wyzwalania strony "nie znaleziono".

    Zrozumienie obsługi 404 w TanStack Router z prefiksami lokalizacji

    W TanStack Router obsługa stron 404 z zlokalizowanymi trasami wymaga podejścia wielowarstwowego:

    1. Dedykowana trasa 404: Konkretna trasa do wyświetlenia interfejsu 404
    2. Walidacja na poziomie trasy: Weryfikuje prefiksy lokalizacji i przekierowuje nieprawidłowe do 404
    3. Trasa catch-all: Przechwytuje wszystkie niedopasowane ścieżki w segmencie lokalizacji
    src/routes/{-$locale}/404.tsx
    Kopiuj kod

    Skopiuj kod do schowka

    import { createFileRoute } from "@tanstack/react-router";// To tworzy dedykowaną trasę /[locale]/404// Jest używana zarówno jako bezpośrednia trasa, jak i importowana jako komponent w innych plikachexport const Route = createFileRoute("/{-$locale}/404")({  component: NotFoundComponent,});// Eksportowane osobno, aby można było ponownie użyć w notFoundComponent i trasach catch-allexport function NotFoundComponent() {  return (    <div>      <h1>404</h1>    </div>  );}
    src/routes/{-$locale}/route.tsx
    Kopiuj kod

    Skopiuj kod do schowka

    import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";import { validatePrefix } from "intlayer";import { NotFoundComponent } from "./404";export const Route = createFileRoute("/{-$locale}")({  // beforeLoad uruchamia się przed renderowaniem trasy (zarówno na serwerze, jak i kliencie)  // To idealne miejsce do walidacji prefiksu lokalizacji  beforeLoad: ({ params }) => {    const localeParam = params.locale;    // validatePrefix sprawdza, czy lokalizacja jest prawidłowa zgodnie z konfiguracją intlayer    const { isValid, localePrefix } = validatePrefix(localeParam);    if (!isValid) {      // Nieprawidłowy prefiks lokalizacji - przekieruj do strony 404 z prawidłowym prefiksem lokalizacji      throw redirect({        to: "/{-$locale}/404",        params: { locale: localePrefix },      });    }  },  component: Outlet,  // notFoundComponent jest wywoływane, gdy trasa potomna nie istnieje  // np. /en/nieistniejaca-strona wyzwala to w układzie /en  notFoundComponent: NotFoundComponent,});
    src/routes/{-$locale}/$.tsx
    Kopiuj kod

    Skopiuj kod do schowka

    import { createFileRoute } from "@tanstack/react-router";import { NotFoundComponent } from "./404";// Trasa $ (splat/catch-all) pasuje do każdej ścieżki, która nie pasuje do innych tras// np. /en/jakas/gleboko/zagniezdzona/niewazna/sciezka// To zapewnia, że WSZYSTKIE niedopasowane ścieżki w lokalizacji wyświetlają stronę 404// Bez tego niedopasowane głębokie ścieżki mogą wyświetlać pustą stronę lub błądexport const Route = createFileRoute("/{-$locale}/$")({  component: NotFoundComponent,});

    Krok 16: Konfiguracja TypeScript (Opcjonalnie)

    Intlayer używa rozszerzenia modułów (module augmentation), aby wykorzystać zalety TypeScript i wzmocnić Twoją bazę kodu.

    Upewnij się, że Twoja konfiguracja TypeScript zawiera automatycznie generowane typy:

    tsconfig.json
    Kopiuj kod

    Skopiuj kod do schowka

    {  // ... Twoje istniejące konfiguracje  include: [    // ... Twoje istniejące include    ".intlayer/**/*.ts", // Dołącz automatycznie generowane typy  ],}

    (Opcjonalnie) Krok 17 : Wyodrębnij zawartość swoich komponentów

    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
    Kopiuj kod

    Skopiuj kod do schowka

    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
    Kopiuj kod

    Skopiuj kod do schowka

    npx intlayer extract

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

    vite.config.ts
    Kopiuj kod

    Skopiuj kod do schowka

    import { defineConfig } from "vite";import { intlayer, intlayerCompiler } from "vite-intlayer";export default defineConfig({ plugins: [   intlayer(),   intlayerCompiler(), // Dodaje wtyczkę kompilatora ],});
    bash
    Kopiuj kod

    Skopiuj kod do schowka

    npm run build # Lub npm run dev

    Konfiguracja Git

    Zaleca się ignorowanie plików generowanych przez Intlayer. Pozwala to uniknąć ich zatwierdzania do repozytorium Git.

    Aby to zrobić, możesz dodać następujące instrukcje do pliku .gitignore:

    .gitignore
    Kopiuj kod

    Skopiuj kod do schowka

    # Ignoruj pliki generowane przez Intlayer.intlayer

    Rozszerzenie VS Code

    Aby poprawić swoje doświadczenie deweloperskie z Intlayer, możesz zainstalować oficjalne rozszerzenie Intlayer dla VS Code.

    Zainstaluj z Marketplace VS Code

    To rozszerzenie oferuje:

    • Autouzupełnianie kluczy tłumaczeń.
    • Wykrywanie błędów w czasie rzeczywistym dla brakujących tłumaczeń.
    • Podgląd w linii przetłumaczonej zawartości.
    • Szybkie akcje umożliwiające łatwe tworzenie i aktualizowanie tłumaczeń.

    Aby uzyskać więcej informacji na temat korzystania z rozszerzenia, zapoznaj się z dokumentacją rozszerzenia Intlayer VS Code.


    Idź dalej

    Aby pójść dalej, możesz zaimplementować edytor wizualny lub wyodrębnić swoją zawartość, korzystając z CMS.


    Odnośniki do dokumentacji

    • Dokumentacja Intlayer
    • Dokumentacja Tanstack Start
    • Hook useIntlayer
    • useLocale hook
    • Deklaracja treści
    • Konfiguracja
    Kompilator
    Tanstack Start Solid
    Alt+→

    Na tej stronie

      Dyskusje są anonimowe i regularnie przeglądane w celu rozwiązania typowych problemów. Podziel się pomysłami na funkcje, opinią o dokumentacji lub czymkolwiek związanym z Intlayer, wykorzystujemy te informacje do kształtowania naszej mapy drogowej i ulepszania produktu.

      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;    // Walidacja prefiksu lokalizacji    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>              {/* Lokalizacja - np. FR */}              {localeEl}            </span>            <span>              {/* Język w swojej własnej lokalizacji - np. Français */}              {getLocaleName(localeEl, locale)}            </span>            <span dir={getHTMLTextDir(localeEl)} lang={localeEl}>              {/* Język w bieżącej lokalizacji - np. Francés przy ustawionej lokalizacji Locales.SPANISH */}              {getLocaleName(localeEl)}            </span>            <span dir="ltr" lang={Locales.ENGLISH}>              {/* Język po angielsku - np. 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(), // Proxy powinno być umieszczone przed serwerem, jeśli używasz 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({    // Pobierz ciasteczko z żądania (domyślnie: 'INTLAYER_LOCALE')    getCookie: (name) => {      const cookieString = getRequestHeader("cookie");      return getCookie(name, cookieString);    },    // Pobierz nagłówek z żądania (domyślnie: 'x-intlayer-locale')    // Rezerwowe rozwiązanie przy użyciu negocjacji Accept-Language    getHeader: (name) => getRequestHeader(name),  });  // Pobierz treść za pomocą getIntlayer()  const content = getIntlayer("app", locale);  return { locale, content };});
      import { createFileRoute } from "@tanstack/react-router";// To tworzy dedykowaną trasę /[locale]/404// Jest używana zarówno jako bezpośrednia trasa, jak i importowana jako komponent w innych plikachexport const Route = createFileRoute("/{-$locale}/404")({  component: NotFoundComponent,});// Eksportowane osobno, aby można było ponownie użyć w notFoundComponent i trasach catch-allexport 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 uruchamia się przed renderowaniem trasy (zarówno na serwerze, jak i kliencie)  // To idealne miejsce do walidacji prefiksu lokalizacji  beforeLoad: ({ params }) => {    const localeParam = params.locale;    // validatePrefix sprawdza, czy lokalizacja jest prawidłowa zgodnie z konfiguracją intlayer    const { isValid, localePrefix } = validatePrefix(localeParam);    if (!isValid) {      // Nieprawidłowy prefiks lokalizacji - przekieruj do strony 404 z prawidłowym prefiksem lokalizacji      throw redirect({        to: "/{-$locale}/404",        params: { locale: localePrefix },      });    }  },  component: Outlet,  // notFoundComponent jest wywoływane, gdy trasa potomna nie istnieje  // np. /en/nieistniejaca-strona wyzwala to w układzie /en  notFoundComponent: NotFoundComponent,});
      import { createFileRoute } from "@tanstack/react-router";import { NotFoundComponent } from "./404";// Trasa $ (splat/catch-all) pasuje do każdej ścieżki, która nie pasuje do innych tras// np. /en/jakas/gleboko/zagniezdzona/niewazna/sciezka// To zapewnia, że WSZYSTKIE niedopasowane ścieżki w lokalizacji wyświetlają stronę 404// Bez tego niedopasowane głębokie ścieżki mogą wyświetlać pustą stronę lub błądexport const Route = createFileRoute("/{-$locale}/$")({  component: NotFoundComponent,});
      {  // ... Twoje istniejące konfiguracje  include: [    // ... Twoje istniejące include    ".intlayer/**/*.ts", // Dołącz automatycznie generowane typy  ],}
      npx intlayer extract
      import { defineConfig } from "vite";import { intlayer, intlayerCompiler } from "vite-intlayer";export default defineConfig({ plugins: [   intlayer(),   intlayerCompiler(), // Dodaje wtyczkę kompilatora ],});
      npm run build # Lub npm run dev
      # Ignoruj pliki generowane przez Intlayer.intlayer