Jak zmienić wersję językową aplikacji używając JavaScript?

Jak zmienić wersję językową Twojej strony lub serwisu internetowego bez przeładowywania przeglądarki? Użyj klas i obiektów w Java Script. Szybkie, proste i efektywne. Dzisiaj opiszę jak sobie tym poradzić. Jak zwykle, krok po kroku 🙂

Zmiana wersji językowej.

Czasy są takie, że jak strona czy serwis internetowy nie ma wielu wersji językowych (zwłaszcza angielskiej) to automatycznie ogranicza swój zasięg. Jak ktoś chce robić jakiś biznes, zwłaszcza internetowy to do wielu klientów po prostu nie dotrze 🙂 Dlatego my jako developerzy musimy sobie z tym jakoś poradzić.

Metod jest pewnie wiele, kiedyś robiło się to w HTML’u i przeładowywało się przeglądarkę. Dzisiaj to już historia dlatego pokażę wam metodę gdzie wszystko dzieje się w JS’ie.

Jak się do tego zabrać.

Całość będzie zawierała się w 2 plikach .js. W głównym pliku ze skryptami umieszcza się klasę a w oddzielnym pliku tworzy się obiekt z tłumaczeniami. Dla potrzeb tego tutorialu (czyli prezentacja w CodePenie) umieszczę wszystko w jednym pliku .js ale okraszę to odpowiednimi komentarzami aby łatwiej było zrozumieć koncepcję.

Demo.

Przygotuję dzisiaj demo w klimacie mojej stronki portfolio jednak jako zawartość wykorzystam cytat ponadczasowego mędrca zwanego Konfucjuszem. Wygląda i działa to mniej więcej tak:

Przygotowanie.

Na początek przygotowujemy plik HTML i stylujemy używając CSS. Na tym etapie kluczowe jest uwzględnić dwie kwestie w HTML’u (poza tym nie zapomnijcie podpiąć jQuery jeśli używacie :P):

  1. Ustal jaki element ma być używany do zmiany języka. W tym przypadku używam selektora gdzie wrzucam poszczególne opcje językowe. Ja sobie tutaj zrobiłem 3 języki ale jak widać można dodawać ich dowolną ilość. WAŻNE aby każda opcja miała przypisaną wartość value.
    <select>
      <option value="pl">PL</option>
      <option value="en">EN</option>
      <option value="lat">LAT</option>
    </select>
  2. Każdy element tekstowy (np. h2, p) powinien mieć przypisany specyficzny id (np. atr1, atr2). W ten sposób będziemy identyfikować i podmieniać konkretne teksty.
<h2 id="atr1">Żaden wiatr nie jest dobry dla okrętu, który nie zna portu swego przeznaczenia. </h2>
<p id=“atr2”>Konfucjusz</p>

Wersja językowa przy użyciu JavaScript.

Jak powiedziałem wcześniej skrypt składa się z dwóch elementów.

Obiekt z tłumaczeniami.

Dla przejrzystości tworzymy nowy plik .js, nazywamy go np. i18n.js (taka jest konwencja). Tam budujemy obiekt ze wszystkimi tłumaczeniami. Wygląda on tak:

var translate = {
  pl: {
    m1: "Żaden wiatr nie jest dobry dla okrętu, który nie zna portu swego przeznaczenia.",
    m2: "Konfucjusz",
  },
  en: {
    m1: "No wind is favourable for a ship that doesn't know its destiny harbor.",
    m2: "Confucius",
  },
  lat: {
    m1: "Nullus suus ventus est in nave, quae non sciunt ad portum fatum.",
    m2: "Confucius",
  }
};

Wszystko przechowujemy w zmiennej translate w której umieszczamy wersje językowe np. pl, en, lat jako elementy obiektu. Ważne aby nazwy tych wersji miały taką samą nazwę jak value z HTMLa.

W każdej wersji językowej zagnieżdżamy nowy obiekt który zawiera tłumaczenia dla każdego elementu HTML posiadającego jakiś tekst który chcemy przetłumaczyć. Niestety tutaj jest trochę manualnej pracy bo trzeba przygotować tłumaczenia i umieścić je wszystkie w obiekcie. W przypadku większych projektów ten cały obiekt może być bardzo rozbudowany. Każdy tekst dostaje jakąś wartość np. m1, m2 która jest taka sama dla wszystkich wersji językowych. Nie musi być taka sama jak id użyte w HTMLu.

Klasa z tłumaczeniem.

Jak nasz HTML i obiekt z tłumaczeniami są gotowe przyszedł czas na napisanie algorytmu obsługującego to zdarzenie. Zbuduję klasę w JavaScripcie. Wygląda to tak:

class translator {
  constructor() {
    this.changeLanguage();
  }

  changeLanguage() {
    var i18n = translate;
    $(".language select").change(function() {
      var lang = $(this).val();
      $("#atr1").text(i18n[lang].m1, 500);
      $("#atr2").text(i18n[lang].m2, 500);
    });
  }
}

new translator()

Proste, prawda? Zaraz opiszę co się tam dzieje.

Na początek tworzymy klasę np. translator. Kolejny krok to stworzenie konstruktora w którym definiujemy użycie metody o nazwie np. changeLanguage. Potem tworzymy metodę changeLanguage czyli:

  1. Tworzę nową zmienną np. i18n która pobiera obiekt z tłumaczeniami stworzony wcześniej.
  2. Wybieram selektor z HTMLa i na zdarzenie zmiany jego wartości rozpoczynam funkcję.
  3. Tworzę zmienną lang która pobiera wartość value z selektora w HTMLu.
  4. Tutaj tworzę INDYWIDUALNĄ formułę dla każdego elementu zawierającego tekst w HTMLu, ujętego w obiekcie z tłumaczeniami. Przy dużym projekcie tych linijek z kodem może być trochę dużo ale jak zastosujemy sensowną konwencję nazewniczą można napisać jakąś pętlę i wtedy kodu będzie znacznie mniej. Ja tego tutaj nie mam.
  5. O co chodzi w tym kodzie? Pobieram element HTML przy pomocy id i mówię, że ma być do niego wstawiony tekst 🙂 Proste 🙂 Tekst ma być wzięty ze zmiennej i18n (nasz obiekt) przeszukanej przez pryzmat wartości [lang] (np. pl, en, lat) i na końcu ma być pobrany string oznaczony jako np. m1 (czyli konkretny tekst). Ustawiamy jakieś opóźnienie np. 500 ms.
  6. Teraz już poza klasą wywołujemy tą klasę poprzez komendę new className()

Jeśli wszystko zrobiliśmy dokładnie i nie było pomyłki przy nazewnictwie id, obiektów itp. to kod powinien działać. Jak się domyślacie późniejsza rozbudowa serwisu o kolejną wersję językową jest bajecznie prosta bo wystarczy dodać opcję do selektora i tłumaczenia do obiektu 🙂

Podsumowanie.

Mam nadzieję, że ten krótki samouczek był dla was przydatny 🙂 Teraz zmiana języka na stronie to dla was pestka! Jeśli znacie inne, ciekawsze metody to piszcie w komentarzach. 

  • A jak pokazać Google, jakie mamy wersje językowe? Bez tego i tak nasz biznes nie zwiększy zasięgu…

    A jak poinformować technologię asystującą o istniejących wersjach językowych? Jak ją poinformować o zmianie języka na stronie?

    A jak komuś posłać linka do konkretnej wersji językowej?

    A jak zmienić język w wielu elementach naraz? Mam się do nich bezpośrednio odwoływać i zmieniać tekst? A co jeśli w jakimś elemencie mam już podpięte listenery pod eventy?

    • Bartłoś Ce

      No właśnie. Bardzo dobre pytania. Jak się za to zabrać? Jakieś pomysły?

      • Mimo wszystko dla normalnych stron (nie aplikacji) najsensowniejszym rozwiązaniem jest robienie tego po server-side, gdzie każda wersja językowa ma oddzielny adres. Wówczas wersje językowe bardzo łatwo połączyć przy pomocy atrybutu [hreflang] i przy pomocy link[rel=alternate].

        W przypadku aplikacji wypada zastosować placeholdery w miejscach tekstu. Ogólnie to spojrzałbym np. na l20n → http://l20n.org/

  • „m1”, „m2″… – przy większych projektach to będzie męczarnia 😀
    Tutaj jest spore miejsce do „optymalizacji” 😉

  • Kacper Pruszyński

    Jak nazywa się ta konwencja? Chciałbym o niej poczytać 😀