Gdzie SSG w Astro pasuje do wielojęzycznego sklepu
dobrze pasuje do wielojęzycznej warstwy treści sklepu z kilku konkretnych powodów:
- Każdy język dostaje własny, z góry wygenerowany HTML — optymalny dla i indeksacji, bez tłumaczenia po stronie klienta, które wyszukiwarki widzą gorzej.
- Łatwość buforowania na CDN — statyczne pliki rozkładają się globalnie, więc użytkownik w Tokio i w Berlinie dostaje stronę z bliskiego węzła.
- Brak JavaScriptu po stronie klienta bez wyraźnej potrzeby — Astro pozwala dołączać interaktywność tylko do wybranych komponentów.
- Kolekcje treści Astro (
Content Collections) — typowane, walidowane zarządzanie treścią w wielu językach.
Podejście statyczne jest łatwiejsze do buforowania i bardziej przewidywalne dla robotów niż tłumaczenie treści dopiero po stronie klienta. Nie oznacza to jednak, że cały sklep musi być statyczny — aktualne ceny, stany magazynowe, konto i koszyk mogą korzystać z API, wysp interaktywnych albo tras renderowanych na żądanie.
Konfiguracja i18n w Astro: trasy językowe i prefiksy
Astro ma już wbudowaną obsługę tras i18n, a przykładowa konfiguracja deklaruje obsługiwane języki oraz język domyślny:
Decyzja prefixDefaultLocale jest istotna o tyle, że false daje czystsze adresy dla języka domyślnego (/produkt zamiast /pl/produkt), co w większości przypadków wystarcza. true wybieraj wtedy, jeśli szczególnie zależy Ci na spójności struktury (każdy język z prefiksem).
Konfiguracja musi odpowiadać strukturze src/pages. Przy prefixDefaultLocale: false strony języka domyślnego znajdują się bezpośrednio w katalogu pages, a pozostałe w katalogach językowych:
Trasy oparte na prefiksie (/en/, /de/) są proste i działają ze statycznym hostingiem. Subdomeny (en.sklep.com) pozwalają mocniej rozdzielić serwisy, ale to rozwiązanie komplikuje wiele spraw i zwykle dla SSG prefiks jest najprostszym, najwygodniejszym wyborem.
Astro pozwala również zdefiniować języki zapasowe, które poprzez domyślny wariant redirect przenosi użytkownika na istniejący URL w innym języku. Wariant rewrite pozostawia żądany lokalizowany URL, ale wyświetla pod nim treść z języka zapasowego. Dla SEO bezpieczniejszy jest zwykle redirect albo 404, ponieważ niebezpieczeństwo tkwi w tym, że rewrite może utworzyć wiele adresów z tą samą treścią, których nie należy przedstawiać jako prawdziwych tłumaczeń w hreflang.
Organizacja treści wielojęzycznej w Kolekcjach treści Astro
Dla sklepu internetowego sprawdza się trzymanie treści w folderach dla każdego języka wewnątrz Kolekcji treści Astro (Content Collections):
Każdy wpis powinien mieć stabilny klucz łączący tłumaczenia niezależnie od języka i sluga:
Wersja angielska może używać tego samego translationKey, ale sluga ceramic-mug. Dzięki temu generator nie zgaduje odpowiedników na podstawie nazw plików. Słowniki interfejsu (etykiety przycisków, komunikaty) trzymaj osobno, np. w src/i18n/*.json, i sięgaj po nie funkcją pomocniczą t('button.dodaj_do_koszyka') w oparciu o Astro.currentLocale.
Ustaw także język dokumentu w głównym layoucie, bo to wyraźnie pomaga przeglądarkom i technologiom asystującym, choć Google ustala język przede wszystkim na podstawie widocznej treści:
Hreflang w Astro — najważniejszy sygnał międzynarodowego SEO
mówi Google, które URL-e są językowymi lub regionalnymi odpowiednikami. Oczywiście, nie zastępuje tłumaczenia, linku kanonicznego ani rozpoznawania języka na podstawie treści, ale pomaga wybrać właściwy adres dla użytkownika na danym rynku.
Tagi hreflang możesz generować w <head> szablonu. Astro daje do tego funkcję pomocniczą getAbsoluteLocaleUrl. W przykładzie poniżej zakładamy pełne pokrycie tłumaczeń, taką samą końcówkę adresu w każdym języku i zmianę wyłącznie prefiksu:
Jeśli tłumaczysz końcówki adresów (/produkt/, /en/product/, /de/produkt-de/), to nie podmieniaj prefiksu mechanicznie. Wtedy potrzebujesz mapy odpowiedników dla każdego języka i generujesz hreflang z tej mapy, tylko dla realnie istniejących wersji. Trzeba zrobić to możliwie jak najdokładniej — im dłużej istniały stare adresy, tym boleśniej odczuje się ich zmianę. Tracimy wtedy realną moc starych adresów.
Trzy reguły, których pilnuj rygorystycznie:
Kody lokalizacji poprawne. Używaj
en,de,zh-CN— a nie wymyślonych wariantów, bo niespójne kody psują cały mechanizm.x-defaultjako świadoma wersja zapasowa. Wskazuje stronę dla użytkowników, których języka nie obsługujesz i zwykle będzie to język domyślny albo selektor języka.Link kanoniczny dla każdej wersji językowej. Każda wersja wskazuje na siebie jako kanoniczną, a nie na język domyślny.
Częściowe tłumaczenia — pułapka hreflang w wielojęzycznym sklepie
Teraz uwaga na przypadek, który wywraca standardowe konfiguracje. Dopóki każda strona istnieje w każdym języku i struktura adresów jest jednolita, opcja i18n w @astrojs/sitemap oraz szablon emitujący hreflang powinny wystarczyć.
Problem pojawia się, gdy masz częściowe tłumaczenia, różne slugi albo treść zapasową. Globalna lista języków nie wystarcza wtedy do ustalenia, które warianty konkretnego produktu naprawdę istnieją. Mechaniczne wygenerowanie pełnego zestawu alternatyw może wskazać nieistniejące strony albo adresy wyświetlające treść zapasową.
Standardowy hreflang wystarczy, dopóki każda strona istnieje w każdym języku.
Rozwiązaniem jest jedno źródło relacji między tłumaczeniami, wykorzystywane zarówno przez layout, jak i sitemapę. Poniższa funkcja grupuje wpisy po translationKey i zachowuje wyłącznie faktycznie istniejące wersje:
Ten sam translationKey przy różnych slugach (kubek-ceramiczny, ceramic-mug) pozwala budować poprawne odpowiedniki nawet wtedy, gdy końcówki adresów się różnią. Ważniejszy od konkretnej metody grupowania jest stabilny translationKey i jedna funkcja budująca docelowe ścieżki.
Layout nie powinien już przechodzić po globalnej tablicy języków. Otrzymuje alternatywy bieżącego produktu i emituje wyłącznie te adresy:
Każda wersja musi otrzymać ten sam zestaw wzajemnych odnośników, łącznie z odnośnikiem do samej siebie. Produkt dostępny wyłącznie po polsku dostanie link kanoniczny do samej siebie, ale nie potrzebuje fikcyjnych alternatyw en i de.
Tłumaczyć końcówki adresów URL czy zostawić niezmienne?
Teraz wchodzimy w decyzję architektoniczną, która ma konsekwencje zarówno operacyjne, jak i SEO. Jeśli prefiks języka się zmienia, a końcówka adresu nie (/en/produkt, /de/produkt), generowanie hreflang sprowadza się do podmiany fragmentu adresu, przełącznik języka nie potrzebuje mapy odpowiedników, a adresy URL pozostają „kopiowalne”. Dla anglojęzycznego sklepu z tłumaczonym pokryciem to zwykle właściwy wybór.
Warto zaznaczyć natomiast, że dla treści mocno osadzonej w danym języku (np. blog kulinarny celujący w lokalną publiczność) tłumaczone końcówki adresów są warte kosztu operacyjnego, ponieważ same w sobie niosą wartość SEO. To decyzja dla konkretnego projektu i musisz wyważyć koszt utrzymania wobec zysku z lokalnych fraz w adresie.
Sitemapa z hreflang i dane strukturalne w Astro
Przy pełnym pokryciu i jednakowych slugach możesz użyć opcji i18n w @astrojs/sitemap. Przy modelu z translationKey wygeneruj własny statyczny endpoint, korzystający z tych samych grup co layout:
Google traktuje adnotacje w HTML, nagłówkach HTTP i sitemapie jako równoważne metody — nie ma dodatkowych punktów SEO za utrzymywanie wszystkich naraz. Jeśli jednak generujesz HTML i sitemapę, oba miejsca muszą korzystać z tego samego źródła danych, aby nie rozjechały się po kolejnej publikacji.
Drugim kluczowym elementem są dane strukturalne (schema.org), które pomagają wyszukiwarkom lepiej zrozumieć kontekst treści. Należy wstawić właściwość inLanguage zgodną z Astro.currentLocale — precyzyjnie opisuje ona język danej encji, ale nie zastępuje tagów hreflang, które służą do wskazywania alternatywnych wersji językowych strony.
Test hreflang po buildzie: nie ufaj samej konfiguracji
Poprawność oceniaj na wygenerowanych plikach i nie sugeruj się samym astro.config.mjs. Dla każdego publicznego URL-a, test regresji powinien sprawdzić:
- odpowiedź
200oraz właściwe<html lang>; - link kanoniczny do samej siebie zgodny z bieżącym adresem;
- self-reference i wzajemność wszystkich wpisów hreflang;
- brak alternatyw prowadzących do 404, redirectu albo treści zapasowej;
- zgodność zestawu alternatyw w HTML i sitemapie, jeśli utrzymujesz obie metody.
Przy wdrożeniu na CDN sprawdź również, czy hosting zachowuje trailing slash zgodny z wygenerowanymi linkami kanonicznymi i nie dokłada własnych przekierowań między wariantami adresu.
