Wszystkie posty
wordpress

Wielojęzyczny WordPress z Polylang: praktyczny przewodnik implementacji

Jak wdrożyć wielojęzyczność w WordPress z Polylang: konfiguracja, SEO, hreflang, tłumaczenia automatyczne, integracja z ACF i WooCommerce. Realne pułapki, kod, ustawienia.

7 min czytaniaAktualizacja: 9 lipca 2026

Wielojęzyczny WordPress z Polylang

Polylang to najlepsza wtyczka do wielojęzyczności w WordPress. Darmowa, open-source, aktywnie rozwijana. Ten post to kompletny przewodnik wdrożenia — instalacja, konfiguracja, SEO, integracje, realne problemy.

Dlaczego Polylang, nie WPML

Porównanie, które pokazuję klientom:

| Cecha | Polylang | WPML | |-------|----------|------| | Cena (1 strona, 1 rok) | $0 / $99 (Pro) | $39-159 | | Cena (1 strona, 5 lat) | $0 / $495 | $195-795 | | Custom post types | ✅ w darmowej | ✅ w płatnej | | ACF Pro integracja | ✅ w Pro | ✅ w pełnej | | WooCommerce integracja | ✅ w Pro | ✅ w pełnej | | Tłumaczenia automatyczne | DeepL (Pro) | Własny system | | Wydajność | Lżejsza | Cięższa (więcej query) | | Społeczność PL | Aktywna | Mniejsza |

Moja rekomendacja: Polylang. WPML jest 5-10x droższy w 5-letniej perspektywie i nie oferuje nic, czego Polylang nie ma. Wyjątek: gigantyczne portale z >50 custom post types, gdzie WPML ma bardziej dojrzałe integracje.

Instalacja i konfiguracja

# Wp-cli (szybsze niż przez GUI)
wp plugin install polylang --activate
wp plugin install polylang-pro --activate  # opcjonalnie

Lub przez WP Admin → Plugins → Add New → "Polylang" → Install → Activate.

Ustawienia języków

Languages → Languages:

Języki: Polski (pl), English (en)
Kolejność URL: /pl/ dla polskiego (domyślny), /en/ dla angielskiego
Hide default language URL: OFF  (lepsze dla SEO)
Language switcher: ON

Kluczowa decyzja: subdirectory (/pl/, /en/) vs subdomain (pl.example.com, en.example.com).

Subdirectory wygrywa:

  • Łatwiejsze SEO (cała domena buduje autorytet)
  • Łatwiejsze certyfikaty SSL (jeden cert, nie dwa)
  • Prostsze zarządzanie (jeden hosting, jedna konfiguracja)

Subdomain ma sens gdy:

  • Różne zespoły obsługują różne wersje językowe
  • Różne wymagania prawne (RODO, dane wrażliwe per kraj)

URL structure

W Settings → Permalinks:

Ustawienie: Post name (/%postname%/)
Polylang prefix: /pl/, /en/

Rezultat:

  • Polska wersja: example.com/pl/o-mnie/
  • Angielska wersja: example.com/en/about-me/

Każdy post/page/CPT ma osobny URL per język plus drugi URL w drugim języku. Polylang automatycznie je linkuje.

Tłumaczenie treści

Ręczne tłumaczenie (edytor WP)

Dla każdego postu Polylang dodaje meta box "Language" + przycisk "+" obok tytułu. Kliknij "+", wybierz język, napisz treść. Pola są zsynchronizowane (tytuł EN ↔ tytuł PL), ale treść jest niezależna.

Tłumaczenie automatyczne DeepL

Polylang Pro + DeepL API:

// wp-config.php
define('POLYLANG_DEEPL_API_KEY', 'twoj-klucz-deepl');

Workflow:

  1. Napisz post po polsku
  2. Kliknij "Translate with DeepL" w edytorze
  3. Polylang tłumaczy treść + excerpt + meta na EN
  4. Native speaker review + poprawki

DeepL Pro ($8/m dla 500k znaków) daje 80-90% jakości dla EN↔PL. Gorzej dla par NO/FI/DK. Zawsze review dla krytycznych stron (cennik, regulamin, polityka prywatności).

SEO: hreflang, canonical, sitemap

hreflang automatyczny

Polylang automatycznie dodaje hreflang w <head>:

<link rel="alternate" hreflang="pl" href="https://example.com/pl/o-mnie/" />
<link rel="alternate" hreflang="en" href="https://example.com/en/about-me/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/pl/o-mnie/" />

To jest najlepsza praktyka SEO dla wielojęzycznych stron. Google używa hreflang do pokazywania prawidłowej wersji językowej w wynikach.

Weryfikacja:

# Sprawdź hreflang na stronie
curl -s https://example.com/pl/o-mnie/ | grep "hreflang"

Canonical URL

Polylang ustawia canonical URL do bieżącej wersji językowej (nie do wersji domyślnej). To jest poprawne SEO — każda wersja językowa ma własny canonical.

Sitemap (z Yoast / RankMath / SEOPress)

Wszystkie trzy popularne SEO pluginy mają integrację z Polylang. Sitemap zawiera wszystkie wersje językowe z prawidłowymi hreflang.

<!-- Przykład sitemap.xml -->
<url>
  <loc>https://example.com/pl/o-mnie/</loc>
  <xhtml:link rel="alternate" hreflang="pl" href="https://example.com/pl/o-mnie/" />
  <xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/about-me/" />
</url>
<url>
  <loc>https://example.com/en/about-me/</loc>
  <xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/about-me/" />
  <xhtml:link rel="alternate" hreflang="pl" href="https://example.com/pl/o-mnie/" />
</url>

Sprawdź czy SEO działa

# 1. hreflang w <head>
curl -s https://example.com/pl/o-mnie/ | grep hreflang

# 2. Canonical per język
curl -s https://example.com/pl/o-mnie/ | grep canonical
curl -s https://example.com/en/about-me/ | grep canonical

# 3. Search Console → International Targeting
# Sprawdź czy hreflang jest rozpoznawany (może trwać 2-4 tygodnie)

Integracja z ACF (custom fields)

Darmowy Polylang: custom fields ACF są per post, nie per język. To znaczy: wartość pola w EN musisz ręcznie wpisać w PL (lub odwrotnie).

Polylang Pro + ACF Pro rozwiązuje to: custom fields per język.

// functions.php — Polylang Pro + ACF Pro
add_filter('acf/settings/l10n', function () {
    return true;  // włącza tłumaczenia ACF
});

add_filter('acf/settings/l10n_textdomain', function () {
    return 'your-textdomain';
});

Potem w ACF:

// Definicja pola z tłumaczeniem
acf_add_local_field_group([
    'key' => 'group_clients',
    'title' => 'Klienci',
    'fields' => [
        [
            'key' => 'field_client_name',
            'label' => 'Nazwa klienta',
            'name' => 'client_name',
            'type' => 'text',
        ],
    ],
    'location' => [
        [
            [
                'param' => 'post_type',
                'operator' => '==',
                'value' => 'projekt',
            ],
        ],
    ],
]);

Od teraz client_name ma osobne wartości per język. W pl.mdx masz "Jan Kowalski", w en.mdx masz "John Smith".

Integracja z WooCommerce

Darmowy Polylang: produkty WooCommerce są wspólne (jeden produkt, dwie wersje językowe). Problem: cena, atrybuty, warianty są wspólne — co jest złe dla wielu sklepów.

Polylang Pro dla WooCommerce ($99/rok) daje:

  • Ceny per język (np. 99 PLN / €22)
  • Atrybuty per język (kolor "czerwony" / "red")
  • Kategorie per język
  • Shipping zones per język

Bez Pro: albo używasz multi-currency plugin (np. WOOCS), albo akceptujesz wspólną cenę (przeliczanie po kursie w display).

Language switcher w menu

Dodaj do Appearance → Menus:

Menu: Header
Items:
  - Strona główna (PL)  → /pl/
  - O mnie (PL)         → /pl/o-mnie/
  - Blog (PL)           → /pl/blog/
  - [Polylang Language Switcher] ← dodaj jako "Language Switcher"

Language switcher pokazuje aktywny język + flagi (opcjonalnie). Możesz wybrać styl: dropdown, lista, flagi.

Moja rekomendacja: dropdown bez flag (flagi są problematyczne — np. polska strona nie ma jednej "oficjalnej" flagi, code-switch PL/EN z flagami jest niepoprawne politycznie dla niektórych rynków).

Hardening produkcyjny

1. Sprawdź czy nie ma duplikatów URL

Błąd: ta sama strona dostępna pod dwoma URL-ami (/o-mnie/ i /pl/o-mnie/). Fix:

// functions.php — przekieruj non-prefixed URL do domyślnego języka
add_action('template_redirect', function () {
    if (strpos($_SERVER['REQUEST_URI'], '/pl/') === 0 ||
        strpos($_SERVER['REQUEST_URI'], '/en/') === 0) {
        return; // OK
    }
    // Brak prefiksu — przekieruj do domyślnego
    $default = pll_default_language();
    wp_redirect(home_url("/{$default}" . $_SERVER['REQUEST_URI']), 301);
    exit;
});

2. Cache per język

Jeśli używasz WP Super Cache lub W3 Total Cache, musisz wyłączyć cache dla strony lub cache per język. Polylang ma integrację z większością cache pluginów — włącz "Don't cache pages for visitors with cookies" (Polylang ustawia cookie pll_language).

Dla pełnej kontroli (Cloudflare + APO) — patrz mój post o Cloudflare. Cache HTML per język to osobny URL, więc cache działa automatycznie.

3. Testowanie przed produkcją

# Test 1: Wszystkie wersje językowe są dostępne
for lang in pl en; do
  echo "=== /${lang}/ ==="
  curl -s -o /dev/null -w "%{http_code}\n" https://example.com/${lang}/
done
# Oczekiwane: 200, 200

# Test 2: hreflang w <head>
for lang in pl en; do
  echo "=== hreflang /${lang}/ ==="
  curl -s https://example.com/${lang}/ | grep hreflang | head -5
done

# Test 3: Canonical per język
for lang in pl en; do
  echo "=== canonical /${lang}/ ==="
  curl -s https://example.com/${lang}/ | grep canonical
done

# Test 4: Language switcher działa
curl -s https://example.com/pl/ | grep "pll-switcher" || echo "MISSING!"

Częste problemy

1. Po aktualizacji WP niektóre tłumaczenia znikają

Polylang trzyma tłumaczenia w wp_term_relationships. Po dużych update'ach WP czasem czyści tę tabelę. Fix: backup bazy przed aktualizacją, restore jeśli coś zniknie.

2. SEO plugin nie rozpoznaje wielojęzycznych URL

Yoast / RankMath wymaga ręcznej konfiguracji per język. Sprawdź w ustawieniach SEO czy "Permalink" jest prawidłowy per język (Polylang powinien to robić automatycznie, ale sprawdź ręcznie).

3. Sitemap.xml nie ma wszystkich wersji językowych

Włącz "Include all languages in sitemap" w ustawieniach SEO. Sprawdź sitemap w /sitemap.xml — powinien mieć wszystkie wersje z hreflang w <xhtml:link>.

4. ACF custom fields są puste po przełączeniu języka

Darmowy Polylang + ACF (bez Pro) → custom fields są wspólne. Wartość wpisana w PL jest widoczna w EN. Fix: Polylang Pro + ACF Pro, albo ręczne zarządzanie per język (przełącz język → wpisz inną wartość → zapisz).

Realne case studies

Case 1: Strona firmowa IT (PL + EN, 30 podstron)

Stack: Polylang (darmowy) + Elementor + ACF Wdrożenie: 2 dni Koszt: 2000 PLN SEO: Po 3 miesiącach ruch z EN keywords +120% (większość klientów zagranicznych)

Case 2: Sklep WooCommerce (PL + EN + DE, 500 produktów)

Stack: Polylang Pro + WooCommerce + ACF Pro Wdrożenie: 5 dni Koszt: 6500 PLN Funkcjonalność: Ceny per język (PLN, EUR, GBP), atrybuty per język, shipping zones per kraj

Case 3: Portal edukacyjny (PL + UA, 1000+ artykułów)

Stack: Polylang Pro + custom post types + DeepL Wdrożenie: 7 dni (w tym migracja z WPML) Koszt: 12000 PLN Efekt: tłumaczenie 1000 artykułów z PL na UA w 2 tygodnie (DeepL + native speaker review)

Co dalej

Jeśli potrzebujesz wdrożenia wielojęzycznego WordPress z Polylang — napisz do mnie. Realizacja: 2-5 dni, koszt od 2000 PLN.

Tagi:#wordpress#polylang#i18n#wielojezyczny#seo

Najczęściej zadawane pytania

Polylang Pro czy darmowy Polylang?
Darmowy Polylang wystarcza do 90% stron. Polylang Pro ($99/rok) daje: integrację z WooCommerce (prawidłowe ceny i atrybuty per język), integrację z ACF Pro (custom fields per język), lepsze wsparcie dla URL slug-ów. Dla typowej strony firmowej (PL + EN) darmowy = OK. Dla sklepu WooCommerce lub strony z dużą liczbą custom fields — Pro się opłaca.
Czy mogę użyć Polylang z WPML import?
Tak. Polylang ma importer WPML — narzędzie WPML to Polylang w menu Narzędzia. Bezpośrednia migracja nie jest idealna (inna struktura), ale dla typowej strony firmowej z 50-100 podstronami działa. Dla dużych migracji (>1000 strings) rekomendacja: skrypt eksportujący WPML XML → import do Polylang. Realny czas migracji: 1-3 dni dla średniej strony.
Jak działa SEO hreflang z Polylang?
Polylang automatycznie generuje hreflang linki w <head> dla każdej wersji językowej strony. Trzeba włączyć 'SEO' w ustawieniach Polylang + skonfigurować format URL (subdirectory /pl/ /en/ jest rekomendowany dla SEO, subdomains pl.example.com są mniej optymalne). Polylang dodaje też x-default hreflang (domyślny język dla nieznanych przeglądarek).
Czy mogę tłumaczyć automatycznie przez DeepL / Google Translate?
Tak, Polylang Pro ma wbudowaną integrację z DeepL API. Jakość: 80-90% dla EN↔PL, mniej dla rzadziej wspieranych par (np. NO, FI). Workflow: ręczne tłumaczenie kluczowych stringów, DeepL dla reszty, native speaker review dla krytycznych stron (cennik, regulamin). DeepL Pro: $8/m dla 500k znaków, zwykle wystarcza dla średniej strony.

Powiązane posty