Zadaj pytanie i otrzymaj streszczenie dokumentu, odwołując się do tej strony i wybranego dostawcy AI
Dzięki integracji serwera Intlayer MCP z ulubionym asystentem AI możesz uzyskać dostęp do całej dokumentacji bezpośrednio z ChatGPT, DeepSeek, Cursor, VSCode itp.
Zobacz dokumentację serwera MCPHistoria wersji
- Wersja początkowav7.0.01.11.2025
Treść tej strony została przetłumaczona przy użyciu sztucznej inteligencji.
Zobacz ostatnią wersję oryginalnej treści w języku angielskimJeśli masz pomysł na ulepszenie tej dokumentacji, zachęcamy do przesłania pull requesta na GitHubie.
Link do dokumentacji na GitHubieKopiuj dokument Markdown do schowka
Jak internacjonalizować aplikację Next.js za pomocą next-intl w 2025 roku
Spis treści
Czym jest next-intl?
next-intl to popularna biblioteka do internacjonalizacji (i18n) zaprojektowana specjalnie dla Next.js App Router. Zapewnia płynny sposób tworzenia wielojęzycznych aplikacji Next.js z doskonałym wsparciem TypeScript oraz wbudowanymi optymalizacjami.
Jeśli wolisz, możesz również odwołać się do przewodnika next-i18next lub bezpośrednio korzystać z Intlayer.
Zobacz porównanie w next-i18next vs next-intl vs Intlayer.
Praktyki, których powinieneś przestrzegać
Zanim przejdziemy do implementacji, oto kilka praktyk, których powinieneś przestrzegać:
- Ustaw atrybuty HTML lang i dir
W swoim układzie oblicz dir za pomocą getLocaleDirection(locale) i ustaw <html lang={locale} dir={dir}> dla odpowiedniej dostępności i SEO. - Podziel wiadomości według przestrzeni nazw
Organizuj pliki JSON według lokalizacji i przestrzeni nazw (np. common.json, about.json), aby ładować tylko to, co potrzebujesz. - Minimalizuj obciążenie klienta
Na stronach wysyłaj do NextIntlClientProvider tylko wymagane przestrzenie nazw (np. pick(messages, ['common', 'about'])). - Preferuj strony statyczne
Używaj stron statycznych tak często, jak to możliwe, dla lepszej wydajności i SEO. - I18n w komponentach serwerowych
Komponenty serwerowe, takie jak strony lub wszystkie komponenty nieoznaczone jako client, są statyczne i mogą być wstępnie renderowane podczas budowania. Dlatego będziemy musieli przekazać do nich funkcje tłumaczeń jako propsy. - Skonfiguruj typy TypeScript
Dla swoich lokalizacji, aby zapewnić bezpieczeństwo typów w całej aplikacji. - Proxy do przekierowań
Użyj proxy do obsługi wykrywania lokalizacji i routingu oraz przekierowania użytkownika na odpowiedni URL z prefiksem lokalizacji. - Internacjonalizacja metadanych, mapy witryny, robots.txt
Internacjonalizuj swoje metadane, mapę witryny, robots.txt za pomocą funkcji generateMetadata dostarczonej przez Next.js, aby zapewnić lepsze odkrywanie przez wyszukiwarki we wszystkich lokalizacjach. - Lokalizuj linki
Lokalizuj linki za pomocą komponentu Link, aby przekierować użytkownika na odpowiedni URL z prefiksem lokalizacji. Jest to ważne, aby zapewnić odnajdywalność Twoich stron we wszystkich lokalizacjach. - Automatyzuj testy i tłumaczenia
Automatyzacja testów i tłumaczeń pomaga zaoszczędzić czas potrzebny na utrzymanie wielojęzycznej aplikacji.
Zobacz naszą dokumentację zawierającą wszystko, co musisz wiedzieć o internacjonalizacji i SEO: Internationalization (i18n) with next-intl.
Przewodnik krok po kroku, jak skonfigurować next-intl w aplikacji Next.js
Zobacz Szablon aplikacji na GitHub.
Oto struktura projektu, którą będziemy tworzyć:
.├── global.ts├── locales│ ├── en│ │ ├── common.json│ │ └── about.json│ ├── fr│ │ ├── common.json│ │ └── about.json│ └── es│ ├── common.json│ └── about.json└── src # Src jest opcjonalny ├── proxy.ts ├── app │ ├── i18n.ts │ └── [locale] │ ├── layout.tsx │ ├── (home) # / (Grupa tras, aby nie zaśmiecać wszystkich stron zasobami home) │ │ ├── layout.tsx │ │ └── page.tsx │ └── about # /about │ ├── layout.tsx │ └── page.tsx └── components ├── ClientComponent.tsx └── ServerComponent.tsxKrok 1: Instalacja zależności
Zainstaluj niezbędne pakiety za pomocą npm:
npm install next-intl- next-intl: Podstawowa biblioteka do internacjonalizacji dla Next.js App Router, która dostarcza hooki, funkcje serwerowe oraz klienta do zarządzania tłumaczeniami.
Krok 2: Konfiguracja projektu
Utwórz plik konfiguracyjny, który definiuje obsługiwane lokalizacje i konfiguruje ustawienia żądań next-intl. Ten plik służy jako pojedyncze źródło prawdy dla Twojej konfiguracji i18n oraz zapewnia bezpieczeństwo typów w całej aplikacji.
Centralizacja konfiguracji lokalizacji zapobiega niespójnościom i ułatwia dodawanie lub usuwanie lokalizacji w przyszłości. Funkcja getRequestConfig jest wywoływana przy każdym żądaniu i ładuje tylko tłumaczenia potrzebne dla każdej strony, umożliwiając dzielenie kodu i zmniejszając rozmiar pakietu.
Skopiuj kod do schowka
import { notFound } from "next/navigation";import createMiddleware from "next-intl/middleware";import { createNavigation } from "next-intl/navigation";// Definiuj obsługiwane lokalizacje z bezpieczeństwem typówexport const locales = ["en", "fr", "es"] as const;export type Locale = (typeof locales)[number];export const defaultLocale: Locale = "en";export function isRTL(locale: Locale | (string & {})) { // Sprawdza, czy język jest zapisywany od prawej do lewej return /^(ar|fa|he|iw|ur|ps|sd|ug|yi|ckb|ku)(-|$)/i.test(locale);}// Dynamiczne ładowanie wiadomości dla każdej lokalizacji, aby umożliwić dzielenie kodu// Promise.all ładuje przestrzenie nazw równolegle dla lepszej wydajnościasync function loadMessages(locale: Locale) { // Ładuj tylko przestrzenie nazw potrzebne dla twojego layoutu/stron const [common, home, about] = await Promise.all([ import(`../locales/${locale}/common.json`).then((m) => m.default), import(`../locales/${locale}/home.json`).then((m) => m.default), import(`../locales/${locale}/about.json`).then((m) => m.default), // ... Przyszłe pliki JSON powinny być dodane tutaj ]); return { common, home, about } as const;}// Pomocnik do generowania zlokalizowanych URL-i (np. /about vs /fr/about)export function localizedPath(locale: string, path: string) { return locale === defaultLocale ? path : `/${locale}${path}`;}// getRequestConfig uruchamia się przy każdym żądaniu i dostarcza wiadomości do komponentów serwera// To tutaj next-intl integruje się z renderowaniem po stronie serwera Next.jsexport default async function getRequestConfig({ requestLocale,}: { requestLocale: Promise<string | undefined>;}) { const requested: Locale = ((await requestLocale) as Locale) ?? defaultLocale; if (!locales.includes(requested)) notFound(); return { locale: requested, messages: await loadMessages(requested), };}export function getCookie(locale: Locale) { return [ `NEXT_LOCALE=${locale}`, "Path=/", `Max-Age=${60 * 60 * 24 * 365}`, // 1 rok "SameSite=Lax", ].join("; ");}const routingOptions = { locales, defaultLocale, localePrefix: "as-needed", // Zmienia trasę /en/... na /... // Opcjonalnie: zlokalizowane ścieżki // pathnames: { // '/': '/', // '/about': {en: '/about', fr: '/a-propos', es: '/acerca-de'}, // '/blog/[slug]': '/blog/[slug]' // } // localeDetection: true, // zapobiega przekierowaniom "/" -> "/en" na podstawie ciasteczek} as const;export const { Link, redirect, usePathname, useRouter, getPathname } = createNavigation(routingOptions);export const proxy = createMiddleware(routingOptions);Krok 3: Definiowanie dynamicznych tras lokalizacji
Skonfiguruj dynamiczne routowanie dla lokalizacji, tworząc katalog [locale] w folderze aplikacji. Pozwala to Next.js obsługiwać routowanie oparte na lokalizacji, gdzie każda lokalizacja staje się segmentem URL (np. /en/about, /fr/about).
Użycie dynamicznych tras umożliwia Next.js generowanie statycznych stron dla wszystkich lokalizacji podczas budowania, co poprawia wydajność i SEO. Komponent layout ustawia atrybuty HTML lang i dir na podstawie lokalizacji, co jest kluczowe dla dostępności i zrozumienia przez wyszukiwarki.
Skopiuj kod do schowka
import type { ReactNode } from "react";import { locales } from "@/i18n";import { getLocaleDirection, setRequestLocale } from "next-intl/server";// Wstępne generowanie statycznych stron dla wszystkich lokalizacji podczas budowania (SSG)// To poprawia wydajność i SEOexport function generateStaticParams() { return locales.map((locale) => ({ locale }));}export default function LocaleLayout({ children, params,}: { children: ReactNode; params: Promise<{ locale: string }>;}) { // W Next.js App Router, params jest Promise (można użyć await) // Pozwala to na asynchroniczne rozwiązywanie dynamicznych segmentów ścieżki const { locale } = await params; // Kluczowe: setRequestLocale informuje next-intl, której lokalizacji użyć dla tego żądania // Bez tego getTranslations() nie będzie wiedzieć, której lokalizacji użyć w komponentach serwerowych setRequestLocale(locale); // Pobierz kierunek tekstu (LTR/RTL) dla poprawnego renderowania HTML const dir = getLocaleDirection(locale); return ( <html lang={locale} dir={dir}> <body>{children}</body> </html> );}Skopiuj kod do schowka
import { getTranslations, getMessages, getFormatter } from "next-intl/server";import { NextIntlClientProvider } from "next-intl";import pick from "lodash/pick";import ServerComponent from "@/components/ServerComponent";import ClientComponent from "@/components/ClientComponent";export default async function AboutPage({ params,}: { params: Promise<{ locale: string }>;}) { const { locale } = await params; // Wiadomości są ładowane po stronie serwera. Przekaż tylko to, co jest potrzebne do klienta. // Minimalizuje to rozmiar paczki JavaScript wysyłanej do przeglądarki const messages = await getMessages(); const clientMessages = pick(messages, ["common", "about"]); // Tłumaczenia/formatowanie ściśle po stronie serwera // Te funkcje działają po stronie serwera i mogą być przekazywane jako propsy do komponentów const tAbout = await getTranslations("about"); const tCounter = await getTranslations("about.counter"); const format = await getFormatter(); const initialFormattedCount = format.number(0); return ( // NextIntlClientProvider udostępnia tłumaczenia komponentom po stronie klienta // Przekazuj tylko te przestrzenie nazw, których faktycznie używają Twoje komponenty klienta <NextIntlClientProvider locale={locale} messages={clientMessages}> <main> <h1>{tAbout("title")}</h1> <ClientComponent /> <ServerComponent formattedCount={initialFormattedCount} label={tCounter("label")} increment={tCounter("increment")} /> </main> </NextIntlClientProvider> );}Krok 4: Utwórz pliki tłumaczeń
Utwórz pliki JSON dla każdego locale i namespace. Ta struktura pozwala na logiczne organizowanie tłumaczeń oraz ładowanie tylko tego, co jest potrzebne na każdej stronie.
Organizowanie tłumaczeń według namespace (np. common.json, about.json) umożliwia dzielenie kodu (code splitting) i zmniejsza rozmiar bundla. Ładujesz tylko tłumaczenia potrzebne dla danej strony, co poprawia wydajność.
Skopiuj kod do schowka
{ "welcome": "Welcome", "greeting": "Hello, world!"}Skopiuj kod do schowka
{ "welcome": "Bienvenue", "greeting": "Bonjour le monde!"}Skopiuj kod do schowka
{ "title": "About", "description": "About page description", "counter": { "label": "Counter", "increment": "Increment" }}Skopiuj kod do schowka
{ "title": "À propos", "description": "Description de la page À propos", "counter": { "label": "Compteur", "increment": "Incrémenter" }}Krok 5: Wykorzystaj tłumaczenia na swoich stronach
Utwórz komponent strony, który ładuje tłumaczenia po stronie serwera i przekazuje je zarówno do komponentów serwerowych, jak i klienckich. Zapewnia to, że tłumaczenia są załadowane przed renderowaniem i zapobiega migotaniu treści.
Ładowanie tłumaczeń po stronie serwera poprawia SEO i zapobiega FOUC (Flash of Untranslated Content - migotanie nieprzetłumaczonej treści). Używając pick do wysłania tylko wymaganych przestrzeni nazw do klienta, minimalizujemy rozmiar pakietu JavaScript wysyłanego do przeglądarki.
Skopiuj kod do schowka
import { getTranslations, getMessages, getFormatter } from "next-intl/server";import { NextIntlClientProvider } from "next-intl";import pick from "lodash/pick";import ServerComponent from "@/components/ServerComponent";import ClientComponent from "@/components/ClientComponent";export default async function AboutPage({ params,}: { params: Promise<{ locale: string }>;}) { const { locale } = await params; // Wiadomości są ładowane po stronie serwera. Przekaż tylko to, co jest potrzebne klientowi. // Minimalizuje to pakiet JavaScript wysyłany do przeglądarki const messages = await getMessages(); const clientMessages = pick(messages, ["common", "about"]); // Tłumaczenia i formatowanie ściśle po stronie serwera // Te operacje są wykonywane na serwerze i mogą być przekazane jako propsy do komponentów const tAbout = await getTranslations("about"); const tCounter = await getTranslations("about.counter"); const format = await getFormatter(); const initialFormattedCount = format.number(0); return ( // NextIntlClientProvider udostępnia tłumaczenia komponentom klienckim // Przekazuj tylko te przestrzenie nazw, których faktycznie używają Twoje komponenty klienckie <NextIntlClientProvider locale={locale} messages={clientMessages}> <main> <h1>{tAbout("title")}</h1> <ClientComponent /> <ServerComponent formattedCount={initialFormattedCount} label={tCounter("label")} increment={tCounter("increment")} /> </main> </NextIntlClientProvider> );}Krok 6: Używanie tłumaczeń w komponentach klienckich
Komponenty klienckie mogą używać hooków useTranslations i useFormatter, aby uzyskać dostęp do tłumaczeń i funkcji formatowania. Hooki te odczytują dane z kontekstu NextIntlClientProvider.
Komponenty klienckie potrzebują hooków React, aby uzyskać dostęp do tłumaczeń. Hooki useTranslations i useFormatter integrują się bezproblemowo z next-intl i zapewniają reaktywne aktualizacje po zmianie lokalizacji.
Nie zapomnij dodać wymaganych przestrzeni nazw do komunikatów klienta na stronie (uwzględnij tylko te przestrzenie nazw, których faktycznie potrzebują Twoje komponenty klienckie).
Skopiuj kod do schowka
"use client";import React, { useState } from "react";import { useTranslations, useFormatter } from "next-intl";const ClientComponent = () => { // Zakres bezpośrednio do zagnieżdżonego obiektu // useTranslations/useFormatter to hooki, które odczytują kontekst NextIntlClientProvider // Działają tylko wtedy, gdy komponent jest opakowany w NextIntlClientProvider const t = useTranslations("about.counter"); const format = useFormatter(); const [count, setCount] = useState(0); return ( <div> <p>{format.number(count)}</p> <button aria-label={t("label")} onClick={() => setCount((count) => count + 1)} > {t("increment")} </button> </div> );};Krok 7: Używanie tłumaczeń w komponentach serwerowych
Komponenty serwerowe nie mogą używać hooków React, dlatego otrzymują tłumaczenia i formatery przez propsy od komponentów nadrzędnych. Takie podejście utrzymuje komponenty serwerowe synchroniczne i pozwala na ich zagnieżdżanie wewnątrz komponentów klienckich.
Komponenty serwerowe, które mogą być zagnieżdżone pod granicami komponentów klienckich, muszą być synchroniczne. Przekazując przetłumaczone ciągi znaków i sformatowane wartości jako propsy, unikamy operacji asynchronicznych i zapewniamy prawidłowe renderowanie. Przetwarzaj tłumaczenia i formatowanie w komponencie nadrzędnym strony.
Skopiuj kod do schowka
// Komponenty serwerowe zagnieżdżone wewnątrz komponentów klienckich muszą być synchroniczne// React nie może serializować funkcji asynchronicznych przez granicę serwer/klient// Rozwiązanie: przetwarzaj tłumaczenia/formaty w komponencie nadrzędnym i przekazuj jako propsytype ServerComponentProps = { formattedCount: string; // sformatowana liczba label: string; // etykieta increment: string; // inkrementacja};const ServerComponent = ({ formattedCount, label, increment,}: ServerComponentProps) => { return ( <div> <p>{formattedCount}</p> <button aria-label={label}>{increment}</button> </div> );};Na swojej stronie/układzie użyj getTranslations i getFormatter z next-intl/server, aby wstępnie obliczyć tłumaczenia i formatowanie, a następnie przekaż je jako propsy do komponentów serwerowych.
(Opcjonalny) Krok 8: Zmień język swojej zawartości
Aby zmienić język swojej zawartości za pomocą next-intl, renderuj linki uwzględniające lokalizację, które wskazują na tę samą ścieżkę, zmieniając jednocześnie lokalizację. Provider automatycznie przepisuje URL-e, więc musisz tylko wskazać aktualną trasę.
Skopiuj kod do schowka
"use client";import Link from "next/link";import { usePathname } from "next/navigation";import { useLocale } from "next-intl";import { defaultLocale, getCookie, type Locale, locales } from "@/i18n";const getLocaleLabel = (locale: Locale): string => { try { const displayNames = new Intl.DisplayNames([locale], { type: "language" }); return displayNames.of(locale) ?? locale.toUpperCase(); } catch { return locale.toUpperCase(); }};const localeFlags: Record<Locale, string> = { en: "🇬🇧", fr: "🇫🇷", es: "🇪🇸",};export default function LocaleSwitcher() { const activeLocale = useLocale(); const pathname = usePathname(); // Usuń prefiks lokalizacji ze ścieżki, aby uzyskać ścieżkę bazową const getBasePath = (path: string) => { for (const locale of locales) { if (path.startsWith(`/${locale}`)) { return path.slice(locale.length + 1) || "/"; } } return path; }; const basePath = getBasePath(pathname); return ( <nav aria-label="Selektor języka"> <div> {(locales as readonly Locale[]).map((locale) => { const isActive = locale === activeLocale; // Buduje href w zależności od tego, czy jest to domyślny język const href = locale === defaultLocale ? basePath : `/${locale}${basePath}`; return ( <Link key={locale} href={href} aria-current={isActive ? "page" : undefined} onClick={() => { document.cookie = getCookie(locale); }} > <span>{localeFlags[locale]}</span> <span>{getLocaleLabel(locale)}</span> <span>{locale.toUpperCase()}</span> </Link> ); })} </div> </nav> );}(Opcjonalny) Krok 9: Użyj lokalizowanego komponentu Link
next-intl dostarcza podpakiet next-intl/navigation, który zawiera lokalizowany komponent linku automatycznie stosujący aktywną lokalizację. Już wyodrębniliśmy go dla Ciebie w pliku @/i18n, więc możesz go użyć w ten sposób:
Skopiuj kod do schowka
import { Link } from "@/i18n";return <Link href="/about">t("about.title")</Link>;(Opcjonalny) Krok 10: Uzyskaj dostęp do aktywnej lokalizacji w Server Actions
Server Actions mogą odczytać aktualną lokalizację używając next-intl/server. Jest to przydatne do wysyłania zlokalizowanych e-maili lub przechowywania preferencji językowych wraz z przesłanymi danymi.
Skopiuj kod do schowka
"use server";import { getLocale } from "next-intl/server";export async function getCurrentLocale() { return getLocale();}export async function handleContactForm(formData: FormData) { const locale = await getCurrentLocale(); // Użyj locale do wyboru szablonów, etykiet analitycznych itp. console.log(`Otrzymano formularz kontaktowy z locale ${locale}`);}getLocale odczytuje locale ustawione przez proxy next-intl, więc działa wszędzie na serwerze: w Route Handlers, Server Actions i funkcjach edge.
(Opcjonalny) Krok 11: Internacjonalizacja metadanych
Tłumaczenie treści jest ważne, ale głównym celem internacjonalizacji jest uczynienie Twojej strony bardziej widoczną dla świata. I18n to niesamowita dźwignia do poprawy widoczności Twojej strony poprzez odpowiednie SEO.
Prawidłowo zinternacjonalizowane metadane pomagają wyszukiwarkom zrozumieć, jakie języki są dostępne na Twoich stronach. Obejmuje to ustawianie meta tagów hreflang, tłumaczenie tytułów i opisów oraz zapewnienie prawidłowego ustawienia kanonicznych URL dla każdego języka.
Skopiuj kod do schowka
import type { Metadata } from "next";import { locales, defaultLocale, localizedPath } from "@/i18n";import { getTranslations } from "next-intl/server";// generateMetadata działa dla każdego języka, generując metadane przyjazne SEO// To pomaga wyszukiwarkom zrozumieć alternatywne wersje językoweexport async function generateMetadata({ params,}: { params: { locale: string };}): Promise<Metadata> { const { locale } = params; const t = await getTranslations({ locale, namespace: "about" }); const url = "/about"; const languages = Object.fromEntries( locales.map((locale) => [locale, localizedPath(locale, url)]) ); return { title: t("title"), description: t("description"), alternates: { canonical: localizedPath(locale, url), languages: { ...languages, "x-default": url }, }, };}// ... Reszta kodu strony(Opcjonalny) Krok 12: Internacjonalizacja Twojej mapy witryny
Wygeneruj mapę witryny, która zawiera wszystkie wersje językowe Twoich stron. Pomaga to wyszukiwarkom odnaleźć i zaindeksować wszystkie wersje językowe Twoich treści.
Prawidłowo zinternacjonalizowana mapa witryny zapewnia, że wyszukiwarki mogą znaleźć i zaindeksować wszystkie wersje językowe Twoich stron. Poprawia to widoczność w międzynarodowych wynikach wyszukiwania.
Skopiuj kod do schowka
import type { MetadataRoute } from "next";import { defaultLocale, locales } from "@/i18n";const origin = "https://example.com";const formatterLocalizedPath = (locale: string, path: string) => locale === defaultLocale ? `${origin}${path}` : `${origin}/${locale}${path}`;/** * Pobierz mapę wszystkich lokalizacji i ich zlokalizowanych ścieżek * * Przykładowy wynik: * { * "en": "https://example.com", * "fr": "https://example.com/fr", * "es": "https://example.com/es", * "x-default": "https://example.com" * } */const getLocalizedMap = (path: string) => Object.fromEntries([ ...locales.map((locale) => [locale, formatterLocalizedPath(locale, path)]), ["x-default", formatterLocalizedPath(defaultLocale, path)], ]);// Generuj mapę witryny ze wszystkimi wariantami językowymi dla lepszego SEO// Pole alternates informuje wyszukiwarki o wersjach językowychexport default function sitemap(): MetadataRoute.Sitemap { return [ { url: formatterLocalizedPath(defaultLocale, "/"), lastModified: new Date(), changeFrequency: "monthly", priority: 1.0, alternates: { languages: getLocalizedMap("/") }, }, { url: formatterLocalizedPath(defaultLocale, "/about"), lastModified: new Date(), changeFrequency: "monthly", priority: 0.7, alternates: { languages: getLocalizedMap("/about") }, }, ];}(Opcjonalny) Krok 13: Internacjonalizacja pliku robots.txt
Utwórz plik robots.txt, który prawidłowo obsługuje wszystkie wersje językowe Twoich chronionych ścieżek. Zapewnia to, że wyszukiwarki nie będą indeksować stron admina ani panelu w żadnym języku.
Prawidłowa konfiguracja robots.txt dla wszystkich lokalizacji zapobiega indeksowaniu przez wyszukiwarki wrażliwych stron, gdy Twoje ścieżki różnią się dla każdej lokalizacji.
Skopiuj kod do schowka
import type { MetadataRoute } from "next";import { locales, defaultLocale } from "@/i18n";const origin = "https://example.com";// Generowanie ścieżek dla wszystkich lokalizacji (np. /admin, /fr/admin, /es/admin)const withAllLocales = (path: string) => [ path, ...locales .filter((locale) => locale !== defaultLocale) .map((locale) => "/" + locale + path),];export default function robots(): MetadataRoute.Robots { const disallow = [ ...withAllLocales("/dashboard"), ...withAllLocales("/admin"), ]; return { rules: { userAgent: "*", allow: ["/"], disallow }, host: origin, sitemap: origin + "/sitemap.xml", };}(Opcjonalny) Krok 14: Skonfiguruj Proxy dla trasowania lokalizacji
Utwórz proxy, które automatycznie wykryje preferowaną lokalizację użytkownika i przekieruje go na odpowiedni adres URL z prefiksem lokalizacji. next-intl dostarcza wygodną funkcję proxy, która obsługuje to automatycznie.
Proxy zapewnia, że użytkownicy są automatycznie przekierowywani do preferowanego języka podczas odwiedzania Twojej strony. Zapisuje również preferencje użytkownika na przyszłe wizyty, poprawiając doświadczenie użytkownika.
Skopiuj kod do schowka
import { proxy } from "@/i18n";// Middleware działa przed trasami, obsługując wykrywanie i trasowanie lokalizacji// localeDetection: true używa nagłówka Accept-Language do automatycznego wykrywania lokalizacjiexport default proxy;export const config = { // Pomija API, wewnętrzne elementy Next oraz zasoby statyczne // Regex: dopasowuje wszystkie trasy z wyjątkiem tych zaczynających się od api, _next lub zawierających kropkę (pliki) matcher: ["/((?!api|_next|.*\\..*).*)"],};(Opcjonalny) Krok 15: Skonfiguruj typy TypeScript dla lokalizacji
Konfiguracja TypeScript pomoże Ci uzyskać autouzupełnianie i bezpieczeństwo typów dla Twoich kluczy.
W tym celu możesz utworzyć plik global.ts w katalogu głównym projektu i dodać następujący kod:
Skopiuj kod do schowka
import type { locales } from "@/i18n";type Messages = { common: typeof import("./locales/en/common.json"); home: typeof import("./locales/en/home.json"); about: typeof import("./locales/en/about.json"); // ... Przyszłe pliki JSON również powinny być tutaj dodane};declare module "next-intl" { interface AppConfig { Locale: (typeof locales)[number]; Messages: Messages; }}Ten kod użyje Module Augmentation, aby dodać locales i messages do typu AppConfig w next-intl.
(Opcjonalny) Krok 15: Automatyzuj swoje tłumaczenia za pomocą Intlayer
Intlayer to bezpłatna i otwartoźródłowa biblioteka zaprojektowana, aby wspierać proces lokalizacji w Twojej aplikacji. Podczas gdy next-intl zajmuje się ładowaniem i zarządzaniem tłumaczeniami, Intlayer pomaga zautomatyzować przepływ pracy związany z tłumaczeniami.
Ręczne zarządzanie tłumaczeniami może być czasochłonne i podatne na błędy. Intlayer automatyzuje testowanie, generowanie i zarządzanie tłumaczeniami, oszczędzając Twój czas i zapewniając spójność w całej aplikacji.
Intlayer pozwala Ci na:
Deklarowanie treści tam, gdzie chcesz w swojej bazie kodu Intlayer pozwala deklarować treści tam, gdzie chcesz w swojej bazie kodu, używając plików .content.{ts|js|json}. Umożliwi to lepszą organizację treści, zapewniając lepszą czytelność i łatwiejszą konserwację kodu.
Testowanie brakujących tłumaczeń Intlayer dostarcza funkcje testowe, które można zintegrować z Twoim pipeline CI/CD lub testami jednostkowymi. Dowiedz się więcej o testowaniu tłumaczeń.
Automatyzuj swoje tłumaczenia, Intlayer oferuje CLI oraz rozszerzenie do VSCode do automatyzacji tłumaczeń. Może być zintegrowany z pipeline CI/CD. Dowiedz się więcej o automatyzacji tłumaczeń. Możesz używać własnego klucza API oraz wybranego dostawcy AI. Zapewnia również tłumaczenia uwzględniające kontekst, zobacz wypełnianie treści.
Połącz zewnętrzne treści Intlayer pozwala na połączenie Twoich treści z zewnętrznym systemem zarządzania treścią (CMS). Aby pobierać je w zoptymalizowany sposób i wstawiać do Twoich zasobów JSON. Dowiedz się więcej o pobieraniu zewnętrznych treści.
Edytor wizualny Intlayer oferuje darmowy edytor wizualny do edycji Twoich treści za pomocą edytora wizualnego. Dowiedz się więcej o wizualnej edycji Twoich tłumaczeń.
I więcej. Aby odkryć wszystkie funkcje oferowane przez Intlayer, prosimy zapoznać się z dokumentacją Zainteresowanie Intlayer.