Mit SilverStripe nach Babylon II

Zur Zeit entwickele ich zusammen mit Sascha und Sebastian ein SilverStripe-Modul, das kurz vor der Veröffentlichung steht. Einer der letzten Schritte ist die Implementierung der Mehrsprachigkeit. Dazu müssen allte Texte und Wörter aus Klassen und Templates, die im Frontend oder Backend erscheinen, durch eine Funktion ersetzt werden. Diese Funktion(_t()) setzt je nach eingestellter Sprache dann die passenden Sprachkonstanten ein.

Text Collector

Die erste Hürde, die es dabei zu nehmen gilt, ist der innere Schweinehund, denn bei diesem Arbeitsschritt handelt es sich größtenteils um eine Fleißarbeit. Jetzt da ich fertig bin, habe ich über 600 mal Text durch die _t()-Funktion ersetzt. Hilfe gibt es beim Erstellen der Sprachkonstanten vom "Text Collector". Dieser liest die Aufrufe der _t()-Funktion in allen Templates und Klassen und erstellt eine entsprechende Zeile in der Datei /lang/de_DE.php, dem sogenannten Sprachpaket. Der Text Collector wird mit folgender URL aufgerufen:

http://<mysite>/dev/tasks/i18nTextCollectorTask/?module=<modulename>

Da ich zum ersten mal mit dem Text Collector gearbeitet hatte, wusste ich nicht, dass er dass Sprachpaket der in der _config.php eingestellten Standardsprache beschreibt, denn ich hatte dummerweise alle _t()-Funktionen mit englischem zweiten Parameter befüllt. Hier ein Beispiel:

_t('DataPage.TITLE', 'my data')

Der Text Collector macht daraus im Sprachpaket folgende Zeile:

$lang['de_DE']['DataPage']['TITLE'] = 'my data';

Der Text Collector verarbeitet zudem automatisch die Klassenattribute $singular_name und $plural_name. Diese müssen an keiner Stelle mit _t() dynamisiert werden, denn das Framework ersetzt die Klassenattribute automatisch, wenn sie mit dem Bezeichner SINGULARNAME bez. PLURALNAME im Sprachpaket vorhanden sind. Hier ein Beispiel:

$lang['de_DE']['DataPage']['SINGULARNAME'] = 'my data'

Der Wert 'My data' kam dabei aus der Klassenkonstanten $singular_name:

class DataPage extends Page {

public static $singular_name = "My data";

Die anderen statischen Attribute

In PHP ist es nicht möglich einem statischen Attribut einer Klasse in der Definition einen dynamischen Wert zuzuweisen. Das muss im Constructor erfolgen. Auf diese weise lassen sich Attribute wie $field_label übersetzen:

public function __construct($record = null, $isSingleton = false) {


self::$field_labels = array(


'Title' => _t('Country.SINGULARNAME'),


'ISO2' => 'ISO2 Code',


'ISO3' => 'ISO3 Code',


'AttributedZones' => _t('Country.ATTRIBUTED_ZONES', 'attributed zones'),


);


parent::__construct($record, $isSingleton);


}


Workflow

Ich finde es sinnvoll, das zweite Attribut der _t()-Funktion in Englisch zu pflegen. So weis jeder Programmierer gleich, an welcher Stelle er gerade bastelt und muss nicht erst im Sprachpaket nachschauen, wenn er des Deutschen nicht mächtig ist. Ich setzte dabei voraus, dass jeder Programmierer Englisch kann.

Beim Aufruf des Text Collectors wir das Sprachpaket der Systemsprache komplett überschrieben und alle Änderungen gehen verloren. Vor dem Aufruf des Text Collectors sollte man die Systemsprache auf en_US setzten, denn die _t()-Funktionen liefern ja englische Sprachwerte. Das $lang-Array habe ich dann mit der Hand in die de_DE.php kopiert und mit "replace" alle "en_US" in "de_DE" verwandelt. Jetzt muss ich nur noch 600 Textstellen ins Deutsche übersetzten :(

Fazit

Internationalisierung ist eine wichtiger Arbeitsschritt beim Bau eines Moduls. Ein Modul kann sich nur verbreiten, wenn Entwickler möglichst vieler Länder damit arbeiten. Dass man seine Sprachpakete automatisiert erstellt bekommt, ist ein super Feature.

Danke SilverStripe-Team :)

Tags: