Internationalisierung von eStudy

Aus THM-Wiki
Wechseln zu: Navigation, Suche

Schnellstart

Keine Zeit? Folgende Schritte müssen durchgeführt werden:

  1. Bibliotheken/Programme installieren und einrichten
  2. Datenbank und Code konvertieren
  3. Branch mit hktv mergen
  4. Internationalisierung, Lokalisierung und Umwidmung der Lernplattform eStudy durchführen

Vorbereitung

Windows

Benutzer von Windows haben in der Regel kein gettext installiert. Daher müssen folgende Programme von ftp://ftp.gnu.org heruntergeladen werden:

  1. gettext-runtime
  2. gettext-tools
  3. libiconv

Diese Dateien können alle in das gleiche Verzeichnis entpackt werden. Zum Beispiel nach C:\Programme\gettext. Als letzten Schritt muss C:\Programme\gettext\bin zur PATH-Variablen hinzugefügt werden, damit darauf von überall her zugegriffen werden kann.

PHP Erweiterungen

gettext

In der php.ini muss die Erweiterung für gettext aktiviert werden (php_gettext.dll). Alternativ kann PHP auch mit der Konfiguration --with-gettext[=PFAD_ZU_GETTEXT] kompiliert werden.

mbstring

Gleiches gilt für die Multibyte String-Erweiterung: php_mbstring.dll unter Windows aktivieren oder die Konfiguration mit --enable-mbstring durchführen. mbstring muss außerdem mit folgenden Laufzeitparamtern in der php.ini eingestellt werden:

[mbstring]
mbstring.language = German
mbstring.internal_encoding = UTF-8
mbstring.http_input = UTF-8
mbstring.http_output = UTF-8
mbstring.encoding_translation = On
mbstring.func_overload = 7

Die Erweiterung sorgt dafür, dass PHP mit UTF-8 kodierten Zeichen umgehen kann. Dieser Schritt ist notwendig, da sonst selbst einfache Funktionen wie strlen falsche Ergebnisse liefern.

Bild 1: Einstellungen für Auto-Complete

Zend-Framework

Der Zend Framework muss heruntergeladen ([1]) und entpackt werden. Der Ordner library/ aus dem Archiv muss dem PHP-Include-Pfad hinzugefügt werden, so dass auf den Framework wie im folgenden Beispiel zugegriffen werden kann: require_once "Zend/Loader.php";

Auto-Complete mit Eclipse

Um die Auto-Complete-Funktion der Eclipse und dem PDT-Plugin auch für die Klassen des Zend-Frameworks nutzen zu können, muss lediglich der Pfad zu dem Zend-Framework unter Properties->PHP Include Path angegeben werden.

Migrieren der Datenbank

Die Migration der bestehenden Entwicklerdatenbank muss teilweise manuell durchgeführt werden. Wenn die Datenbank auf dem zuletzt veröffentlichten Dump basiert, sind allerdings nur wenige Schritte nötig. Wir gehen zunächst davon aus, dass der aktuelle Dump in der Datenbank eingespielt ist:

Im Wurzel-Verzeichnis befinden sich die Dateien utf8_migration.sql und utf8_migration.php. Die SQL-Datei muss als erstes mit einem UTF-8 fähigen Editor geöffnet werden. In dieser Datei ist die Datenbank "hktv" als Quelldatenbank angegeben. Dieser Name muss natürlich an die eigenen Bedingungen angepasst werden. Die Zieldatenbank wird "estudy_v2" heißen. Wurden alle Änderungen durchgeführt, kann die Datei ausgeführt werden:

mysql -u root -p
> source utf8_migration.sql

Wenn dies ohne Fehler durchgelaufen ist, kann im nächsten Schritt die Migration abgeschlossen werden. Sollten jedoch Fehler aufgetreten sein, sollte nochmals überprüft werden, ob alle Angaben der Quelldatenbank korrekt gesetzt werden. Möglicherweise fehlen der Quelldatenbank auch einige Tabellen, dann muss die SQL-Datei weiter angepasst werden.

php utf8_migration.php hktv estudy_v2 migrate

Damit wird die Migration abgeschlossen; "hktv" ist hier wieder die Quelldatenbank und "estudy_v2" die Zieldatenbank. Wenn das Skript unerwartet die Datenbank nicht benutzen kann, hilft vielleicht der Trick, in der Datei estudy_connect.inc.php den Wert des Feldes $settings['dbHost'] auf "127.0.0.1" zu setzen anstelle von "localhost".

Die eStudy-Installation muss jetzt noch die neue Datenbank verwenden, dazu muss die Datei estudy_connect.inc.php angepasst werden. Diese befindet sich entweder im XAMPP-Verzeichnis oder unter eStudy/web/common/. Darin muss das Feld $settings['dbName'] auf die neue Datenbank verweisen.

Sollten der Quelldatenbank einige Tabellen fehlen, kann mit dem Befehl php utf8_migration.php hktv estudy_v2 insert eine Liste von SQL-Befehlen erstellt werden. Diese Liste muss kopiert werden und in die Datei utf8_migration.sql an die Stelle, wo dort die gleichen Befehle stehen, kopiert werden. Die bestehenden Befehle müssen entfernt werden. Falls dem Datenbank-Nutzer nicht automatisch Rechte für die neue Datenbank gegeben werden, ist folgender Befehl hilfreich: GRANT ALL PRIVILEGES ON `estudy\_v2` . * TO 'hktv'@'localhost' (hktv ist diesmal der Datenbank-Benutzer).

Projektdateien umwandeln

Alle Textdateien im eStudy Projekt werden in Zukunft als UTF-8 gespeichert. Das bedeutet erstmal, dass in den Projekteinstellungen der Eclipse die Zeichenkodierung von CP1252, ISO-8859-1 oder Mac Roman auf UTF-8 umgestellt werden muss. Da hierdurch aber bei einem Commit z.B. die Umlaute entstellt werden, müssen zuvor alle Projektdateien nach UTF-8 konvertiert werden. Durch ein Bash-Skript ist dieser Schritt jedoch sehr einfach: Das Skript kann hier heruntergeladen werden; es muss im Wurzel-Verzeichnis des Projektes platziert werden (also nicht im web-Ordner), dort wo sich u.a. auch die Ordner "sessions", "lang" und "doku" befinden. Wie üblich muss anschließend mit chmod +x skript.sh die Ausführbarkeit gesetzt werden. Schließlich kann das Skript über

skript.sh . cp1252 utf-8

ausgeführt werden. Der "." bedeutet: Fange im aktuellen Ordner an und gehe dann rekursiv durch alle Unterordner. Dabei wird für jede Datei die Kodierung von CP1252 auf UTF-8 umgestellt. Nun muss das Projekt nur noch mit den geänderten Einstellungen in der Eclipse (UTF-8, s.o.) commitet werden.

Diese Konvertierung muss nur ein einziges Mal pro Branch durchgeführt werden. Zuletzt muss der eigene Branch mit hktv gemergt werden. Windows Benutzer: Anton Afanasjew war so freundlich und hat ein Java-Programm plus Batch-Skript geschrieben, mit dem die Konvertierung auch unter Windows durchgeführt werden kann.

Durchführung einer Übersetzung

Zum Übersetzen sollten nicht direkt die gettext-Funktionen zum Einsatz kommen, sondern sie sollen am Besten über die Zend_Translate-Klasse angesprochen werden. Ein Zend_Translate-Objekt wird wie folgt angelegt:

$translate = new Zend_Translate('gettext', PATH_TO_ROOT . '../lang/pfad/zur/sprachdatei', 'de');

Den Entwicklern steht mit der Funktion getTranslate("modulname") bereits ein einfacher Weg zur Verfügung, das passende Zend_Translate-Objekt zu erhalten. "modulname" lädt die gleichlautende .mo Datei aus dem Verzeichnis des Portaltyps und der gewählten Sprache. Desweiteren gibt es die Funktion getLocale(), die ein Zend_Locale-Objekt zurückliefert.

Jetzt können die Quelldaten bearbeitet werden, dazu müssen alle textuellen Ausgaben ersetzt werden durch folgenden Aufruf: $translate->_("Dies ist eine Ausgabe"). Der String "Dies ist eine Ausgabe" wird damit zum Übersetzungsschlüssel. Das heißt, dass ein Übersetzer diesen String in die verschiedenen Sprachen transferieren wird. Die Übersetzungen müssen für die unterschiedlichen Portal-Arten jeweils neu übersetzt werden. Siehe dazu auch Bild 2.

Regeln zum Übersetzen

Das Handbuch von gettext gibt fünf einfache Regeln vor, die es zu beachten gilt, wenn Software übersetzbar sein soll:

Guter sprachlicher Stil

Es soll möglichst kein Slang verwendet werden, da sonst Übersetzer, die nicht vom Fach sind, Schwierigkeiten bei der Arbeit haben werden. Auf Abkürzung soll daher ebenfalls verzichtet werden.

Ganze Sätze verwenden

Für einen Übersetzer ist es schwierig, eine geeignete Übersetzung zu wählen, wenn die Wörter ohne Zusammenhang auftauchen. Daher immer ganze Sätze verwenden.

Trennung erst an Absätzen

Mehrere Sätze, die zusammengehören, sollen nach Möglichkeit erst an einem Absatz getrennt werden. Dies hilft wieder, den Kontext zu bewahren. Das bedeutet auch, dass zuvor konkatenierte Sätze zu einem großen String zusammengefasst werden müssen. Dies ist mit der Funktion sprintf möglich. Mit der Positionsangabe von Platzhaltern muss außerdem weitgehend gearbeitet werden.

Ein Beispiel:

$userInfo = sprintf(
        $this->translate->_("Sie gehören der eStudy-Benutzergruppe %1\$s %2\$s an."),
        $usergroup,
        $userGroupInfo
    );

Statt dem Einsatz von %s als Platzhalter, kann mittels %1\$s (erste Variable - $usergroup) oder %2\$s (zweite Variable - $userGroupInfo) die Position der Variable durch den Übersetzer angegeben und verändert werden. So ist es dann auch möglich, den sich unterschiedenden Satzbau verschiedener Sprachen zu berücksichtigen.

Formatierte Zeichenketten anstelle von Konkatenation verwenden

Das Konkatenieren von mehreren Teilstrings und Variablen führt dazu, dass sich der entsprechende Text nicht übersetzen lässt. Statt dessen sollen die Zeichenketten über Funktionen wie etwa sprintf formatiert werden. Ein Übersetzer kann in der Regel mit den Platzhaltern innerhalb der Zeichenkette umgehen.

Vermeiden von ungewöhnlichen Steuerzeichen und Auszeichnungen

HTML-Code ist in Ordnung, aber zum Beispiel alles, was über die gängigen Entitäten hinaus geht, soll vermieden werden.

Einsatz von gettext

Erstellen einer Übersetzung

Mit dem Tool xgettext kann aus dem bestehenden Quelltext automatisch eine *.po-Datei erstellt werden [2]:

xgettext meineDatei.php

Die daraus resultierende Datei messages.po kann dann in weiteren Schritten bearbeitet werden [3].

Eine übersetzte *.po-Datei kann mit Hilfe des Programms msgfmt in die eigentlich benötigte Binärform übersetzt werden [4]:

msgfmt mymodule_en.po

Daraus entsteht die *.mo-Datei, auf die gettext zur Laufzeit zugreift um die Übersetzungen zu erhalten.

Es empfielt sich hier grundsätzlich, eine noch unübersetzte *.po-Datei eines Moduls im Ordner _templates zu speichern. Diese Datei sollte die Dateiendung *.pot erhalten und bietet anderen Übersetzern eine Grundlage für ihre Arbeit.

Hinweise zum Umgang mit xgettext

Falls bei der Verwendung von xgettext Fehler auftreten: xgettext versucht hier mit dem ASCII-Zeichensatz zu arbeiten. Dieser kennt jedoch keine Umlaute; kommen Umlaute in den zu übersetzenden Zeichenketten vor, führt dies bereits zu Fehlern. Für einige Entwickler sollte daher die Option --from-code=cp1252 hilfreich sein, denn die Quelltexte von eStudy sind in diesem Zeichensatz codiert. Hier wird die Eingabedatei explizit im CP1252 (Windows-1252) Zeichensatz eingelesen und verarbeitet. Weiterhin ist zu beachten, dass es unter Umständen, abhängig vom verwendeten System, in der weiteren Verarbeitung zu Problemen kommen kann, wenn Umlaute in den zu übersetzenden Strings vorkommen. Hier sollten allgemein Umlaute in den entsprechenden PHP-Dateien vermieden werden, da sonst unter Umständen eine Lokalisierung durch gettext fehlschlägt. Die Ursache dessen liegt ebenfalls in der Verwendung unterschiedlicher Zeichensätze.

Aktualisieren einer Übersetzung

Was geschieht nun mit einer Übersetzung, wenn dich der Quellcode geändert hat, oder neue Strings für gettext markiert wurden?

Hier hilft ein weiteres Tool aus dem gettext-Paket weiter: msgmerge. Der Aufruf ist sehr einfach:

msgmerge mymodule_en.po mymodule.pot

Die Datei mymodule_en.po ist eine PO-Datei mit alten Übersetzungen, die - solange sie immer noch aktuell sind - in die neu zu erstellende Datei übernommen werden. Die Datei mymodule.pot ist die zuletzt erstellte *.po oder *.pot-Datei welche von xgettext neu erstellt wurde. Das Resultat wird in die Datei mymodule_en.po geschrieben. Ein Übersetzer kann nun mit seiner Arbeit beginnen, und die Übersetzung aktualisieren bzw. erweitern.

Ordner Layout

Das Verzeichnis für die Internationalisierung der einzelnen Teilprojekte (Lern-, Community- und Kollaborationsplattform) befinden sich im Repository auf gleicher Höhe wie das Web-Verzeichnis. Zusätzlich jedoch das Verzeichnis _templates für die POT-Dateien eines Moduls. Die Einteilung sieht wie folgt aus:

Bild 2: Ordner Layout Internationalisierung


  • [...]
  • lang
    • _templates
    • community
      • en_GB
      • de_DE
      • [...]
    • learning
      • en_GB
      • de_DE
      • [...]
    • collaboration
      • en_GB
      • de_DE
      • [...]
  • [...]
  • web

Achtung! Für die Sprachdateien bitte Ordnernamen nehmen nach dem Muster de_DE (Sprache_Land), anhand dieser Struktur wird die Sprachdatei ausgewählt und die Locale festgelegt. Der Screenshot wird noch aktualisiert. Innerhalb der einzelnen Unterordner der Sprache befinden sich die .po und .mo Dateien von gettext, die die Übersetzungen beinhalten.

Verwendung vom Zend-Framework

Die benötigten Klassen werden bereits in der Datei init.inc.php durch ein require_once eingebunden. Um nun das Zend-Framework, speziell die Klasse Zend_Translate verwenden zu können, muss das Objekt der Klasse Zend_Translate angelegt werden. Dieses Objekt wird aber in Kürze für ganz eStudy global zur Verfügung stehen, diese Vorgehensweise dient also lediglich der Veranschaulichung!

$this->translate = new Zend_Translate( 
        'gettext', 
        '<Pfad zur Übersetzten Datei (*.mo)>',
        '<Lokalisierung>'
    );

Nun kann in der entsprechenden Klasse die Funktionalität zum Übersetzen mit Hilfe von gettext, wie im obigen Beispiel gezeigt, genutzt werden.

Weitere Informationen zur Nutzung von gettext mit Hilfe des Zend-Frameworks finden sich in der Dokumentation [5].

Übersetzen von Modulnamen

Die Bezeichner von Modulen können durch den Administrator jederzeit geändert werden. Daher ist an dieser Stelle der Einsatz von gettext nicht möglich. Statt dessen stehen Übersetzungen in einer Datenbank-Tabelle Namens modules_lang. Diese Tabelle beinhaltet die Spalten Script, PortalType, Locale und Name. Die Verknüpfung zu der Modul-Tabelle von eStudy (modules) stellt die Spalte Script her. Über PortalType können einem Modul unterschiedliche "Übersetzungen" gegeben werden, je nach dem ob das Portal gerade als E-Learning-, Kollaborations- oder Communityplattform betrieben wird (mehr dazu unter Umwidmung der Lernplattform eStudy). Locale wählt die Sprache aus, beispielsweise de_DE. Name ist schließlich der eigentliche Bezeichner des Moduls, wie er im Menü erscheinen soll.

In .mkf-Dateien können übrigens bereits Übersetzungen angegeben werden. Über den optionalen Befehl lang kann zum Beispiel ein englischer Titel für ein Modul definiert werden: lang en_GB Title Goes Here. Für de_DE muss hier nichts angegeben werden, da der herkömmliche Modultitel automatisch als deutscher Bezeichner eingetragen wird.

Weitere Maßnahmen

Datum und Zeit

Die Internationalisierung einer Software betrifft aber nicht nur die Übersetzung von Strings. Es werden auch angepasste und lokalisierte Datums- und Zeitformate, sowie Formatierungen für die Ausgabe von Zahlen benötigt.

Auch hier bietet das Zend-Framework einige Lösungen:

// Benutze Locale anhand der Browserkennung 
$locale = new Zend_Locale(Zend_Locale::BROWSER);
// Benutze Locale anhand einer festen Einstellung
// $locale = new Zend_Locale("de_DE");
// Gibt die Zahl mit einer gültigen Formatierung aus (Komma/Punkt)
echo Zend_Locale_Format::toNumber(3.141592, array('locale' => $locale));
/* 
 * Gibt ein Datum entsprechend der gewählten Lokalisierung aus
 * Also für en_US: "Tuesday, October 21, 2008"
 * oder für de_DE: "Donnerstag, 21. Oktober 2008"
 */ 
$date = new Zend_Date($locale);
echo $date->get(Zend_Date::DATE_FULL);

Umrechnen von Einheiten

Nicht nur Manipulationen von Datumsformaten, sondern auch das Umrechnen von Einheiten gelingt hier relativ einfach:

/*
 * Ausgehend von eine Länge von "30 km" werden diese umgerechnet
 * und eine Länge von "18.64 mi" ausgegeben.
 */
$length = new Zend_Measure_Length(30, Zend_Measure_Length::KILOMETER);
echo $length->convertTo(Zend_Measure_Length::MILE_US);
/*
 * 100 Grad Celsius werden hier korrekt in 212 Grad Fahrenheit, 
 * sowie 373.15 Kelvin umgerechnet.
 */
$temp = new Zend_Measure_Temperature(100, Zend_Measure_Temperature::CELSIUS);
echo $temp->convertTo(Zend_Measure_Temperature::FAHRENHEIT);
echo $temp->convertTo(Zend_Measure_Temperature::KELVIN);

Perl-Compatible Regular Expressions (PCRE)

Da die PCRE-Funktionen von PHP nicht durch die mbstring-Erweiterung abgedeckt werden, können diese unter Umständen mit einem UTF-8 kodierten Text nicht richtig umgehen. Um erst gar nicht in Probleme zu kommen, sollte beim Einsatz der preg_*-Funktionen der Modifizierer u angewendet werden. Modifizierer werden hinter dem Muster angegeben: /[a-z]*/u

Angabe der Zeichenkodierung

Verschiedene PHP-Funktionen akzeptieren als optionalen Parameter eine Zeichenkodierung. Dieser Paramter muss immer angegeben werden! Sonst besteht die Möglichkeit, dass die Ausgabe der Funktion nicht mehr in UTF-8 kodiert ist oder dass die Funktion erst gar nicht mit der Eingabe umgehen kann. Dem Parameter kann entweder der eStudy-Zeichensatz ($settings['charset']) oder direkt der String "UTF-8" übergeben werden. eStudy wird in Zukunft nur noch UTF-8 verwenden, daher ist von der Verwendung es Einstellungs-Parameter abzuraten (deprecated). Die direkte Angabe von UTF-8 sollte bevorzugt werden.

--Thelen-CTh 00:34, 11. Nov. 2008 (UTC)

--Henry-SHe 08:35, 12. Nov. 2008 (UTC)

--Volkmer-PCV 21:02, 12. Nov. 2008 (UTC)

Literatur