Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Wielojęzykowość
Forum PHP.pl > Forum > PHP
markonix
Przyszło mi się po raz pierwszy zmierzyć z wielojęzykową stroną.
Jest to modyfikacja istniejącej strony, która ma ją już zaaplikowaną na zasadzie tablicy PHP:
$lang['ciąg'] = 'Tłumaczenie';
Każda tablica w oddzielnym pliku i w zależności od wczytanego języka dany plik jest includowany.

Na dobrą sprawę mógłbym zostawić tę metodę (chyba najpopularniejszą), ale wg mnie nie jest ona praktyczna:
- w kodzie widzimy nic nie mówiące <?= $lang['ab123'] ;?>
- nowe zdanie czy słowo wymaga edycji X plików, gdzie X to liczba języków
- źle obsługuje brak tłumaczenie dla danego języka (np. wyrażenie, która nie wymaga tłumaczenia)

Napisałem coś własnego na podstawie tablicy wielowymiarowej co pozwala na pominięcie całego tłumaczenia czy tylko danego języka.
Gdy nie znajdzie tłumaczenia wyświetla tekst domyślnie wprowadzony (wzorowałem się troszkę gettext).

  1. function lg ($str) {
  2.  
  3. /* default lang */
  4. $default = 'pl';
  5.  
  6. /* ciasteczka, sesje.. nm.. */
  7. $lang = 'ru';
  8.  
  9.  
  10. $arr = array();
  11.  
  12. $arr[] = array('pl' => 'Ala ma kota', 'en' => 'Ala has a cat', 'ru' => 'questionmark.gif? questionmark.gifquestionmark.gif questionmark.gifquestionmark.gif?');
  13. $arr[] = array('pl' => 'Jacek ma kota', 'en' => 'Jacek has a cat');
  14.  
  15.  
  16. foreach ($arr as $key => $translations) {
  17.  
  18. if ($translations[$default] == $str) {
  19.  
  20. if (!empty($translations[$lang])) {
  21.  
  22. $str = $translations[$lang];
  23.  
  24. }
  25. break;
  26.  
  27. }
  28.  
  29. }
  30.  
  31. echo $str;
  32.  
  33. }
  34.  
  35. lg ( 'Jacek ma kota' );


Działa prosto, a zarazem bardziej intuicyjnie.
Zastanawia mnie tylko kwestia optymalności.
Może ktoś to rozwiązał w inny sposób?
Może pliki XML (bazę pomijam, to strona typu "wizytówka" bez bazy danych)?

Wcześniejszy pomysł opierał się na używaniu indeksów do wyszukiwania fraz:
$arr['ala_ma_kota'] = [ tablica z tłumaczeniami ]
ale tutaj zastanawia mnie kwestia tego ile znaków można wpakować w indeks no i wygląda to troszkę irracjonalnie.
tehaha
Wydaje mi się, że przekombinowałeś sprawę, przede wszystkim nie dodałeś nic nowego oprócz innego ułożenia tablicy i foreach().

1. Twój sposób już teraz wydaje się mało czytelny, a wyobraź sobie sytuację, gdzie masz 8 języków i 900 komunikatów/słówek itp. - w każdej tablicy będzie trzeba oddzielnie doklejać klucz, a edycja czegoś to już w ogóle będzie bardzo trudna bo w tym gąszczu kluczy trzeba będzie znaleźć co trzeba.

2. Ten pierwszy sposób z oddzielnym plikiem z tablicą jest naprawdę bardzo skuteczny, ale faktycznie nie w takim wydaniu jak go zastałeś. Osobiście robię to tak:

- dla każdego języka oddzielny plik z tablicą np. pl.php, en.php, ru.php ładowany na podstawie języka ustawione w przeglądarce lub język ustawiony jako domyślny;
- tablice wielowymiarowe z podziałem na wiadomości, oraz treść użyta na sztywno w html, czyli $_LANG['msg'] = array(), $_LANG['html'] = array(), oraz inne w zależności od potrzeb.
- Każdy klucz ma w miarę logiczną nazwę(hasło) i jest w swojej sekcji, wygląda to mniej więcej tak:

  1. /* TOPIC */
  2. 'topic_no_title'=>'Nie podano tytułu',
  3. 'topic_no_desc'=>'Nie podano treści',
  4. 'topic_not_logged'=>'Musisz się zalogować, aby dodać temat.',
  5.  
  6. /* GALLERY */
  7. 'gallery_no_label'=>'Nie podano tytułu',
  8. 'gallery_not_logged'=>'Musisz się zalogować, aby dodać galerię.',
  9. 'gallery_wrong_image'=>'Nie poprawny format obrazka, tylko: JPG, JPEG, GIF, PNG',
  10.  
  11. itd.


- jak potrzebne jest tłumaczenie to wysyłasz plik z tablicą do tłumacza i on odsyła przetłumaczony, nie wyobrażam sobie, żeby tłumacz miał sam doklejać klucze to wielowymiarowych tablic;
- jeżeli chcesz się zabezpieczyć przed ewentualnym brakiem klucza to wystarczy mieć dodatkowy plik np. default.php i ładować tłumaczenie funkcją http://php.net/manual/en/function.array-replace.php - wtedy brakujące klucze będą pochodziły z default.php
markonix
Przekonałeś mnie wink.gif
enviro
Zagadnienie obsługi wielu języków to ... a ciekawy temat.

W Twojej wersji kodu użycie samego foreach jest nieoptymalne (lepiej używać for'a na podstawie już obliczonego rozmiaru tablicy).

Jednak dla stron typu wizytówka, gdzie ilość tłumaczonego tekstu jest niewielka, można użyć dwóch rozwiązań.

1. Klasa odczytująca z pliku XML wartości (lepsza metoda).

2. Stworzenie trzech plików 'pl.lang', 'en.lang', 'de.lang' i zawarcie w nich stałych, np.:
define('__HELLO__', 'Witaj');

I w zależności od zmiennej $lang robisz require_once pliku językowego.

A wszędzie używasz tych samych stałych.
toaspzoo
Wg mnie nie wygląda to zbyt ciekawie, ponadto jest o niebo wolniejsze od zastosowania zwykłej tablicy dla zmiennej $lang.
Nie prościej by było zakomentować linie, w których wywołujesz tłumaczenie ?
!*!
Zamiast pętli użyłbym funkcji vsprintf na tablicy.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.