Mehrsprachige Webseiten mit Lift und OSGi
Für die Internationalisierung von Webseiten bietet Lift bereits einige Mechanismen. Wird das Framework aber in einer OSGi-Umgebung verwendet, benötigt man einen kleinen Workaround, damit die Resource Bundles in Form von Property-Files gefunden werden können.
Internationalisierung mit Lift
Zunächst eine kleine Zusammenfassung der Möglichkeiten zur Internationalisierung mit Lift: Die String-Ressourcen müssen in so genannten "Property-Bundles" abgelegt werden. Das sind ganz normale Java-Properties-Dateien in der folgenden Form:
title=Meine Website
yes=Ja
no=Nein
deletequestion=Möchten Sie alles löschen?
Der Name der Property-Bundles beginnt immer mit lift. Jedoch werden
unterschiedliche Suffixe angehängt, die die entsprechende Sprache und
optional das Land im ISO-Format angeben. Zum Beispiel enthält die Datei
lift_en.properties englische String-Ressourcen während
lift_de.properties deutsche und lift_de_CH.properties
schweizerdeutsche enthält. Den Präfix lift kann man im Boot-Loader der
Webapplikation spezifizieren:
LiftRules.resourceNames = "anotherPrefix" :: Nil
Die Variable resourceNames ist dabei eine Liste von Strings. Das
heißt, man kann seine Resource-Bundles auch in mehrere Dateien mit
unterschiedlichen Präfixen aufteilen, damit man z.B. in großen
Projekten nicht den Überblick verliert.
Hat man die Resource-Bundles erstellt, kann man Strings in HTML-Templates
mit <lift:loc locid="..." /> übersetzen. Verwendet man also die
Properties-Datei aus obigem Beispiel, dann wird das folgende Template
<html>
<head>
<title><lift:loc locid="title" /></title>
</head>
<body>
<lift:loc locid="deletequestion" />
<button><lift:loc locid="yes" /></button>
<button><lift:loc locid="no" /></button>
</body>
</html>
in folgenden HTML-Code übersetzt:
<html>
<head>
<title>Meine Website</title>
</head>
<body>
Möchten Sie alles Löschen?
<button>Ja</button>
<button>Nein</button>
</body>
</html>
Im Scala-Quellcode kann man stattdessen das Stateful-Objekt
net.liftweb.http.S verwenden. Es definiert die Methode ?, die einen
String als Parameter annimmt und diesen im Resource-Bundle sucht:
def snippet(xhtml: NodeSeq): NodeSeq =
<p>{ S ? "deletequestion" }</p>
Ein kleiner Tipp: Möchte man in den HTML-Templates Tag-Attribute
übersetzen (z.B. das Attribut value eines input-Elements), dann
sollte man den entsprechenden Teil in ein Snippet auslagern, sodass man
das S-Objekt verwenden kann:
def inputButton(xhtml: NodeSeq): NodeSeq =
<input type="button" value={ S ? "yes" } />
Resource-Bundles in der OSGi-Umgebung
Das Problem mit der oben beschriebenen Methode ist, dass die
Resource-Bundles von Lift im Classpath mittels
getClass.getClassLoader.getResourceAsStream() gesucht werden. In einer
OSGi-Umgebung können Sie demnach nicht mehr gefunden werden, da der
Classloader des Bundles net.liftweb.lift-webkit verwendet wird.
Wie eingangs erwähnt, kann man dies mit einem Workaround lösen. Dazu muss man im BootLoader eine Resource-Bundle-Factory definieren:
LiftRules.resourceBundleFactories prepend {
case (basename, locale) => ResourceBundle.getBundle(basename, locale)
}
Dadurch werden die Resource-Bundles über den Classloader des Bundles, das den BootLoader enthält, geladen.
Zusammenfassung
Die Mechanismen zur Internationalisierung mit Lift sind ausreichend für die meisten Webseiten. Wenn man etwas mit dem Lift-Tag nicht übersetzen kann (z.B. Attribute) oder man mehr Kontrolle benötigt, muss man auf Snippets ausweichen. In OSGi-Umgebungen muss man eine Resource-Bundle-Factory erzeugen, die die Properties-Dateien über den korrekten Classloader lädt.
Add to: