What are the best practices for internationalizing

2019-02-05 06:07发布

I'm sure there are a lot of methods, but what's the recommended way to do this that has the least amount of impact to your code?

The obvious is that you create properties files, but how do you swap the values in the rendering? In J2EE you always just re-render the whole page so it's easy. But in Swing apps, do you just add the code for the .getProperty() in the paintComponent(Graphics g) method?

If that's the case, doesn't it seem heavy since now you'll have to override this method everywhere where before you didn't need to...

Additional: How do you setup a notification system to re-render all currently visible components without forcing some kind of registration pattern?

I guess if I overwrite paintComponent(Graphics g) all I have to do is fire an event that something has changed and the paintComponent(Graphics g) method will be called...

5条回答
smile是对你的礼貌
2楼-- · 2019-02-05 06:22

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();
        }
    }
}
查看更多
Fickle 薄情
3楼-- · 2019-02-05 06:26

The only solution I came up with was to create a massive registry of all components that would need to be re-rendered. Then if a call is made to switch Locale you can just call the registry and it will go through all the registered components and adjust their values. So for example for all the registered JLabels it will do something along the lines of

for(JLabel specificJLabel : REGISTRY.registeredJLabels)
{
  String localeKey = specificJLabel.getActionCommand();
  specificJLabel.setText(ResourceBundle.getString(localeKey)); 
}

where the Locale key is stored in the components ActionCommand. Then whatever screen is currently being rendered, the main parent panel is responsible for re-rendering it. Also this way the registry doesn't have to manage the Locale keys, these are completely decoupled from the registry. Each component is responsible to manage it's own Locale Keys to the ResourceBundle.

查看更多
\"骚年 ilove
4楼-- · 2019-02-05 06:27

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.

查看更多
太酷不给撩
5楼-- · 2019-02-05 06:33

Java 6 SE allows you to reload resource bundles on the fly. Just call the clearCache() static function of the ResourceBundle class. Then call getBundle () again.

See this article under Cache Controls

查看更多
相关推荐>>
6楼-- · 2019-02-05 06:39

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

查看更多
登录 后发表回答