Using the language bean from XPages Toolkit for Internationalization

Introduction

You have people who tend to tick around where they live and work and you have people who tend to switch location now and then. Especially in Europe which is divided into many countries with many different languages, somehow operating under one flague,  you are sometimes amazed that organizations have not fully adapted to the trend of “travelling” co-workers.

different langiages

If you are lucky an application is presented bilingual but in a lot of occasions an application is presented either in English (when that is the official language of communication) or in a native language where the application is initiated and being used.

But what if that cross-border European co-worker enters the work floor?

Internationalization

Internationalization refers to the process whereby you prepare your application for users from varied geographies. There are two parts to this:

The need for localization is obvious; a German user wants to see an application in German and a French user in French, and so on. Localization involves making different language versions of all the application’s user interface available and ensuring the correct strings are used based on user preferences.

Support in XPages

In the IBM Notes and Domino Application Development wiki you can learn about the support for internationalization in XPages.

In this post I will describe how you can use the language bean that is part of the XPages Toolkit available in OpenNTF.

Sample application

In this post we will build a simple XPages UI which looks as followed:

sample

In a combo-box you get presented a list with available language options. And based upon your selection values will be collected from a set of property files.

I will include a dropbox link to the sample application.

Walkthrough

First: download & install the library. Beside the library there is also a sample application which comes in handy to borrow code from.

Java classes

The following files you will need:

class

Property files

The property files contain the actual string values. The amount of files depends on the number of languages you want to support. In our case 4: English (default), Swedish, German and Dutch. There will be three types of files: general, contacts and keywords.  That makes 12 (4*3) in total.

propfiles

Here is what the files could look like. First the general poperties file:

AppTitle=Language Bean
Formula=Formula
Bean=Bean
NotAvailable=Not Available
SwitchLanguage=Choose Your Language
Select=Select
Header=Demo Language Bean
SubHeader=Register A Person
Submit=Submit

Which becomes in Swedish:

AppTitle=Språk Böna
Formula=Formel
Bean=Böna
NotAvailable=Inte Tillgänglig
SwitchLanguage=Välj Ditt Språk
Select=Välj
Header=Demo Språk Böna
SubHeader=Registrera En person
Submit=Skicka

The contacts properties files:

LastName=Last Name
FirstName=First Name
Gender=Gender
Hair=Hair

In German:

LastName=Nachname
FirstName=Vorname
Gender=Geschlecht
Hair=Har

And at last the keywords properties file:

Male=male
Female=female
White=white
Brown=brown
Black=black
Red=red

Which becomes in Dutch:

Male=mannelijk
Female=vrouwelijk
White=wit
Brown=bruin
Black=zwart
Red=rood

The properties files are “registrered” in the language bean via the following method:

public List<String> getPropertyFileNames() {
List<String> propertyFileNames = new ArrayList<String>();
propertyFileNames.add(“contact”);
propertyFileNames.add(“keywords”);
propertyFileNames.add(“general”);
return propertyFileNames;
}

Layout custom control

My demo app contains 2 pages which demonstrates the 2 options you have with the toolkit: use the language bean or the toolkit @formula.

<?xml version=”1.0″ encoding=”UTF-8″?>
<xp:view xmlns:xp=”http://www.ibm.com/xsp/core&#8221; xmlns:xe=”http://www.ibm.com/xsp/coreex”&gt;
<xe:applicationLayout id=”applicationLayout1″><xp:this.facets>
<xp:panel xp:key=”LeftColumn”>
<xe:navigator id=”navigator1″>
<xe:this.treeNodes>
<xe:pageTreeNode page=”/bean.xsp”>
<xe:this.label><![CDATA[#{javascript:xptI18NBean.getValue(“general.Bean”)}]]></xe:this.label>
</xe:pageTreeNode>
<xe:pageTreeNode page=”/formula.xsp”>
<xe:this.label><![CDATA[#{javascript:xptI18NBean.getValue(“general.Formula”)}]]></xe:this.label>
</xe:pageTreeNode>
</xe:this.treeNodes>
</xe:navigator></xp:panel></xp:this.facets>
<xp:callback facetName=”facet_1″ id=”callback1″></xp:callback>
<xe:this.configuration>
<xe:simpleResponsiveConfiguration navbarText=”Language Bean”
collapsedLeftMenuLabel=”Pages”>
<xe:this.navbarUtilityLinks>
<xe:basicLeafNode
href=”https://quintessens.wordpress.com/&#8221;
label=”Kwintessential Notes” title=”Visit My Site”>
</xe:basicLeafNode>
<xe:basicLeafNode
href=”http://www.openntf.org/main.nsf/project.xsp?r=project/XPages%20Toolkit&#8221;
label=”XPages Toolkit” title=”Visit Project on OpenNTF”>
</xe:basicLeafNode>
</xe:this.navbarUtilityLinks>
</xe:simpleResponsiveConfiguration>
</xe:this.configuration>
</xe:applicationLayout>
</xp:view>

Bean XPage

I will spare you the  complete code for the Bean page. Check the download if you want the complete code.  The principle is simple. You collect the value via the following pattern

xptI18NBean.getValue(“[properties file].[key]”)

That could become something like:

xptI18NBean.getValue(“general.SwitchLanguage”)

Switching language

In order to switch language a combobox control is presented with the following code:

<xp:comboBox id=”cbSwitchLanguage” defaultValue=”#{javascript:xptI18NBean.getCurrentLanguage()}”>
<xp:selectItems>
<xp:this.value>
<![CDATA[#{javascript:xptI18NBean.getAllLanguages()}]]>
</xp:this.value>
</xp:selectItems>
<xp:eventHandler event=”onchange” submit=”true” refreshMode=”complete”>
<xp:this.action>
<![CDATA[#{javascript:var sv = getComponent(“cbSwitchLanguage”).getValue()
if(sv != null && sv != “”) {
var locSet:Locale = new Locale(sv);
context.setLocale(locSet);
context.reloadPage();
}}]]>
</xp:this.action>
</xp:eventHandler>
</xp:comboBox>

Language options

The getAllLanguages method in the language bean “registers” the available language options:

public List<String> getAllLanguages() {
List<String> languages = new ArrayList<String>();
languages.add(“en”);
languages.add(“de”);
languages.add(“sv”);
languages.add(“nl”);
return languages;
}

That is basically it!

Formula XPage

This page differs from the Bean page in the way it accesses the property files. It uses a formula which is defined in the XPages Toolkit library.

The formula follows the following pattern:

@XPTLanguageValue(“[properties file].[keyword]”)

Which could become something like:

@XPTLanguageValue(“general.SwitchLanguage”)

Download

A sample application for download is available under the following URL.

Wrapup

I am curious what method you use to make your applications available in multiple languages. Please drop a line how you have solved it.

I found the language bean in the XPages Toolkit very intuitive and easy to use. At least in some cases it solves the problem nice and quickly so my thanks go out to it’s project members.

svenska

Processing JSON data from Domino Access Services with Jackson

Introduction

In order to separate the data model from the business logic you could use Domino Access Services as your default data provider and process the JSON client- or server-side.

In this blog I demonstrate how you can use the Jackson library to process the incoming JSON and bind it to a repeat control.

About Jackson

Jackson is a multi-purpose Java library for processing JSON data format. Jackson aims to be the best possible combination of fast, correct, lightweight, and ergonomic for developers.

Find out more about the library here.

Sample – Fakenames application

In this example we will use the infamous fakenames application from codestore (grab it while it still out there). I have altered the data in my example a bit more so it contains company and job title information.

If you happen to have a script who can fill in the database with more sensible data please drop a line here.

People view

We will use the people view as our data-source  and access it via Domino Access Service. The  URI for the view is something as followed (depending on your installation):

http://server1/fakenames.nsf/api/data/collections/name/people

XPage

We will use and XPage to display the data from the view. The xpage contains a repeater and a couple of fields e.g.:

<?xml version=”1.0″ encoding=”UTF-8″?>
<xp:view
xmlns:xp=”http://www.ibm.com/xsp/core&#8221;
xmlns:xc=”http://www.ibm.com/xsp/custom”&gt;

<xp:panel>
<xp:repeat id=”rptPersons” rows=”10″ var=”persons”
value=”#{javascript:com.quintessens.FakeNames.DASRest.getPersons(‘http://server1/fakenames.nsf/api/data/collections/name/people?count=100&#8242;)}”>
<xp:panel id=”personsPanel”>
<h1>
<xp:text escape=”true” id=”computedField1″
value=”#{javascript:persons.getName()}”
>
</xp:text>
</h1>
<h3>
<xp:text escape=”true” id=”computedField2″
value=”#{javascript:persons.getCompanyname()}”
>
</xp:text>
</h3>
<xp:text escape=”true” id=”computedField3″
value=”#{javascript:persons.getJobtitle()}”
style=”font-style:italic”>
</xp:text>

</xp:panel>
</xp:repeat>
<xp:pager layout=”Previous Group Next”
partialRefresh=”true” id=”pager1″ for=”rptPersons”>
</xp:pager>
</xp:panel>
</xp:view>

Note I call in the repeater control a method getPersons in the class DASRest and provide an URL of the data-source.

I add the count parameter to get more initial results than set in the server configuration.

I also have added a pager control to navigate through the returned collection.

DASRest class

The DASRest class looks as followed:

package com.quintessens.FakeNames;

import javax.ws.rs.core.MediaType;
import org.codehaus.jackson.map.ObjectMapper;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;

import com.quintessens.FakeNames.Person;

public class DASRest {

public static Person[] getPersons(String url) {
Person[] persons = null;
try {
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client.resource(url);
String json = service.accept(MediaType.APPLICATION_JSON).get(String.class);
ObjectMapper mapper = new ObjectMapper();
persons = mapper.readValue(json, Person[].class);
} catch (Exception e) {
e.printStackTrace();
}
return persons;
}
}

Jersey

This class uses the Jersey library to setup a client to contact the Domino Access Service.

Developing RESTful Web services that seamlessly support exposing your data in a variety of representation media types and abstract away the low-level details of the client-server communication is not an easy task without a good toolkit. In order to simplify development of RESTful Web services and their clients in Java, a standard and portable JAX-RS API has been designed.

The received JSON is then converted into a Java object. I find this a good site to learn more about mapping JSON and Java.

Person class

The class also uses a Person class. In this class we specify which fields we want to map and how they should look like:

package com.quintessens.FakeNames;

import javax.xml.bind.annotation.XmlRootElement;

import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.annotate.JsonProperty;

@XmlRootElement
@JsonIgnoreProperties(ignoreUnknown = true)
public class Person {
private String name;//$17
private String companyName;
private String jobtitle;

@JsonProperty(“$17″)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@JsonProperty(“CompanyName”)
public String getCompanyname() {
return companyName;
}
public void setCompanyname(String companyname) {
this.companyName = companyname;
}
public String getJobtitle() {
return jobtitle;
}
public void setJobtitle(String jobtitle) {
this.jobtitle = jobtitle;
}
}

As you can see @JsonProperty(“$17″) makes the code a bit more user-friendly. In this case it maps the programmatic column name with a variable name.

The result

The following image shows the result of the code above:

jackson

As you see the markup is still basic but you can easily beautify it with Bootstrap or preferred CSS framework of choice.

The purpose of this blog was to demonstrate separating the data model and the business logic. You could have received the same result just using a repeat control and server-side javascript. But since the JSON & Java combination is more hype in the Domino world I guess it is interesting to take a look at the possibilities.

Wrap up

Some thoughts I have after this experiment:

  • What about the other documents?

In my example I make a call to DAS and include the count = 100 parameter. The number 100 is the limit that is set on my server. I have not figured out yet how to load a next set of documents and include it to the existing collection (please drop a note in case you have an answer to this).

  • What about performance?

Is Domino Access Services faster than e.g. defining my own data provider e.g. via a viewnavigator? I don’t know. In case you have suggestions on the preferred or fastest way to provide the data then let me know.

  • What about the language?

Java is not my native language in the Domino world. But the example above is understandable for a lot of us I would think. But who died out of a bit of curiosity?

Thanks for reading. Happy coding!

Presentations from EntwicklerCamp 2014 – Track 4

Track Session Subject Download Presentation
Track4 Session1 The Road to Damascas – LS and @Formula to SSJS http://www.entwicklercamp.de/konferenz/ent2014.nsf/bc36cf8d512621e0c1256f870073e627/ddd7b3baaf49dbadc1257be200295cc1/$FILE/T4S1-Xpages-road%20to%20damascas.pdf
Track4 Session2 Wo speichert Notes was? Und was kann der Entwickler damit anfangen? http://www.entwicklercamp.de/konferenz/ent2014.nsf/bc36cf8d512621e0c1256f870073e627/2071360f70207a00c1257be200295cbf/$FILE/T4S2-Wo%20speichert%20Notes%20was.pdf
Track4 Session3 WebServices unter Notes/Domino http://www.entwicklercamp.de/konferenz/ent2014.nsf/bc36cf8d512621e0c1256f870073e627/0eca636da0020f78c1257be200295cb7/$FILE/T4S3-WebServices.pdf
Track4 Session4 C / C++ Api benutzung in Domino und Notes http://www.entwicklercamp.de/konferenz/ent2014.nsf/bc36cf8d512621e0c1256f870073e627/c7c7068c38e3ce99c1257be200295cb4/$FILE/T4S4-Domino%20C-API.pdf
Track4 Session5 Coffee from a Friend – Using Third Party Java Libraries http://www.entwicklercamp.de/konferenz/ent2014.nsf/bc36cf8d512621e0c1256f870073e627/c9fadb7e1ca4a6d2c1257be200295cb5/$FILE/T4S5-Xpages-coffe%20from%20a%20friend.pdf
Track4 Session6 Notes und die Zeit http://www.entwicklercamp.de/konferenz/ent2014.nsf/bc36cf8d512621e0c1256f870073e627/3b9b4049f4b5a50fc1257ca200413f27/$FILE/T4S6-Notes%20und%20die%20Zeit.pdf
Track4 Session7 Schick mit Grid – DataGrids in XPages http://www.entwicklercamp.de/konferenz/ent2014.nsf/bc36cf8d512621e0c1256f870073e627/0a3a4e6d95ce04c3c1257ca200411c72/$FILE/T4S7-SchickMitGrid.pdf
Track4 Session8 Wo speichert Notes was? Und was kann der Entwickler damit anfangen? http://www.entwicklercamp.de/konferenz/ent2014.nsf/bc36cf8d512621e0c1256f870073e627/59dd26d2f93162f6c1257ca2004120c3/$FILE/T4S8-Wo%20speichert%20Notes%20was.pdf

Presentations from EntwicklerCamp 2014 – Track 3

Track Session Subject Download Presentation
Track3 Session1 LotusScript Best-Practices (“keep it simple”) http://www.entwicklercamp.de/konferenz/ent2014.nsf/bc36cf8d512621e0c1256f870073e627/60c08dbd3c75cf5fc1257be200295cba/$FILE/T3S1-Lotusscript.pdf
Track3 Session2 Java Beans sind kompliziert? Nicht die Bohne! http://www.entwicklercamp.de/konferenz/ent2014.nsf/bc36cf8d512621e0c1256f870073e627/1a9601442b32b155c1257be200295ca6/$FILE/T3S2-JavaBeans.pdf
Track3 Session3 OpenNTF – Die neue Applikationen and Controls für 2014 http://www.entwicklercamp.de/konferenz/ent2014.nsf/bc36cf8d512621e0c1256f870073e627/510bdd4e5e9ce293c1257be200295cad/$FILE/T3S3-openNTF.pdf
Track3 Session4+5 All things X – 180 Minuten Session http://www.entwicklercamp.de/konferenz/ent2014.nsf/bc36cf8d512621e0c1256f870073e627/e41f08ce52a8fc81c1257be200295ca5/$FILE/T3S4+5-All-Things-X.pdf
Track3 Session6 Applikationsentwicklung mit XPages und IBM Connections http://www.entwicklercamp.de/konferenz/ent2014.nsf/bc36cf8d512621e0c1256f870073e627/a24c25326d66bb47c1257be200295c96/$FILE/T3S6-Entwicklung-Xpages-Connections.pdf
Track3 Session7 DOTS – reloaded http://www.entwicklercamp.de/konferenz/ent2014.nsf/bc36cf8d512621e0c1256f870073e627/e4b81f973365e741c1257be200295ca7/$FILE/T3S7-DOTS_reloaded.pdf
Track3 Session8 JavaScript für Fortgeschrittene http://www.entwicklercamp.de/konferenz/ent2014.nsf/bc36cf8d512621e0c1256f870073e627/4aef36d031c64898c1257be200295cc0/$FILE/T3S8-JavaScript%20f%C3%BCr%20Fortgeschrittene.pdf

Presentations from EntwicklerCamp 2012 available

I have experienced that IBM has some problems linking to their material that lies out in the open, but I hope this post does not cause the same kind of trouble. I also know the solution in case needed: contact the content publisher to remove the files…

Nevertheless Entwicklercamp sounds like a excellent technical conference and for those of you who have no problems with reading a bit of German (not all presentations are in German, by the way) here are some interesting presentations:

Track 0 – Session 1 – Eröffnungssession – Rudi Knegt (link)

Track 0 – Session 2 – Opening Session – Phil Riand (link)

Track 0 – Session 3 – Speeddemoing – Diverse (link)

Track 0 – Session 5 – Closing Session: Ein (grausamer Selbstversuch) – 5 Monate ohne Lotus Notes – Werner Motzet

“Ein (Arbeits-)Leben ohne Lotus Notes” / “Ein (grausamer Selbstversuch) – 4 Monate ohne Lotus Notes” (link)


Track 1 – Session 1 – XPages – 1 – Grundlagen – Ulrich Krause (link)

Track 1 – Session 2 – XPages: Practical Ideas for Converting Existing Notes Applications – Matthew Fyleman (link)

Track 1 – Session 3 – XPages – 3 – eXtension Library – Viagra für die XPages – Ulrich Krause (link)

Track 1 – Session 4 – XPages – 4 – IBM oneUI + MyTheme = myUI – Manfred Meise (link)

Track 1 – Session 5 – XPages – 5 – Wie mache ich meine XPages Applikationen ‘social’? – Niklas Heidloff (link)

Track 1 – Session 6 – XPages – 6 – XPages Extensibility API – going deep – René Winkelmeyer (link)

Track 1 – Session 7 – Zähme den Tiger – Java-Entwicklung in Notes und Domino – Bernd Hort (link)

Track 1 – Session 8 – XPages – 8 – Nutzung des Dojo Toolkits zur Optimierung bestehender Notes-Web-Anwendungen – Matthias Bierl (link)


Track 2 – Session 1 – Extending Lotus Notes – Widgets, Livetext, Plugins – Detlev Poettgen (link)

Track 2 – Session 3 – Agile Softwareentwicklung mit LotusNotes – Werner Motzet (link)

Track 2 – Session 4 – Ich weiß was du diesen Sommer tun wirst – Gregory Engels (link)

Track 2 – Session 5 – Erfolgreiches Projektmanagement mit agilen Methoden – Christian Habermueller (link)

Track 2 – Session 6 – Make the impossible possible with XPages – Frank van der Linden (link)

Track 2 – Session 7 – Connect your Lotus Notes app to the Activity Stream with XPages – Frank van der Linden (link)

Track 2 – Session 8 – Keine Angst vor großen Tieren – Peter Klett (link)


Track 3 – Session 1 – Rediscover the Power of LotusScript in Notes/Domino 8.5 – Rocky Oliver (link)

Track 3 – Session 2 – Die besten Open Source Projekte von OpenNTF – Niklas Heidloff (link)

Track 3 – Session 3 – Richtig(er) Kommunizieren! – Wie bringe ich meine Botschaft rüber? – Jürgen Kunert (link)

Track 3 – Session 4 – XPages und Domino App Dev Erweiterungen – Phil Riand und Niklas Heidloff (link)

Track 3 – Session 5 – Turbocharge Development in Notes/Domino 8.5 – with @Formulas! – Rocky Oliver (link)

Track 3 – Session 6 – Mobiler Zugriff auf Notes Daten – Matthias Schneider (link)

Track 3 – Session 7 – Es gibt keine Ausreden mehr – eGit im DDE : Versionskontrolle leicht gemacht – Holger Chudek (link)

Track 3 – Session 8 – Using the XPages Mobile Controls… and looking at alternatives – Rich Sharpe (link)


Track 4 – Session 1 – Security in Notes – Manfred Meise (link)

Track 4 – Session 2 – Workflow – Richtig analysieren, dokumentieren und schlüssig hinterfragen – Christian Habermueller (link)

Track 4 – Session 3 – Lotus Protector programmieren – Matthias Schneider (link)

Track 4 – Session 4 – WebServices unter Notes/Domino – Tim Pistor (link)

Track 4 – Session 5 – Hilfe, ich habe geerbt! – Bernhard Köhler (link)

Track 4 – Session 6 – NoSQL-Datenbanken – ein Überblick – Karsten Lehmann (link)

Track 4 – Session 7 – Notes und die Zeit – Bernhard Köhler (link)

Track 4 – Session 8 – Schnittstellendesign mit dem Tivoli Directory Integrator – Am Beispiel SAP – Andreas Artner (link)


In case you are a bit lazy or dont care about bandwidth: <here> you can find the presentations archived together by track…

There are also some hands-on sessions available:

Hands-On 1 – Javascript – die ersten Schritten – Manuel Nientit (link)

Hands-On 3 – XPages – the first Steps 1 – Howard Greenberg (link)

Hands-On 4 – XPages – the second steps 2 – Howard Greenberg (link)

Hands-On 5 – Signierung und Verteilung von Plugins für den Notes Client – Detlev Poettgen (link)

Hands-On 6 – LotusScript – so einfach geht es los – Peter Klett (link)

Hands-On 7 – Mobiler Zugriff auf Notes Daten – Matthias Schneider (link)

Hands-On 8 – XPages Extensibility API – first steps – René Winkelmeyer (link)

Btw, all links were collected from this source.

Lotusphere 2011 – Wednesday 2 Feb.

After breakfast I went back straight to bed due to some fever. I managed to recover for some sessions after lunch :-/

 

Show 107 The datasource session

During this session was demonstrated how new binding can be made to other datasources except Notes documents and views. Very interesting and potential allthough you might wonder if it wouldn’t make more sense when IBM provides a couple of out of the box connections for example RDBMS.

Rated 8

 

 

AD306 IBM Lotus SameTime Proxy – A collaborative recipe for success

This was more a developer session for the SameTime proxy and some use cases where highlighted.

Rated 7

 

 

BP106 Where is the love? How to get your users fall in love with Lotus Notes.

Because the ST Proxy session next door finished early I took a glimpse at this session (we heard already lots of applause in the other room from this session).

My tip: try to get additional time for improving the user experience when developing new application. Users could be working with them the next 10 years. Also dare to invest in the lifecycle of elder applications by reviving their look  & feel.

Rated 7

 

 

Lotusphere 2011 Party

Due to a sickness I did not need to take any roller-coaster after having drinking one beer. What else can I see? For some decent food you do not need to be at an amusement park?

Rated 6