Monday, February 2, 2015

A better MessageFormat for Java

The MessageFormat class is widely used by Java, especially when it comes to internationalisation. At first sight, using it is simple and straight forward. Define a pattern like "There are {0} files on {1}", either in Java - or better in a in a .properties file. Create a new instance of MessageFormat and supply arguments for the two parameters when calling the format method. This create a formatted string like "There are 100 files on /dev/sda".

Couldn't be easier, right? Yep, but there's still room for improvement. One such improvement is replacing parameter indices with names. "There are ${numberOfFiles} on ${disk}", provides way more context to the poor soul having to translate a properties files.

Another improvement are optional sections. Imagine you have to represent a person as string. It can have a salutation, a firstname and a lastname. Depending on what a user entered, the salutation and or the firstname might be empty. Valid combinations could be "Mr. John Foo", "John Foo", "Mr. Foo". Using a pattern like "[${salutation} ][${firstname} ]${lastname}" is enough to create this output if optional patterns are supported. That idea is, that blocks in angular brackets are only output if at least one enclosed parameter is replaced with a non-null value.

All this is implemented by the Formatter class provided by Sirius. Using it is quite simple. For internationalisation, use NLS.fmtr("Property.key").set("paramName", value).format(). Note that Sirius automatically loads all properties files and makes them available using the NLS class. To use the smart formatting capabilities a formatter can be directly instantiated like this: Formatter.create("${foo}[ ${bar}]").set("foo", foo).set("bar", bar).smartFormat().