Babelskript

Skripte glänzen selten durch ausführliche Mitteilungen. Das Programm gettext aus dem gleichnamigen Gnu-Paket kann dem abhelfen.

In Pocket speichern vorlesen Druckansicht 1 Kommentar lesen
Lesezeit: 4 Min.
Von
  • Thomas Freudenberg

Unix-Nutzer setzen häufig Shell-Skripte ein, um Routineaufgaben zu vereinfachen. Allerdings lässt deren „User Interface“ oft zu wünschen übrig - vor allem mangelt es an ausführlichen Meldungen in verständlicher (deutscher) Sprache. Mit gettext lassen sie sich leicht hinzufügen - sogar nachträglich.

Ein Aufruf von gettext ähnelt dem von echo. Vor der Ausgabe der Meldung jedoch sieht das Programm in einer Sprachdatei nach, ob es eine Übersetzung gibt: gettext "Hello, world!" könnte mit einer deutschen Sprachdatei den Text „Hallo, Welt!“ ausgeben. Findet das Programm keine Übersetzung, gibt es den Ursprungstext aus. Das erlaubt es dem Programmierer, Skripte nachträglich zu lokalisieren.

Schwierigkeiten verursacht gettext, wenn der Text Variablen enthält. Ändert sich deren Wert, ändert sich auch der Schlüssel für die Übersetzung. Die Shell-Funktion eval_gettext hingegen sucht erst die Übersetzung und setzt anschließend die Werte der Variablen ein. Um zu verhindern, dass die Shell ihr zuvorkommt, sollte der Programmierer den Text in einfache Anführungszeichen setzen.

Mehr Infos

Am Anfang seines eigenen Skripts muss der Entwickler das zum Gnu-Paket gehörende gettext.sh einbinden. Danach kann er eval_gettext verwenden. Leider gibt die Funktion ebenso wie gettext kein abschließendes Return aus. Dem kann man jedoch abhelfen, indem man den übersetzten Text zum Beispiel an echo übergibt: echo $(eval_gettext ’Hello, World!’).

Um zu vermeiden, dass böswillige Nutzer über eine manipulierte Sprachdatei eigenen Code in das Skript einschleusen, setzt eval_gettext nur die Werte derjenigen Variablen ein, die bereits im Originaltext vorkommen.

Neben gettext enthält das Gnu-Paket mehrere Werkzeuge zum Erstellen von Sprachdateien, den sogenannten „Message Catalogs“. Mit xgettext kann der Entwickler die zu übersetzenden Texte aus seinem Quellcode extrahieren. Das Programm schreibt sie in die Datei messages.po im Arbeitsverzeichnis. Mit -o kann der Nutzer ein anderes Ziel bestimmen. Üblicherweise verwendet man dafür einen Namen mit der Endung .pot (Portable Object Template).

Aus der Template-Datei erzeugt msginit für jede Sprache eine separate Textdatei, das Portable Object mit der Endung .po. Spätere Änderungen an der POT-Datei lassen sich mit msgmerge in die PO-Datei einpflegen, ohne dass bereits übersetzte Passagen verloren gehen.

Hat der Übersetzer seine Arbeit beendet, erzeugt msgfmt aus dem Portable Object ein binäres Machine Object, (.mo) für gettext. Das erwartet normalerweise die Dateien in einem Systemverzeichnis, meist unter /usr/share/locale//LC_MESSAGES/.mo. Für setzt man üblicherweise den Namen des Programms ein, für ein Kürzel wie de oder de_DE.

Wer in /usr/share/locale nicht schreiben darf, muss anderswo einen Platz für die Sprachdateien reservieren, etwa im gleichen Verzeichnis wie das Skript. Mit den Variablen TEXTDOMAINDIR und TEXTDOMAIN kann man gettext die genaue Lage mitteilen (siehe Listing 1).

Mehr Infos

Listing 1: HelloWorld.sh

#!/bin/sh
. gettext.sh
export TEXTDOMAIN="$(basename $0)"
export TEXTDOMAINDIR="$(dirname $0)/locale"
echo $(eval_gettext 'Hello, world!')

Im Installationsverzeichnis muss der Nutzer mit mkdir -p locale/de/LC_MESSAGES die nötigen Unterverzeichnisse für die Sprachdatei anlegen. Anschließend kann er mit xgettext -o HelloWorld.sh.pot HelloWorld.sh die enthaltenen Texte extrahieren. msginit - -locale=de - -input=HelloWorld.sh.pot -o HelloWorld.sh.de.po erzeugt eine PO-Datei für die deutsche Übersetzung.

Zu Beginn enthält die PO-Datei neben diversen Angaben zum Projekt nur die Originalmeldungen:

#: HelloWorld.sh:5
#, sh-format
msgid "Hello, world!"
msgstr ""

Nach dem Schlüsselwort msgstr kann der Übersetzer den gewünschten Text eintragen. Bleibt die Zeichenkette leer, gibt gettext den Originaltext aus.

Abschließend muss der Nutzer mit msgfmt -o locale/de/LC_MESSAGES/HelloWorld.sh.mo HelloWorld.sh.de.po die binäre Sprachdatei generieren und im passenden Unterverzeichnis installieren. Startet er danach das Skript mit LANG=de_DE ./HelloWorld.sh, sollte es die Welt auf Deutsch begrüßen.

Neben einer Übersetzung in andere Sprachen erlaubt gettext auch das Trennen von Programm und ausführlichen Meldungen. Im Programm sollte man dafür kurze englische Texte als Schlüssel verwenden und die lange Fassung in der jeweiligen Sprachdatei nachreichen. Es bietet sich an, auch für die englische Ausgabe eine Sprachdatei anzulegen. So kann man lange Passagen mit Kommandos wie echo $(eval_gettext ’Help’) abkürzen.

Zum Bearbeiten von PO-Dateien gibt es eine Reihe von Werkzeugen, etwa poEdit, KBabel, gtranslator oder das Eclipse-Plug-in gted. Für den Gnu-Editor emacs existiert ebenfalls eine Erweiterung (po-mode) zum Editieren von PO-Dateien.

Thomas Freudenberg
ist Vorstand der 4commerce technologies AG in Hamburg. (mr)