React / i18n

    Internationalization (i18n) w Next.js

    next-intl dla App Router, locale routing, ICU message format, Intl API, hreflang SEO i workflow zarządzania tłumaczeniami.

    next-intl
    App Router i18n
    ICU
    Plural forms
    alternates
    SEO hreflang
    Intl API
    Native format

    6 bibliotek i18n dla React i Next.js

    next-intl, next-i18next, react-i18next, Paraglide, Tolgee i Intl API — podejścia do internacjonalizacji od App Router po bundle-size-critical.

    Biblioteka Framework Podejście Format Kiedy
    next-intl Next.js App Router Server + Client components ICU messages Next.js 13+ — domyślny wybór
    next-i18next Next.js Pages Router getServerSideProps + useTranslation JSON namespaces Legacy Next.js Pages Router
    react-i18next React (Vite, CRA) Context + hooks JSON namespaces Dowolna React app bez Next.js routing
    Paraglide JS Framework-agnostic Compile-time type-safe Message functions Type safety critical, bundle size
    Tolgee React / Vue / Angular In-context editing + SDK JSON + TMS Non-dev tłumacze, in-context workflow
    Intl API (native) Wszystkie Browser native CLDR data Formatowanie liczb, dat, walut

    Często zadawane pytania

    Co to jest i18n (internationalization) i jak wdrożyć w Next.js?

    i18n (internationalization): przygotowanie aplikacji na wiele języków i regionów. i18n = 18 liter między 'i' a 'n'. L10n (localization): tłumaczenie dla konkretnego języka/regionu. g11n (globalization): połączenie obu. Next.js App Router i18n: brak wbudowanego i18n (w przeciwieństwie do Pages Router). Rekomendowane: next-intl, next-i18next (tylko Pages Router), Paraglide. next-intl (rekomendowany 2024): middleware do routing. app/[locale]/page.tsx — locale w URL. getTranslations('HomePage') w Server Components. useTranslations('HomePage') w Client Components. Plik wiadomości: messages/pl.json i messages/en.json. Struktura: {HomePage: {title: 'Witaj', description: 'Opis'}}. t('title') w komponentach. Pages Router next-i18next: i18n config w next.config.js. useTranslation('common'). serverSideTranslations(locale, ['common']). getStaticPaths z locale. Locale detection: middleware — Accept-Language header. Cookie (user preference). URL prefix /pl, /en. Subdomain pl.example.com. ICU message format: t('greeting', {name: 'Adam'}) + 'Witaj {name}'. Pluralization: {count, plural, one {# produkt} other {# produktów}}. Date/number formatting: Intl.DateTimeFormat, Intl.NumberFormat — native JS. t.rich() — formatowanie z JSX (linki, bold).

    next-intl — jak skonfigurować i używać w Next.js App Router?

    next-intl instalacja: npm install next-intl. Struktura plików: messages/ (pl.json, en.json). i18n.ts (routing config). middleware.ts (locale detection). app/[locale]/layout.tsx (locale provider). app/[locale]/page.tsx. i18n.ts konfiguracja: import {defineRouting} from 'next-intl/routing'. export const routing = defineRouting({locales: ['pl', 'en'], defaultLocale: 'pl'}). middleware.ts: import {createMiddleware} from 'next-intl/middleware'. export default createMiddleware(routing). export const config = {matcher: ['/', '/(pl|en)/:path*']}. layout.tsx: import {NextIntlClientProvider} from 'next-intl'. import {getMessages} from 'next-intl/server'. const messages = await getMessages(). NextIntlClientProvider locale={locale} messages={messages}. Server Component: import {getTranslations} from 'next-intl/server'. const t = await getTranslations('HomePage'). t('title'). Client Component: 'use client'. import {useTranslations} from 'next-intl'. const t = useTranslations('HomePage'). t('title'). Link i navigation: import {Link} from '@/i18n/navigation'. href='/about' — automatycznie dodaje locale prefix. import {usePathname, useRouter} from '@/i18n/navigation'. Locale switcher: router.replace(pathname, {locale: 'en'}). Statyczne generowanie: generateStaticParams: routing.locales.map(locale => ({locale})). SEO: alternates.languages w generateMetadata.

    Formatowanie liczb, dat, walut i plural rules — Intl API?

    Intl API (native JS): pełne wsparcie formatowania bez zewnętrznych bibliotek. Intl.NumberFormat: new Intl.NumberFormat('pl-PL', {style: 'currency', currency: 'PLN'}).format(1234.56) = '1 234,56 zł'. style: 'decimal', 'percent', 'currency', 'unit'. unit: 'kilometer', 'liter', 'kilogram'. Intl.DateTimeFormat: new Intl.DateTimeFormat('pl-PL', {dateStyle: 'full', timeStyle: 'short'}).format(new Date()) = 'sobota, 13 kwietnia 2024, 12:00'. Options: year, month, day, weekday, hour, minute. timeZone: 'Europe/Warsaw'. Intl.RelativeTimeFormat: new Intl.RelativeTimeFormat('pl', {numeric: 'auto'}).format(-1, 'day') = 'wczoraj'. format(-3, 'month') = '3 miesiące temu'. Intl.PluralRules: new Intl.PluralRules('pl').select(1) = 'one'. select(2) = 'few'. select(5) = 'many'. Języki mają złożone reguły (PL: one/few/many). next-intl integracja: t.number(1234, {style: 'currency', currency: 'PLN'}). t.dateTime(new Date(), {dateStyle: 'medium'}). t.relativeTime(-1, 'day'). Pluralizacja next-intl: messages: {products: '{count, plural, =0 {Brak} one {# produkt} few {# produkty} many {# produktów} other {# produktu}}'} t('products', {count: 5}). Waluty i regiony: różne formaty liczb (. vs , separator). Kierunek tekstu: LTR/RTL (arabski, hebrajski). dir='rtl' na html. Tailwind RTL: rtl: prefix. date-fns/locale: locale-aware date parsing.

    SEO dla wielojęzycznych stron — hreflang, canonical i sitemap?

    hreflang: informuje Google o alternatywnych wersjach językowych. link rel='alternate' hreflang='pl' href='https://example.pl/pl/strona'. hreflang='en' href='https://example.pl/en/page'. hreflang='x-default' href='https://example.pl'. Musi być w każdej wersji językowej (wzajemne oznaczenia). Next.js generateMetadata: alternates: {canonical: '/pl/strona', languages: {'pl': '/pl/strona', 'en': '/en/page', 'x-default': '/'}}. Canonical URL: każda strona ma swój canonical w swoim języku. Nie wskazuj EN jako canonical dla PL strony. Sitemap: osobne sitemapy per język lub jedno z hreflang. next-sitemap: sitemapSize, robotsTxt, alternateRefs. app/sitemap.ts: return routing.locales.flatMap(locale => pages.map(page => ({url: ..., alternates: {languages: {...}}})). URL struktura: /pl/o-nas vs /en/about — przełożone URL (lepszy UX i SEO). /pl/o-nas vs /en/o-nas — łatwiejsze technicznie. Subdomain: pl.example.com (osobne crawl budget). Domain: example.pl vs example.com/pl. Google Search Console: osobne właściwości per język/kraj. Target country w GSC dla każdej wersji. Performance tracking: per locale metrics. Tłumaczenie meta: title i description w każdym języku. Unikaj auto-translate dla SEO — manualnie lub profesjonalnie. Open Graph per locale.

    CMS i zarządzanie tłumaczeniami — Lokalise, Crowdin i workflow?

    Wyzwania i18n: kto tłumaczy? jak synchronizować zmiany? jak unikać missing keys? Translation Management System (TMS): Lokalise: popularny TMS dla deweloperów. CLI, GitHub integration, AI translation. Crowdin: open-source friendly. podobny do Lokalise. Phrase (Memsource): enterprise. Weblate: open-source TMS. Tolgee: open-source, in-context editing, React SDK. Workflow: Developer dodaje nowy klucz w messages/en.json (primary language). CI/CD push do TMS (Lokalise CLI push). Tłumacz tłumaczy w TMS. CI/CD pull przetłumaczone (Lokalise CLI pull). PR z tłumaczeniami. Missing translations: next-intl: fallback na defaultLocale dla brakujących. Kompilacja: Paraglide-JS generuje type-safe funkcje (nie strings). Błąd przy missing kluczu w TS. Pluralization edge cases: polski ma 4 formy plural (zero/one/few/many). Arabski — 6 form. ICU message format obsługuje wszystko. i18n dla React Native: react-i18next działa też w RN. expo-localization — device locale. React i18next: useTranslation hook. Trans component dla JSX. i18nInstance.changeLanguage('pl'). Astro i18n: Astro 4+ wbudowane i18n routing. getRelativeLocaleUrl(). astro:i18n virtual module. Vue: vue-i18n (Options API, Composition API). Nuxt: @nuxtjs/i18n.

    Czytaj dalej

    Powiązane artykuły

    Kontakt

    Skontaktuj się z nami

    Porozmawiajmy o Twoim projekcie. Bezpłatna wycena w ciągu 24 godzin.

    Wyślij zapytanie

    Bezpłatna wycena w 24h
    Bez zobowiązań
    Indywidualne podejście
    Ekspresowa realizacja

    Telefon

    +48 790 814 814

    Pon-Pt: 9:00 - 18:00

    Email

    adam@fotz.pl

    Odpowiadamy w ciągu 24h

    Adres

    Plac Wolności 16

    61-739 Poznań

    Godziny pracy

    Pon - Pt9:00 - 18:00
    Sob - NdzZamknięte

    Wolisz porozmawiać?

    Zadzwoń teraz i porozmawiaj z naszym specjalistą o Twoim projekcie.

    Zadzwoń teraz