Multilingual websites with Lift and OSGi

Lift already provides mechanisms to publish a website in different languages. If Lift is used within an OSGi environment, a little workaround is needed in order to make it find the Resource Bundles containing language-dependent strings (usually provided as property files).

Internationalization with Lift

First of all, let me summarize the possibilities of internationalization with Lift: String resources have to be placed in so-called “property bundles”. These are normal Java property files like the following:

title=My Website
yes=Yes
no=No
deletequestion=Do you want to delete everything?

The name of a property bundle always starts with lift, but different suffixes in the ISO format will be appended describing the file’s language and country. For example, the file lift_en.properties contains English string resources, lift_de.properties contains German ones and lift_en_US.properties US American English. The prefix lift can be specified in the web application’s boot loader:

LiftRules.resourceNames = "anotherPrefix" :: Nil

The variable resourceNames is a list of strings, so resource bundles can be divided into multiple files with different prefixes. This is useful for larger projects with a lot of string resources.

After the resource bundles have been created, strings in HTML templates can be translated using the <lift:loc locid="..." /> tag. For example, following 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>

… will be translated to the following HTML code (using the properties file from above):

<html>
<head>
<title>My Website</title>
</head>
<body>
Do you want to delete everything?
<button>Yes</button>
<button>No</button>
</body>
</html>

In the Scala source code, the stateful object net.liftweb.http.S can be used instead. It provides the method ? which takes a string and looks for the corresponding translation in the resource bundle:

def snippet(xhtml: NodeSeq): NodeSeq =
  <p>{ S ? "deletequestion" }</p>

If you want to translate a tag’s attribute in a HTML template (e.g. the attribute value of the input tag), you should copy the respective code into a snippet. With this, you can use the S object to translate the attribute:

def inputButton(xhtml: NodeSeq): NodeSeq =
  <input type="button" value={ S ? "yes" } />

Resource Bundles in the OSGi environment

Lift tries to find resource bundles in the classpath using the method getClass.getClassLoader.getResourceAsStream(). In an OSGi environment, this is not going to work, because the classloader of the net.liftweb.lift-webkit bundle is used.

As mentioned above, this can be solved with a little workaround. A resource bundle factory has to be added in the application’s boot loader:

LiftRules.resourceBundleFactories prepend {
  case (basename, locale) => ResourceBundle.getBundle(basename, locale)
}

Therefore, the resource bundles will be loaded by the classloader of the bundle that contains the boot loader.

Conclusion

The means for internationalization provided by Lift are comprehensive enough for most websites. If something is not translatable using the <lift:loc> tag (e.g. attributes) or if more control over the process is needed, snippets can be used instead. In OSGi environments a resource bundle factory has to be created, so property files will be loaded by the correct classloader.


Profile image of Michel Krämer

Posted by Michel Krämer
on 5 April 2010


Next post

Easier use of Git

Git is my version control system of choice. I really love it but I found myself having to type the same commands over and over again. In this article, I share my Bash aliases that help me speed up my workflow.

Previous post

Scala projects with Eclipse PDE Build

The Scala IDE does not support Eclipse PDE yet. This article explains how to configure your OSGi-based project, so you can run your PDE build in headless mode and compile your Scala code.

Related posts

Build Scala projects with Eclipse Buckminster

Buckminster is a tool to build Eclipse RCP applications. It contains a lightweight Eclipse SDK and features but no means to build Scala projects yet. This post tries to bridge this gap.

10 recipes for gradle-download-task

gradle-download-task is a Gradle plugin that allows you to download files during the build process. This post summarizes common patterns and use cases of gradle-download-task and provides useful tips and tricks.

5 anti-spam measures for phpBB 3.0

Discussion boards powered by phpBB are regularly targeted by spammers. Version 3 has introduced an improved Captcha but there are more possibilities to reduce spam. In this article, I present five useful and effective measures.