Mai
26

Mehrsprachigkeit mit Zend_Application

Eine Multilinguale Seite mit Zend_Application aufzubauen ist gar nicht so schwer, wie man denkt. Ich gehe hier davon aus, dass man schon Erfahrung mit Zend_Application hat und werde es nicht in jeder Kleinigkeit erklären. Das ganze basiert auf dem Zend Framework 1.8.1

Wenn man am Ende alles richtig eingebaut hat anhang der Beispieldaten, dann sind die Sprachen Deutsch und Englisch verfügbar über die folgenden Adressen:

http://en.domain.tld -> Englisch
http://de.domain.tld -> Deutsch
http://fr.domain.tld -> Deutsch, da dies als Standard gesetzt wird in der Bootstrap

Zuerst einma benötigt man Translate Dateien. Ich habe dafür eine Verzeichnisstruktur angelegt, in der sich ein Ordner für jede Sprache findet. In meinem Fall sind dies “de” und “en”. In diesen liegen dann die verschiedenen PHP Dateien mit Arrays. Hier kurz Beispielhaft für Deutsch und Englisch jeweils die string.php

return array(

'WELCOME' => 'Willkommen zum Test'

);
return array(

'WELCOME' => 'Welcome to the Test'

);

Über die application.ini setzt man die nötigen Routen, Locale und Translate Einstellungen. Bitte die angegebene Domain im Router auch in die richtige ändern.

resources.router.routes.language.type = "Zend_Controller_Router_Route_Hostname"
resources.router.routes.language.route = ":lang.domain.tld"
resources.router.routes.language.defaults.controller = "index"
resources.router.routes.language.defaults.action = "index"
resources.router.routes.language.defaults.lang = "de"
resources.router.routes.language.chains.index.type = "Zend_Controller_Router_Route"
resources.router.routes.language.chains.index.route = ":controller/:action/*"
resources.router.routes.language.chains.index.defaults.module = "default"
resources.router.routes.language.chains.index.defaults.controller = "index"
resources.router.routes.language.chains.index.defaults.controller = "index"
resources.router.routes.language.chains.base.type = "Zend_Controller_Router_Route"
resources.router.routes.language.chains.base.route = "/*"
resources.router.routes.language.chains.base.defaults.module = "default"
resources.router.routes.language.chains.base.defaults.controller = "index"
resources.router.routes.language.chains.base.defaults.controller = "index"

resources.translate.adapter = "array"
resources.translate.data = APPLICATION_PATH "/languages"
resources.translate.locale = "en"
resources.translate.options.disableNotices = true
resources.translate.options.scan = "directory"

Und zuletzt die Bootstrap Klasse

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{

protected function _initRequest()
{
// Nötige Abhängigkeiten auflösen
$this->bootstrap('FrontController');
$this->bootstrap('router');

// Den Frontcontroller holen
$front = $this->getResource('FrontController');

// Ein Request Objekt in den Frontcontroller setzen
$request = new Zend_Controller_Request_Http();
$request->setBaseUrl('/');
$front->setRequest($request);

// Den Request in die Registry des Bootstrap Objekt setzen
return $request;
}

protected function _initLang()
{
// Die nötigen Abhhängigkeiten aufbauen
$this->bootstrap('FrontController');
$this->bootstrap('router');
$this->bootstrap('translate');

// Den Frontcontroller mit dem Request Objekt holen und den Router ausführen
$front = Zend_Controller_Front::getInstance();
$request = $front->getRequest();
$router = $front->getRouter();
$router->route($request);

// Das Translate Objekt holen
$lang = $this->getResource('translate');

// Prüfen, ob die ausgewählte Sprache zur verfügung steht, wenn nicht, dann Standard setzen.
if (!$lang->isAvailable($front->getRequest()->getParam('lang','de'))) {
$front->getRequest()->setParam('lang','de');
}

// Die ausgewählte Sprache in das Translate setzen
$lang->setLocale($front->getRequest()->getParam('lang'));

return;
}

}

Zum Test kann man sich einen String ausgeben lassen in der View

<?=$this->translate('WELCOME')?>

Das ganze ist natürlich noch um einige Features erweiterbar, aber mit diesen Schritten hat man eine gute Basis um weiter zu kommen. Interessant sind für den Einbau wohl noch Zend_Cache, entsprechende andere Router oder das speichern der Standardsprache in der Konfiguration für schnelle Änderungen.

  • Christian 28. Juni 2009 um 22:41

    Also irgendwie gibt es da Probeme mit dem Routen, wenn man Module mit params nutzen möchte: Wenn ich die Params weg lasse funktioniert es?
    resources.router.routes.language.chains.index.route = “:module/:controller/:action/*”

  • admin 29. Juni 2009 um 13:09

    Hi Christian,
    also das wundert mich etwas. Durch das endende * auf die Params werden eigentlich alle folgenden Parameter verwendet. Ich werde das aber mal testen. Bisher habe ich das ganze nur in nicht-modularen Umgebungen am Laufen.

  • Christian 29. Juni 2009 um 13:21

    Hi Zorta,
    danke für die AW. Genau, das gleiche wundert mich auch. ;)
    Bin jetzt leider noch keinen schritt weiter gekommen. Außer, wenn ich * durch :p0/:p1 ersetze scheint es zu funktionieren, wenn ich es aber mit * versuche wird der Controller mit dem modul verwechselt.
    Mache jetzt einfach mal einen Auszug ;): /main/index/login/hallo/welt (main=modul, index=controller, login=action, hallo=param)

    Request Parameters:
    array(4) {
    ["controller"]=>
    string(4) “main”
    ["action"]=>
    string(5) “index”
    ["login"]=>
    string(5) “hallo”
    ["module"]=>
    string(7) “default”
    }

    Vielleicht siehst Du da ja was raus. (Das “default” modul heißt übrigens wirklich main)
    Many THX. ;) Christian

  • Christian 29. Juni 2009 um 17:46

    So. ich habe es geschafft. ;)
    Einfach
    resources.router.routes.language.chains.index.route = “:controller/:action/*” nutzen.
    Trotzdem wird beim aufuf von modul/controller/action/params alles korrekt ausgeführt. ;)

  • Denis 30. Juni 2009 um 07:59

    Hmm … ok. Danke.
    Also ist für die modulare Nutzung keine Anpassung nötig. Das ist gut zu wissen :)

  • mime 14. Januar 2010 um 17:33

Kommentar schreiben