Just recently I came across a not-uncommon problem where I needed to display the value of an enum on one of the pages of a web application in a more human friendly manner. An additional consideration was that this particular application needed to be i18n friendly - the display values of the enum needed to be shown in the whichever language the application was currently being viewed with. This took some thinking but I came up with (what I think at least) is a neat little solution…

The enum itself is unimportant, but for the sake of illustration I’ll use the following as a simple example:

public enum SystemStatus

To reiterate my problem using the above example, when I’m displaying an object that has a reference to the SystemStatus enum I don’t want to show the value of the SystemStatus itself, but instead a more human friendly equivalent e.g. DEVELOPMENT could become ‘Under development’ or RETIRED could become ‘System retired’. Furthermore this should work in an internationalised sense, i.e. if the application if being used in a French locale then ‘En d?veloppement’ should be displayed in place of ‘DEVELOPMENT’.

My application is being developed using the Spring framework, so it makes sense to use Spring’s built in i18n tools. I define all text that is to be displayed on any pages in the application in a file called messages_en_GB.properties (for UK English locales) and make use of Spring’s ResourceBundleMessageSource to make this available across the application.

I use Velocity to render and display the html pages for my application and getting values from the messages resource bundles made trivial using Spring’s Velocitymacro:

#springMessageText("home.welcome", "Welcome")

which in this case would look in the messages.properties resource bundle for the current locale (messages_en_GB.properties), find the key ‘home.welcome’ and display the text set as the value (and in this case default to ‘Welcome’ if no matching key was found). Easy!

Where things get a little trickier (and this is really the crux of this article) is in managing the example of enum above. How can we display a human friendly and internationalised representation of an enum value?The answer I propose, is to add messages to our message source which share the name of the enum as the message key and add a human readable equivalent as the value pairing. So in the example above we would define 3 new messages in our messages_en_GB.properties:

systemstatus.DEVELOPMENT=Under Development
systemstatus.DEPLOYED =System Deployed
systemstatus.RETIRED=System Retired

Then when we come across a property that references the enum we can use the Spring Velocitymacro to go and get the human friendly text for it. In this example below, we have an object reference to a System called ‘$currentsystem’ and we want to display the value of it’s ’status’ property (which is a reference to the SystemStatus enum):

#set($status = $currentsystem.status)
#springMessageText("systemstatus.${status}", "$status")

The Velocity engine will render the first argument of the macro to be ’systemstatus.*’ where * is the current value of the status e.g. systemstatus.DEVELOPMENT. The macro will then get the value of any key in the message resource bundle where the key is named ’systemstatus.DEVELOPMENT’ and show this text instead e.g. ‘Under Development’. If no key value pair can be found then the default value in the second argument of the macro ‘$status’ will simply display the real value of the enum i.e. DEVELOPMENT. Thus, even though the message value of the enum might be missing, the macro still degrades gracefully and shows a fairly meaningful message.

How does this work internationally? Easy, if your application is internationally-aware then presumably you have a number of different resource bundles for each locale, for example a messages file for French language users called ‘messages_fr_FR.properties’. This file will contain exactly the same set of enum keys as in the British document, except with French values instead of English, for example:

systemstatus.DEVELOPMENT=En d?veloppement
systemstatus.DEPLOYED =Syst?me de d?ploiement
systemstatus.RETIRED=Syst?me de retraite

Providing a user is using a French locale then any messages displayed for enums should be in the French.

So there we have it, not exactly ground-breaking stuff, but quite a neat little solution and a useful piece of knowledge nevertheless and hopefully something that others may find of use.