PHP Anwendungen lokalisieren mit Gettext
Viele standen mit Sicherheit schon einmal vor dem Problem: eine Web-Anwendung muss in mehreren Sprachen bereitgestellt werden.
Dabei möchte man es denn Übersetzern natürlich möglichst einfach gestalten und das Script so schreiben, dass eine weitere Sprache im Nachhinein im System einzupflegen einen möglichst geringen Aufwand bereitet.
Ansätze gibt es mehrere. Eine Möglichkeit ist die Sprachvariablen in ein Array auszulagern…
<?php if (!is_array($lang) || empty($lang)) { $lang = array(); } $lang = array_merge( 'post_geloescht' => 'Dieser Eintrag wurde leider geloescht', 'post_hinzufuegen' => 'Einen neuen Eintrag hinzufuegen', ); ?>
Und im Maincode dann beispielsweise…
<?php // Natürlich ist dieser Code in echten Projekten tödlich für die Sicherheit // Nur als Beispiel, es fehlen diverse Checks gegen Remote Inclusions $user_lang = (isset($_SESSION['user_language']) && !empty($_SESSION['user_language'])) ? $_SESSION['user_language'] : ''; $user_lang = (!empty($user_lang) && is_file(dirname(__FILE__) . '/language/main_' . $user_lang . '.php')) ? $user_lang : 'de'; include_once dirname(__FILE__) . '/language/main_' . $user_lang . '.php'; echo $lang['post_geloescht']); ?>
Jeder Entwickler muss, sofern er eine neue Sprachvariable braucht, diese in zwei verschiedenen Teilen des Codes einfügen. Dann natürlich noch jeweils eine zusätzliche Änderung pro weiteres Sprachpaket – nicht allzu komfortabel. Zudem ist dieses Konzept auch noch recht fehleranfällig, insbesondere weil wir Programmierer ja meistens eher Schreibfaul sind. 😉
Zusätzlich muss man den Fall absichern, dass ein Übersetzer ein Feld im Array komplett aus seiner Übersetzung vergessen hat.
Bei kleinen Projekten ist das alles durchaus akzeptabel. Problematisch wird es eher, wenn man mehrere hundert Variablen speichern muss.
Lokalisierung mit setlocale
Diese Methode wird bei diversen größeren quell offenen Scripten wie auch Beispielsweise WordPress verwandt.
Mit den gettext Tools kann automatisch ein Übersetzungstemplate generiert werden. Dieses kann man dem Übersetzungsteam bei jedem neuen Release einfach zusenden und fertig.
Eine schöne Sache ist dabei, dass man sich auch nicht mehr um einen Fallback kümmern muss. Falls ein Feld in der Sprachdatei nicht existiert oder im worst case das Sprachfile nicht gelesen werden kann wird der „Standard“ (nicht übersetzte) Text ausgegeben.
Der größte Vorteil liegt jedoch darin, dass man, sofern man gettext von Anfang an in seine Scripte einpflegt, mit niedrigsten Aufwand eine Anwendung auch noch später lokalisieren kann – vielleicht ohne das dies Anfangs überhaupt geplant war.
<?php setlocale(LC_ALL, 'de_DE'); // Sprache auf Deutsch stellen bindtextdomain('messages', './locale'); // Pfad der Uebersetzungstabellen textdomain('messages'); // Domain auswaehlen echo _('Hello World'); // Beispiel Ausgabe (_() ist der Alias zu gettext()) ?>
Aus diesem Code kann man sich nun mittels des folgenden Befehls ein Übersetzungstemplate generieren lassen:
root@localhost: xgettext index.php
Dieses File kann man nun seinen Übersetzern zukommen lassen. Wichtig ist hier vor allem, dass der der Zeichensatz angepasst wird. Fertig sieht das ganze etwa so aus:
# German Translation for MyProject # Copyright (C) 2010 MyProject Translation Team # This file is distributed under the same license as the MyProject package. # Tom Riddle >n;foobar@example.com<n;, 2010. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: 1.0\n" "Report-Msgid-Bugs-To: bugs@example.com\n" "POT-Creation-Date: 2010-02-22 22:42+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Tom Riddle foobar@example.com\n" "Language-Team: de_DE foo@li.org\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" #: index.php:14 msgid "Hello World" msgstr "Hallo Welt"
Ist das geschafft muss das Template „kompiliert“ werden, sprich in Maschinensprache übersetzt werden. Das geschieht mit diesem Befehl:
root@localhost: msgfmt -o messages.mo messages.po
Man erhält nun eine Datei messages.mo. Diese verschiebt man nach locale/de_DE/LC_MESSAGES/messages.mo.
Wenn man nun die Anwendung startet sollte „Hallo Welt“ auf dem Schirm erscheinen. Gibt es irgendeinen Fehler, oder wurde das File nicht gefunden erscheint „Hello World.“
Alternative Tools für das bearbeiten der Sprachfiles
Weitere Infos gibt es in der PHP Doku auf den Seiten zu Gettext.