好的,我已经接受了这个挑战来实现一个“服务”,它加载了我们支持的所有语言环境的所有资源。然后应该可以根据密钥和当前的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.properties
,MessageTexts_ja_JP.properties
等。然后根据使用的语言环境以及我发送的密钥,我应该能够告诉哪个Bundle要查找密钥而不循环遍历我的所有Bundle。所以,如果我得到Locale
和fr_FR
key
的{{1}},那么我就知道我必须在PUSH_NOTIFICATION_REMINDER
中查找文本不得不像我一样循环遍历所有资源。所以甚至可以像这样做,或者我必须循环遍历我现在所做的所有资源,如果为所有Locales加载资源是可能的,我最终还是需要处理属性命名冲突,所以我不会得到错误的语言属性?
答案 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"));
}
}
对此解决方案的初步测试表明,这样可以正常工作,但如果有人有更好的解决方案或更顺畅的方式,我会全力以赴:)。