PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : GNU gettext



SeeksTheMoon
07-11-2003, 12:35
Ich habe hier mal gefragt, wie man mit gettext umgeht, aber niemand wußte was dazu.

Mit gettext kann man ganz einfach Programmausgaben lokalisieren/übersetzen und so ziemlich jedes GNU-Linux Programm macht Gebrauch davon (deshalb war ich überrascht, dass niemand etwas dazu sagen konnte).

Eigentlich ist es die beste und einfachste Methode für C/C++/(beliebige Programmiersprache)-Programme und funktioniert vom Prinzip her wie bei Java.

Leider ist die offizielle Doku bescheiden (viel zu groß und unverständlich) und auch sonst gibts im Netz nichts über gettext.

Nach mühsamer Suche hab ich endlich was dazu gefunden. Bevor sich jemand anders dumm sucht, habe ich aus meinem Fund die Essenz für den Programmierer herausgepickt (der Artikel umfaßt 70 Seiten und behandelt noch Dinge, die den normalsterblichen Programmierer nicht interessieren werden):


GNU gettext und locale Guide

Das Original gibts mit Demodateien auf http://www.kizito.uklinux.net/en_wanula.html
GNU gettext gibts hier:
http://www.gnu.org/software/gettext/gettext.html
und für win32 hier (es gibt 4 implementationen, man bekommt es auch auf der GNU FTP-Seite von gettext):
http://gettext.sourceforge.net/

Das große (und völlig unverständliche) Manual gibts hier:
http://www.gnu.org/software/gettext/manual/

gettext gibts auch für Perl und andere Sprachen, einfach mal googlen.


Locale:
Ein locale ist ein System, das Infos über verschiedene Sprachen und kulturelle Konventionen beinhaltet.
Eine der locale-Funktionen ist die Eigenschaft, Wörter einer Sprache anzubieten.
Diese werden in den "message" oder ".gmo" bzw. ".mo" Dateien gespeichert.

Man holt die Texte nun nicht selber aus diesen Dateien, sondern benutzt dafür gettext.
Kann es die Übersetzung in der .mo nicht finden, so zeigt es den Standard an.

locale ist ein Satz von Verzeichnissen, der die Sprachinfos beinhaltet.
Eine Sprache kann in mehreren Ländern/Kulturen gesprochen werden und sich dort unterscheiden.
In der Umgebungsvariable LC_ALL steht der Wert ll_cc (ll=language, cc=culture)
z.B. de_DE, de_AT
Die Codes stehen in der ISO 639. Unter Linux gibts das Kommando locale, dass die installierten locale-Codes anzeigt:
locale -a |less
Man kann auch im $localepath nachsehen, z.B. /usr/lib/locale
Wie das genau organisiert ist, steht im Abschnitt "Anatomy of a locale" in dem eigentlichen Guide.

GNU gettext:
gettext ist eine Hilfsfunktion, die den Text für einen besorgt:
statt printf("hallo"); schreibt man printf(gettext("hallo"));

====Einschub:
Auf der gettext-Seite wird folgendes empfohlen:


#include <libintl.h>
#include <locale.h>

#define _(string) gettext (string)


Dann kann man anstatt gettext("huhu") nur noch _("huhu") schreiben.
Vor der ersten Benutzung sollte man noch
setlocale("LC_ALL","de_DE"); aufrufen, gefolgt von
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
PACKAGE und LOCALEDIR kommen aus der config.h oder Makefile, oder man gibt sie fest vor.
====Ende Einschub

gettext sucht dann in $localepath/ll/LC_MESSAGES/ nach der Datei "programm.mo"
Dort steht dann die Übersetzung von "hallo" drin, die gettext ausliest und zurückgibt.

textdomain:
gettext weiß wo die message File liegt, aber es können auch mehrere dort liegen.
Welche davon genommen werden soll, das sagt textdomain:
textdomain("programm.mo");

Die .mo-Dateien sind aber Binärdateien. Als Vorlage dienen .po-Dateien, die einen einfachen Aufbau haben:



# Kommentarzeilen werden durch einen Lattenzaun eingeleitet
# Test für meine erste po
msgid "hello"
msgstr "hallo"

msgid "world!\n"
msgstr "Welt!\n"


msgid ist die id, die man der C-Funktion gettext() übergibt und gettext liefert dann den msgstr.

Damit man die .po-Dateien in die .mo Dateien umwandeln kann, braucht man zum "kompilieren" der po-Datei folgenden Befehl:

msgfmt -v -o example-a.mo example-a.po

Am besten gibt man in den Kommentaren immer an, aus welcher Datei und aus welcher Zeile im Quelltext der übersetzte Text ist.

=============================
=============================

Das wars auch schon. Hier nochmal in Kurzform:

C++ -Quelltext (statt cout für C++ kann man auch printf für C nehmen, das spielt für gettext keine Rolle):

#include <libintl.h>
#include <locale.h>

#define _(string) gettext (string)

#include <iostream>
using namespace std;

int main() {
setlocale ("LC_ALL", "de_DE"); //oder en_US oder sonstwas
//PACKAGE und LOCALEDIR kommen aus der config.h oder Makefile
//bindtextdomain (PACKAGE, LOCALEDIR); //bindtextdomain scheint nicht notwendig zu sein
textdomain ("de.mo");
cout<<_("hello")<<endl;
}

de.po:
msgid "hello"
msgstr "HALLO WELT!!"