国际化Java应用程序(资源包)的方法的优点和缺点

时间:2014-08-15 04:00:23

标签: java properties internationalization resourcebundle

我有两种方法可以将我的应用国际化,我知道有更多方法可以通过Resource Bundle(如果您认为有更好的方法可以解释我的话),有点新使用Resource Bundle这就是为什么这个疑问合并。

这些是我这样做的方式:

1st - ListResourceBundle

    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带来的示例。我想知道为什么当两个类都不在默认包中时它不起作用(我已经使用了资源的完全限定名称)。

2nd - PropertiesResourceBundle

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

    }
}

以下是属性:

properties

它们都有效,但是哪一个更好,更快,并且重量最轻?,还是有更好的方法?

还想知道何时使用它们(PropertiesResourceBundle和ListResourceBundle)

2 个答案:

答案 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);

The documentation解释道:

  

注意: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的所有细节,否则你不应该尝试。

相关问题