Friday, February 04, 2005

Localized exception messages

Some programs I work on use getMessage() from an exception for display to end-users when problems crop up. Other programs use the message as a key into a message bundle. The question is, how do I localize the text of getMessage()?

The authors of java.lang.Throwable planned for this and provided getLocalizedMessage() which is not overridden in java.lang.Exception. However, the implementation is:

public String getLocalizedMessage() {
    return getMessage();
}

To make this useful I write a new abstract class, LocalizedException, with two overriden methods and a new abstract method:

/**
 * {@inheritDoc}
 * <p/>
 * This implementation throws {@code UnsupportedOperationException}.  Use
 * {@link #getLocalizedMessage()} instead.
 *
 * @return this implementation never returns
 *
 * @throws UnsupportedOperationException
 * @see #getLocalizedMessage()
 */
public String getMessage() {
    throw new UnsupportedOperationException(
            "CODING ERROR: call getLocalizedMessage() instead");
}

/**
 * {@inheritDoc}
 * <p/>
 * This implementation delegates to {@link #translateMessage(String)}
 * with the original exception message text.
 *
 * @return {@inheritDoc}
 *
 * @see #translateMessage(String)
 */
public String getLocalizedMessage() {
    return translateMessage(super.getMessage());
}

/**
 * Translates exception <var>message</var> text.
 * Implementations depend on the nature of the text.  For example,
 * one implementation might require the text to be keys into a
 * message bundle.  Another might require the text to be the message
 * text in the default locale.
 *
 * @return the translated exception message text
 */
protected abstract String translateMessage(final String message);

Using this class, write concrete implementations of translateMessage that can figure out how to internationalize the message strings particular to your program.

No comments: