我从Oracle Java教程中看到了这段代码,但对它的实际工作方式感到困惑。我正在寻找以下几个问题的答案:
1)我看不到从任何地方调用public List<Locale> getCandidateLocales(String baseName, Locale locale)
,那么它实际上是如何执行的?
2)作为参数传递给public List<Locale> getCandidateLocales(String baseName, Locale locale)
的内容
3)public List<Locale> getCandidateLocales(String baseName, Locale locale)
返回List<Locale>
,返回List<Locale>
的目的是什么
4)如果不满足任何public List<Locale> getCandidateLocales(String baseName, Locale locale)
语句,则super.getCandidateLocales(baseName, locale);
返回if
,关键字super所指的是哪个类?
public class RBControl {
public static void main(String[] args) {
test(Locale.CHINA);
test(new Locale("zh", "HK"));
test(Locale.TAIWAN);
test(Locale.CANADA);
}
private static void test(Locale locale) {
ResourceBundle rb = ResourceBundle.getBundle("Internationalisation/RBControl", locale,
new ResourceBundle.Control() {
@Override
public List<Locale> getCandidateLocales(String baseName, Locale locale) {
if (baseName == null)
throw new NullPointerException();
if (locale.equals(new Locale("zh", "HK"))) {
return Arrays.asList(
locale,
Locale.TAIWAN,
// no Locale.CHINESE here
Locale.ROOT);
} else if (locale.equals(Locale.TAIWAN)) {
return Arrays.asList(
locale,
// no Locale.CHINESE here
Locale.ROOT);
}
return super.getCandidateLocales(baseName, locale);
}
});
System.out.println("locale: " + locale);
System.out.println("\tregion: " + rb.getString("region"));
System.out.println("\tlanguage: " + rb.getString("language"));
}
}
最佳答案
老实说,由于您的代码风格早于Java 7(您是考古学家?),所以回答您的问题可能非常困难,但是我会尽力的。
我只能向您保证,在代码搜索有效的文件名或类名以从中加载文本资源时,实际上会调用getCandidateLocales(String, String)
。例如:
// ResourceBundle.java line 1314
private static ResourceBundle getBundleImpl(String baseName, Locale locale,
ClassLoader loader, Control control) {
// (...) many lines removed
// line 1352 - loop through files to find the best one
ResourceBundle baseBundle = null;
for (Locale targetLocale = locale;
targetLocale != null;
targetLocale = control.getFallbackLocale(baseName, targetLocale)) {
// line 1356, there you are
List<Locale> candidateLocales = control.getCandidateLocales(baseName, targetLocale);
if (!isKnownControl && !checkList(candidateLocales)) {
throw new IllegalArgumentException("Invalid Control: getCandidateLocales");
}
bundle = findBundle(cacheKey, candidateLocales, formats, 0, control, baseBundle);
// lengthy comment removed for clarity
if (isValidBundle(bundle)) {
// checking if it is the right one, removed
}
}
// logic to deal with missing file, removed
return bundle;
}
我认为现在应该很明显,但是让我详细介绍一下。假设您以属性文件的形式发送消息:
messages.properties
-基本,默认语言资源,messages_fr.properties
-基本法语资源,messages_fr_CA.properties
-加拿大法语资源以及最后messages_de.proprties
-基本德语资源。基本名称就是您可能猜到的基本文件名messages
。候选语言环境是用户界面语言环境。如果您使用的是桌面应用程序(极不可能)或移动应用程序,则只需调用
Locale.getDetault(Locale.Category.DISPLAY)
即可获取UI语言环境。在Java的旧版本中,它只是Locale.getDefault()
。在Web应用程序中,解决方案实际上取决于技术(即Spring,JSF,Thymeleaf,Play等)和您的语言环境检测方法。无论如何,您应该首先尝试最专业的产品,而不要回退。例如,加拿大法语用户(语言标签fr-CA)应该已经看到了messages_fr_CA.properties
的内容,而其他法语用户则应该看到了messages_fr.properties
的内容。同样,任何其他语言环境都应遵守messages.properties
的翻译。此方法的作用是,它将为用户生成后备语言环境(即对于输入
Locale.forLanguageTag("fr-CA")
,它将返回输入本身,法语语言环境(“ fr”)和未定义的语言环境标记(“ und”)。一个告诉ResourceBundle
使用默认文件。如上所述,它返回后备语言环境列表。
它在父类-
ResourceBundle.Control
中调用该方法。您所附的代码清单中定义的匿名内部类实际上是从ResourceBundle.Control派生的。