Wprowadzenie
Często zdarza się, że chcesz, aby twoja aplikacja mogła mieć kilka (a nawet kilkanaście) wersji językowych, pytanie tylko, jak to zrobić? Pewnie wpadłeś na pomysł, aby stworzyć własne pliki językowe i ładować treść do zmiennych tekstowych, lecz takie rozwiązanie jest trochę niewygodne, gdy można użyć lepszego rozwiązania, jakim jest wykorzystanie biblioteki
gettext.
W tej lekcji chciałbym Ci pokazać najprostszy sposób jak zrobić tłumaczenie do swojej aplikacji GTK+. No to zaczynamy :).
Tworzymy prosty program
Stwórzmy najpierw jakiś prosty program, na którym można by przetestować działanie naszego tłumaczenia. Do lekcji polecam Ci podany poniżej kod, aby uniknąć błędów.
Aby skompilować poniższy kod, musisz dodać do linkowanych bibliotek intl.lib. Możesz ją znaleźć w katalogu lib biblioteki GTK+. |
Kod:
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#define GETTEXT_PACKAGE "foo"
#define LOCALEDIR "share/locale"
int main( int argc, char * argv[] )
{
bindtextdomain( GETTEXT_PACKAGE, LOCALEDIR );
bind_textdomain_codeset( GETTEXT_PACKAGE, "UTF-8" );
textdomain( GETTEXT_PACKAGE );
gtk_set_locale();
GtkWidget * okno, * vbox, * etykieta, * przycisk;
gtk_init( & argc, & argv );
okno = gtk_window_new( GTK_WINDOW_TOPLEVEL );
gtk_window_set_position( GTK_WINDOW( okno ), GTK_WIN_POS_CENTER );
gtk_window_set_default_size( GTK_WINDOW( okno ), 200, 50 );
gtk_window_set_title( GTK_WINDOW( okno ), "Kurs GTK+" );
etykieta = gtk_label_new( _( "Label" ) );
gtk_misc_set_alignment( GTK_MISC( etykieta ), 0.1, 0.5 );
przycisk = gtk_button_new_with_label( _( "Button" ) );
vbox = gtk_vbox_new( FALSE, 1 );
gtk_container_set_border_width( GTK_CONTAINER( vbox ), 10 );
gtk_container_add( GTK_CONTAINER( okno ), vbox );
gtk_box_pack_start( GTK_BOX( vbox ), etykieta, TRUE, TRUE, 2 );
gtk_box_pack_start( GTK_BOX( vbox ), przycisk, TRUE, TRUE, 2 );
gtk_widget_show_all( okno );
g_signal_connect( G_OBJECT( okno ), "destroy", G_CALLBACK( gtk_main_quit ), NULL );
gtk_main();
return 0;
}
Teraz czas na wyjaśnienie. Nowo dodanym nagłówkiem jest
#include <glib/gi18n.h>
. Trzema funkcjami ustawiamy domenę tekstu. Następnie ustawiamy '
locale'. Funkcja
void gtk_misc_set_alignment( GtkMisc * misc, gfloat xalign, gfloat yalign )
odpowiada za rozstawienie obiektu typu
GtkMisc (czyli również GtkLabel). Jako pierwszy argument przyjmuje widget, drugi to ustawienie na osi
x, a ostatni na osi
y.
Teraz najważniejsza funkcja (a właściwie makro) w naszym programie, którą jest właśnie
_( text )
, dzięki niej zaznaczamy tekst do tłumaczenia, który zostanie podmieniony w czasie, gdy program będzie uruchomiony. Więcej o tych makrach (tak, jest ich więcej ;)), możesz przeczytać w
dokumentacji GLib.
Przygotowanie pakietów językowych
Internacjonalizacja z użyciem gettext polega na pobieraniu przez program tekstów ze skompilowanych paczek językowych, co jest szybsze. Aby najwygodniej stworzyć takie paczki potrzebujesz programu xgettext lub nakładki na niego -
Poedit. Ja opiszę tworzenie tych pakietów z użyciem tego drugiego (graficznego).
Utwórzmy nowy pakiet w programie Poedit wybierając z menu '
Plik -> Nowy katalog ...'. Następnie w '
Ustawieniach projektu' w zakładce '
Informacje o projekcie' musimy wypełnić pole '
Projekt', które będzie nazwą pakietu, opcjonalnie wypełniamy pola:
Zespół, Adres e-mail. W zakładce '
Ścieżki' dodajemy katalogi, z których Poedit wyszuka źródła naszego programu, aby wyszukać zadeklarowane w trzeciej karcie słowa kluczowe (funkcji). W tejże karcie dodajemy przynajmniej jedną ścieżkę (jeśli plik .po będzie obok naszych źródeł, ustaw ścieżkę tak jak na obrazku.
Jeśli wykonałeś poprawnie to co wcześniej napisałem, powinien wyskoczyć dialog zapisu pliku, zapisz go tam, gdzie Ci pasuje (
Pamiętaj o ścieżkach!).
Następnie Poedit powinien wyszukać wyróżnione stringi w naszym kodzie, a następnie pokazać nam taki oto dialog:
Potwierdź go klikając 'OK'.
Tłumaczenie
Tłumaczenie tekstów w Poedit jest banalnie proste i intuicyjne, wystarczy kliknąć obok, lub na wybrany przez nas obiekt i przetłumaczyć go w polu tekstowym znajdującym się niżej. Po stringach możemy poruszać się za pomocą skrótu klawiszowego '
Tab + Strzałka w górę lub w dół'. Przetłumaczmy więc nasze 2 stringi na język polski (można stworzyć więcej pakietów, dla innych języków). A następnie zapiszmy nasz projekt, co jest równoznaczne z utworzeniem binarnego pliku z tłumaczeniem, z którego będzie korzystała nasza aplikacja.
Konfiguracja
Pora, by użyć naszego tłumaczenia. Wg ustawionej ścieżki w kodzie (u nas 'share/locale') musimy utworzyć odpowiednie foldery obok naszego programu. Pierwsze folder
share, w nim
locale. W katalogu locale tworzymy katalogi odpowiadające językom, czyli dla języka polskiego: pl, angielskiego: en, itd. Pełną listę znajdziesz na
stronie w3schools, przy czym dla j.angielskiego nie musimy tworzyć tłumaczenia, gdyż wszystkie teksty zostały przez nas napisane w tymże języku. Utwórzmy więc katalog '
pl' i jeśli jak ja utworzyłeś pakiet dla języka niemieckiego stwórz folder '
de'. W każdym folderze odpowiadającemu danemu językowi utwórz katalog o nazwie '
LC_MESSAGES'. Następnie przejdź do folderu, gdzie zapisałeś pakiet i zmień nazwę pliku z rozszerzeniem
.mo na nazwę pakietu, czyli '
foo.mo'. Skopiuj plik ze zmienioną nazwą do katalogu '
LC_MESSAGES'.
Jeśli wszystko poprawnie wykonałeś, po uruchomieniu powinna się pokazać aplikacja w polskiej wersji językowej (oczywiście tylko wtedy, gdy język systemu jest ustawiony na
pl).
Podsumowanie
Jak można się domyślić, internacjonalizacja programów jest bardzo przydatna w tworzeniu aplikacji. Tłumacząc program zyskujesz dodatkowe grono użytkowników, dla których jedna wersja językowa jest niewystarczająca, więc takie działanie jest opłacalne :)