i18n für your.trash.net


Von Roman (romanf auf trash.net)


Unsere Mitglieder Self-Service (https://your.trash.net/) wurde von Anfang an auf Mehrsprachigkeit (Internationalization = i18n, weil zwischen I und N 18 Buchstaben liegen) ausgelegt. Dieser Artikel beschreibt, wie dies in PHP mit den Bordmitteln von Unix/Linux (Stichwort GNU gettext) umgesetzt wurde.

*nix Grundlagen

Der Wikipedia-Artikel beschreibt die Grundlagen ziemlich erschöpfend: https://de.wikipedia.org/wiki/GNU_gettext

Für your.trash.net haben wir folgende Verzeichnis-Struktur aufgesetzt (für bessere Lesbarkeit etwas verkürzt):

/your/ = Basis-Verzeichnis von your.trash.net
/your/www = Webroot für die virtuelle Domain your.trash.net
/your/locale/ = Basis-Verzeichnis für die i18n Files
/your/locale/source = Ausgangsfile your.pot, sowie die Klartext-Übersetzungen (your_de.po, your_fr.po, ...)
/your/locale/de/LC_MESSAGES/your.mo = Kompiliertes Sprachfile für Deutsch
/your/locale/fr/LC_MESSAGES/your.mo = ...

In unserem Fall ist die Original-Sprache in den PHP-Files Englisch. Darum brauchts auch keine .../en/... Struktur.

Workflow

Immer wenn ein Text im Source-Code neu hinzugefügt oder geändert wird, müssen die folgenden Schritte ausgeführt werden:

  1. xgettext: Sammelt aus allen PHP-Files die in _(...) gekapselten Strings ein und speichert diese im your.pot File
  2. msgmerge: Führt die Strings aus 1. mit den bereits übersetzten Strings zusammen. Dies ergibt geänderte <lang>.po Files
  3. Die Übersetzer übersetzen/korrigieren die .po Files (z.B. mit PoEdit)
  4. msgfmt: Die .po Files werden zu .mo Files kompiliert

Zu beachten ist, dass beim ersten Durchgang leere .po Files erzeugt werden müssen. Das geht nicht mit dem msgmerge Befehl, sondern mit msginit.

Dieser Workflow sowie das Setup der Verzeichnisstruktur ist noch völlig unabhängig von der gewählten Programmiresprache!

Der Einfachheit halber, haben wir diese Befehle in einem kleinen Skript in /your/ zusammengefasst. Dabei werden immer die Schritte 1, 2 und 4 ausgeführt:

cd /your/www
xgettext -d your_trash_net -L PHP --from-code=UTF-8 -o ../locale/source/your_trash_net.pot $(find -name "*.php")

cd ../locale/source
msgmerge -U your_de_DE.po your.pot

msgfmt your_de_DE.po -o ../de_DE/LC_MESSAGES/your.mo

cd ../.. 

Da xgettext hier mit -L PHP aufgerufen wird, ist dieses Beispiel natürlich auf PHP zugeschnitten.

i18n in PHP

In PHP gibt es (was gibt es da nicht?) eine Integration der gettext Library: PHP Gettext Functions. In diesem Kapitel wird eine einfache Implementierung der Funktionalität zur Auswahl und Aktivierung von Übersetzungen gezeigt.

Es braucht 3 grobe funktionale Blöcke für die Auswahl und Aktivierung von Sprachen:

  • Aktivieren einer gewählten Sprache für die gettext Library (damit die gewünschte Sprache gezogen wird)
  • Auswahl der gewünschten Sprache im GUI
  • Persistente Speicherung der ausgewählten Sprache

Aktivieren einer Sprache

In unserem Beispiel wird die gewählte Sprache intern mit einem 2-Buchstaben-Kürzel (en, de, fr) geführt. Für gettext brauchts die längere Form, darum der Dreh über $supported. Der Rest sollte recht selbsterklärend sein.

$supported = array("en"=>"en_US", "de"=>"de_DE", "fr"=>"fr_FR");
$domain = "your_project";
if(!setlocale(LC_MESSAGES, $supported[$lang]))
exit("error_msg");
bind_textdomain_codeset($domain, "UTF-8");
bindtextdomain($domain, "/your/locale");
textdomain($domain);

Auswahl der Sprache im GUI

Damit der Anwender die Sprache wechseln kann, sollte im GUI entsprechende Schaltflächen vorgesehen sein. Ausserdem sollte - sofern noch keine Sprache gewählt ist und auch keine aus der Persistenz (s. unten) verfügbar ist - ein sinnvoller Default gewählt werden. Hierzu kann man z.B. aus dem Browser-Request HTTP_ACCEPT_LANGUAGE auswerten.

Persistente Speicherung der Sprachwahl

Damit die vom User gewählte Sprache auch erhalten bleibt, bieten sich die üblichen Verdächtigen an: Session, Cookie, Datenbank. Für your.trahs.net ist die Wahl auf Cookie gefallen.

Die gewählte Sprache wird also in einem Cookie beim User abgelegt. Das hat den Vorteil, dass sogar vor der Authentisierung die Sprache schon korrekt gezogen wird. Nachteil ist natürlich, dass Cookie-Allergische User immer auf Englisch bleiben.