加载所有ResourceBundle并根据键和Locale选择正确的资源

时间:2018-02-14 10:45:26

标签: java resourcebundle

好的,我已经接受了这个挑战来实现一个“服务”,它加载了我们支持的所有语言环境的所有资源。然后应该可以根据密钥和当前的Locale从正确的ResourceBundle中选择资源。我怎样才能做到这一点?

所以这就是我的解决方案,我有Service名为TranslationService

public class TranslationService {

    private List<ResourceBundle> resourceBundles;

    public TranslationService(final Locale locale) {
        ResourceBundle messageTexts = ResourceBundle.getBundle("MessageTexts", locale, new Utf8Control());
        ResourceBundle notificationTexts = ResourceBundle.getBundle("NotificationTexts", locale, new Utf8Control());
        ResourceBundle generalTexts = ResourceBundle.getBundle("GeneralTexts", locale, new Utf8Control());
        Collections.addAll(this.resourceBundles, messageTexts, notificationTexts, generalTexts);
    }

    public String getText(String key) {
        String text = null;

        for (ResourceBundle resourceBundle : resourceBundles) {
            try {
                text = resourceBundle.getString(key);
            } catch (MissingResourceException e) {
                // DO NOTHING: If the key is not found in first resource means not that it isn't in the next
                // check all resources for the key.
            }
        }

        if (text == null) {
            log.error("Could not find key {} in any resource.", key);
        }

        return text;
    }
}

所以我想要实现的是能够为所有支持的Bundles加载所有指定的Locales,以便说我想在MessageTexts_en_GB.properties的初始化时加载, MessageTexts_fr_FR.propertiesMessageTexts_ja_JP.properties等。然后根据使用的语言环境以及我发送的密钥,我应该能够告诉哪个Bundle要查找密钥而不循环遍历我的所有Bundle。所以,如果我得到Localefr_FR key的{​​{1}},那么我就知道我必须在PUSH_NOTIFICATION_REMINDER中查找文本不得不像我一样循环遍历所有资源。所以甚至可以像这样做,或者我必须循环遍历我现在所做的所有资源,如果为所有Locales加载资源是可能的,我最终还是需要处理属性命名冲突,所以我不会得到错误的语言属性?

1 个答案:

答案 0 :(得分:0)

所以我目前正在寻找一个看起来像这样的解决方案:

public class MyResourceBundle {

    private Map<Locale, Map<String, String>> localeResources;


    public MyResourceBundle() {
        localeResources = new HashMap<>();
        for (LocaleConfig config : LocaleConfig.values()) {
            Map<String, String> resources = new HashMap<>();

            ResourceBundle systemTexts = ResourceBundle.getBundle("SystemTexts", config.getLocale());
            ResourceBundle translationTexts = ResourceBundle.getBundle("TranslationTexts", config.getLocale());

            Enumeration systemKeys = systemTexts.getKeys();

            while (systemKeys.hasMoreElements()) {
                String key = (String) systemKeys.nextElement();
                resources.put(key, systemTexts.getString(key));
            }

            Enumeration translationKeys = translationTexts.getKeys();
            while (translationKeys.hasMoreElements()) {
                String key = (String) translationKeys.nextElement();
                resources.put(key, translationTexts.getString(key));
            }

            localeResources.put(config.getLocale(), resources);
        }

    }

    public String getText(Locale locale, String key) {
        String text = null;

        text = localeResources.get(locale).get(key);

        if (text == null) {
            String errorMessage = "Key: " + key + " does not exist for locale " + locale.toString();
            throw new MissingResourceException(errorMessage, this.getClass().getName(), key);
        }

        return text;
    }

}

LocaleConfig.java:

public enum LocaleConfig {

    DANISH("da", "DK"),
    ENGLISH("en", "GB")
    ;

    private String language;
    private String country;

    LocaleConfig(String language, String country) {
        this.language = language;
        this.country = country;
    }

    public Locale getLocale() {
        return new Locale(language, country);
    }
}

SystemTexts_da_DK.properties:

PERSON_1=Hans Hansen
PERSON_2=Anders Andersen
PERSON_3=Ib Ibsen

REMINDER_MESSAGE=Husk at teste...

SystemTexts_en_GB.properties:

PERSON_1=Frank Testerson
PERSON_2=Julie Testerson
PERSON_3=Test Testerson

REMINDER_MESSAGE=Remember to test...

TranslationTexts_da_DK.properties:

NOTE_NEW=Ny
NOTE_SEEN=Set

TranslationTexts_en_GB.properties:

NOTE_NEW=New
NOTE_SEEN=Seen

现在我可以打电话:

public class MyResourceBundleExample {

    public static void main(String[] args) {
        Locale locale = new Locale("da", "DK");

        MyResourceBundle myResourceBundle = new MyResourceBundle();

        System.out.println(myResourceBundle.getText(locale, "PERSON_3"));
    }

}

对此解决方案的初步测试表明,这样可以正常工作,但如果有人有更好的解决方案或更顺畅的方式,我会全力以赴:)。