我有两种方法可以将我的应用国际化,我知道有更多方法可以通过Resource Bundle(如果您认为有更好的方法可以解释我的话),有点新使用Resource Bundle这就是为什么这个疑问合并。
这些是我这样做的方式:
import java.util.*;
//http://docs.oracle.com/javase/tutorial/i18n/resbundle/list.html
public class ListDemo {
static void displayValues(Locale currentLocale) {
ResourceBundle stats = ResourceBundle.getBundle("StatsBundle",currentLocale);
Integer gdp = (Integer)stats.getObject("GDP");
System.out.println("GDP = " + gdp.toString());
Integer pop = (Integer)stats.getObject("Population");
System.out.println("Population = " + pop.toString());
Double lit = (Double)stats.getObject("Literacy");
System.out.println("Literacy = " + lit.toString());
} // displayValues
static public void main(String[] args) {
Locale[] supportedLocales = {
//new Locale("en","CA"),
new Locale("ja","JP")
//new Locale("fr","FR")
};
for (int i = 0; i < supportedLocales.length; i ++) {
System.out.println("Locale = " + supportedLocales[i]);
displayValues(supportedLocales[i]);
System.out.println();
}
} // main
} // class
这是包含数据的类
import java.util.*;
public class StatsBundle_ja_JP extends ListResourceBundle {
public StatsBundle_ja_JP() {
this.contents = new Object[][]{{ "GDP", 21300}, { "Population", 125449703}, { "Literacy", 0.99}};
}
@Override
public Object[][] getContents() {
return contents;
}
private final Object[][] contents;
}
注意: 这是oracle带来的示例。我想知道为什么当两个类都不在默认包中时它不起作用(我已经使用了资源的完全限定名称)。
import java.util.Locale;
import java.util.ResourceBundle;
public class InternationalizationDemo {
public static void main(String[] args) {
ResourceBundle bundle = ResourceBundle.getBundle("oTHER/MessageBundle", Locale.US);
System.out.println("Message in " + Locale.US + ": " + bundle.getString("greeting"));
//changing the default locale to indonasian
Locale.setDefault(new Locale("in", "ID"));
bundle = ResourceBundle.getBundle("oTHER/MessageBundle");
System.out.println("Message in " + Locale.getDefault() + ": " + bundle.getString("greeting"));
}
}
以下是属性:
它们都有效,但是哪一个更好,更快,并且重量最轻?,还是有更好的方法?
还想知道何时使用它们(PropertiesResourceBundle和ListResourceBundle)
答案 0 :(得分:2)
它们都足够快。属性资源包有点慢,因为必须解析文件,但这种开销是可以忽略的,结果会缓存在内存中。
选择不是基于性能。它基于功能。 ListResourceBundle更灵活。它允许使用Java来创建密钥和值所需的一切。
属性资源包更易于阅读,编辑和维护。即使是非程序员翻译也可以轻松编辑这样的文件。
关于您关于默认包的问题,当然可以将您的类和资源包放在您想要的任何包中。如果类StatsBundle_ja_JP
位于包com.foo.bar
中,则必须使用
ResourceBundle stats = ResourceBundle.getBundle("com.foo.bar.StatsBundle", japanLocale);
同样的规则适用于prperty resourcebundles:如果MessageBundle属性文件位于包com.foo.bar
中,则应使用
ResourceBundle stats = ResourceBundle.getBundle("com.foo.bar.MessageBundle", someLocale);
注意:baseName参数应该是完全限定的类名。但是,为了与早期版本兼容,Sun的Java SE运行时环境不会对此进行验证,因此可以通过指定路径名(使用&#34; /&#34;)代替a来访问PropertyResourceBundles完全限定的类名(使用&#34;。&#34;)。
答案 1 :(得分:1)
它们都有效,但是哪一个更好,更快,并且具有最小的重量?
提出错误的问题。当你编写将要发展的软件时(如果你想要外化字符串,这是相当明显的),你应该重视可维护性。 ListResourceBundle
基本上是代码文件 - 这些文件无法轻松维护。想象一下,你将负责更新一个条目...对于所有语言。你如何设置翻译记忆库?或者如何在源文件上使用机器翻译?
但真正的问题是,如果你想在未来添加语言怎么办?你真的想重新编译一切吗?
PropertiesResourceBundle
有一些缺点(ISO8859-1
任何人?),但有办法解决它们。一旦你加载它们,它们(几乎)与ListResourceBundle
一样快 - 性能方面 - 在内部使用HashMap
来保持翻译的简单原因。
如果你想在将来添加一种语言,它可能就像简单地将资源文件复制到正确的位置一样简单(如果你覆盖ResourceBundle.Control
,则在jar文件或磁盘上)。
Java 8进一步简化了此过程 - now ResourceBundle.Control实现了Service Provider Interface,因此您可以非常轻松地创建语言包并使其在运行时可被发现。当然,这些文件可以用UTF-8编码
好的,理论上你可以自动发现ListResourceBundles
,但可维护性问题不会消失。
还是有更好的方法吗?
不要走那条路。我见过很多人试图重新发明轮子。它总是比ResourceBundle
更糟糕。除非你知道I18n的所有细节,否则你不应该尝试。