Mehrsprachige Smarty Templates

In den letzten Jahren php Entwicklung ist neben den pScripten, meinem pSys System und anderen Dingen auch ein kleiner eigener Framework entstanden mit dem ich verschiedene Projekte umsetze. Vor einigen Jahren habe ich angefangen mit der Smarty Template Engine zu arbeiten. Neben vielen eigenen Plugins für Smarty ist auch eine Technik entstanden mit der ich Templates mehrsprachig mache. Hier einige Anregungen für „Nachahmer“.

Formate und Variablen

Als Smarty Benutzer wisst ihr das ihr viele verschiedene Formate beeinflussen könnt. Zum Beispiel solche Dinge wie:

  • Datumsformate
  • Zahlenformate und Währungen
  • Namen von Tagen und Monaten etc.

Für das behandeln solcher festen Werte benutze ich die Möglichkeit .conf Dateien in Smarty einfach laden zu können. In diesen kann man so verschiedene Daten vorkonfiguriert ablegen. Bsp.:

datetime="d.m.Y H:i:s"
shortdate="d.m.y"
timemin="H:i"
timesec="H:i:s"

Diese kann man später mit den Format Modifiern in Smarty benutzen um zum Bsp. Datumsformate korrekt darzustellen. Je nach Sprache muss man nur das entsprechende Config File laden. Bsp.:

$smarty->configLoad('de_DE.conf');

Templates übersetzbar machen

Um später in Templates verschiedene Wörter in verschiedenen Sprachen zu erhalten müssen Schlüsselwörter mit den entsprechenden Werten ersetzt werden können. Gern wird auch dies mit CONF Dateien gelöst, dies hat für mich aber keinen Sinn gemacht.
Das Problem: Ist eine Variable im CONF File nicht enthalten, so wird diese aus dem Template gelöscht, das macht das Übersetzten schwer, denn man sieht die zu übersetzenden Elemente nicht mehr. Somit wird Übersetzten zum Glücksspiel.
Meine Lösung geht einen anderen Weg. Ich habe einen eigenen PRE Filter entwickelt welcher mir entsprechende Zeichenketten bearbeitet. PRE Filter werden vor dem Compilieren des Templates ausgeführt, somit erfolgt der eigentliche Übersetzungsprozess immer nur ein einzigstes mal, dann wenn ein Template geändert wurde, danach nie wieder. Somit benötigt das System bei einem einmal übersetzten Template keinerlei Ressourcen mehr! Zudem weise ich der compile_id jeweils den Locale Code zu. Somit werden Templates je Sprache compiliert und benutzt. Bsp:

$smarty->compile_id = 'de';
$smarty->registerFilter("pre","smarty_prefilter_uebersetzer");

Filter Arbeitsweise

Der Filter funktioniert auf folgender Art und Weise. Da ich keine Variablen in dem Sinn ersetzten will möchte ich definierte Zeichenketten finden und ersetzen können. Ich habe das gelöst indem alle Zeichenketten mit ## beginnen und enden. Bsp.: ##HALLO## oder ##SUBMIT##. Diese Zeichenfolgen kann man simpel mit einem preg_replace finden und bearbeiten. Im speziellen benutze ich preg_replace_callback() und behandle die Zeichenfolgen mit anderen Funktionen weiter.

Findet die Übersetzer Funktion zu ##HALLO## einen abgespeicherten Wert, so liefert es diesen Zurück. In diesem Falle zum Beispiel „Hallo Du„. Findet die Übersetzer Funktion keinen Wert so liefert sie das zurück was sie erhalten hat, also wieder „##HALLO##„.
Der Vorteil nun: Es bleiben keine Passagen in Templates leer, ihr könnt nicht übersetzte Stellen visuell sofort erkennen.

Übersetzungstabelle

Man könnte die übersetzten Werte auch hier wieder in einer CONF Datei speichern. Bsp.:

HALLO=Hallo DU
SUBMIT=Absenden
language_editor
Language Editor

Aber ich wollte es noch ein Stück intelligenter haben, denn ich war faul und wollte mir nicht immer alle Tags zur Übersetzung von Hand zusammen suchen. Aus diesem Grunde habe ich in meinem Framework eine mySQL Tabelle in welcher ich die Tags speichere. Ich frage also für jeden Tag in der Datenbank an ob es ihn gibt und hole mir dazu den übersetzten Wert. Wie weiter oben beschrieben passiert das nur ein ein zigstes mal wenn sich ein Template geändert hat, die Datenbank wird also später nie wieder angesprochen!
Der schöne Effekt: Finde ich eine Zeichenfolge nicht in der Tabelle, welche ja aber gerade für das Template angefordert wird, so schreibe ich diese Zeichenfolge einfach in die mySQL Datenbank. Somit finde ich sofort und automatisch alle Tags die ich noch nicht übersetzt habe, die aber in den Templates der jeweiligen Anwendung enthalten sind.
Um dies einfach administrieren zu können besitzt der Framework einen Editor der mir das einfach im Browser ermöglicht zu tun.  Nachdem Änderungen an der Übersetzung vorgenommen wurden muss man danach nur das Löschen aller vorkompilierten Templates triggern:

$smarty->clearCompiledTemplate();

Tabellen Beispiel

Meine  mySQL Tabelle sieht so aus (mit Beispieldaten):

ID (int) TAG (varchar) WORD (varchar) LOCALE (varchar) TPL (varchar)
1 HALLO Hallo Du de form.tpl
2 HALLO Hello You en form.tpl
3 SUBMIT Jetzt abschicken de register.tpl
4 SUBMIT Submit now en register.tpl

Ich speichere also alle ## Zeichenfolgen mit der Übersetzung dazu, dem Sprachcode (gleichzeitig die compile_id der Templates) und auch noch zusätzlich die Herkunft der Zeichenkette (Template).

Live Beispiel

Ein aktuelles Beispiel für den Einsatz ist die Modellflugplätze Datenbank. Die Seite ist somit in Deutsch und Englisch verwendbar, das ganze benötigt aber nur ein Set Templates.

Link: http://ma-db.com

Ich hoffe ihr könnt für eure eigenen Projekte ein paar Anregungen mitnehmen!

One Comment

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.