There are some rather disturbing problems with ResourceBundle:
- if the translations are stored in a database, there is no way for an application to create a new localization without code changes (that is, without creating a new database-backed ResourceBundle class for each new Locale).
- prior to JDK 6, there is no way of refreshing the underlying data at runtime.
These are serious defects.
In addition, there are many nuisances associated with using ResourceBundles and their associated properties files:
- the encoding used in a properties file is ISO-8859-1, not UTF-8. If the developer is using a language which does not use ISO-8859-1, then the native2ascii tool must be used to process the files. (Rather rude for an internationalization mechanism, is it not?)
- natural text keys versus coder keys: from the point of the caller, using a natural text lookup key has the advantage that it increases legibility. However, such a lookup key appears as blah=blah in a properties file. Such duplication makes most programmers justifiably nervous. (If a database is used, a ResultSet having the same blah=blah structure can be easily created, but without any actual data repeated in the underlying tables.)
- in a properties file, there is no easy way to find duplicates. In general, there is no easy way to perform any sort of query on the data (as there is in a database).
- mailing raw properties files to translators does not seem desirable, but building a front end tool for such files is not easy - so it never gets done
- if an item has more than one line, then the line continuation character "\" must be appended to each line
- apostrophe characters are a problem: the MessageFormat class treats apostrophes as special characters. If an apostrophe appears in a pattern passed to a MessageFormat, it must be escaped, or else a nice little RuntimeException is thrown. If you send properties files to translators, the probabilty of errors related to apostrophes is very high. If a database is used instead of properties files, however, then it is possible to build a front end tool which can do the necessary validations. (Building such a tool is especially attractive when it can be used with multiple projects.)
- use of module names: the ResourceBundle mechanism allows the caller to specify a module name, which is mapped into a corresponding class name or properties file name. It is possible to seriously question this design. In general, a method should not know the identity of its caller. Now, translation is just another feature. Why should should this particular feature care about which other feature is calling it? What compelling reason is there for breaking this basic rule of program design? The only thing a translation needs is the base text and the target Locale. That is all. If there is any context which is important to the translation, then that context is either a linguistic context, or a user interface context. It is not, strictly speaking, attached to a program feature. If you are still not convinced, ask yourself this question : does a human translator care in any way if text comes from feature A or feature B? In any way? If you ponder this question closely, the answer will likely be "no".
In summary, it seems that ResourceBundle was intended originally for desktop applications, and that its design is not robust enough for easy use in the context of a web application backed by a database.
Fortunately, text translation is not a difficult task, and
creating an alternative to ResourceBundle is actually fairly easy.
For an example, please see the
package of the WEB4J tool. It uses a technique called
"last second localization".