加载所有 ResourceBundle 并根据密钥和区域设置选择正确的资源

Load all ResourceBundles and pick correct resource based on key and Locale

好的,所以我面临的挑战是实施一个 "Service" 加载我们支持的所有语言环境的所有资源。然后应该可以根据键和当前的 Locale 从正确的 ResourceBundle 中选择资源。我怎样才能做到这一点?

这就是我制定解决方案的方式,我有一个名为 TranslationService

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

所以我想要实现的是能够为所有支持的 Locales 加载所有指定的 Bundles 所以说我想在初始化前加载 MessageTexts_en_GB.propertiesMessageTexts_fr_FR.propertiesMessageTexts_ja_JP.properties 等。然后根据使用的语言环境和我发送的密钥,我应该能够知道在哪个 Bundle 中寻找密钥,而无需遍历我的所有 Bundle .也就是说,如果我得到 fr_FRLocalekey PUSH_NOTIFICATION_REMINDER,那么我就知道我必须在 NotificationTexts_fr_FR.properties 中查找文本而不必须像我一样遍历所有资源。那么是否有可能这样做,或者我是否必须像现在这样遍历我的所有资源,如果可以为所有语言环境加载资源,我最终将如何处理 属性 命名冲突,所以我没有听错语言 属性?

所以我目前正在研究如下所示的解决方案:

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

}

对该解决方案的初步测试表明它可以正常工作,但如果有人有更好的解决方案或更流畅的方法,我会洗耳恭听:)。