Wie schon angedeutet habe ich beschlossen einen eigenen Adapter für Zend_Translate zu schreiben. Den Namen habe ich jetzt Ben R. zu verdanken
: “XML Translation Source”, oder kurz “XTS”.
Hintergrund
Für alle, die den alten Artikel nicht lesen wollen, fasse ich mal kurz zusammen. Grundsätzlich bin ich mit den vorhandenen Adapter unzufrieden, weil Array, CSV oder Ini zu rudimentär sind und es immer wieder zu Problemen mit Sonderzeichen gekommen ist, die XML-basierten Formate sind dagegen recht komplex. Dazu muss man allerdings sagen, dass entsprechende Adapter vom Zend Framework natürlich nur eine geringe Teilmenge der jeweiligen Spezifikation nutzen, so dass die Komplexität wieder etwas herunter gebrochen wird. Letzten Endes Gettext ist mir zu unpraktisch für Skriptsprachen. Die Anwendung muss man nicht kompilieren, die Sprachdateien schon? Irgendwie verkehrte Welt. Ursprünglich nur als Tech-Demo geplant habe ich schließlich einmal ausprobiert, ob die Entwicklung eines eigenen Formats überhaupt in Betracht gezogen werden kann.
Umsetzung
Der Adapter selbst heißt Libcrunch_Translate_Adapter_Xts und befindet sich (natürlich) in Libcrunch. Will man ihn von Zend_Translate erstellen lassen, muss man leider den gesamten Klassennamen angeben, weil es nur Klassen mit dem Präfix Zend_Translate_Adapter_ selbst auflöst. Zur Zeit akzeptiert der Adapter keine weiteren Optionen, kann aber auch mit Scanning verwendet werden, wobei allerdings die Locale-Informationen aus Verzeichnis- oder Dateinamen ignoriert werden, sie befinden sich schließlich bereits in der XML selbst.
Das Dateiformat für die XML:
< ?xml version="1.0" encoding="UTF-8"?>
<xts>
<msg id="forbidden">
<str lang="de">Zugriff verweigert</str>
<str lang="en">Access denied</str>
</msg>
</xts>
Der Root-Tag muss xts sein, darin kommen ein oder mehrere msg-Tags und dort wiederum ein oder mehrere str-Tags vor. Die beiden Attribute id und lang müssen vorkommen, aber sie können beide sowohl in msg, als auch in str vorkommen. Das heißt, das folgende Format ist ebenso gültig und theoretisch können beide Formate in einer Datei verwendet werden:
< ?xml version="1.0" encoding="UTF-8"?>
<xts>
<msg lang="de">
<str id="forbidden">Zugriff verweigert</str>
</msg>
<msg lang="en">
<str id="forbidden">Access denied</str>
</msg>
</xts>
Jetzt kommt das “Aber”: Man sollte das Mischen der beiden Formate in einer Datei vermeiden, da es nicht besonders übersichtlich ist und ich zudem nicht verspreche, dass ich es in der Zukunft nicht doch noch verbiete
Zur Zeit gibt es dafür keinen Grund: Wers macht, ist selbst Schuld, ich habe euch gewarnt. Wie erwähnt dürfen die Attribute in beiden Tags auftreten, also auch gleichzeitig. In dem Fall überschreibt der Wert vom Attribut im str-Tag den vom msg-Tag. Man sollte sich also auch hier lieber für eine Variante entscheiden.
Eigenschaften
- Allen XML-Formaten ist gemein, dass sie geparst werden müssen. Sie sind also langsamer, als zum Beispiel Gettext.
- Die Namen der Tags und Attribute sind an Gettext angelehnt. So wurde aus “msgid” “id” und aus “msgstr” “str”, der msg-Tag umschließt alles und das lang-Attribut vervollständigt das Format um die bei Gettext fehlende “Mehrsprachen”-Fähigkeit. Umsteiger sollte es entgegen kommen.
- Die beiden vorgeschlagenen Varianten zur Umsetzung haben strukturbedingt schon verschiedene Eigenschaften, die sie für unterschiedliche Szenarien interessant macht. Die erste Variante mit dem id-Attribut im msg-Tag erlaubt es schnell und einfach neue IDs zur Übersetzung hinzuzufügen. Zusätzlich lässt sich schnell kontrollieren, ob eine ID in alle Sprachen übersetzt wurde. Damit eignet es sich für Szenarien, in dem sich die IDs häufiger ändern, als die Sprachen. Anders herum erlaubt die zweite Variante mit der Sprache im msg-Tag genau den umgekehrten Fall. Einzelne Sprachen lassen sich leicht hinzufügen und auf Vollständigkeit kontrollieren, also genau das Szenario, in dem sich Sprachen häufiger ändern, als die Übersetzungs-IDs. In zwei separaten Dateien kann man auch beides in einem Projekt nutzen.
Zukunftspläne
Ehrlich gesagt gibt es keine, weil ich das Format aus dem Grund entwickelt habe, damit es einfach ist, und ich vermeiden möcht, dass sich daran etwas ändert. Denkbar sind eher Detailänderungen, die optional angeboten werden. Zum Beispiel überlege ich noch, ob ich auch das aus Gettext bekannte “Eine Datei Eine Sprache”-Format ohne eigene Sprachangabe wieder einführe.
Zur Zeit gibt es nur den Adapter für Zend_Translate. Ich selber plane keine Ausdehnung auf andere Sprachen. Falls sich allerdings jemand bereit erklärt dazu etwas zu Veröffentlichen, soll sich derjenige keinen Zwang antun. Ich würde mich dann über einen kleinen Hinweis freuen
Soso… “Der Adapter selbst heißt Libcrunch_Translate_Adapter_Xts und befindet sich (natürlich) in Libcrunch.”
Kann ich leider nicht finden haha, was mach ich denn falsch?
Würd mich sehr interessieren wie das mit dem eigenen Adapter geht, schreibe auch gleich einen aber auf DB-Basis, denn schön gekoppelt mit dem Logger dass nur geloggt wird, was fehlt, und zwar nur 1x!
Dann was du hier sehr schön gelöst hast: Die ID’s! Endlich mal ne Lösung wo man die Message-ID auch nur an einem Ort ändern muss. Wird bei meiner DB-Lösung gleich aussehen.
Wäre toll wenn ich noch zu diesem Libcrunch_Translate_Adapter_Xts-Adpater kommen würde.
Gruss
http://github.com/KingCrunch/libcrunch/tree/master/lib/Libcrunch/Translate/Adapter/
Es muss nur die Methode “_loadTranslationData()” implementiert werden. Will man den Adapter dann über “Zend_Translate::factory()” initialisieren, muss man allerdings denn vollständigen Klassennamen angeben, weil die Factory davon ausgeht, dass alles mit “Zend” beginnt ^^
Danke, funktioniert super. Habe den Adapter in einem grösseren Projekt eingesetzt