38.5 Lokalisierung von Programmen – gettext
Das Modul gettext der Standardbibliothek ist bei der Internationalisierung und Lokalisierung von Python-Programmen von Nutzen. Mit Internationalisierung wird der Vorgang bezeichnet, die Benutzerschnittstelle eines Programms so zu abstrahieren, dass sie leicht an andere sprachliche oder kulturelle Umgebungen angepasst werden kann. Als Lokalisierung wird das Anpassen des Programms an die Gegebenheiten eines bestimmten Landes oder einer Region bezeichnet. Beachten Sie, dass sich das Modul gettext dabei auf die Übersetzung von Strings beschränkt. Andere Unterschiede, wie etwa Datumsformate oder Währungssymbole, werden nicht berücksichtigt.
Das Modul gettext lehnt sich an die GNU gettext API[ 180 ](http://www.gnu.org/s/gettext) an, die als Teil des GNU-Projekts weitverbreitet ist und die rein sprachliche Anpassung eines Programms gewährleistet. Das Modul erlaubt es, eine möglichst genaue Nachbildung der GNU gettext API zu verwenden. Zudem ist eine gegenüber der GNU gettext API etwas abstraktere, objektorientierte Schnittstelle vorhanden, auf die wir uns in diesem Abschnitt beziehen werden.
Zunächst ein paar Worte dazu, wie die Lokalisierung eines Programms vonstattengeht. Der Programmierer schreibt sein Programm, in dem die Benutzerführung vorzugsweise in englischer Sprache erfolgt. Zur Lokalisierung des Programms wird jeder String, der ausgegeben werden soll, durch eine sogenannte Wrapper-Funktion geschickt. Das ist eine Funktion, die den nicht lokalisierten englischen String als Parameter übergeben bekommt und die passende Übersetzung zurückgibt.
Intern verwendet gettext zur Übersetzung verschiedene Sprachkompilate. Das sind Binärdateien, die die Übersetzung des Programms in jeweils eine bestimmte Sprache enthalten. Diese Binärdateien werden aufgrund ihrer Dateiendung .mo-Dateien genannt. Wie diese Dateien erzeugt werden, ist unter anderem Inhalt des nächsten Abschnitts.
38.5.1 Beispiel für die Verwendung von gettext
Internationalisierung spielt immer dann eine Rolle, wenn ein Programm veröffentlicht und somit einer großen Gruppe von Anwendern zugänglich gemacht wird. Dabei ist es besonders bei Open-Source-Projekten üblich, dass das Programm ursprünglich nur in einer oder zwei Sprachen veröffentlicht wird und weitere Übersetzungen später von den Anwendern erstellt und an den Autor geschickt werden. Damit das funktioniert, sollte der Programmierer zumindest die Übersetzbarkeit seines Programms gewährleisten.
An dieser Stelle zeigen wir Ihnen die Verwendung von gettext an einem kleinen Beispielprogramm. Der Quellcode des Beispielprogramms sieht folgendermaßen aus:
import gettext
import random
trans = gettext.translation("meinprogramm", "locale", ["de"])
trans.install()
werte = []
while True:
w = input(_("Please enter a value: "))
if not w:
break
werte.append(w)
print(_("The random choice is {}").format(random.choice(werte)))
Das Programm selbst ist unspektakulär – es liest so lange Strings vom Benutzer ein, bis einer dieser Strings leer ist, der Benutzer also (¢) gedrückt hat, ohne eine Eingabe vorzunehmen. Dann wählt das Programm zufällig einen dieser Strings und gibt ihn aus. Mit diesem Programm könnte also beispielsweise eine zufällig gewählte Person einer Gruppe für den nächsten Samstagabend zum Fahrer ernannt werden. Die Interaktion mit dem Benutzer erfolgt ausschließlich auf Englisch, jeder String, der ausgegeben wird, wird aber vorher durch eine Funktion namens _ geschickt.
[»] Hinweis
Bei der print-Ausgabe am Ende des Beispielprogramms wird die Funktion _ für einen mit einem Platzhalter behafteten String aufgerufen, bevor dieser Platzhalter durch dynamischen Inhalt ersetzt wird. Das ist wichtig, da sonst keine Übersetzung erfolgen kann.
Der eigentlich interessante Teil des Programms sind die beiden Zeilen nach den import-Anweisungen:
trans = gettext.translation("meinprogramm", "locale", ["de"])
trans.install()
Hier wird ein sogenanntes Translation-Objekt erstellt. Das ist eine Instanz, die die Übersetzung aller Strings in eine bestimmte Sprache gewährleistet. Um ein solches Objekt zu erstellen, wird die Funktion gettext.translation aufgerufen. Diese bekommt einen frei wählbaren Namen, die sogenannte Domain, als ersten Parameter. Der zweite Parameter ist das Unterverzeichnis, in dem sich die Übersetzungen befinden, und der dritte Parameter ist schließlich eine Liste von Sprachen. Das Translation-Objekt übersetzt nun in die erste Sprache aus der Liste, für die ein Sprachkompilat gefunden werden kann.
Durch Aufruf der Methode install des Translation-Objekts installiert dieses seine interne Übersetzungsmethode als Funktion _ im lokalen Namensraum. Damit werden alle Strings, mit denen die Funktion _ aufgerufen wird, in die Sprache übersetzt, für die das Translation-Objekt steht, sofern denn eine Übersetzung verfügbar ist.
[»] Hinweis
Es ist möglich, mehrere Translation-Objekte anzulegen und im Laufe des Programms verschiedene dieser Objekte zu installieren. Strings werden dann mithilfe des jeweils aktuell installierten Translation-Objekts übersetzt.
38.5.2 Erstellen des Sprachkompilats
Zum Erstellen des Sprachkompilats müssen Sie zunächst eine Liste aller zu übersetzenden Strings erstellen. Das sind all jene, die vor der Ausgabe durch die Funktion _ geschickt werden. Da es eine unzumutbare Arbeit wäre, diese Liste von Hand anzufertigen, ist in Python ein Programm namens pygettext.py[ 181 ](Unter Windows finden Sie das Programm pygettext.py im Unterordner Tools/i18n Ihrer Python-Installation. Unter Unix-ähnlichen Betriebssystemen wie beispielsweise Linux sollte sich die Programmdatei im Systempfad befinden und direkt ausführbar sein.Möglicherweise installiert Ihre Linux-Distribution das Programm pygettext.py von Python 3 unter einem veränderten Namen, beispielsweise pygettext3.py, um die parallele Installation von Python 2 und 3 zu ermöglichen. ) im Lieferumfang enthalten, das genau dies für Sie erledigt. Das Programm erstellt eine sogenannte .po-Datei. Das ist eine für Menschen lesbare Variante des .mo-Dateiformats. Diese .po-Datei wird dann von den Übersetzern in verschiedene Sprachen übersetzt. Dies kann von Hand geschehen oder durch Einsatz diverser Tools, die für diesen Zweck erhältlich sind. Die für unser Beispielprogramm erstellte .po-Datei sieht folgendermaßen aus:[ 182 ](Dabei sind nur die deutschsprachigen Inhalte der Datei manuell hineingeschrieben worden. Der Rest wurde mithilfe von pygettext automatisch erzeugt. )
[…]
#: main.py:9
msgid "Please enter a value: "
msgstr "Bitte geben Sie einen Wert ein: "
#: main.py:13
msgid "The random choice is {}"
msgstr "Die Zufallswahl ist {}"
Anstelle der Auslassungszeichen enthält die Datei Informationen wie etwa den Autor, die verwendete Software oder das Encoding der Datei.
Eine übersetzte .po-Datei wird durch das Programm msgfmt.py[ 183 ](Unter Windows finden Sie das Programm msgfmt.py im Unterordner Tools/i18n Ihrer Python-Installation. Unter Unix-ähnlichen Betriebssystemen wie beispielsweise Linux sollte sich die Programmdatei im Systempfad befinden und direkt ausführbar sein. Hier gilt derselbe Hinweis wie bei pygettext.py. ), das ebenfalls zum Lieferumfang von Python gehört, in das binäre .mo-Format kompiliert. Ein fertiges Sprachkompilat muss sich in folgendem Ordner befinden, damit es von gettext als solches gefunden wird:
Programmverzeichnis/Unterordner/Sprache/LC_MESSAGES/Domain.mo
Der Name des Verzeichnisses Unterordner wird beim Aufruf der Funktion gettext.translate angegeben und war in unserem Beispiel locale. Dieses Verzeichnis muss für jede vorhandene Sprache ein weiteres Verzeichnis enthalten, das seinerseits über ein Unterverzeichnis LC_MESSAGES verfügen muss. Das Sprachkompilat selbst muss die im Programm angegebene Domain als Namen haben.
In unserem Beispielprogramm muss das Sprachkompilat also in folgendem Verzeichnis liegen:
Programmverzeichnis/locale/de/LC_MESSAGES/meinprogramm.mo
Wenn das Sprachkompilat nicht vorhanden ist, wird beim Aufruf der Funktion gettext.translation eine entsprechende Exception geworfen:
Traceback (most recent call last):
[…]
FileNotFoundError: [Errno 2] No translation file found for domain: 'meinprogramm'
Wenn das Sprachkompilat an seinem Platz ist, werden Sie beim Ausführen des Programms feststellen, dass alle Strings ins Deutsche übersetzt wurden:
Bitte geben Sie einen Wert ein: Donald Duck
Bitte geben Sie einen Wert ein: Daisy Duck
Bitte geben Sie einen Wert ein: Onkel Dagobert
Bitte geben Sie einen Wert ein:
Die Zufallswahl ist Donald Duck