---
createdAt: 2025-08-06
updatedAt: 2026-08-06
title: "Solid Start i18n - Kompletny przewodnik po tłumaczeniu swojej aplikacji"
description: "Koniec z i18next. Przewodnik 2026 do budowania wielojęzycznej (i18n) aplikacji SolidStart. Server-rendered routing lokalizacji, hreflang, mapa strony i tłumaczenie wspomagane przez AI."
keywords:
- Internationalization
- Documentation
- Intlayer
- SolidStart
- Solid
- i18n
- TypeScript
- Locale Routing
- Sitemap
slugs:
- doc
- environment
- solid-start
applicationTemplate: https://github.com/aymericzip/intlayer-solid-start-template
history:
- version: 9.1.3
date: 2025-08-06
changes: "Initial history"
author: aymericzip
---
# Przetłumacz swoją stronę SolidStart za pomocą Intlayer | Internacjonalizacja (i18n)
## Spis treści
Ten przewodnik dotyczy aplikacji SolidStart **renderowanej po stronie serwera (SSR)**: detekcja lokalizacji odbywa się podczas żądania, strony są renderowane na serwerze w odpowiednim języku, a sygnały ``, `hreflang` oraz mapy strony wymagane przez wyszukiwarki są generowane po stronie serwera.
## Dlaczego Intlayer zamiast alternatyw?
W porównaniu z głównymi rozwiązaniami, takimi jak `@solid-primitives/i18n` czy `i18next`, Intlayer jest rozwiązaniem wyposażonym w zintegrowane optymalizacje, takie jak:
Intlayer jest zoptymalizowany do idealnej współpracy z Solid, oferując **zakresowanie treści na poziomie komponentów**, **reaktywne tłumaczenia** i wszystkie funkcje potrzebne do skalowania internacjonalizacji (i18n).
Zamiast ładować ogromne pliki JSON do swoich stron, ładuj tylko niezbędną treść. Intlayer pomaga **zmniejszyć rozmiar paczki i stron nawet o 50%**.
Zakresowanie treści aplikacji **ułatwia utrzymanie** w przypadku aplikacji o dużej skali. Możesz powielić lub usunąć pojedynczy folder funkcji bez obciążenia psychicznego wynikającego z przeglądania całej bazy kodowej treści. Ponadto Intlayer jest **w pełni typowany**, aby zapewnić dokładność treści.
Wspólna lokalizacja treści **zmniejsza kontekst wymagany** przez duże modele językowe (LLM). Intlayer zawiera również zestaw narzędzi, takich jak **CLI** do testowania brakujących tłumaczeń, **[LSP](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/lsp.md)**, **[MCP](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/mcp_server.md)** oraz **[umiejętności agenta](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/agent_skills.md)**, aby czynić doświadczenie programistyczne (DX) jeszcze płynniejszym dla agentów AI.
Używaj automatyzacji do tłumaczenia w swoim potoku CI/CD za pomocą wybranego LLM po kosztach Twojego dostawcy AI. Intlayer oferuje również **kompilator** do automatyzacji ekstrakcji treści, a także [platformę internetową](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_CMS.md) pomagającą **tłumaczyć w tle**.
Łączenie ogromnych plików JSON z komponentami może prowadzić do problemów z wydajnością i reaktywnością. Intlayer optymalizuje ładowanie treści na etapie budowania.
Czymś więcej niż tylko rozwiązaniem i18n, Intlayer zapewnia **samodzielnie hostowany [edytor wizualny](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_visual_editor.md)** oraz **[pełny CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_CMS.md)** pomagający zarządzać wielojęzyczną treścią w **czasie rzeczywistym**, dzięki czemu współpraca z tłumaczami, copywriterami i innymi członkami zespołu jest płynna. Treść może być przechowywana lokalnie i/lub zdalnie.
---
## Przewodnik krok po kroku dotyczący konfiguracji Intlayer w aplikacji SolidStart
Zainstaluj niezbędne pakiety za pomocą npm:
```bash packageManager="npm"
npx intlayer init --interactive
```
```bash packageManager="pnpm"
pnpm dlx intlayer@canary init --interactive
```
```bash packageManager="yarn"
yarn dlx intlayer@canary init --interactive
```
```bash packageManager="bun"
bunx intlayer@canary init --interactive
```
> flaga `--interactive` jest opcjonalna. Użyj `intlayer-cli init`, jeśli jesteś agentem AI.
> To polecenie wykryje Twoje środowisko i zainstaluje wymagane pakiety. Na przykład:
```bash packageManager="npm"
npm install intlayer solid-intlayer vite-intlayer
```
```bash packageManager="pnpm"
pnpm add intlayer solid-intlayer vite-intlayer
```
```bash packageManager="yarn"
yarn add intlayer solid-intlayer vite-intlayer
```
```bash packageManager="bun"
bun add intlayer solid-intlayer vite-intlayer
```
- **intlayer**
Główny pakiet zapewniający narzędzia internacjonalizacji do zarządzania konfiguracją, tłumaczeń, [deklaracji treści](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/dictionary/content_file.md), transpilacji oraz [poleceń CLI](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/cli/index.md).
- **solid-intlayer**
Pakiet integrujący Intlayer z aplikacją Solid. Zapewnia dostawców kontekstu i haki (hooki) dla internacjonalizacji Solid.
- **vite-intlayer**
Zawiera wtyczkę Vite do integracji Intlayer z [bundlerem Vite](https://vite.dev/guide/why.html#why-bundle-for-production), a także obsługę routingu lokalizacji, która wykrywa preferowaną lokalizację użytkownika, zarządza plikami cookie i obsługuje przekierowania URL.
> `vite-intlayer` jest tutaj kwestią po stronie serwera, a nie tylko etapu budowania: dostarcza procedurę obsługi żądań uruchamianą przez serwer Nitro w SolidStart. Przechowywanie go w `dependencies` jest bezpiecznym domyślnym rozwiązaniem — możesz przenieść go do `devDependencies` tylko wtedy, gdy wdrażasz zbudowany katalog `.output`, w którym Nitro osadza tę procedurę.
Utwórz plik konfiguracyjny, aby skonfigurować języki Twojej aplikacji:
```typescript fileName="intlayer.config.ts" codeFormat={["typescript", "esm", "commonjs"]}
import { type IntlayerConfig, Locales } from "intlayer";
const config: IntlayerConfig = {
internationalization: {
locales: [
Locales.ENGLISH,
Locales.FRENCH,
Locales.SPANISH,
// Twoje inne lokalizacje
],
defaultLocale: Locales.ENGLISH,
},
routing: {
mode: "prefix-no-default",
},
};
export default config;
```
W przypadku `prefix-no-default` domyślna lokalizacja jest serwowana z adresów URL bez przedrostka:
```plaintext
/ /about → Angielski (domyślna lokalizacja)
/fr /fr/about → Francuski
/es /es/about → Hiszpański
```
> Za pomocą tego pliku konfiguracyjnego możesz skonfigurować zlokalizowane adresy URL, przekierowania middleware, nazwy plików cookie, 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](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/configuration.md).
Dodaj wtyczkę Intlayer do swojej konfiguracji:
```typescript fileName="vite.config.ts" codeFormat={["typescript", "esm", "commonjs"]}
import { solidStart } from "@solidjs/start/config";
import { nitro } from "nitro/vite";
import { defineConfig } from "vite";
import { intlayer } from "vite-intlayer";
export default defineConfig({
plugins: [solidStart(), nitro(), intlayer()],
});
```
> Wtyczka Vite `intlayer()` buduje pliki deklaracji treści, obserwuje je w trybie deweloperskim i definiuje zmienne środowiskowe Intlayer wewnątrz aplikacji. Zapewnia również aliasy optymalizujące wydajność.
### Routing lokalizacji jest dostarczany z wtyczką
SolidStart działa na [Nitro](https://nitro.build), a `intlayer()` rejestruje swoją procedurę obsługi routingu lokalizacji bezpośrednio w potoku serwera Nitro (poprzez opcję `routing.enableProxy`, domyślnie `true`). Nic więcej nie trzeba podłączać: na zbudowanym serwerze każde żądanie jest sprawdzane, zanim dotrze do routera, oraz:
- lokalizacja jest odczytywana z przedrostka URL, następnie z pliku cookie `INTLAYER_LOCALE`, a potem z nagłówka `Accept-Language`;
- adres URL bez przedrostka jest przekierowywany do swojego zlokalizowanego odpowiednika, gdy rozstrzygnięta lokalizacja nie jest domyślną (`/` → `/fr`);
- nadmiarowo zlokalizowany adres URL jest przekierowywany z powrotem do swojej kanonicznej formy (`/en/about` → `/about`);
- plik cookie lokalizacji jest zapisywany z powrotem w odpowiedzi.
Utwórz i zarządzaj deklaracjami treści, aby przechowywać tłumaczenia:
```tsx fileName="src/contents/home.content.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
import { type Dictionary, t } from "intlayer";
const homeContent = {
key: "home-page",
content: {
title: t({
en: "Hello world!",
fr: "Bonjour le monde !",
es: "¡Hola mundo!",
}),
metaTitle: "SolidStart + Intlayer",
metaDescription: t({
en: "A SolidStart application internationalized with Intlayer.",
fr: "Une application SolidStart internationalisée avec Intlayer.",
es: "Una aplicación SolidStart internacionalizada con Intlayer.",
}),
documentation: t({
en: "Visit start.solidjs.com to learn how to build SolidStart apps.",
fr: "Visitez start.solidjs.com pour apprendre à créer des applications SolidStart.",
es: "Visita start.solidjs.com para aprender a crear aplicaciones SolidStart.",
}),
},
} satisfies Dictionary;
export default homeContent;
```
```json fileName="src/contents/home.content.json" contentDeclarationFormat="json"
{
"$schema": "https://intlayer.org/schema.json",
"key": "home-page",
"content": {
"title": {
"nodeType": "translation",
"translation": {
"en": "Hello world!",
"fr": "Bonjour le monde !",
"es": "¡Hola mundo!"
}
},
"metaTitle": "SolidStart + Intlayer",
"metaDescription": {
"nodeType": "translation",
"translation": {
"en": "A SolidStart application internationalized with Intlayer.",
"fr": "Une application SolidStart internationalisée avec Intlayer.",
"es": "Una aplicación SolidStart internacionalizada con Intlayer."
}
},
"documentation": {
"nodeType": "translation",
"translation": {
"en": "Visit start.solidjs.com to learn how to build SolidStart apps.",
"fr": "Visitez start.solidjs.com pour apprendre à créer des applications SolidStart.",
"es": "Visita start.solidjs.com para aprender a crear aplicaciones SolidStart."
}
}
}
}
```
> ⚠️ **Haczyk specyficzny dla SolidStart**: każdy plik `.ts` / `.tsx` w `src/routes` staje się ścieżką (route), a plik `.content.ts` posiada domyślny eksport, więc zostałby wyłapany jako strona. Przechowuj deklaracje treści swoich **stron** poza katalogiem routes (`src/contents/` działa dobrze). Treść **komponentów** może pozostać w tej samej lokalizacji, ponieważ `src/components` nie jest skanowany przez router oparty na systemie plików.
> Deklaracje treści można definiować w dowolnym miejscu aplikacji, o ile są zawarte w katalogu `contentDir` (domyślnie `./src`) i pasują do rozszerzenia pliku deklaracji treści (domyślnie `.content.{json,ts,tsx,js,jsx,mjs,cjs,md,mdx,yaml,yml}`).
>
> Aby uzyskać więcej szczegółów, zapoznaj się z [dokumentacją deklaracji treści](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/dictionary/content_file.md).
Celem tego kroku jest nadanie każdemu językowi własnego adresu URL, co jest indeksowane przez wyszukiwarki.
Przenieś swoje strony pod **opcjonalny dynamiczny segment**. W routerze opartym na systemie plików SolidStart `[[locale]]` kompiluje się do wzorca ścieżki `:locale?`:
```plaintext
src/routes/
[[locale]].tsx ← układ (layout), który weryfikuje segment
[[locale]]/
index.tsx → / oraz /fr oraz /es
about.tsx → /about oraz /fr/about oraz /es/about
[...404].tsx → zbiorczy plik dla wszystkiego innego
```
Jedynym zadaniem pliku układu (layout) jest ograniczenie segmentu do skonfigurowanej lokalizacji:
```tsx fileName="src/routes/[[locale]].tsx" codeFormat="typescript"
import type { RouteSectionProps } from "@solidjs/router";
import { locales } from "intlayer";
export const route = {
matchFilters: {
locale: locales,
},
};
export default function LocaleLayout(props: RouteSectionProps) {
return <>{props.children}>;
}
```
`@solidjs/router` rozwija `:locale?` do dwóch wzorców — jednego z segmentem i jednego bez — i próbuje ich według malejącej szczegółowości. `matchFilters` to różnica między działającą konfiguracją a mylącą:
| Adres URL | Bez `matchFilters` | Z `matchFilters` |
| ----------- | ----------------------------------------------- | ----------------------------------------------------- |
| `/fr/about` | Strona o nas po francusku | Strona o nas po francusku |
| `/about` | Strona o nas (statyczny segment wygrywa) | Strona o nas |
| `/unknown` | **Strona główna**, po cichu, z `locale=unknown` | Brak dopasowania → przechodzi do zbiorczej strony 404 |
> Preferuj `[locale]` (wymagane) zamiast `[[locale]]`, jeśli używasz trybu routingu `'prefix-all'`, i całkowicie pomiń segment dla `'no-prefix'` lub `'search-params'`.
Adres URL jest jedynym źródłem prawdy dla lokalizacji: middleware przekierował już żądanie do zlokalizowanej ścieżki, więc odczytanie ścieżki w układzie głównym (root layout) utrzymuje zgodność renderowania po stronie serwera i hydracji po stronie klienta, oraz powoduje, że każda nawigacja po stronie klienta aktualizuje lokalizację automatycznie.
```tsx fileName="src/app.tsx" codeFormat="typescript"
import { MetaProvider } from "@solidjs/meta";
import { Router, useLocation } from "@solidjs/router";
import { FileRoutes } from "@solidjs/start/router";
import { defaultLocale, getHTMLTextDir, getLocaleFromPath } from "intlayer";
import { IntlayerProvider } from "solid-intlayer";
import { createEffect, type ParentProps, Suspense } from "solid-js";
import { isServer } from "solid-js/web";
import { Nav } from "~/components/Nav";
import "./app.css";
const RootLayout = (props: ParentProps) => {
const location = useLocation();
const locale = () => getLocaleFromPath(location.pathname) ?? defaultLocale;
// Serwer renderuje w entry-server.tsx; nawigacja po stronie klienta
// między lokalizacjami musi samodzielnie aktualizować atrybuty.
createEffect(() => {
if (isServer) return;
document.documentElement.lang = locale();
document.documentElement.dir = getHTMLTextDir(locale());
});
return (
{props.children}
);
};
export default function App() {
return (
);
}
```
> `IntlayerProvider` reaguje na swój rekwizyt (prop) `locale`, więc przekazanie wywołania akcesora `locale()` wewnątrz JSX wystarczy — Solid kompiluje je do gettera, a całe drzewo renderuje się ponownie w nowym języku, gdy zmienia się URL.
Element `` jest renderowany przez `entry-server.tsx`, poza `Router`. Zamiast tego odczytaj lokalizację z adresu URL żądania:
```tsx fileName="src/entry-server.tsx" codeFormat="typescript"
// @refresh reload
import { createHandler, StartServer } from "@solidjs/start/server";
import { defaultLocale, getHTMLTextDir, getLocaleFromPath } from "intlayer";
import { getRequestEvent } from "solid-js/web";
export default createHandler(() => (
{
const url = getRequestEvent()?.request.url ?? "/";
const locale = getLocaleFromPath(url) ?? defaultLocale;
return (
{assets}
{children}
{scripts}
);
}}
/>
));
```
Roboty indeksujące otrzymują teraz właściwy język od pierwszego bajtu:
```html
```
Uzyskaj dostęp do słowników treści w całej aplikacji:
```tsx fileName="src/routes/[[locale]]/index.tsx" codeFormat="typescript"
import { Meta, Title } from "@solidjs/meta";
import { useIntlayer } from "solid-intlayer";
import Counter from "~/components/Counter";
export default function Home() {
const content = useIntlayer("home-page");
return (
{content.metaTitle.value}
{content.title}
{content.documentation}
);
}
```
> W Solid `useIntlayer` zwraca reaktywną treść (np. `content`). Możesz uzyskać dostęp do jej właściwości bezpośrednio.
> Jeśli chcesz użyć treści w atrybucie typu `string`, takim jak `alt`, `title`, `href`, `aria-label` itp., możesz użyć wartości funkcji, na przykład:
>
> ```html
>
>
>
> ```
> Aby dowiedzieć się więcej o haku `useIntlayer`, zapoznaj się z [dokumentacją](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/packages/solid-intlayer/useIntlayer.md).
Węzły treści nie ograniczają się do zwykłych tłumaczeń. Na przykład licznik z liczbą mnogą:
```typescript fileName="src/components/Counter.content.ts" codeFormat="typescript"
import { type Dictionary, plural, t } from "intlayer";
const counterContent = {
key: "counter",
content: {
clicks: plural({
one: t({
en: "{{count}} click",
fr: "{{count}} clic",
es: "{{count}} clic",
}),
other: t({
en: "{{count}} clicks",
fr: "{{count}} clics",
es: "{{count}} clics",
}),
}),
},
} satisfies Dictionary;
export default counterContent;
```
```tsx fileName="src/components/Counter.tsx" codeFormat="typescript"
import { useIntlayer } from "solid-intlayer";
import { createSignal } from "solid-js";
export default function Counter() {
const [count, setCount] = createSignal(0);
const content = useIntlayer("counter");
return (
);
}
```
`plural()` wybiera kategorię za pomocą `Intl.PluralRules` dla aktywnej lokalizacji, dzięki czemu języki z więcej niż dwoma formami liczby mnogiej działają bez dodatkowego kodu.
Utwórz niestandardowy komponent `Link`, który automatycznie dodaje przedrostek aktualnego języka do wewnętrznych adresów URL:
```tsx fileName="src/components/LocalizedLink.tsx" codeFormat="typescript"
import { A, type AnchorProps } from "@solidjs/router";
import { getLocalizedUrl } from "intlayer";
import { useLocale } from "solid-intlayer";
import type { ParentComponent } from "solid-js";
export const LocalizedLink: ParentComponent = (props) => {
const { locale } = useLocale();
const isExternal = () => /^[a-z][a-z0-9+.-]*:/i.test(props.href);
const localizedHref = () =>
isExternal() ? props.href : getLocalizedUrl(props.href, locale());
return ;
};
```
```tsx fileName="src/components/Nav.tsx" codeFormat="typescript"
import { useIntlayer } from "solid-intlayer";
import type { Component } from "solid-js";
import { LocaleSwitcher } from "./LocaleSwitcher";
import { LocalizedLink } from "./LocalizedLink";
export const Nav: Component = () => {
const content = useIntlayer("nav");
return (
);
};
```
Napisanie `href="/about"` raz powoduje teraz wygenerowanie `/about`, `/fr/about` lub `/es/about` w zależności od aktywnej lokalizacji — bez ręcznego dodawania przedrostków w jakimkolwiek miejscu na stronach.
Renderuj przełącznik jako **prawdziwe odnośniki (anchors)**, a nie `
Anotacje `hreflang` informują wyszukiwarki, że `/about`, `/fr/about` i `/es/about` to ta sama strona w różnych językach. `getMultilingualUrls` wywodzi je z kanonicznej ścieżki (bez lokalizacji), zgodnie z Twoim trybem routingu, więc nic nie jest zakodowane na sztywno:
```tsx fileName="src/components/AlternateLinks.tsx" codeFormat="typescript"
import {
defaultLocale,
getMultilingualUrls,
getPathWithoutLocale,
} from "intlayer";
import { type Component, For } from "solid-js";
export type AlternateLinksProps = {
/** Bezawzględny URL renderowanej strony. */
url: string;
};
export const AlternateLinks: Component = (props) => {
const multilingualUrls = () => {
const { origin, pathname } = new URL(props.url);
return Object.entries(
getMultilingualUrls(`${origin}${getPathWithoutLocale(pathname)}`)
);
};
const canonicalUrl = () =>
new URL(props.url).origin + new URL(props.url).pathname;
return (
<>
{([locale, localizedUrl]) => (
)}
locale === defaultLocale)?.[1]
}
hreflang="x-default"
rel="alternate"
/>
>
);
};
```
Wyrenderuj to w nagłówku dokumentu (head), gdzie dostępny jest adres URL żądania:
```tsx fileName="src/entry-server.tsx" codeFormat="typescript"
import { AlternateLinks } from "~/components/AlternateLinks";
// … wewnątrz , obok innych tagów meta:
;
```
`GET /fr/about` serwuje wtedy:
```html
```
> **Uwaga dotycząca `@solidjs/meta`**: w momencie pisania tego tekstu, `` i `` z `@solidjs/meta` są stosowane po stronie klienta po hydracji, ale **nie** są emitowane do renderowanego po stronie serwera `` w SolidStart v2. Dopóki nie zostanie to naprawione, renderuj tagi, które roboty indeksujące muszą widzieć bez JavaScript — `canonical`, `hreflang` oraz, jeśli to konieczne, `title` / `description` — bezpośrednio w `entry-server.tsx`, jak pokazano powyżej.
Trasa wieloznaczna (splat route) w korzeniu `src/routes` wyłapuje każdą ścieżkę, do której segment lokalizacji nie pasował — w tym nieprawidłowe przedrostki lokalizacji odrzucone przez `matchFilters`. Ponieważ lokalizacja nadal pochodzi z adresu URL poprzez układ główny, strona 404 jest wyświetlana w języku odwiedzającego:
```tsx fileName="src/routes/[...404].tsx" codeFormat="typescript"
import { Title } from "@solidjs/meta";
import { HttpStatusCode } from "@solidjs/start";
import { useIntlayer } from "solid-intlayer";
import { LocalizedLink } from "~/components/LocalizedLink";
export default function NotFound() {
const content = useIntlayer("not-found-page");
return (
{content.metaTitle.value}
{content.title}
{content.backHome}
);
}
```
| Żądanie | Wynik |
| ----------------- | ------------------------------------------------ |
| `/xx` | `404` — `xx` nie jest skonfigurowaną lokalizacją |
| `/nonexistent` | `404` w domyślnej lokalizacji |
| `/fr/nonexistent` | `404` po francusku (`Page introuvable`) |
Generator mapy strony Intlayer rozwija każdą ścieżkę do jednego wpisu na lokalizację i łączy alternatywy `xhtml:link` między nimi, dzięki czemu trasa musi jedynie wymienić kanoniczne ścieżki bez lokalizacji.
> W przeciwieństwie do podstawowych generatorów, które emitują tylko płaskie adresy URL, Intlayer łączy dwukierunkowe linki między wszystkimi zlokalizowanymi wariantami każdej strony, co pomaga wyszukiwarkom powiązać zlokalizowane adresy URL i dostarczać właściwy właściwym odbiorcom.
SolidStart zmienia plik eksportujący metodę HTTP w trasę API i usuwa rozszerzenie `.ts` ze ścieżki — więc `src/routes/sitemap.xml.ts` jest serwowane pod adresem `/sitemap.xml`:
```typescript fileName="src/routes/sitemap.xml.ts" codeFormat={["typescript", "esm", "commonjs"]}
import type { APIEvent } from "@solidjs/start/server";
import { generateSitemap } from "intlayer";
const SITE_URL = process.env.SITE_URL ?? "http://localhost:3000";
export const GET = (_event: APIEvent) => {
const sitemap = generateSitemap(
[
{ path: "/", changefreq: "daily", priority: 1.0 },
{ path: "/about", changefreq: "monthly", priority: 0.8 },
],
{ siteUrl: SITE_URL }
);
return new Response(sitemap, {
headers: { "Content-Type": "application/xml" },
});
};
```
```xml fileName="output of GET /sitemap.xml"
https://example.com/aboutmonthly0.8
```
> Trasy API nie obsługują parametrów opcjonalnych, więc trzymaj ten plik w korzeniu `src/routes`, poza segmentem `[[locale]]`. Mapa strony zawiera już każdą lokalizację.
Możesz zbudować `robots.txt` w ten sam sposób za pomocą `getMultilingualUrls`, tak aby wpisy `Disallow` obejmowały każdy zlokalizowany zapis wrażliwej ścieżki:
```typescript fileName="src/routes/robots.txt.ts" codeFormat={["typescript", "esm", "commonjs"]}
import { getMultilingualUrls } from "intlayer";
const SITE_URL = process.env.SITE_URL ?? "http://localhost:3000";
const disallowedPaths = ["/admin", "/private"].flatMap((path) =>
Object.values(getMultilingualUrls(path))
);
export const GET = () =>
new Response(
[
"User-agent: *",
"Allow: /",
...disallowedPaths.map((path) => `Disallow: ${path}`),
"",
`Sitemap: ${SITE_URL}/sitemap.xml`,
].join("\n"),
{ headers: { "Content-Type": "text/plain" } }
);
```
Możesz chcieć uzyskać dostęp do bieżącej lokalizacji z wnętrza funkcji serwerowej lub trasy API.
W konfiguracji opartej na przedrostkach, takiej jak ta, **adres URL jest rozstrzygający**: `getLocaleFromPath` odczytuje przedrostek z adresu URL żądania. `getLocale` jest alternatywą dla żądań, które nie przenoszą przedrostka lokalizacji — sprawdza plik cookie `INTLAYER_LOCALE`, następnie nagłówek `x-intlayer-locale`, a potem negocjuje `Accept-Language`.
```tsx fileName="src/routes/[[locale]]/index.tsx" codeFormat="typescript"
import { createAsync } from "@solidjs/router";
import { getCookie, getIntlayer, getLocale, getLocaleFromPath } from "intlayer";
import { getRequestEvent } from "solid-js/web";
const loadLocalizedData = async () => {
"use server";
const request = getRequestEvent()?.request;
const locale =
getLocaleFromPath(request?.url) ??
(await getLocale({
// Pobiera plik cookie z żądania (domyślnie: 'INTLAYER_LOCALE')
getCookie: (name) =>
getCookie(name, request?.headers.get("cookie") ?? ""),
// Pobiera nagłówek z żądania (domyślnie: 'x-intlayer-locale'),
// przechodząc w razie potrzeby do negocjacji Accept-Language
getHeader: (name) => request?.headers.get(name) ?? undefined,
}));
// Pobierz część treści poza komponentem za pomocą getIntlayer()
const content = getIntlayer("home-page", locale);
return { locale, title: String(content.title) };
};
export default function Page() {
const data = createAsync(() => loadLocalizedData());
return
{data()?.title}
;
}
```
> Nie polegaj tutaj wyłącznie na `getLocale`: plik cookie lokalizacji jest zapisywany dopiero wtedy, gdy odwiedzający aktywnie zmieni język, więc pierwsza wizyta na `/fr/...` rozstrzygnęłaby się do domyślnej lokalizacji.
Jeśli masz istniejącą bazę kodu, przekształcanie tysięcy plików może być czasochłonne.
Aby ułatwić ten proces, Intlayer proponuje [kompilator](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/compiler.md) / [ekstraktor](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/cli/extract.md) do przekształcania komponentów i ekstrakcji treści.
Aby go skonfigurować, możesz dodać sekcję `compiler` w swoim pliku `intlayer.config.ts`:
```typescript fileName="intlayer.config.ts" codeFormat={["typescript", "esm", "commonjs"]}
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 przekształceniu.
*
* - Jeśli `true`, kompilator nadpisze plik komponentu na dysku. Przekształcenie będzie więc trwałe, a kompilator pominie przekształcenie przy następnym procesie. W ten sposób kompilator może przekształcić aplikację, a następnie można go usunąć.
*
* - Jeśli `false`, kompilator wstrzyknie wywołanie funkcji `useIntlayer()` do kodu tylko w danych wyjściowych budowania i zachowa bazową bazę kodu nienaruszoną. Przekształcenie zostanie wykonane tylko w pamięci.
*/
saveComponents: false,
/**
* Przedrostek klucza słownika
*/
dictionaryKeyPrefix: "",
},
};
export default config;
```
Uruchom ekstraktor, aby przekształcić komponenty i wyodrębnić treść
```bash packageManager="npm"
npx intlayer extract
```
```bash packageManager="pnpm"
pnpm intlayer extract
```
```bash packageManager="yarn"
yarn intlayer extract
```
```bash packageManager="bun"
bun x intlayer extract
```
> Przenieś wygenerowane pliki treści swoich stron poza `src/routes` po wykonaniu tej czynności, z powodu wyjaśnionego w kroku 5.
> Od v9 `intlayerCompiler` jest dołączony do wtyczki `intlayer`. Nie musisz więc dodawać go ręcznie.
Zaktualizuj swój `vite.config.ts`, aby dołączyć wtyczkę `intlayerCompiler`:
```ts fileName="vite.config.ts"
import { solidStart } from "@solidjs/start/config";
import { nitro } from "nitro/vite";
import { defineConfig } from "vite";
import { intlayer, intlayerCompiler } from "vite-intlayer";
export default defineConfig({
plugins: [
solidStart({ middleware: "src/middleware.ts" }),
nitro(),
intlayer(),
intlayerCompiler(), // Dodaje wtyczkę kompilatora
],
});
```
```bash packageManager="npm"
npm run build # Lub npm run dev
```
```bash packageManager="pnpm"
pnpm run build # Lub pnpm run dev
```
```bash packageManager="yarn"
yarn build # Lub yarn dev
```
```bash packageManager="bun"
bun run build # Lub bun run dev
```
Intlayer używa rozszerzania modułów (module augmentation), aby czerpać korzyści z TypeScript i uczynić bazę kodu silniejszą.
Upewnij się, że Twoja konfiguracja TypeScript zawiera automatycznie wygenerowane typy:
```json5 fileName="tsconfig.json"
{
compilerOptions: {
// ... Twoje istniejące konfiguracje
},
include: [
"src",
"*.ts",
".intlayer/**/*.ts", // Dołącz automatycznie wygenerowane typy
],
}
```
Klucze słownika i ścieżki treści są teraz sprawdzane w czasie kompilacji:
```tsx
useIntlayer("home-page"); // ✅
useIntlayer("hom-page"); // ❌ Argument of type '"hom-page"' is not assignable to parameter of type 'keyof __DictionaryRegistry'
```
---
## Weryfikacja Twojej konfiguracji
Zbuduj i uruchom serwer, a następnie sprawdź, czy te żądania zachowują się zgodnie z oczekiwaniami:
```bash
npm run build
node .output/server/index.mjs
```
| Żądanie | Oczekiwana odpowiedź |
| ------------------------------------- | -------------------------------------------- |
| `GET /` | `200` — Angielski |
| `GET /` z `Accept-Language: fr` | `302` → `/fr` |
| `GET /` z cookie `INTLAYER_LOCALE=es` | `302` → `/es` |
| `GET /fr` | `200` — Francuski, `` |
| `GET /fr/about` | `200` — Francuska strona o nas |
| `GET /en/about` | `302` → `/about` (kanoniczne przekierowanie) |
| `GET /xx` | `404` |
| `GET /fr/nonexistent` | `404` po francusku |
| `GET /sitemap.xml` | `200` — wielojęzyczna mapa strony XML |
Wiersze renderujące stronę zachowują się identycznie w trybie `vite dev`. Trzy wiersze z przekierowaniami mają zastosowanie tylko do zbudowanego serwera, chyba że samodzielnie zarejestrujesz procedurę obsługi jako middleware — zobacz krok 3.
> Uruchamiaj serwer deweloperski w środowisku Node (`vite dev`), a nie w Bun (`bun --bun vite dev`): SSR w SolidStart obecnie nie działa w środowisku uruchomieniowym Bun z błędem `Expected a Response object, but received 'NodeResponse'`. Nie jest to związane z Intlayer — powtarza się to na zwykłym szablonie — i dotyczy tylko serwera deweloperskiego, a nie `vite build`.
---
## Konfiguracja Git
Zaleca się ignorowanie plików generowanych przez Intlayer. Pozwala to uniknąć zatwierdzania ich w repozytorium Git.
Aby to zrobić, możesz dodać następujące instrukcje do pliku `.gitignore`:
```plaintext fileName=".gitignore"
# Ignoruj pliki generowane przez Intlayer
.intlayer
```
---
## Rozszerzenie VS Code
Aby poprawić doświadczenie programistyczne z Intlayer, możesz zainstalować oficjalne **Rozszerzenie Intlayer dla VS Code**.
[Zainstaluj z VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=intlayer.intlayer-vs-code-extension)
To rozszerzenie zapewnia:
- **Autouzupełnianie** dla kluczy tłumaczeń.
- **Wykrywanie błędów w czasie rzeczywistym** dla brakujących tłumaczeń.
- **Podgląd wstawny (inline)** przetłumaczonej treści.
- **Szybkie akcje** do łatwego tworzenia i aktualizowania tłumaczeń.
---
## Przejdź dalej
Aby pójść dalej, możesz zaimplementować [edytor wizualny](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_visual_editor.md) lub uzewnętrznić swoją treść za pomocą [CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_CMS.md).
---
## Odnośniki do dokumentacji
- [Dokumentacja Intlayer](https://intlayer.org)
- [Dokumentacja SolidStart](https://start.solidjs.com)
- [Haczyk useIntlayer](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/packages/solid-intlayer/useIntlayer.md)
- [Haczyk useLocale](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/packages/solid-intlayer/useLocale.md)
- [Deklaracja treści](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/dictionary/content_file.md)
- [Konfiguracja](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/configuration.md)