

Next.js má dvě oficiální stránky s dokumentací k internacionalizaci (i18n), které popisují zcela odlišné systémy a mezi nimi neexistují žádné odkazy.
Jedna se zabývá směrovačem stránek. Druhá se zabývá směrovačem aplikací. Ani jedna z nich nevysvětluje, jak spolu tyto dva prvky souvisejí, jaké knihovny použít ani jak zacházet s atributem hreflang pro vícejazyčné SEO.
Propojíme oba směrovače. Probereme strategie směrování, výběr knihoven, nastavení middlewaru, překlady serverových komponent a vícejazyčné SEO.
Naším cílem je vytvořit užitečný zdroj informací pro vývojáře, kteří dostali za úkol přidat do aplikace Next.js podporu pro další jazyk a potřebují si udělat jasnou představu, než se rozhodnou pro konkrétní postup. Pojďme na to!
Internacionalizace má tři úrovně:
Next.js pomáhá pouze s směrováním.
Směrovač stránek disponuje integrovaným směrováním s podporou internacionalizace již od verze 10.0.0. Konfigurační blok se třemi poli v souboru next.config.js automaticky zajišťuje detekci národního prostředí, přidávání předpon k URL adresám a přesměrování.
App Router je jiný. Na jeho stránce s dokumentací k internacionalizaci (i18n) je popsán vzor, který si sestavíte sami pomocí middlewaru, a [jazyk] dynamický segment a knihovna.
Co se týče překladů a formátování, musíte si poradit sami, bez ohledu na to, jaký router používáte. Dokumentace k App Routeru uvádí seznam všech kompatibilních knihoven, ale neposkytuje žádné rady ohledně toho, kterou z nich zvolit. Ani jedna z těchto dokumentačních stránek se nezabývá značkami hreflang ani vícejazyčnými sitemapy.
Přístup pomocí Pages Routeru vyžaduje změnu konfigurace. Do souboru next.config.js přidejte blok i18n se třemi poli:
// next.config.js
module.exports = {
i18n: {
locales: ['en', 'fr', 'de'],
defaultLocale: 'en',
},
}To je všechno.
Next.js automaticky rozpozná národní prostředí z Accept-Language hlavička, respektuje DALŠÍ_JAZYK přepsání souboru cookie a zpřístupňuje aktuální národní prostředí prostřednictvím useRouter().locale. Nepotřebujete žádný middleware ani přeskupování adresářů.
App Router nemá žádnou odpovídající konfiguraci. Směrování si sestavíte sami ze tří částí:
@formatjs/intl-localematcher a vyjednavač analyzovat Accept-Language hlavičky. Oficiální dokumentace ponechává samotnou logiku detekce jako otazník: funkce getLocale(request) { ... }. To si vysvětlíme v další části.[jazyk] dynamický segment obklopuje celý váš app/ adresář. Každá trasa je díky struktuře složek přizpůsobena místnímu nastavení.vygenerovat statické parametry předem vykreslí každou jazykovou variantu již při kompilaci.Ze všech tří částí je to právě `generateStaticParams`, která nahrazuje to, co dříve automaticky zajišťoval Pages Router při kompilaci.
export function generateStaticParams() {
return [{ locale: 'en' }, { locale: 'fr' }, { locale: 'de' }]
}🚨 Vestavěná internacionalizace (i18n) routeru Pages nefunguje s výstup: 'export'. Pokud potřebujete zcela statický export, budete místo toho muset použít ruční směrování na základě složek. Toto omezení se týká pouze vestavěné konfigurace. Oba směrovače podporují statické exporty při ručním nastavení.
Než si vyberete knihovnu, rozhodněte se pro strategii směrování. Ovlivňuje to SEO, nastavení DNS a také to, kolik middlewaru budete muset napsat:
další-mezinárodní považuje to za vynikající volbu.U veřejných webů, kde je SEO klíčové, je směrování podle podadresy správným výchozím nastavením. Směrování podle domény se vyplatí jen v případě, že jsou výslovně vyžadovány silné signály pro geografické cílení.
Pokud nechcete strukturu URL spravovat ručně, reverzní proxyWeglot automaticky zajistí přesměrování do podadresářů a subdomén, včetně vložení atributu hreflang a překladu URL adres.
Jak jsme již zmínili, oficiální dokumentace uvádí seznam knihoven, aniž by některou z nich doporučovala. Zde je srovnání hlavních možností:
next-intl je de facto standardem pro App Router. Podpora RSC je zabudována, směrování je integrováno a automatické doplňování v TypeScriptu funguje bez další konfigurace.
react-i18next je vhodnější volbou, pokud používáte Pages Router nebo již i18next využíváte jinde ve vašem stacku. Podpora App Routeru sice funguje, ale vyžaduje více ručního nastavování.
Lingui je vhodný pro týmy, které již využívají pracovní postupy s .po soubory. Překlady se extrahují již při kompilaci, takže se nikdy neodešlou nepoužité zprávy.
💡 Paraglide JS sice nepatří mezi nejvýznamnější hráče na trhu, ale stojí za zmínku jako alternativa založená na kompilátoru, která generuje menší výstupní balíčky. Pokud vás však tento nástroj zaujal, musíte počítat s tím, že jeho ekosystém je méně rozvinutý než u ostatních.
Pro formátování data a čísel využívá knihovna next-intl nativní rozhraní Intl prostřednictvím metody useFormatter. Ostatní knihovny využívají knihovnu FormatJS nebo nechávají na vás, abyste přímo volali metody Intl.DateTimeFormat a Intl.NumberFormat.
💡 Tyto knihovny se starají o zobrazení. Někdo však stále musí překlady vytvářet a udržovat je v synchronizaci s měnícím se obsahem. Weglot na zcela jiné úrovni a překladový obsah spravuje prostřednictvím reverzního proxy mimo kód. Nepovažujte jej za náhradu za knihovny.
Ve verzi Next.js 16 byl soubor middleware.ts přejmenován na proxy.ts. Důvodem bylo to, že název „middleware“ byl zavádějící a naznačoval obecnou logiku uvnitř aplikace. Ve skutečnosti se tento soubor spouští na síťové hranici, kde zachycuje a upravuje požadavky podobně jako proxy, ještě než se dostanou do aplikace.
Zde je kompletní implementace detekce jazykového prostředí a přesměrování, která doplňuje výše zmíněné mezery v oficiální dokumentaci:
// proxy.ts
import { match } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'
import { NextRequest, NextResponse } from 'next/server'
const locales = ['en', 'fr', 'de']
const defaultLocale = 'en'
function getLocale(request: NextRequest): string {
const cookie = request.cookies.get('NEXT_LOCALE')?.value
if (cookie && locales.includes(cookie)) return cookie
const headers = { 'accept-language': request.headers.get('accept-language') ?? '' }
const languages = new Negotiator({ headers }).languages()
return match(languages, locales, defaultLocale)
}
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl
const hasLocale = locales.some(l => pathname.startsWith(`/${l}/`) || pathname === `/${l}`)
if (hasLocale) return
const locale = getLocale(request)
request.nextUrl.pathname = `/${locale}${pathname}`
return NextResponse.redirect(request.nextUrl)
}
Soubory jsou vnořené pod app/[jazyk]/, s slovníky/ složku vedle vašich rozvržení a stránek. Kořenové rozvržení obdrží národní prostředí jako parametr a nastaví jej na html značka:
export default async function RootLayout({ children, params }) {
const { locale } = await params
return (
<html lang={locale}>
<body>{children}</body>
</html>
)
}
V případě překladů uvádí oficiální dokumentace vzor s použitím prostého slovníku, který nevyžaduje žádnou knihovnu:
const dictionaries = {
en: () => import('./dictionaries/en.json').then(m => m.default),
fr: () => import('./dictionaries/fr.json').then(m => m.default),
}
export const getDictionary = async (locale: string) => dictionaries[locale]()
Funguje to, ale nepodporuje tvorbu množného čísla ani interpolaci. další-mezinárodní zahrnuje obojí prostřednictvím getTranslations() a useTranslations() v Komponenty serveru a komponenty klienta resp.
V každém případě se překladové soubory zpracovávají na serveru a do prohlížeče se dostane pouze výsledný HTML kód, takže velikost překladových souborů nemá žádný vliv na velikost balíčku na straně klienta.
U klientských komponent předávejte přeložené řetězce pokud možno jako vlastnosti z nadřazené serverové komponenty. Použijte Další mezinárodní poskytovatel služeb pro klienty s omezenou podmnožinou zpráv pouze v případě, že klientská komponenta potřebuje překlady zpracovávat přímo.
V případě přepínače jazyků zobrazuje serverová komponenta popisky v daném jazykovém nastavení, zatímco klientská komponenta zpracovává useRouter() volání:
// LocaleSwitcher.tsx (Server Component)
import LocaleSwitcherClient from './LocaleSwitcherClient'
export default function LocaleSwitcher({ locale }) {
return <LocaleSwitcherClient locale={locale} labels={{ en: 'English', fr: 'Français' }} />
}Klient sleduje změny výběru a odesílá novou trasu pro národní prostředí:
// LocaleSwitcherClient.tsx
'use client'
import { useRouter } from 'next/navigation'
export default function LocaleSwitcherClient({ locale, labels }) {
const router = useRouter()
return (
<select value={locale} onChange={e => router.push(`/${e.target.value}`)}>
{Object.entries(labels).map(([value, label]) => (
<option key={value} value={value}>{label}</option>
))}
</select>
)
}Pokud používáte Weglot, nic z toho se vás netýká. Weglot integrovaný widget pro přepínání jazyků a nevyžaduje žádnou konfiguraci proxy ani middleware.
Ani jeden z těchto routerů nezvládá vícejazyčné SEO automaticky:
html lang správně, ale v dokumentaci se uvádí, že implementace atributu hreflang je „na vás“.Díky nástroji App Router vám rozhraní Metadata API umožní dosáhnout maximální automatizace. Definujte lokální URL adresy v vygenerovat metadata prostřednictvím alternativní jazyky objekt a Next.js jej automaticky vloží odkaz rel="alternate" hreflang="..." štítky:
export async function generateMetadata({ params: { locale } }) {
return {
alternates: {
languages: {
'en': 'https://example.com/en',
'fr': 'https://example.com/fr',
'de': 'https://example.com/de',
},
},
}
}Nejnáročnější částí je shromáždit pro každou jazykovou variantu na každé stránce správnou URL adresu. Tuto logiku si musíte napsat sami.
Ještě dvě věci je třeba nastavit ručně, a to bez ohledu na to, jaký router používáte. Kanonické URL adresy je třeba nastavit pro každé jazykové prostředí, aby se předešlo signálům o duplicitním obsahu. Vaše sitemap.ts potřeby xhtml:link záznamy pro každou jazykovou variantu každé stránky.
Na hreflang samotná hodnota, použití hreflang="en-US" při zaměření na konkrétní region a hreflang="en" pokud se zaměřujete na všechny mluvčí angličtiny. Jejich zaměňování vysílá vyhledávačům protichůdné signály.
další-mezinárodní přidává jednu částečnou automatizaci: jeho proxy automaticky vkládá atribut hreflang Odkaz hlavičky odpovědi při použití směrování s lokalizovanými cestami. Ostatní konfigurace směrování je třeba nadále implementovat ručně.
S rostoucí velikostí webu to představuje značnou zátěž v podobě průběžné údržby. Naštěstí reverzní proxy Weglot vše automaticky zpracovává na serveru, takže přeložené stránky lze plně indexovat bez nutnosti přidávat další kód.
Reverse proxy Weglot ve skutečnosti automaticky zajišťuje vše, co bylo popsáno v předchozí části: tagy hreflang, přeložené URL adresy, kanonické tagy a generování sitemapy. Přeložené stránky jsou poskytovány na straně serveru, takže je vyhledávače mohou plně indexovat.
⚠️ snippet JavaScriptového snippet Weglot nepřináší žádné výhody z hlediska SEO. Překlady na straně klienta nelze prohledávat. Pokud je pro vás SEO důležité, je nutné nastavit reverzní proxy.
Dalším přínosem je doba kompilace. Weglot přeložené stránky prostřednictvím své vlastní sítě CDN, místo aby je generoval až při kompilaci. Přidání 10 jazyků na web Weglot nemá žádný vliv na to, jak dlouho příští sestavení trvá.
Správná volba závisí na tom, na co se zaměřujete.
Pokud stavíte na App Routeru a začínáte úplně od začátku, další-mezinárodní je výchozí volbou. V jediném balíčku zahrnuje směrování, překlady, automatické doplňování v TypeScriptu a podporu RSC.
Pokud používáte Pages Router nebo již máte ve svém stacku i18next, react-i18next je cesta nejmenšího odporu.
Pokud jsou vaší prioritou vícejazyčné SEO a průběžná správa překladů, žádná z těchto knihoven problém zcela nevyřeší. Stále budete muset implementovat atribut hreflang, soubory Sitemap a pracovní postup pro udržování aktuálnosti překladů v souvislosti se změnami obsahu. Reverzní proxy Weglot to vše zvládá automaticky.
Weglot knihovna na úrovni komponent se vzájemně nevylučují. Weglot na úrovni HTML a jako proxy, takže může fungovat společně s jakoukoli knihovnou, kterou vaše komponenty používají.
Pokud vám tento přístup vyhovuje, podívejte se nejprve na stránku věnovanou integraci Weglot pomocí JavaScriptu a vyzkoušejte naši 14denní bezplatnou zkušební verzi!
Nejlepší způsob, jak pochopit sílu Weglot vyzkoušet si ho na vlastní kůži. Vyzkoušejte ho zdarma a bez jakýchkoli závazků.
Pokud ještě nejste připraveni propojit svůj web, je k dispozici demo webová stránka ve vašem ovládacím panelu.