+1  A: 

What you need is a ResourceBundle that allows you to have properties file based on Locale that you just access like a properties file.

Here is a sample on how to do it

Romain Hippeau
I understand that, that's not really the question. The question is where do you call the ResourceBundle in the components so that it's rendered (or re-rendered) when needed. Is there another way than to overwrite paintComponent(Graphics g) on each JComponent?
Stephane Grenier
@Stephane Grenier - Usually a user starts up a program in a different country and needs a different language based on the Locale he is in. Since as in the example you are adding the I18 stuff at construction it is going to be hard. You would need to change the locale and at least close the window and recreate it, or depending on the widget call setText() or whatever.
Romain Hippeau
@Romain - Unfortunately I need to be able to do it live, it's for a kiosk application I'm working on. I think I can do it by overriding the paintComponent methods, and with some careful thought. I was just hoping there was an easier method.
Stephane Grenier
A: 

Supporting dynamic language changes is a tricky problem. The simplest solution is to organise your UI in such a way that you can recreate any visible panels. That avoids the need to register or update components, when the language changes you simply recreate the view.

Obviously you lose the state of all visible components which may be an issue - but that is usually the same in a web app when the page is refreshed.

Russ Hayward
A: 

As far as I know, some applications use layout/component builders (advised by Karsten Lentzsch, and part of JGoodies API). These builders include the code to localize components (using ResourceBundle under the hood).

Other people (me included) prefer resource injection; this is normally the least intrusive method. This is the way chosen by the Swing Application Framework (JSR-296) and other GUI frameworks like Guts-GUI.

You may also want to take a look at this question which is quite similar to yours.

Regarding changes of language "on the fly" (Locale change notification), I think it is easier to implement when using resource injection (I have implemented this in Guts-GUI already, Swing Application Framework may also have it but I am not sure about it).

Java offers no way to listen to Locale changes, hence you have to create you own "Locale service" (which any Locale change request should be addressed to). In this service, you would have to enumerate all visible windows (this is possible with Window.getWindows(), no need to register visible components before) and then inject resources again.

If you want an example, take a look at the resource package in Guts-GUI source code:

  • ResourceInjector shows resource injection and method to change Locale, which sends a notification event (uses an Event Bus for that, but simple listeners would be fine too) about this change
  • WindowController listens to Locale change events

The interesting code for updating all visible windows is copied hereafter:

for (Window window: Window.getWindows())
{
    if (window.isVisible())
    {
        injectResources(window);
        window.repaint();
        if (window instanceof RootPaneContainer)
        {
            ((RootPaneContainer) window).getRootPane().revalidate();
        }
    }
}
jfpoilpret