views:

270

answers:

3

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.

A: 

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.

crowne
A: 

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.

alex
+1  A: 

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.

Frank Meißner