dominoGuru.com

Your Development & Design Resource

Multi-Lingual Support for XPage Controls via Properties Files

Beats 'Trek's 'Universal Translator'... No Batteries 
Required! While working on Remote Console HD, I thought I would heed the advice of a friend from the community and look into providing language skins for my apps. Of course, there are absolutely tried and tested methods for doing this using traditional IBM Lotus Notes Domino Development techniques... but with .Properties File Resources, it's infinitely easier with XPages!

The idea is simple: Field/Input labels, View Column Headers, and any in-app content would have a translation that could be applied across the application. In other words, the Readers Field for Remote Console HD would have an English label (Restrict to), a Spanish label (Limitar a los), or even a German label (Beschränken auf).

Again, certainly techniques available using traditional Design Elements for something like a label (Computed Text looking up a Language Profile is most common...), but when you get into View Column Headers, it gets really tricky.

XPage Controls, however, don't fall victim of such limitations.

Jeremy Hodge recently wrote an excellent article on using .Properties files to create Global Variables for your XPage apps, and it was that article that inspired the technique I used for my own localization of Remote Console HD.

To start, I created a new File Resource named language.properties, with the following content:

[line numbers below have been added for reference purposes, and not part of the text added to the .Properties File Resource]

  1. #default language options
  2. language=EN
  3. #English
  4. EN_label_server=Server
  5. EN_label_servers=Servers
  6. EN_label_readers=Restrict to
  7. EN_label_command=Command
  8. EN_label_commands=Commands
  9. EN_label_create=Add
  10. EN_label_edit=Edit
  11. EN_label_submit=Submit
  12. #Spanish
  13. SP_label_server=Servidor
  14. SP_label_servers=Servidores
  15. SP_label_readers=Limitar a los
  16. SP_label_command=Comando
  17. SP_label_commands=Comandos
  18. SP_label_create=A\u00F1adir
  19. SP_label_edit=Edici\u00F3n
  20. SP_label_submit=Presentar
  21. #German
  22. DE_label_server=Server
  23. DE_label_servers=Server
  24. DE_label_readers=Beschr\u00E4nken auf
  25. DE_label_command=Befehl
  26. DE_label_commands=Erstellen
  27. DE_label_create=Hinzuf\u00FCgen
  28. DE_label_edit=Editieren
  29. DE_label_submit=Einreichen

Lines 18, 19, 24, and 27 above contain the escaped unicode characters for ñ, ó, ä and ü respectively. A complete list of unicode characters [which you'll need to reference in order to truly go multi-lingual] can be found at http://en.wikipedia.org/wiki/List_of_Unicode_characters.

Once you have created your .Properties File, you can add it as a Resource to your XPage.

XPage Resource Bundle

Once you have selected Add\Resource Bundle... from the XPage Resources section of the XPage Properties Pane, you will select your .Properties File and define a Resource Bundle Name (which acts as a variable declaration for use in your XPage).

Added to the XPage, you can now reference any value in the .Properties File via the following syntax:

Resource Bundle Variable[.Properties File Name/Value Name]

... or, for a less-confusing way to put it:

preferences['EN_label_server']

Fairly straight forward from here really. Let's take a look at a demo block of labels for Remote Console HD:

<div class="card">
    <h3>Static English</h3>
    <xp:text escape="true" id="computedField17"
        styleClass="example">
        <xp:this.value><![CDATA[#{javascript:preferences['EN_label_server']}]]></xp:this.value>
    </xp:text>
    <xp:text escape="true" id="computedField18"
        styleClass="example">
        <xp:this.value><![CDATA[#{javascript:preferences['EN_label_servers']}]]></xp:this.value>
    </xp:text>
    <xp:text escape="true" id="computedField19"
        styleClass="example">
        <xp:this.value><![CDATA[#{javascript:preferences['EN_label_readers']}]]></xp:this.value>
    </xp:text>
    <xp:text escape="true" id="computedField20"
        styleClass="example">
        <xp:this.value><![CDATA[#{javascript:preferences['EN_label_command']}]]></xp:this.value>
    </xp:text>
    <xp:text escape="true" id="computedField21"
        styleClass="example">
        <xp:this.value><![CDATA[#{javascript:preferences['EN_label_commands']}]]></xp:this.value>
    </xp:text>
    <xp:text escape="true" id="computedField22"
        styleClass="example">
        <xp:this.value><![CDATA[#{javascript:preferences['EN_label_create']}]]></xp:this.value>
    </xp:text>
    <xp:text escape="true" id="computedField23"
        styleClass="example">
        <xp:this.value><![CDATA[#{javascript:preferences['EN_label_edit']}]]>< span class="sc3"></xp:this.value>

    </xp:text>
    <xp:text escape="true" id="computedField24"
        styleClass="example">
        <xp:this.value><![CDATA[#{javascript:preferences['EN_label_submit']}]]></xp:this.value>
    </xp:text>
</div>

With some CSS, we get the following:

XPage Mutli-Lingual Control - Static English Demo

Taking this technique one step further, we can use the Default Language Option defined in the language.properties File:

<xp:text escape="true" id="computedField1"
    styleClass="example">
    <xp:this.value><![CDATA[#{javascript:preferences[preferences['language'] + '_label_server']}]]></xp:this.value>
</xp:text>

From here, the Lotus Professional who purchased their copy of Remote Console HD would only need to change the .Properties File Resource [which could even be done programmatically via Java] language value from EN to SP to change all labels, view column titles, and all other content wired to the language.properties Resource Bundle.

You could even provide a user profiling facility in the application to allow for individual language preferences, or base the leveraged name/value pairs on a UI Trigger:

<div class="card">
    <h3>Default, with UI Trigger</h3>
    <h4>
        <xp:comboBox id="languagepicker">
        <xp:this.defaultValue><![CDATA[#{javascript:preferences['language']}]]></xp:this.defaultValue>
        <xp:selectItem itemLabel="English" itemValue="EN"></xp:selectItem>
        <xp:selectItem itemLabel="Spanish" itemValue="SP"></xp:selectItem>
        <xp:selectItem itemLabel="German" itemValue="DE"></xp:selectItem>
        <xp:eventHandler event="onchange" submit="true"
            refreshMode="partial" refreshId="uitrigger_elements">
        </xp:eventHandler>
        </xp:comboBox>
    </h4>
    <xp:panel id="uitrigger_elements">
        <xp:text escape="true" id="computedField25"
        styleClass="example">
        <xp:this.value><![CDATA[#{javascript:var fv = getComponent("languagepicker").getValue();
if (fv == "") {
    fv = preferences['language']
}
preferences[fv + '_label_server']}]]></xp:this.value>
        </xp:text>
        ...
    </xp:panel>
</div>

Here we have a simple comboBox Control that performs a Partial Refresh on the uitrigger_elements panel Control, which is wired to the value of said comboBox Control. The logic here is pretty simple: If the languagepicker comboBox value is blank, use the Resource Bundle's default language designation, otherwise use the language defined by the comboBox.

Combine this with the .Properties Resource Bundle read/write capabilities available vi a Java (which I believe Jeremy is working on a follow-up to the previously-mentioned article that inspired this one illustrating a Java read/write/save example for Resource Bundles), and you can really get a feeling for the awesome potential of this technique.

You can view a demo of this technique in action now at http://guru.gbs.com/demo/demo.nsf/babelfish.xsp, and a huge thanks to Jeremy Hodge, who not only inspired this article but who also helped me figure out the need to escape unicode special characters.


About the author: Chris Toohey

Thought Leadership, Web & Mobile Application Development, Solutions Integration, Technical Writing & Mentoring

A published developer and webmaster of dominoGuru.com, Chris Toohey specializes in platform application development, solutions integration, and evangelism of platform capabilities and best practices.



More from dominoGuru.com


dominoGuru.com is powered by IBM Notes Domino XPages & hosted by Prominic.NET

Contact Us

Use our Contact / Feedback form or one of these email addresses:

Creative Commons License

Except where otherwise noted, dominoGuru.com by Chris Toohey is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.