简体   繁体   English

Java:跨多个GUI对象共享本地化对象的最佳实践?

[英]Java: Best practice for sharing localization object across many GUI objects?

What would be the best practice for sharing localization object (in this case ResourceBundle, where I do save all translations) across many GUI objects in app? 在应用程序中的多个GUI对象之间共享本地化对象(在这种情况下为ResourceBundle,我保存所有翻译)的最佳实践是什么? I have few ideas, but both have drawbacks: 我的想法不多,但都有缺点:

1) passing ResourceBundle via each GUI class constructor, but then I need to save it inside every class (for later use) - means having the same code in each class over and over again 1)通过每个GUI类构造函数传递ResourceBundle,但随后我需要将其保存在每个类中(以备后用)-意味着一次又一次地在每个类中使用相同的代码

2) declare ResourceBundle as public static (but not final, because I may need to change it - eg language changed) in main GUI class (eg "public static ResourceBundle msg") , then later access it always via it (eg calling MainGuiClass.msg.getString("something")), but then it can also be modified/destroyed by any other GUI class in the same package... 2)在主GUI类(例如“ public static ResourceBundle msg”)中将ResourceBundle声明为公共静态(但不是最终的,因为我可能需要更改它-例如更改语言),然后以后始终通过它访问它(例如调用MainGuiClass)。 msg.getString(“ something”))),但是它也可以被同一包中的任何其他GUI类修改/销毁...

Maybe there is some better practice to do the sharing? 也许有一些更好的做法可以进行共享?

Thanks. 谢谢。

The global ResourceBundle Object can not be final but instead should be cached in a Map. 全局ResourceBundle对象不能是最终的,而应缓存在Map中。 Changing the language doesn't require to change this reference: 更改语言不需要更改此引用:

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

public class UIBundle {
    private static final Map<Locale, ResourceBundle> allUIResources = new HashMap<Locale, ResourceBundle>();

    public static String getString(final String key) {
        return getString(key, Locale.getDefault());
    }

    public static String getString(final String key, final Locale locale) {
        ResourceBundle rb = allUIResources.get(locale);
        if (rb == null) {
            rb = ResourceBundle.getBundle("my-ui-resource", locale);
            allUIResources.put(locale, rb);
        }
        return rb.getString(key);
    }

}

With this code you can either access texts in specific languages/locales or just use the default locale. 使用此代码,您可以访问特定语言/语言环境的文本,也可以仅使用默认语言环境。 If you want to switch your locale, just set the default locale. 如果要切换语言环境,只需设置默认语言环境即可。 Your UI needs to know about locale changes, so you may have to introduce some listener interface for all your UI components ( PropertyChangeListener , PropertyChangeSupport ) and not change the locale directly. 您的UI需要了解区域设置更改,因此您可能必须为所有UI组件( PropertyChangeListenerPropertyChangeSupport )引入一些侦听器界面,而不是直接更改区域设置。

You could implement a caching factory, which returns the ResourceBundle based on the value of an input locale parameter. 您可以实现一个缓存工厂,该工厂将根据输入语言环境参数的值返回ResourceBundle。 Upon the first call the ResourceBundle will be constructed and then cached in a static reference, which can subsequently be returned and reused in later calls to the factory. 首次调用时,将构造ResourceBundle,然后将其缓存在静态引用中,随后可以将其返回并在以后的工厂调用中重新使用。

If you are concerned about other classes doing things you do not want to an object, make it a protected/private field of a class which has the methods you want to be performed on it. 如果您担心其他类对您的对象不希望发生的事情,请将其设置为类的受保护/私有字段,该类具有要在其上执行的方法。

Globals are evil, but sometimes their convenience is greater than their evilness. 全球人是邪恶的,但有时他们的便利大于邪恶。

The class ResourceBundle implements already a cache, so there is no need to implement caching yourself. ResourceBundle类已经实现了缓存,因此不需要自己实现缓存。 Your access class can be implemented as singleton. 您的访问类别可以实现为单例。 To switch the language I use a ThreadLocal for the locale: 要切换语言,我将ThreadLocal用作语言环境:

public final class ThreadLocale extends ThreadLocal<Locale>
{
    public static final ThreadLocale theInstance = new ThreadLocale ();

    private ThreadLocale () 
    {
        super ();
    }

    protected Locale initialValue()
    {
        return Locale.getDefault ();
    }
}

In the method of the access class, which gets the text from the resource bundle I use the current thread locale: 在访问类的方法中,该类从资源束中获取文本,我使用当前线程语言环境:

public synchronized String getMessage (Object messageKey, Locale locale) throws MissingResourceException
{
    ResourceBundle resourceBundle = null;
    resourceBundle = ResourceBundle.getBundle (filename, ThreadLocale.theInstance.get ());
    return resourceBundle.getString (messageKey.toString ());
}

So you can set a locale for each thread and not globally. 因此,您可以为每个线程设置区域设置,而不是全局设置。

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

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