Friday, September 25, 2009

Internationalization - dynamic and in a database

So I've been tasked with doing some internationalization for a web application in a less conventional way. I thought it would be useful to put together some thoughts as I get started on what I think will be a decent solution.

From what I understood, internationalization in Java (the language I'm using) involves properties files and locales and such. In the project I'm on, there is a requirement to be able to update the translated texts on the fly, without a server restart. This complicates the using of properties files a bit, since writing to those files seems a bit hackish and then what do I do to reload them.

So we've decided to look into a database backing for the whole business since that's pretty dynamic and accessible to the people - either via some database interface or an admin tool - working on the text.

We were kicking around various options to do something custom, a custom map or something and redirect whatever framework we were using.

Then I found some methods native to Java - no framework required - which should handle it nicely.

  1. ListResourceBundle has been around for a while in Java-land, but it's a nice way of not using properties files, but classes as bundles for different locales. This seems like a great way to get those database backed properties into the mix.
  2. Java 6 also has some nice customization options for how resource bundles get loaded. Specifically, ResourceBundle.Control has some options to customize the time-to-live of the cache for the resource bundle, from no-cache at all, to specifying a timeframe in milliseconds for how long a cache is valid.

So going forward, it looks like I'll need to mess with both for making something that's as close to the wire as I can - which allows me to not have to re-code caching and other things specific to a system for i18n.


Gary Dusbabek said...

If you use a plain ListResourceBundle, you don't gain the opportunity change the contents after it is created. It could work if you reload the bundles periodically.

Another approach would be to subclass ResourceBundle as JDBCResourceBundle (or whatever... you get the idea).

Underneath you could implement whatever kind of caching/expiry suits your needs to satisfy the requirement to be able to have updated translations without a server restart.

jeremy said...

@Gary - good point. I wonder if it would be better to start with a clean slate rather than using the ListResourceBundle and just attaching the data to it. I'll have to take a look at that more.

Some other resources:

- A blog post on about using ResourceBundle.Control

- An article about having more flexible resource bundles, including a db backed resource bundle

- A forum thread about different approaches to the problem