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.
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 --activatewp plugin install polylang-pro --activate # opcjonalnieLub 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 angielskiegoHide default language URL: OFF (lepsze dla SEO)Language switcher: ONKluczowa 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:
define('POLYLANG_DEEPL_API_KEY', 'twoj-klucz-deepl');Workflow:
- Napisz post po polsku
- Kliknij “Translate with DeepL” w edytorze
- Polylang tłumaczy treść + excerpt + meta na EN
- 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 stroniecurl -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ęzykcurl -s https://example.com/pl/o-mnie/ | grep canonicalcurl -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 Proadd_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łumaczeniemacf_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: HeaderItems: - 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ęzykaadd_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ępnefor 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 -5done
# Test 3: Canonical per językfor lang in pl en; do echo "=== canonical /${lang}/ ===" curl -s https://example.com/${lang}/ | grep canonicaldone
# Test 4: Language switcher działacurl -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.
Najczęściej zadawane pytania
Polylang Pro czy darmowy Polylang?
Czy mogę użyć Polylang z WPML import?
Jak działa SEO hreflang z Polylang?
Czy mogę tłumaczyć automatycznie przez DeepL / Google Translate?
Powiązane posty
- wordpress
WordPress REST API: praktyczne przypadki użycia dla custom post types
Jak używać WordPress REST API z custom post types w produkcji. Konkretne przykłady: headless CMS, mobile app backend, integracje z AI. Kod PHP + JS gotowy do użycia.
7 min - ngo
Najlepsze open-source'owe narzędzia do zarządzania NGO zdalnie w 2025
Kompletny przegląd open-source dla NGO: CiviCRM, Odoo, SuiteCRM, Kanboard, Nextcloud, Mattermost, Jitsi. Koszty, funkcje, porównania, realne wdrożenia z polskimi fundacjami.
7 min