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

发布于 2024-08-23 09:14:07 字数 427 浏览 6 评论 0原文

在应用程序中的许多 GUI 对象之间共享本地化对象(在本例中为 ResourceBundle,我在其中保存所有翻译)的最佳实践是什么?我的想法很少,但两者都有缺点:

1)通过每个 GUI 类构造函数传递 ResourceBundle,但随后我需要将其保存在每个类中(以供以后使用) - 意味着每个类中一遍又一遍地使用相同的代码

2)在主 GUI 类(例如“public static ResourceBundle msg”)中将 ResourceBundle 声明为 public static(但不是最终的,因为我可能需要更改它 - 例如更改语言),然后始终通过它访问它(例如调用 MainGuiClass.msg。 getString("something")),但它也可以被同一包中的任何其他 GUI 类修改/销毁......

也许有一些更好的做法来进行共享?

谢谢。

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? 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

2) declare ResourceBundle as public static (but not final, because I may need to change it - e.g. language changed) in main GUI class (e.g. "public static ResourceBundle msg") , then later access it always via it (e.g. calling MainGuiClass.msg.getString("something")), but then it can also be modified/destroyed by any other GUI class in the same package...

Maybe there is some better practice to do the sharing?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

数理化全能战士 2024-08-30 09:14:07

全局ResourceBundle对象不能是最终的,而是应该缓存在Map中。更改语言不需要更改此引用:

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

}

使用此代码,您可以访问特定语言/区域设置的文本,也可以仅使用默认区域设置。如果您想切换区域设置,只需设置默认区域设置即可。您的 UI 需要了解区域设置更改,因此您可能必须为所有 UI 组件引入一些侦听器接口 (PropertyChangeListener, PropertyChangeSupport),而不是直接更改区域设置。

The global ResourceBundle Object can not be final but instead should be cached in a 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.

蓝海似她心 2024-08-30 09:14:07

您可以实现一个缓存工厂,它根据输入区域设置参数的值返回 ResourceBundle。第一次调用时,将构造 ResourceBundle,然后将其缓存在静态引用中,随后可以在以后对工厂的调用中返回并重用该静态引用。

You could implement a caching factory, which returns the ResourceBundle based on the value of an input locale parameter. 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.

梦里寻她 2024-08-30 09:14:07

如果您担心其他类对对象执行您不希望执行的操作,请将其设为具有您想要对其执行的方法的类的受保护/私有字段。

全局变量是邪恶的,但有时它们的便利性大于其邪恶性。

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.

猫烠⑼条掵仅有一顆心 2024-08-30 09:14:07

ResourceBundle类已经实现了缓存,因此不需要自己实现缓存。您的访问类可以实现为单例。为了切换语言,我使用 ThreadLocal 作为区域设置:

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

    private ThreadLocale () 
    {
        super ();
    }

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

在访问类的方法中,从资源包获取文本,我使用当前线程区域设置:

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 ());
}

因此,您可以为每个线程设置区域设置,而不是全局设置。

The class ResourceBundle implements already a cache, so there is no need to implement caching yourself. Your access class can be implemented as singleton. To switch the language I use a ThreadLocal for the locale:

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文