Napisany sty-15-2009

i18n z użyciem gettext

Niekiedy zdarza się sytuacja, w której aplikacja webowa będzie dostępna w kilku językach. Proponowane przeze mnie rozwiązanie pozwoli nam, w łatwy sposób opracować wiele wersji narodowych naszego oprogramowania.

wymagania

Na samym początku musimy sprawdzić, czy php może korzystać z rozszerzenia gettext. Dokonamy tego poprzez wykonanie poniższego skryptu:

phpinfo();

Kolejnym punktem jest pobranie oprogramowania gettext. Istnieją oczywiście wersje na różne systemy operacyjne. Ja skorzystam z tej dla Windows’a. Można ją znaleźć TUTAJ. Po udanym zainstalowaniu możemy śmiało stwierdzić, że spełniliśmy wszystkie wymagania natury technicznej. Czas przejść do implementacji.

prosty przykład

Zobaczmy jak wygląda najprostszy skrypt lang.php bez obsługi wielojęzycznej.

echo 'czesc';

Teraz postarajmy się go tak przerobić, by mógł korzystać z omawianego rozwiązania:

// en_US wykorzystawane w sciezce
// UWAGA wywolanie setlocale() musi sie udac!
// Warto sprawdzac co zwraca ow funkcja!!!!
// Pamietaj ze na roznych serwerach
// ustawienie tej opcji moze wygladac inaczej
setlocale(LC_ALL,'en_US.UTF8');

// messages wykorzystwane w sciezce
// do pliku - jest to jego nazwa messages.mo
$my_name = 'messages';

// wiazemy nazwe messages z katalogiem
// gdzie znajdowac sie beda tlumaczenia
bindtextdomain($my_name,'./locale');

// ustalamy aktywna domene
// korzysta z niej gettext
textdomain($my_name);

// alias tej funkcji to _("czesc")
echo gettext("czesc");

Przejdźmy do szczegółowej analizy tego co znajduje się powyżej. Setlocale() umożliwia nam określenie lokalnych ustawień językowych. Zmienna $my_name to tzw. domena aplikacji. Bindtextdomain() wiąże ów nazwę z konkretną lokalizacją, przeszukiwaną w celu odnalezienia przełożonych fraz. Co jednak ważne, opisane dotychczas kroki okazują się konieczne, gdyż na ich podstawie wyznaczana jest ścieżka do pliku tłumaczeń. Popatrzmy:

./locale/en_US/LC_MESSAGES/messages.mo

Textdomain() ustala aktywną domenę, która będzie używana przy wywołaniach gettext() - funkcji, która w parametrze otrzymuje łańcuch znaków do przetłumaczenia.

W kolejnym etapie musimy wygenerować plik *.po, który zawierać będzie wszystkie string’i z skryptu lang.php wymagające przełożenia. Wykorzystujemy pobrane oprogramowanie gettext, a dokładniej xgettext. W moim przypadku wszystko sprowadzi się do jednego polecenia:

D:\gettext>”C:\Program Files (x86)\GnuWin32\bin\xgettext.exe” -o messages.po -n
–from-code utf8 lang.php

Oto co otrzymamy - messages.po:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE’S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR , YEAR.
#
#, fuzzy
msgid “”
msgstr “”
“Project-Id-Version: PACKAGE VERSION\n”
“Report-Msgid-Bugs-To: \n”
“POT-Creation-Date: 2009-01-17 12:21+0100\n”
“PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n”
“Last-Translator: FULL NAME \n”
“Language-Team: LANGUAGE \n”
“MIME-Version: 1.0\n”
“Content-Type: text/plain; charset=CHARSET\n”
“Content-Transfer-Encoding: 8bit\n”

#: lang.php:18
msgid “czesc”
msgstr “”

Jak widać msgid zawiera oryginalne frazy, natomiast naszym zadaniem jest wprowadzenie tłumaczeń w msgstr, oraz ewentualnych zmian w nagłówku. Końcowy efekt:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE’S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR , YEAR.
#
#, fuzzy
msgid “”
msgstr “”
“Project-Id-Version: PACKAGE VERSION\n”
“Report-Msgid-Bugs-To: \n”
“POT-Creation-Date: 2009-01-17 12:21+0100\n”
“PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n”
“Last-Translator: FULL NAME \n”
“Language-Team: LANGUAGE \n”
“MIME-Version: 1.0\n”
“Content-Type: text/plain; charset=utf-8\n”
“Content-Transfer-Encoding: 8bit\n”

#: lang.php:18
msgid “czesc”
msgstr “hello”

Pozostaje generacja messages.mo. Z pomocą przychodzi nam msgfmt. U mnie wystarczy wykonanie poniższej komendy z cmd:

D:\gettext>”C:\Program Files (x86)\GnuWin32\bin\msgfmt.exe” -o messages.mo messages.po

To wszystko! Na koniec umieszczamy plik messages.mo w odpowiedniej lokalizacji i uruchamiamy skrypt lang.php. Działający kod wraz z dodatkowymi uwagami znajdziecie TUTAJ.

Tagi : , ,

Komentarze:

Napisz komentarz