Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Geleitwort des Fachgutachters
Vorwort
1 Einleitung
2 Einführung in eZ Components
3 Die Applikationsbasis
4 Fehlerbehandlung und Debugging
5 Konfiguration
6 Datenbankanbindung
7 ORM mit PersistentObject
8 Template
9 Übersetzung
10 Benutzereingaben validieren
11 Authentifizierung
12 Bildverarbeitung
13 Archive und Dateien
14 Mail
15 Logging
16 Diagramme
17 Feeds und Caching
18 Setup
A Inhalt der Buch-CD
Stichwort
Download: - ZIP, ca. 2,7 MB
Ihre Meinung?
<< zurück | Galileo Computing / <openbook> /eZ Components | vor >>
eZ Components von Tobias Schlitt, Kore Nordmann Das Entwickler-Handbuch
eZ Components geb., mit CD 454 S., 39,90 Euro Galileo Computing ISBN 978-3-8362-1073-7 |
| 9 Übersetzung
|  | 9.1 Komponente ezcTranslation
|  | 9.2 Qt Linguist
|  |  | 9.2.1 Das Dateiformat
|  |  | 9.2.2 Das Programm
|  | 9.3 Einbindung in die Applikation
|  |  | 9.3.1 Template-Funktion
|  |  | 9.3.2 Einfügen nicht vorhandener Übersetzungen
|  |  | 9.3.3 Templates anpassen
|  |  | 9.3.4 Parametrisierte Übersetzungen
|  |  | 9.3.5 Übersetzen
|  |  | 9.3.6 Filter
|  | 9.4 Caching von Übersetzungen
|  | 9.5 Fazit
## 9.3 Einbindung in die Applikation Die Integration in die Applikation muss drei Probleme lösen: Aufbauen der Übersetzungsdateien Übersetzen der Zeichenketten Verwenden der übersetzten Zeichenketten in den Templates Der zweite Schritt wird durch das zuvor beschriebene Programm Qt Linguist übernommen und muss nicht von der Webapplikation selbst behandelt werden. Das Aufbauen der Übersetzungsdateien kann auf zwei Arten funktionieren: Entweder schreibt man ein Programm, das die vorhandenen Templates nach zu übersetzenden Zeichenketten scannt, oder man fügt nicht übersetzte Zeichenketten in die Übersetzungsdateien ein, wenn sie in der Applikation angefordert werden, und benachrichtigt eventuell den Übersetzer, damit dieser sie übersetzen kann. Bei der Integration in das gpblog wählen wir den zweiten Weg. In der eigenen Template-Funktion zur Übersetzung von Zeichenketten wird diese in die Übersetzungsdatei eingefügt, falls noch nicht vorhanden, oder die Übersetzungsdatei neu angelegt. Um die Übersetzungen zu aktivieren, müssen dann nur noch die Templates angepasst werden, indem alle relevanten Zeichenketten in einen Funktionsaufruf gekapselt werden und eine Funktion zu den eigenen Template-Funktionen hinzugefügt wird. ### 9.3.1 Template-Funktion Die Template-Funktion wird, wie aus dem vorigen Kapitel 8, »Template«, bekannt, in der Datei classes/template_functions.php erstellt. Dazu wird die Funktion unter dem Namen gp_translate() der Template-Komponente bekanntgemacht, indem sie in der Methode getCustomFunctionDefinition() registriert wird.
    public static function getCustomFunctionDefinition( $name )
    {
        switch ( $name )
        {
        // ...
        case 'gp_translate':
                $def = new ezcTemplateCustomFunctionDefinition();
                $def->class = __CLASS__;
                $def->method = 'translate';
                return $def;
        }

        return false;
    }
Listing 9.2 Definition einer weiteren Template-Funktion Die Definition beschreibt, dass Aufrufe an die Template-Funktion gp_translate() an die statische Methode translate() aus der aktuellen Klasse weitergeleitet werden sollen. Die Template-Funktion akzeptiert drei Parameter: die zu übersetzende Zeichenkette gefolgt von einem optionalen Kontext und eine optionale Liste mit den angesprochenen Ersetzungen.
    public static function translate(
        $string, $context = 'none', $replacements = array()
    ) {
        // Get current locale for output
        $configuration = ezcConfigurationManager::getInstance();
        $locale = $configuration->getSetting(
            'site', 'installation', 'locale'
        );

        // Try to receive translation from translation component
        try
        {
            $fileBackend = new ezcTranslationTsBackend(
                dirname( __FILE__ ) . '/../translations/'
            );
            $fileBackend->setOptions(
                array( 'format' => 'translation-[LOCALE].ts' )
            );

            $manager = new ezcTranslationManager( $fileBackend );
            $translationContext = $manager->getContext(
                $locale, $context
            );

            $translated = $translationContext->getTranslation(
                $string, $replacements
            );
        }
        catch ( ezcTranslationException $e )
        {
            // Add translation to file, because this one still needs
            // to be translated
            gpBlogCustomFunctions::addTranslation(
                $context, $string, $locale
            );
            // ...
        }

        return $translated;
    }
Listing 9.3 Übersetzung einer Zeichenkette Zu Beginn der Methode wird die aus Kapitel 5, »Konfiguration«, bekannte Configuration-Komponente benutzt, um die zu verwendende Locales festzustellen. Anstelle dieses sehr einfachen Mechanismus könnte natürlich auch auf die vom Besucher vorgenommene Spracheinstellung (gespeichert in der Session oder Datenbank) oder auf die vom Besucher gewünschten Sprachen (definiert im Header des HTTP-Requests) zurückgegriffen werden. Was hier sinnvoll ist, entscheidet sich durch das Konzept der Applikation. Ein Blog mit meist einsprachigen Inhalten wird wohl häufig auch nur in einer Sprache verwendet werden. Entscheidend ist, dass Sie sich in der Applikation auf einen Locale-String festlegen, der für jede Sprache ein einheitliches Format hat, denn darüber entscheidet sich die Wahl der verwendeten Übersetzungsdatei. Wie bereits angesprochen, werden im Blog ts-Dateien für die Übersetzungen verwendet, entsprechend wird das ezcTranslationTsBackend mit dem Pfad zu den Übersetzungsdateien initialisiert. Als Option wird der zu verwendende Dateiname explizit gesetzt, wobei die Zeichenkette [LOCALE] natürlich intern durch die für die Übersetzung verwendete Locale ersetzt wird. Als Nächstes wird der ezcTranslationManager mit dem initialisierten Backend erzeugt und aus diesem der Kontext für die zu übersetzende Zeichenkette erfragt. – Sie erinnern sich: Ein Kontext bildet Gruppierungen für übersetzte Zeichenketten. Von dem Objekt der Klasse ezcTranslationContext in der Variablen $translationContext können nun die eigentlichen Übersetzungen erfragt werden. Bei der Abfrage der Übersetzung wird zusätzlich das optionale Array mit Übersetzungen übergeben, sodass in der Rückgabe in der Variablen $translated eine für die Ausgabe verwendbare Zeichenkette erzeugt wird. Eine Exception der Klasse ezcTranslationException während dieses Prozesses kann mehrere Ursachen haben. Es kann passieren, dass die Übersetzungsdatei, der Kontext dieser Datei oder die Übersetzung selbst bislang noch nicht angefordert wurden, und damit nicht verfügbar sind. In diesem Fall wird die statische Methode gpBlogCustomFunctions::addTranslation() aufgerufen, die die Übersetzung der Datei hinzufügt. Wenn lediglich die Übersetzung noch nicht von dem Übersetzer angefertigt worden ist, ist die Rückgabe von getTranslation() ebenfalls leer. Hier hilft einer der schon zuvor angesprochenen Filter. Diese lassen sich nach der Instanziierung dem Manager zuweisen, weswegen der entsprechende Abschnitt folgendermaßen erweitert wird:
    // ...
    $manager = new ezcTranslationManager( $fileBackend );
    $manager->addFilter(
        ezcTranslationComplementEmptyFilter::getInstance()
    );
    $translationContext = $manager->getContext( $locale, $context );
    // ...
Listing 9.4 Filter verwenden Der Filter ezcTranslationComplementEmptyFilter sorgt dafür, dass noch nicht fertiggestellte Übersetzungen, die das Attribute type="unfinished" im XML-Code haben, durch die Originalzeichenkette ersetzt werden. Damit ist sichergestellt, dass alle Texte in der Applikation auftauchen, auch wenn sie noch zu neu sind, um bereits übersetzt zu sein. Mit weiteren Filtern, die in der Translation-Komponente enthalten sind, lassen sich zum Beispiel übersetzte Texte nach Leet-Code verwandeln. Natürlich können auch eigene Filter entwickelt und verwendet werden.
Leet-Code
Ursprünglich diente Leet-Code dazu, automatische Programme zur Textanalyse von E-Mails und anderer textueller Kommunikation zu täuschen. Diese Täuschung funktioniert durch die Ersetzung von Buchstaben in Wörtern durch Zahlen und Sonderzeichen. Die so entstehenden unzähligen Varianten sind mit einiger Übung leicht zu lesen, aber erheblich schwieriger automatisiert zu erkennen. Eine ernsthafte Anwendungsmöglichkeit ist uns jedoch nicht bekannt. Ein Beispiel wäre die Transformation der Zeichenkette »eZ Components« nach »3z (0mp0n375« – die Transformationen der einzelnen Buchstaben sind jedoch nicht definiert).
### 9.3.2 Einfügen nicht vorhandener Übersetzungen Bislang nicht vorhandene Übersetzungen können mehrere Ursachen haben. Die Methode zum Einfügen muss alle diese möglichen Gründe abfangen.
    protected static function addTranslation(
        $context, $string, $locale
    ) {
    }
Listing 9.5 Signatur der Methode addTranslation() Als Parameter bekommt die statische Methode den Kontext, die zu übersetzende Zeichenkette sowie die aktuelle Locale. Als Erstes muss überprüft werden, ob die Datei mit den Übersetzungen vorhanden ist und andernfalls entsprechend dem zuvor beschriebenen Schema erstellt werden.
    $filename = dirname( __FILE__ ) .
        '/../translations/translation-' . $locale . '.ts';

    // Check if translation file exists
    if ( !is_file( $filename ) )
    {
        // Create otherwise
        $dom = new DOMDocument();
        $root = $dom->createElement( 'TS' );
        $dom->appendChild( $root );
    }
    else
    {
        // Or just load it
        $dom = new DOMDocument();
        $dom->load( $filename );
        $root = $dom->getElementsByTagName( 'TS' )->item( 0 );
    }
Listing 9.6 Initialisierung des DOM-Dokuments Dazu wird erst der Dateiname aufgebaut, der verwendet werden soll, um dann zu überprüfen, ob diese Datei existiert. Falls dies nicht der Fall ist, wird ein neues DOMDocument-Objekt mit einem Wurzelknoten <TS> erstellt. Eine Referenz auf den Wurzelknoten wird dabei in der Variablen $root gespeichert, da hier eventuell nachher nicht vorhandene Kontexte hinzugefügt werden müssen. Falls die Datei jedoch bereits vorhanden ist, wird ein DOMDocument-Objekt aus der Datei erstellt, also die Datei geladen und das erste <TS>-Element, also wieder der Wurzelknoten, in der Variablen $root referenziert.
    $xpath = new DOMXPath( $dom );

    // Check if context already exists
    $result = $xpath->
    query( '//context/name[text()="' . htmlspecialchars( $context ) . '"]' );
    if ( !$result->length )
    {
        // Create context
        $contextNode = $dom->createElement( 'context' );
        $nameNode = $dom->createElement(
            'name', htmlspecialchars( $context )
        );
        $contextNode->appendChild( $nameNode );
        $root->appendChild( $contextNode );
    }
    else
    {
        $contextNode = $result->item( 0 )->parentNode;
    }
Listing 9.7 Die Existenz des Kontextes sicherstellen Um zu überprüfen, ob der verwendete Kontext bereits in der XML-Datei existiert, wird eine XPath-Query verwendet. XPath ist eine Abfragesprache für XML-Dokumente, ähnlich wie es SQL für relationale Datenbanken ist. Damit lassen sich direkt Teile eines XML-Dokuments adressieren. Über Elementnamen, Attribute, Attribut-Inhalte oder andere Charakteristika. In dem obigen Beispiel beschreibt die XPath-Query alle <context>-Elemente mit einem <name>-Element als Kind, deren textueller Inhalt dem angefragtem Kontext entspricht. Wenn die Ergebnisliste leer ist, muss ein neuer Kontext mit demjenigen Namen erzeugt werden, der in der Variablen $contextNode referenziert bleibt. Falls der Kontext bereits existiert und in der Ergebnisliste enthalten ist, kann er in der Variablen $contextNode über das Eltern-Element des in der Ergebnisliste enthaltenen <name>-Elements referenziert werden, um später die Übersetzung einzufügen.
    // Add translation node to context
    $message = $dom->createElement( 'message' );

    $source = $dom->
    createElement( 'source', htmlspecialchars( $string ) );
    $message->appendChild( $source );

    $translation = $dom->createElement( 'translation' );
    $translation->setAttribute( 'type', 'unfinished' );
    $message->appendChild( $translation );

    $contextNode->appendChild( $message );

    // Save xml
    $dom->save( $filename );
Listing 9.8 Übersetzung einfügen Da die Methode aufgerufen wurde, ist gewiss, dass die Translation-Komponente keine Übersetzung finden kann, sie also in der Datei nicht vorhanden ist. Aus diesem Grund wird ein neues <message>-Element erzeugt, das ein <source>-Element mit der originalen Zeichenkette enthält, sowie ein <translation>-Element mit dem Attribut type=«unfinished«, das sowohl Qt Linguist als auch der Translation-Komponente zeigt, dass diese Zeichenkette noch übersetzt werden muss. Zum Schluss wird das manipulierte oder neu erstellte Dokument gespeichert. Optional könnte hiernach noch eine Nachricht an den Übersetzer gehen, dass sich eine neu zu übersetzende Zeichenkette in der Datei befindet. Nach dem Aufruf dieser Methode ist somit sichergestellt, dass sich die Übersetzung in der Datei befindet. Ist dies der Fall, so kann in der ursprünglichen Methode translate() zur Abfrage der Übersetzungen diese einfach neu erfragt werden. Dazu wird der Code, der die Exception fängt, noch einmal geringfügig modifiziert.
    catch ( ezcTranslationException $e )
    {
        // Add translation to file, because this one still needs to
        // be translated
        gpBlogCustomFunctions::addTranslation(
            $context, $string, $locale
        );

        // Rerequest translation after adding translation to file
        $translated = self::translate(
            $string, $context, $replacements
        );
    }
Listing 9.9 Erneutes Erfragen der Übersetzung Nach dem Hinzufügen der zu übersetzenden Zeichenkette wird die Methode translate() mit den originalen Parametern erneut aufgerufen. Auch wird nun auf Grund von ezcTranslationComplementEmptyFilter die erfolgreiche Übersetzung in der Variablen $translated gespeichert, sodass sie im Template verwendet werden kann. ### 9.3.3 Templates anpassen Damit die Translation-Komponente auch wirklich verwendet wird, müssen die Templates angepasst werden, um die neu geschriebene Template-Funktion gp_translate() zu verwenden. Im nächsten Kapitel 10, »Benutzereingaben validieren«, wird die User-Input-Komponente in die Applikation eingebunden, sodass wir dafür in diesem Kapitel das Formular zum Erstellen von Kommentaren vorbereiten, das zum Ende des aus Kapitel 8, »Template«, bekannten Templates show_entry.ezt über ein {include} eingebunden wird.
    {include "comment_form.ezt" send $entry, $base}
Das Template inklusive der Verwendung der Funktion gp_translate() gestaltet sich dann folgendermaßen:
    {use $entry, $base}

    <form name="comment_form" id="comment_form"
        action="{$base}save_comment" method="POST">
    <input type="hidden" name="entryId" id="entryId"
        value="{$entry->id}" />
        <fieldset>
            <legend>
                {gp_translate('Leave a comment', 'comment/new')}
            </legend>
            <label for="name">
                {gp_translate('Name:', 'comment/new')}
            </label>
            <input name="name" id="name" type="text" /><br />
            <label for="email">
                {gp_translate('Email:', 'comment/new')}
            </label>
            <input name="email" id="email" type="text" /><br />
            <label for="body">
                 {gp_translate('Body:', 'comment/new')}
            </label>
            <textarea name="body" id="body"></textarea><br />
            <label for="save">
                {gp_translate('Save:', 'comment/new')}
            </label>
            <input name="save" id="save" type="submit"
                value="{gp_translate('Store entry', 'comment/new')}"
                /><br />
        </fieldset>
    </form>
Listing 9.10 Übersetztes Kommentarformular Das Template zeigt die aus Kapitel 8, »Template«, bekannte Syntax, nur dass hier alle für den Benutzer sichtbaren Zeichenketten durch einen Aufruf von gp_translate() gekapselt werden. Als Kontext wird comment/new verwendet, was es dem Übersetzer später leicht machen sollte, die Herkunft der Zeichenkette zuzuordnen. Bei der ersten Anfrage der URL http://gpblog/index.php/show_entry/1 wird nun eine Datei mit nicht übersetzten Zeichenketten erstellt und es werden die originalen englischen Zeichenketten ausgegeben. Hier klicken, um das Bild zu vergrößern Abbildung 9.2 Angepasstes, nicht übersetztes Template ### 9.3.4 Parametrisierte Übersetzungen Wie zuvor schon angesprochen, ist es möglich, durch die Applikation bestimmte Parameter in die Übersetzungen zu integrieren. Auf dem obigen Screenshot sind die noch zu übersetzenden Zeichenketten »at $datum« und »$user at $datum« im Template templates/show_entry.ezt beziehungsweise templates/comment.ezt zu erkennen. Der relevante Teil des ersten Templates gestaltet sich folgendermaßen:
    <h3>{$entry->title}</h3>
    <h4>{
    gp_translate(
        'at %date',
        'blog/entry',
        array(
            'date' => gp_show_date( '%A, %d. %B %Y – %H:%M',
                $entry->date
            )
        )
    ) }</h4>

    <p>
        {raw $entry->body}
    </p>
Listing 9.11 Übersetzung mit Parametern In diesem Beispiel enthält die zu übersetzende Zeichenkette den Platzhalter %date, dessen Ersetzung über den dritten Parameter der Template-Funktion definiert wird – die aus Abschnitt 8.3.10, »Gebietsabhängiges Datum«, bekannte Funktion zur Anzeige eines lokalisierten Datums. Das Array kann beliebig viele Platzhalter enthalten. ### 9.3.5 Übersetzen Die Zeichenketten, die sich in der Datei translations/translation-de_DE.ts angesammelt haben, müssen nun natürlich noch übersetzt werden, damit das Interface wirklich lokalisiert ist. Wenn Sie eine andere Locale in Ihrer Konfiguration eingestellt haben, heißt die Datei dementsprechend. Zu finden ist sie in jedem Fall im Pfad translations/ im Basisverzeichnis des Blogs. Wenn Qt Linguist nun mit der neu erstellten Datei geöffnet wird, ist keine der Zeichenketten übersetzt. Die hierarchisch sortierten Übersetzungen können einzeln ausgewählt und übersetzt oder per + durchgegangen und übersetzt werden. Mit den Übersetzungen für alle Zeichenketten sollte dies anschließend etwa folgendermaßen aussehen: Hier klicken, um das Bild zu vergrößern Abbildung 9.3 Übersetzen der Blog-Texte mit Qt-Linguist Hier klicken, um das Bild zu vergrößern Abbildung 9.4 Vollständige Übersetzung mit Qt Linguist Wenn die Applikation nun erneut aufgerufen wird, sollten sich die gerade mit Qt Linguist übersetzen Texte zeigen. Hier klicken, um das Bild zu vergrößern Abbildung 9.5 Resultat: Übersetztes Blog Abgesehen von Titel und Namen ist die Applikation nun durchweg in deutscher Sprache gehalten. ### 9.3.6 Filter Um die Wirkung der weiteren, bislang nur kurz angesprochenen Filter zu zeigen, wird der ezcTranslationLeetFilter in die Applikation eingebunden. Dies geschieht direkt nach dem Einbinden des Filters ezcTranslationComplementEmptyFilter in der nachfolgenden Zeile.
    $manager = new ezcTranslationManager( $fileBackend );
    $manager->addFilter(
        ezcTranslationComplementEmptyFilter::getInstance()
    );
    $manager->addFilter(
        ezcTranslationLeetFilter::getInstance()
    );
    $translationContext = $manager->getContext( $locale, $context );
Listing 9.12 Leet-Filter einfügen Das Ergebnis ist, dass nun alle übersetzten Zeichenketten in Leet-Schrift in der Applikation auftauchen. Hier klicken, um das Bild zu vergrößern Abbildung 9.6 Leet-Filter zeigt an, welche Texte übersetzt sind. So unsinnig diese Manipulation im ersten Augenblick scheinen mag, so lassen sich über diesen Mechanismus doch sehr sinnvolle Applikationserweiterungen implementieren. So ist beispielsweise denkbar, einen applikationsspezifischen Filter zu schreiben, der bislang nicht übersetzte Zeichenketten mit einem Link oder Popup versieht, womit es dem Besucher oder einem autorisierten Administrator ermöglicht wird, direkt eine Übersetzung einzugeben und zu speichern. Während der Entwicklung der Applikation ließen sich die nicht übersetzten Zeichenketten auch einfärben oder in eine Log-Datei schreiben. ### Ihr Kommentar Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück | <top> | vor >>
Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen? Ihre Meinung
Buchempfehlungen
| PHP 5.3 und MySQL 5.1
| Besser PHP programmieren
| Webshops mit Magento
| Sichere Webanwendungen
| PHP 5.3 und MySQL 5.1 - Videotraining
| Apache 2
| Suchmaschinen- Optimierung für Webentwickler
| Joomla! 1.5
Shopping
Versandkostenfrei bestellen in Deutschland und Österreich Info

Copyright © Galileo Press 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

[Galileo Computing]
Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de