PABLO.ENGINEERING
// WRÓĆ DO WSZYSTKICH WPISÓW
// 3 min

Wykrywanie języka przeglądarki z prawem odmowy: propozycja, a nie przymus

#nextjs#i18n#ux#client-components#localstorage

Pewnie znasz ten scenariusz: wchodzisz na zagraniczny portal z polskiego komputera, a strona siłowo przerzuca Cię na wersję z automatycznym, łamanym tłumaczeniem. Klikasz powrót do oryginału, przechodzisz do kolejnego artykułu, a system znowu uparcie robi to samo. Albo przy każdej wizycie wyskakuje okno z pytaniem o kraj, ignorując fakt, że już pięć razy wybrałeś preferowany język.

Problem: Chamskie przekierowania niszczą wrażenia z czytania

Wielojęzyczność w aplikacjach webowych bardzo często cierpi na dwie wady:

  • Agresywne auto-redirecty: Przekierowywanie użytkownika na podstawie adresu IP lub nagłówków serwera psuje linki (nie możesz wysłać znajomemu linku do konkretnej wersji) i potrafi zapętlić roboty indeksujące wyszukiwarki Google.
  • Brak pamięci o decyzji: Użytkownik klika „Nie, dziękuję, chcę czytać po polsku”, a baner wraca przy każdym kliknięciu podstrony, bo autorzy strony nie pomyśleli o trwałym zapisaniu wyboru.

Co zrobiłem: Subtelny komponent LanguageGate z prawem odmowy

Projektując wielojęzyczną witrynę inżynierską (PL/ENG/ES), postanowiłem zbudować mechanizm oparty o prostą filozofię: uprzejma propozycja zamiast przymusu.

Stworzyłem komponent LanguageGate, który działa według jasnych zasad:

1. Zero automatycznych skoków po stronach

Użytkownik zawsze ląduje dokładnie na tej wersji językowej, w którą kliknął. Jeśli system wykryje, że język przeglądarki różni się od języka artykułu, wyświetla jedynie dyskretny pasek: „Wykryliśmy język angielski. Czy chcesz przełączyć na wersję English?”. Wybór należy w 100% do człowieka.

2. Odmowa jest święta i zapamiętana w localStorage

Jeśli czytelnik kliknie „Zostań przy obecnym języku”, informacja ta zostaje zapisana w pamięci podręcznej przeglądarki (localStorage). Od tego momentu baner milczy na zawsze - nie nękamy użytkownika kolejnymi pytaniami przy kolejnych wizytach.

3. Całkowita prywatność i zero obciążenia serwera

Mechanizm działa w 100% po stronie przeglądarki (navigator.language). Nie wysyłamy żadnych zapytań do zewnętrznych baz geolokalizacji IP, nie używamy śledzących ciasteczek (cookies) i nie spowalniamy ładowania pierwszego widoku strony.

// Zasada działania w pigułce:
// 1. Sprawdź, czy użytkownik podjął już kiedyś decyzję:
const savedPreference = localStorage.getItem("lang_preference");
if (savedPreference) {
  return null; // Uszanuj decyzję i nie pokazuj nic
}

// 2. Sprawdź język systemu operacyjnego / przeglądarki:
const browserLang = navigator.language.slice(0, 2);

// 3. Jeśli język pasuje do dostępnych tłumaczeń i jest inny niż obecna strona:
if (AVAILABLE_LOCALES.includes(browserLang) && browserLang !== currentLang) {
  showSuggestionBanner(browserLang);
}

4. Elastyczność architektoniczna

Dopóki dany artykuł istnieje tylko w jednym języku, komponent pozostaje w uśpieniu. Gdy tylko w repozytorium pojawi się wersja angielska lub hiszpańska, mechanizm budzi się sam, bez konieczności przebudowy interfejsu.

Dlaczego to ważne (Use Case)

Dlaczego takie podejście ma kluczowe znaczenie dla serwisu technicznego?

  • Komfort odbiorcy z dowolnego kraju: Inżynier z Hiszpanii czy rekruter ze Stanów Zjednoczonych od razu widzi, że witryna szanuje jego preferencje, ale nie narzuca się nachalnymi wyskakującymi okienkami.
  • Czyste SEO dla Google: Każda wersja językowa żyje pod własnym czytelnym adresem (/pl, /en, /es), a roboty wyszukiwarek widzą stabilne treści bez niespodziewanych przekierowań 302.
  • Brak zbędnych zgód na cookies: Ponieważ preferencja językowa jest przechowywana lokalnie w przeglądarce i nie służy do śledzenia użytkownika, nie wymaga irytujących banerów ze zgodami RODO.

Czego się nauczyłem

  1. Szacunek do użytkownika to najlepsza strategia UX: Propozycja z prawem odmowy zawsze budzi większą sympatię niż arbitralne decydowanie za odbiorcę.
  2. Natywne API przeglądarki rozwiązuje większość problemów: Zamiast skomplikowanych bibliotek serwerowych, localStorage i navigator.language dały lekki i niezawodny mechanizm.
  3. Projektuj z myślą o przyszłości: Zaprogramowanie obsługi wielu języków na samym początku pozwala płynnie publikować nowe treści bez powrotu do kodu bazowego.