Java: лучшая практика для совместного использования объекта локализации во многих объектах графического интерфейса?

Как лучше всего использовать объект локализации (в данном случае ResourceBundle, где я сохраняю все переводы) для многих объектов графического интерфейса в приложении? У меня мало идей, но у обеих есть недостатки:

1) передача ResourceBundle через каждый конструктор класса GUI, но затем мне нужно сохранить его внутри каждого класса (для последующего использования) - это означает наличие одного и того же кода в каждом классе снова и снова

2) объявить ResourceBundle как общедоступный статический (но не окончательный, потому что мне может потребоваться изменить его - например, изменить язык) в основном классе графического интерфейса (например, "public static ResourceBundle msg"), а затем получить доступ к нему всегда через него (например, вызов MainGuiClass. msg.getString("something")), но затем он также может быть изменен/уничтожен любым другим классом GUI в том же пакете...

Может быть, есть какая-то лучшая практика для обмена?

Спасибо.


person Laimoncijus    schedule 28.02.2010    source источник


Ответы (4)


Глобальный объект ResourceBundle не может быть окончательным, а вместо этого должен кэшироваться на карте. Изменение языка не требует изменения этой ссылки:

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

}

С помощью этого кода вы можете либо получить доступ к текстам на определенных языках/локалях, либо просто использовать локаль по умолчанию. Если вы хотите изменить свою локаль, просто установите локаль по умолчанию. Ваш пользовательский интерфейс должен знать об изменениях локали, поэтому вам, возможно, придется ввести некоторый интерфейс прослушивателя для всех ваших компонентов пользовательского интерфейса (PropertyChangeListener, PropertyChangeSupport), а не изменять язык напрямую.

person tichy    schedule 28.02.2010

Вы можете реализовать фабрику кэширования, которая возвращает ResourceBundle на основе значения входного параметра локали. При первом вызове ResourceBundle будет создан, а затем кэширован в статической ссылке, которая впоследствии может быть возвращена и повторно использована в последующих вызовах фабрики.

person crowne    schedule 28.02.2010

Если вы обеспокоены тем, что другие классы делают с объектом то, чего вы не хотите, сделайте его защищенным/приватным полем класса, в котором есть методы, которые вы хотите выполнять.

Глобалы — зло, но иногда их удобство больше, чем их зло.

person alex    schedule 28.02.2010

Класс 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 ());
}

Таким образом, вы можете установить локаль для каждого потока, а не глобально.

person thmayr    schedule 19.01.2016