Türchen 03: Magento Übersetzungen - demystified

Die Lokalisierung von Online-Shops auf Magento Basis kann unübersichtlich sein, speziell, wenn Du Dich mit der technischen Umsetzung in Magento noch nicht auseinandergesetzt hast. Die initiale Übersetzung in die Landessprache ist, vor allem wegen der erstklassigen Arbeit von vielen fleißigen Entwicklern aus der Community, noch nicht das Problem. Auf dem deutschen Markt, wo das wunderbare Modul GermanSetup von FireGento existiert (Kudos!), ist es auch für unerfahrene Personen ein leichtes. Schwerer wird es, wenn einzelne Strings nach einem Update noch nicht erfasst wurden, einzelne Extensions keine Übersetzung mitliefern oder Übersetzungen überschrieben werden sollen. Dieser Artikel soll etwas Licht ins Dunkel bringen und die Arbeitsweise von Magento im Bezug auf Übersetzungen beleuchten.

Wo liegen die Herausforderungen?

Als Knackpunkt gibt es im wesentlichen zwei Faktoren. Zum einen solltest Du in etwa wissen wie und wo Text in Magento übersetzt wird, insofern die passende Lokalisierung geladen wurde. Der zweite Schritt ist zu verstehen, woher Übersetzungen kommen und wie diese geladen werden. Genau diese beiden Punkte untersucht der Artikel.

Wie wird übersetzt?

Grundlegend werden in Magento Strings bzw. Zeichenketten nur übersetzt, wenn diese mittels einer speziellen Helfermethode aus den vorhandenen Übersetzungen geladen werden. Im Quellcode wird diese zum Beispiel wie folgt auf angesprochen:

echo $this->__(“My Orders”);

Statt direkt Text im Template zu hinterlegen, wird dieser an die “magische” Methode __() übergeben, die durch die abstrakte Klasse Mage_Core_Helper_Abstract in jeden Helper verfügbar ist.

Wie arbeitet die magische Methode?

Die “magische” Methode ruft in der Klasse Mage_Core_Model_App die Methode getTranslator() auf und bekommt ein Objekt der Klasse Mage_Core_Model_Translate zurück. Darin wird wiederum die Methode translate($args) verwendet, um die Übersetzung vorzubereiten.

Die Übersetzung wird dann mit der Methode _getTranslatedString() (ebenfalls in Mage_Core_Model_Translate) geladen. Der Text, der an die Helfermethode __() übergeben wurde, wird dort als Index für das assoziative Array $_data genutzt das als Instanzvariable in Mage_Core_Model_Translate definiert ist. Darin sind zur Laufzeit alle relevanten Übersetzungen geladen.

Bei unserem Beispiel oben wird geprüft ob der Array-Schlüssel “My Orders” existiert. Wenn ja, wird der zugeordnete Wert zurückgegeben. Bei einer deutschen Lokalisierung wird dort “Meine Bestellungen” zurückgegeben werden. Existiert der Array-Schlüssel nicht, wird der ursprüngliche Text zurückgegeben.

Variablen im Text

Die semi-automagische Übersetzung klingt praktisch. Die Wrapper-Methode für alle ausgegebenen Strings zu verwenden ist nicht kompliziert. Früher oder später begegnest Du jedoch der Frage, wie werden Strings übersetzt, wenn sie Variablen enthalten?

Ganz einfach: Es werden Platzhalter verwendet. Die Technik ist ähnlich wie bei der PHP-Funktion sprintf(), mit der formatierte Strings ausgegeben werden. Du kannst für eine Variable, deren Wert als Zeichenkette ausgegeben werden soll, bspw. den Platzhalter %s verwenden:

$itemCount = 1;
echo $this->__(‘%s items in your cart’, $itemCount);

Übersetzt würde dieser String genau wie jeder andere auch:

“%s items in your cart’”,”%s Artikel in Deinem Warenkorb”

Der Platzhalter wird in der Übersetzung beibehalten. Die Methode __() wird beim Aufruf mit einem zusätzlichen Parameter, der Variable deren Wert in der Ausgabe gegen den Platzhalter getauscht werden sollen, angesprochen. Werden mehrere Platzhalter verwendet, werden einfach noch weitere Variablen als Parameter übergeben, jeweils mit einem Komma getrennt.

Format für Übersetzungen

Die Übersetzungen bestehen, unabhängig von der Quelle, immer aus zwei Teilen. Der erste Teil ist der zu übersetzende Text, der im Quellcode an die “magische Methode” übergeben wird. Der zweite Teil ist die Übersetzung.

Als Quelle dienen entweder CSV Dateien oder Datenbankeinträge. Letztere sind vor allen Dingen ein Ergebnis der “Inline Übersetzung” die Magento anbietet.

Lokalisierung über CSV Dateien

Der beste Weg zur Übersetzung von Magento Shops sind CSV Dateien. Diese haben den großen Vorteil, dass sie von einer hoffentlich vorhandenen Revisionskontrolle, zum Beispiel Git, berücksichtigt und erfasst werden. Werden Änderungen in Dateien gemacht, ist so nicht nur nachvollziehbar, wo im Detail Anpassungen stattgefunden haben. Fast genauso wichtig ist, dass Sie auf mehreren Systemen verfügbar sind. Sei es die lokale Entwicklungsumgebung, eine Testinstallation, ein Stagingsystem oder das Live-Deployment des Online Shops.

Der Aufbau der Dateien ist inhaltlich einfach. Um den Beispieltext “My Orders” aufzugreifen, könnte dieser mit folgender Zeile in einer der CSV-Dateien übersetzt werden:

“My Orders”,“Meine Bestellungen”

Doch das ist, wie erwähnt, nicht die einzige Möglichkeit.

Die Inline Übersetzung

Magento bietet neben den CSV-Dateien zur Lokalisierung die Möglichkeit der sogenannten Inline Übersetzung. Diese wird im Backend unter den Entwickleroptionen aktiviert:

System->Konfiguration->Inline übersetzen

inline-uebersetzen-aktivieren

Wird die Option auf “Ja” gesetzt, bietet Magento im Frontend die Möglichkeit neben dem Text auf ein Icon (ein Buch) zu klicken:

inline-uebersetzung-aktiv

Der Dialog im Anschluss sieht wie folgt aus:

inline-translation-dialog-650x326

Die Benutzung sollte selbsterklärend sein. Ein Hinweis noch: Nachdem eine Übersetzung gespeichert wurde, muss die Seite neu geladen werden. Sonst greift die Übersetzung nicht. Wird sie auch dann nicht geladen, muss der Cache aktualisiert werden.

Soll auf die Übersetzungen zugegriffen werden, kann dies in der Tabelle core_translate erfolgen. Dort werden diese gespeichert, woraus sich ein entscheidender Nachteil ergibt. Die gesamte Inline Übersetzung arbeitet vollständig an der Revisionskontrolle vorbei. Außerdem ist es auch praktikabler CSV-Dateien durch externe Partner übersetzen zu lassen. Als Richtlinie würde ich empfehlen: Die Inline Übersetzung soweit es geht vermeiden.

Wo liegen die Übersetzungen konkret?

Magento kombiniert mehrere Stellen, an denen Übersetzungen definiert werden können:

1.    modulspezifische Übersetzungen
2.    Übersetzungen im Theme
3.    Inline-Übersetzungen

Spannend ist nicht nur die Frage, welche Quellen es sind. Mindestens genauso wichtig ist es zu wissen, das Magento sie in dieser Reihenfolge lädt.

Wie oben gezeigt werden die Übersetzungen in ein assoziatives Array geladen. Der ursprüngliche Text dient als Schlüssel. Da mehrere Quellen eine Übersetzung für den gleichen Text enthalten können, werden die Array-Elemente überschrieben. Eine Regel dabei: Das zuletzt geladene Element gewinnt und überschreibt den zuvor gesetzten Wert. Das bedeutet, die modulspezifischen Übersetzungen haben die niedrigste Priorität und die Inline Übersetzung die höchste.

Der Punkt, an dem die Übersetzungen geladen werden, befindet sich in der Methode init() der Klasse Mage_Core_Model_Translate.

Modulspezifische Übersetzungen

Die modulspezifischen Übersetzungen werden in den CSV-Dateien gespeichert. Die sind unter app/locale zu finden. Dort gibt es für jedes “Locale” ein eigenes Verzeichnis. Im Standard ist dies bspw. en_US. Die Übersetzungen ins Deutsche, mit der Ausrichtung auf Deutschland, sind in de_DE gespeichert.

Dort liegen Dateien, die jeweils den Namen der zugehörigen Extension tragen. In diesen sind Strings sowie deren Übersetzungen wie das Beispiel “My Orders” hinterlegt.

locale-files

Um “My Orders” im Kundenbereich zu übersetzen, muss in app/locale/de_DE die Datei Mage_Customer.csv angelegt werden. In dieser wird die Übersetzung gespeichert:

“My Orders”,”Meine Bestellungen”

Die Übersetzungen sind case-sensitiv! Es muss auf Groß-/Kleinschreibung geachtet werden. Wer sich mit den Übersetzungen aus app/locale befassen möchte, findet in der Klasse Mage_Core_Model_Translate die Methode _loadModuleTranslation(...). Dort werden die Dateien geladen.

Theme Übersetzungen

Die modulspezifischen Übersetzungen bilden die Basis für die Anpassung. Sollen jedoch vereinzelte Wörter, Sätze oder Ausdrücke abweichend übersetzt werden, wird ein anderer Weg gewählt. Es bietet sich die Datei translate.csv des Themes an. Die Anpassungen sind ohnehin meist nur für den jeweiligen Shop relevant. Das Theme wird nahezu immer individuell für den Shop erstellt oder angepasst, es spricht daher nichts gegen diesen Weg.

Es muss im Hauptverzeichnis des Themes (unter app/design…) das Verzeichnis “locale” angelegt werden. Als Unterzeichnis werden, genau wie in app/locale die Verzeichnisnamen gemäß der “Locale”-Einstellung erzeugt und die Datei translate.csv darin angelegt. Wenn das Default-Theme eingesetzt wird und eine deutsche Übersetzung angelegt oder überschrieben werden soll:

theme-translate-csv
app/design/frontend/default/default/locale/de_DE/translate.csv Der Aufbau ist genau wie in den modulspezifischen Übersetzungen. Jede Zeile enthält einen ursprünglichen Text und die Übersetzung. So könntest Du nun den Text “Meine Bestellungen” bspw. in “Bestellhistorie” ändern: “My Orders”,”Bestellhistorie” Das ist noch nicht alles. Es gibt ein Feature, das nicht so bekannt ist. Die Möglichkeit spezifische Übersetzungen einzelner Module zu überschreiben. Ein Beispiel ist der String “Product Name”. Er wird in verschiedenen Extensions benutzt. Möchtest Du bspw. nur die Übersetzung für das Modul Mage_Checkout überschreiben, wird der Scope des Moduls, also der Modulname, vorangestellt und mit zwei Doppelpunkten vom String getrennt: “Mage_Checkout::Product Name”,”Name des Artikels” Von der geänderten Übersetzung sind Verwendungen in der Core-Extension Mage_Checkout betroffen. An den anderen Stellen bleibt die Übersetzung wie gehabt. Dies funktioniert auch in den Datenbank-Übersetzungen. Wer im Code Details nachvollziehen möchte, findet einen guten Einstiegspunkt in der Methode _loadThemeTranslation() der Klasse Mage_Core_Model_Translate.

Probleme mit Theme Übersetzungen

Es gibt spezifische Fälle, in denen Übersetzungen aus der translate.csv-Datei nicht greifen. Der erste Schritt ist in dem Fall den ursprünglichen String zu kontrollieren. Probleme können bspw. die Anführungszeichen verursachen. Da gibt es die einzelnen Anführungsstriche und doppelte. Im Zweifel den Quellstring direkt aus Quellcode kopieren, um Probleme auszuschließen. Es gibt Fälle, in denen Übersetzungen in der Datei translate.csv aus eurem Theme scheinbar nicht greifen wollen. Das liegt häufig an Problemen mit dem »Scope«. Sollte eine Änderung nicht greifen, wie oben gezeigt den Modulnamen bzw. den Scope vor den zu übersetzenden String setzen: “Mage_Checkout::String”,”Übersetzung” Nun wird der Eintrag in der Datei translate.csv höher gewichtet.

Inline Übersetzungen

Die Inline Übersetzungen stammen aus der Datenbank. Dort werden sie in der Tabelle core_translate gespeichert. Es ist nicht zwingend notwendig, den Weg über den Dialog zur Übersetzung zu gehen. Stattdessen kann man direkt in der Tabelle Übersetzungen anlegen. Wie oben erwähnt überschreibt eine Übersetzung aus der Datenbank modulspezifische Übersetzungen und die Übersetzungen aus dem Theme (per translate.csv). Dies liegt daran, dass sie in der init()-Methode der Klasse Mage_Core_Model_Translate zuletzt geladen werden. Dort wird die Methode _loadDbTranslation() aufgerufen, die für das Laden der Übersetzungen aus der Datenbank zuständig ist.

Zusammenfassung

Wege zur Übersetzung von Strings gibt es mehrere, die Magento gekonnt zusammenführt. Alle Varianten existieren berechtigt. Dennoch sollte man, wenn es geht, auf die Übersetzungen aus der Datenbank (Inline Translation) nach Möglichkeit verzichten. Deployment über Git&Co wird erschwert. Die Tabelle »core_translate« wird manuell übernommen. Ergebnis ist, dass Entwicklungsversion und Live-Deployment voneinander abweichen. Spezifische Anpassungen am besten über das Theme (translate.csv) vornehmen.


Ein Beitrag von Jan Brinkmann
Jan's avatar

Jan Brinkmann arbeitet seit über zehn Jahren mit Open-Source-Software und bloggt darüber unter http://the-luckyduck.de. Er ist bei der code-x GmbH aus Paderborn im Bereich Magento angestellt und arbeitet daneben als freiberuflicher Webentwickler.

Alle Beiträge von Jan

Kommentare
Parov am

Hallo, Jan! Wenn du neugierig auf alternative Lokalisierungsmodalitäten für die Übersetzung von .csv-Dateien bist, empfehle ich dich diese Übersetzungsplattform https://poeditor.com/

Thomas Ullrich am

Danke für den Artikel. Übersetzung mit der translate.csv läuft wunderbar. Was ich noch nicht hinbekommen habe, sind Übersetzungen von

dynamischen Texten, z.B. 'My Cart (1 item)'. Da das 1 item nach Zustand des Warenkorbs 'generiert' wird, läuft eine Übersetzung über translate.csv leider nicht.

Texten mit Link, also z.B. 'Click here to reset your password.' Das will mir nicht gelingen. Auch mit doppelten Anführungszeichen nicht.

Wie kann man diese Texte übersetzen?

Danke im Voraus.

Dennis Hüttner am

Hallo Jan,

Update für die die Inline Übersetzung:

Alt: System->Konfiguration->Inline übersetzen

und hier der Neue Pfad:

Konfiguration->System->Entwickleroptionen->Inline Übersetzung

Besten Dank für den Artikel!

Grüße

Dennis

Magento: Übersetzung greift trotz translate.csv nicht! | Apmac's Blog am

[…] www.webguys.de/magento/tuerchen-03-magento-uebersetzungen-demystified/ […]

Magento-Neuigkeiten der Wochen 49/50 2013 am

[…] Magento Übersetzungen – demystified […]

Türchen 07: Aufräumen im Mail-Chaos « Magento Blog für Entwickler und eCommerce-Shops - webguys.de Magento Blog für Entwickler und eCommerce-Shops – webguys.de am

[…] der Translator arbeitet, wurde übrigens im Türchen 03 von Jan sehr gut erklärt. So weit, so gut. Doch wie ändert man den Pfad der EMails sinnig und sorgt […]

Tobias Vogt am

Danke Jan. Wie man am wenigen Feedback merkt: Für alle ein doofes Thema was echt richtig wenig Spaß macht ;)

Gibt es eigentlich Tools die

a) Alle Texte aus den eigenen Modulen extrahieren und b) Warnen wenn Texte direkt ausgegeben werden?

Das wäre doch ein Traum,

Tobi

Dein Kommentar