Recently I have been involved into internationalization and localization on the Java platform for the first time.

In the course of this I have been wondering why java.lang.Throwable does not provide a way to specify a localized message. We have getter getLocalizedMessage() right available but no setter counterpart. Yet for cause there is a initCause method.

That is in order to make getLocalizedMessage() return a sensible message you will have to sub class Throwable and implement corresponding logic.

None the builtin Java exceptions, e.g. IllegalArgumentException, does provide support for a localized message out of the box. So as I see it: If I want to have a localized version of one of those I will have to sub class.

Does anybody have a reasoning for that, respectively what was the intent of the Java developers.

frankly, the "getLocalizedMessage()" method on Throwable is pretty useless. There are lots of places in the jdk (and any other 3rd party libraries you might use) where exceptions are thrown that you don't control, so expecting getLocalizedMessage() to do anything useful is wishful thinking.

Probably the best thing to do is have a layer which translates exceptions and messages into localized messages. this may involve heuristics for certain messages and fallbacks for unexpected ones. you could probably add your own application level exceptions which include extra stuff like error codes which you can use to generate a localized message, but you're still going to need to handle other exception types which you don't control.

togtog wrote:
None the builtin Java exceptions, e.g. IllegalArgumentException, does provide support for a localized message out of the box. So as I see it: If I want to have a localized version of one of those I will have to sub class.

It would be useless to have a localized version of the standard exceptions in the first place. Those are for the developer, not the users.

jtahlborn wrote:
Probably the best thing to do is have a layer which translates exceptions and messages into localized messages. this may involve heuristics for certain messages and fallbacks for unexpected ones. you could probably add your own application level exceptions which include extra stuff like error codes which you can use to generate a localized message, but you're still going to need to handle other exception types which you don't control.

See what you mean. Basically this is what I currently have. I built a LocalizedException which serves as my base application level exception. And this is where I ran into problems: due to inheritance. After more than 100 messages, LogRecords and Exceptions, I have encountered situations where inheritance does not work. For example I had to implement piped i/o streams where IOException is required. So I was not able to inherit from my LocalizedException and that was when I started wondering about a setter for localizedMessage as a cheap solution.

Taking your thoughts into account I will switch from inheritance to interface based design, so I will also be able to deal with situations where I am forced to trigger builtin exceptions by inheriting from them and implementing the LocalizedException interface.

Kayaman wrote:
It would be useless to have a localized version of the standard exceptions in the first place. Those are for the developer, not the users.

Aaaaaahhhh - got it. That makes sens. So a valid paradigm for localized exceptions could then be: catch those low level exceptions, and turn them into the cause of your higher level exceptions, which then support localization. In the case you have to trigger a low level exception, inherit from that exception and have the new exception implement the interface of your localized exceptions, thus enabling the rest of the system to treat it as a localized exception.

Kayaman wrote:
It would be useless to have a localized version of the standard exceptions in the first place. Those are for the developer, not the users.

Agreed for 99.9% of the cases. But the exception handling mechanism also works wonders to deal with such things as validation errors which should be human-readable; the exception message can be reported in a localized manner to the user.

The method is then still utterly useless as you would put the localized message in the exception, you're not going to create it and then translate it :/

I am not comfortable with java's approach, but what would be better?
Suppose you write a network client with a localized GUI. The user clicks 'connect'. You end up with an IOException. You may report it in the GUI as "connection failure" in 50 languages, as appropriate. But you want to be nicer than this, as the exception carries some useful info that may tell the user what is wrong. Like "connection reset by peer", "unknown host" etc. But this is only available in English, which does not look good in a professional GUI that happens to be in French. You can play catch-up with java and translate them all, as you encounter them. Even then, it's an ugly hack and your code assumes that Oracle would not change a single character in the message. The only compromise I can see is to show in the GUI"connection failure (please check the log for details)" and, of course, the log is in English.

baftos wrote:
I am not comfortable with java's approach, but what would be better?

Design the application in the first place with the understanding that the following scenarios exist.
1. Certain errors a user can fix. These are known conditions.
2. Expected errors that some one besides the user must fix.
3. Exceptions that someone else must figure out what happened.

2 and definitely 3 often require collected information that is meaningless to the normal use yet which must be delivered to some one. Log files are one possibility for this. However this process has nothing to do with java exception creation (but would be expected to be triggered by java exceptions but not necessarily only triggered by java exceptions.)

Note that 1/2 represent known states.

Suppose you write a network client with a localized GUI. The user clicks 'connect'. You end up with an IOException. You may report it in the GUI as "connection failure" in 50 languages, as appropriate. But you want to be nicer than this, as the exception carries some useful info that may tell the user what is wrong. Like "connection reset by peer", "unknown host" etc.

What exactly do you expect your user to do with that additional information?

Design the application in the first place with the understanding that the following scenarios exist.
1. Certain errors a user can fix. These are known conditions.
2. Expected errors that some one besides the user must fix.
3. Exceptions that someone else must figure out what happened.

Phew very good point. One question with respect to this: Would you consider rendering 1/2/3 as sub classes of one's root application level exception type a valid approach?

baftos wrote:
The only compromise I can see is to show in the GUI"connection failure (please check the log for details)" and, of course, the log is in English.

I would say this is a good compromise. Playing catch-up with the Java platform developers does not make much sense to me. But something that makes much more sense to me is that you, if I have got you right, introduce the idea of what I refere to as TechLocale and UserLocale.

That is the application knows two locales. The tech locale is used for all the stuff which is actually not meant to be presented to or interpreted by the user at all - e.g. log entries. The user locale on the other hand is there to write console messages or deal with text oriented GUI components, i.e. communicate with the user.

Design the application in the first place with the understanding that the following scenarios exist.
1. Certain errors a user can fix. These are known conditions.
2. Expected errors that some one besides the user must fix.
3. Exceptions that someone else must figure out what happened.

Phew very good point. One question with respect to this: Would you consider rendering 1/2/3 as sub classes of one's root application level exception type a valid approach?

Maybe. Maybe not.

Your app can respond differently to 1 versus 2/3. For example, if you want to deal with the complexity, it is possible to specifically identify fields such that the client app could then adjust based on those. Not necessarily always worth the time but it is doable. 2/3 wouldn't fit into that at all.

And the client app must still deal with the possibility of exceptions that do not originate from the server (your code) but instead originate with the communication protocol.