Posted by dcengija on March 23, 2004 at 6:32 AM PST
Luxor is a free, open-source XML User Interface Language (XUL) toolkit in Java. We use it to define our application's GUI and it really works. Until we needed to provide the multilingual versions. Read how we solved this problem by applying XSLT translations on the fly.
Luxor is a useful tool: it really increases your productivity. Usage is simple: define your user interface in an XML file, add some Java meat around it and you have it running. Everything's nice and clean as long as you have only one human language to support.
As soon as you introduce another language, you have problems. As shown in the XML snippet above, Luxor uses label, value and other attributes to assing the text to be displayed in the GUI. Unfortunatelly, those text values are hard coded and your only option is to provide different set of XML definitions for each human language you want to support. Please note that noone said 'different XML files', but 'different XML definitions', and that's the place where XSLT jumps in.
The approach we took was to translate XML definitions on the fly, using a simple XSLT stylesheet. To achieve that, we needed to do four things: 1. Edit XML definitions and add a custom attribute to those elements you want to translate, 2. Create an XSLT stylesheet which will transform XML definitions, 3. Create your translation file in the language of your choice and 4. Edit Luxor's code and glue it all together.
Changing XML definitions
We decided to add another attribute, tranid to each element we want to translate. So, for example, first label="Test Users" style="height:35px;"/> etc. Of course, those tranids need to unique accross your application.
The XSLT stylesheet is pretty simple: it copies all elements which don't have tranid attribute, and for some elements which might have it (button, label and some other, not shown here) it copies all attributes except value or label or tooltip, depending on the element. Finally, XML translation file is read and the appropriate values in another language are added.
Find out where Luxor reads its resources and just after an XML definition is read and just before it is sent further to the Luxor's system, transform it. The example is shown below. Necessary steps are:
Instantiate TransformerFactory and load the stylesheet
Assign the appropriate translation file
Do the actual transformation
Procede with transformated InputStream
Of course, this code could be written better: possible FileNotFound and other exceptions need to be handled, translation file name will almost certainly be read from some configuration file, stylesheet and translation file could be read from a jar file, TransformerFactory could be static field etc, but for this showcase this approach better shows what should be done.