简体   繁体   English

Java AWT国际化动态

[英]Java AWT Internationalization Dynamic

I am creating a Prototype application, which should support Japanese Locale and English Locale. 我正在创建一个原型应用程序,该应用程序应支持日语语言环境和英语语言环境。 There should me Menuitem to select Japanese or English. 我应该在Menuitem中选择日语或英语。 and accordingly application should show all it's lables buttons text in Japanese or English. 因此,应用程序应以日语或英语显示所有的标签按钮文本。

I developed using Netbeans internationalization support. 我使用Netbeans国际化支持进行开发。 if i pass VM arguments as -Duser.language=ja -Duser.country=JP, application shows Japanese text on lables and buttons etc. 如果我将VM参数传递为-Duser.language = ja -Duser.country = JP,则应用程序会在标签和按钮等上显示日语文本。

if i pass VM arguments as -Duser.language=en -Duser.country=IN, application shows English text on lables and buttons etc. 如果我将VM参数作为-Duser.language = zh-Duser.country = IN传递,则应用程序会在标签和按钮等上显示英文文本。

this works fine. 这很好。 but how to make it dynamic. 但是如何使其动态。 so that no need to restart the application with VM arguments. 这样就无需使用VM参数重新启动应用程序。

I think this is a rather general question about handling the dynamic translations. 我认为这是关于处理动态翻译的一个相当普遍的问题。

Generally I know of three ways to do it. 总的来说,我知道三种方法。

  1. Every label or text set in the application has to register a listener to an event you would issue when the language changes. 应用程序中设置的每个标签或文本都必须注册一个侦听器,以侦听语言更改时将发出的事件。 In the listener you would read the new locale and load the proper string from your bundle. 在侦听器中,您将读取新的语言环境并从包中加载正确的字符串。
  2. Traverse the component hierarchy down from the window and translate all texts found on the way. 从窗口向下遍历组件层次结构,并翻译途中找到的所有文本。
  3. Set the other locale programatically, then destroy and recreate the GUI. 以编程方式设置其他语言环境,然后销毁并重新创建GUI。

Maybe it's a sad thing to say, but all these options need general and rather large changes in the program code. 也许这很可悲,但是所有这些选项都需要在程序代码中进行常规且相当大的更改。

Of these, I would prefer 1. I actually have written some components like JLocalizedLabel receiving the label as label an instance of LocalizedString instead of String. 其中,我更喜欢1。实际上,我已经编写了一些组件,例如JLocalizedLabel,它接收标签作为LocalizedString而不是String的实例的标签。 With this, you don't even need the event listeners, it is sufficient to repaint the component and the change is done. 这样,您甚至不需要事件侦听器,只需重新绘制组件即可完成更改。 But this way it only works for the main text on a button or label, whereas for eg tooltip texts or so you still need the event listeners. 但是这种方式仅适用于按钮或标签上的主要文本,而对于工具提示文本等,您仍然需要事件侦听器。

This is how it could look like (just an example): 这就是它的样子(仅作为示例):

public class JLocalizedLabel extends JLabel
{
   /** The localized string to display. */
   protected LocalizedString              string;

    public JLocalizedLabel(LocalizedString string, Icon icon, int horizontalAlignment)
    {
        super(string.toString(), icon, horizontalAlignment);
        this.string = string;
    }

    @Override
    public String getText()
    {
        if (string == null)
            return "";
        return string.toString();
    }

    @Override
    public void setText(String text)
    {
    }

}

And the LocalizedString class: 和LocalizedString类:

public class LocalizedString
{

    /** The key to search for in the resource bundle. */
    protected String                                 key;
    /** The cached text to display. */
    protected String                                 text;
    /** The name of the resource bundle to use. */
    protected String                                 bundleName;
    /** The cache of resource bundles for the active locale. */
    private static Hashtable<String, ResourceBundle> bundles = new Hashtable<String, ResourceBundle>();
    /** The cached application locale. */
    private static Locale                            locale  = /* get the current locale */

    static {
        //install the locale change listener
        ServiceLocator.get(ConfigurationManager.class).get()
                .addPropertyChangeListener("locale", new PropertyChangeListener() {
                    @Override
                    public void propertyChange(PropertyChangeEvent evt)
                    {
                        bundles.clear();
                        locale = (Locale) evt.getNewValue();
                    }
                });
    }

    /**
     * Create a localized string by reading <code>key</code> from a resource bundle with name <code>name</code>.
     * 
     * @param bundleName The name of the resource bundle (the bundle will be retrieved by calling
     *            <code>ResourceBundle.getBundle(bundleName, locale)</code>)
     * @param key The key to search for in the resource bundle.
     */
    public LocalizedString(String bundleName, String key)
    {
        this.key = key;
        this.bundleName = bundleName;
        updateText();
        installLocaleListener();
    }

    /**
     * The locale has changed, so reload the text from the bundle.
     */
    protected void updateText()
    {
        try {
            text = getBundle().getString(key);
        } catch (MissingResourceException e) {
            text = "";
        }
    }

    /**
     * @return The resource bundle associated with this localized string in the current locale.
     */
    protected ResourceBundle getBundle()
    {
        if (bundles.get(bundleName) == null) {
            bundles.put(bundleName, ResourceBundle.getBundle(bundleName, locale));
        }
        return bundles.get(bundleName);
    }

    /**
     * Return the currently active locale.
     * 
     * You can override this in child classes to reflect another locale. Then you should also override
     * {@link #installLocaleListener()}.
     * 
     * @return The currently active locale.
     */
    protected Locale getLocale()
    {
        return locale;
    }

    /**
     * Add a listener to the active configuration that will call {@link #updateText()} every time the locale has
     * changed.
     * 
     * You can override this in child classes to reflect another locale. Then you should also override
     * {@link #getLocale()} .
     */
    protected void installLocaleListener()
    {
        ServiceLocator.get(ConfigurationManager.class).get()
                .addPropertyChangeListener("locale", new PropertyChangeListener() {
                    @Override
                    public void propertyChange(PropertyChangeEvent evt)
                    {
                        updateText();
                    }
                });
    }

    @Override
    public String toString()
    {
        return text;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM