【问题标题】:Java AWT Internationalization DynamicJava AWT 国际化动态
【发布时间】:2013-09-24 20:55:57
【问题描述】:

我正在创建一个原型应用程序,它应该支持日语语言环境和英语语言环境。我应该有 Menuitem 来选择日语或英语。因此,应用程序应该以日文或英文显示它的所有标签按钮文本。

我使用 Netbeans 国际化支持进行开发。 如果我将 VM 参数传递为 -Duser.language=ja -Duser.country=JP,应用程序会在标签和按钮等上显示日语文本。

如果我将 VM 参数传递为 -Duser.language=en -Duser.country=IN,应用程序会在标签和按钮等上显示英文文本。

这很好用。但是如何使它动态化。这样就无需使用 VM 参数重新启动应用程序。

【问题讨论】:

    标签: java internationalization awt


    【解决方案1】:

    我认为这是关于处理动态翻译的一个相当普遍的问题。

    一般来说,我知道三种方法。

    1. 应用程序中的每个标签或文本集都必须注册一个监听器,以监听您在语言更改时发出的事件。在侦听器中,您将读取新的语言环境并从包中加载正确的字符串。
    2. 从窗口向下遍历组件层次结构并翻译途中找到的所有文本。
    3. 以编程方式设置其他语言环境,然后销毁并重新创建 GUI。

    也许说起来很可悲,但所有这些选项都需要对程序代码进行一般性且相当大的更改。

    其中,我更喜欢 1. 我实际上已经编写了一些组件,例如 JLocalizedLabel,将标签作为 LocalizedString 的实例而不是 String 接收标签。有了这个,你甚至不需要事件监听器,重绘组件就足够了,改变就完成了。但这种方式仅适用于按钮或标签上的主要文本,而例如工具提示文本,所以您仍然需要事件侦听器。

    这就是它的样子(只是一个例子):

    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)
        {
        }
    
    }
    

    还有 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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-16
      • 2013-06-16
      • 1970-01-01
      • 2011-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多