资源包

本文转自https://blog.csdn.net/PacosonSWJTU/article/details/50639756

java国际化——资源包相关

problem+solution

problem: 当本地化一个应用时, 可能会有大量的消息字符串, 按钮标签和其它的东西需要被翻译;

solution: 你会希望在外部定义消息字符串, 通常称之为资源。 在java中, 需要使用属性文件来设定字符串资源,并为其它类型的资源实现相应的类;

定位资源包

当本地化一个应用时,会制造出很多资源包。每个包都是一个属性文件或者是一个描述了与 locale 相关的项的类。对于每一个包, 都要为所有你想要支持的 locale 提供相应的版本;
想要对这些包使用一种统一的命名规则:

包名语言国家;
包名_语言;
来命名所有和语言相关的资源。

最后,作为后备, 可以把默认资源放到一个没有后缀的文件中;

可以用下面的命令加载一个包:

1
ResourceBundle resource = ResourceBundle.getBundle(bundleName, currentLocale);

getBundle 方法试图加载匹配当前 locale 定义的语言和国家的包。如果失败, 通过依次放弃国家和语言来继续进行查找, 然后同样的查找被应用于默认的 locale;

也就是说, getBundle 方法试图加载以下的包:

1
2
3
4
5
6
7
(1)包名当前locale的语言当前Locale的国家_当前Locale的变量; 
(2)包名当前locale的语言当前Locale的国家;
(3)包名_当前locale的语言;
(4)包名默认locale的语言默认Locale的国家_默认Locale的变量;
(5)包名默认locale的语言默认Locale的国家;
(6)包名_默认locale的语言;
(7)包名;

总之, java 的资源包机制会自动定位与给定的locale 匹配得最好的项
可以很容易地吧越来越多的本地化信息加到已有的程序中: 你需要做的只是增加额外的资源包;

利用属性文件进行国际化

  1. 对字符串进行国际化是很直接的, 你可以吧字符串放到一个属性文件中, 典型的 属性文件内容如下:

    1
    2
    3
    computeButton=Rechnen 
    colorName=black
    defaultPaperSize=210X297
    1. 然后利用以上提到的规则去命名你的属性文件

      1
      2
      3
      MyprocStrings.properties 
      MyprocStrings_en.properties
      MyprocStrings_de_DE.properties
  1. 你可以直接加载包:如

    1
    ResourceBundle bundle = ResourceBundle.getBundle(“MyProcStrings”, locale);
  1. 要查找一个具体的字符串,可以调用:

    1
    string str = bundle.getString(“colorName”);
**Warning**:

存储属性的文件都是ASCII文件, 如果你需要将 Unicode 字符放到属性文件中, 那么请用\uxxxx 编码方式对它们进行编码。

你可以使用 native2ascii 工具来产生这些文件;
  1. 看个利用.properties文件进行国际化的荔枝:

    1. for souce code, please visit : https://github.com/pacosonTang/core-java-volume/tree/master/coreJavaAdvanced/chapter5/ResourceBundle_Properties

    2. key source code at a glance:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      public class PropertiesDemo
      {
      // 显示与给定Locale相关的.properties文件中的key对应的value
      static void displayValue(Locale locale, String key)
      {
      ResourceBundle labels = ResourceBundle.getBundle("LabelBundle", locale);
      String value = labels.getString(key);
      System.out.println("locale = " + locale.getDisplayName() +
      ", key = " + key + ", value = " + value);
      }
      // 迭代与给定Locale相关的.properties文件中的keys
      static void iterateKeys(Locale locale)
      {
      ResourceBundle labels = ResourceBundle.getBundle("LabelBundle", locale);
      Enumeration<String> keys = labels.getKeys();
      while(keys.hasMoreElements())
      {
      String key = keys.nextElement();
      String value = labels.getString(key);
      System.out.println("locale = " + locale.getDisplayName() +
      ", key = " + key + ", value = " + value);
      }
      }

      public static void main(String[] args)
      {
      Locale.setDefault(Locale.ENGLISH);
      Locale[] supportedLocales =
      {
      Locale.CHINA,
      Locale.GERMAN,
      Locale.ENGLISH
      };

      System.out.println("=== the output of method displayValue is as follows: ===\n");
      for (int i = 0; i < supportedLocales.length; i++)
      {
      displayValue(supportedLocales[i], "s2");
      }
      System.out.println();
      System.out.println("=== the output of method iterateKeys is as follows: ===\n");
      iterateKeys(supportedLocales[0]);
      }
      }
  1. relative printing results as follows:

利用包类进行国际化

  1. 为了提供字符串外的资源,需要定义类, 它必须扩展于 ResourceBundle 类, 应该使用标准的命名规则来命名你的类, 如:(干货——资源绑定类引入原因——为了对字符串外的资源进行国际化,需要定义资源绑定类)(干货——包类的命名规则)

    1
    2
    3
    MyprogResources.java 
    MyprogResources_en.java
    MyprogResources_de_DE.java
  1. 你可以使用 与 加载属性文件相同的getBundle 方法来加载这个类: (干货——加载资源绑定类与资源包的方法相同,即getBuddle)

    1
    ResourceBundle bundle = ResourceBundle .getBundle(“MyprogResources”, locale);

Warning) 当搜索包时, 如果在类中的包和在属性文件中的包中都存在匹配, 优先选择类中的包;

  1. 每一个资源绑定类都实现了一个查询表。

    1. 你需要为每一个你想定位的设置都提供一个关键字字符串, 使用这个字符串来提取相应的设置, 如;

      1
      2
      Color background = (Color) bundle.getObject(“background”); 
      double[] papersize = (double[]) bundle.getObject(“defaultSize”);
  1. 使用资源绑定类的最简单方法就是 继承 ListReourceBundle类; (干货——使用资源绑定类的最简单方法就是 继承 ListReourceBundle类)

  2. ListReourceBundle: 让你把所有资源都放到一个对象数组并提供查找功能, 请遵循以下框架代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class bundleName_language_country extends ListResourceBundle 
    {
    private static final Object[][] contents =
    {
    {key1, value1];
    {key1, value1];

    }
    public Object[][] getContents() { return contents ; }
    }
  1. 看个栗子

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class ProgramResource_de extends ListResourceBundle
    {
    private static final Object[][] contents =
    {
    {"background",Color.black];
    {"defaultPaperSize", new double[]{210, 297}}
    ...
    }
    public Object[][] getContents() { return contents ; }
    }
  1. 或者, 你的资源绑定类可以扩展 ResourceBundle 类。 然后需要实现两个方法, 一个是枚举所有键,二是用给定的键查找相应的值

    1
    2
    3
    Enumeration<String> getKeys();
    Object handleGetObject(String key);
    ResourceBundle 类的 getObject 方法会调用你提供的 handleGetBundle 方法;
  1. 看个利用.class文件进行国际化的荔枝:

    1. for souce code, please visit : https://github.com/pacosonTang/core-java-volume/tree/master/coreJavaAdvanced/chapter5/ResourceBundle_Class
    2. key source code at a glance:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public class ListResourceBundleDemo
    {
    // 显示与给定Locale相关的.properties文件中的key对应的value
    static void displayValue(Locale locale)
    {
    ResourceBundle stats = ResourceBundle.getBundle("com.corejava.chapter573.StatsBundle", locale);
    Integer gdp = (Integer) stats.getObject("GDP");
    Integer population = (Integer) stats.getObject("Population");
    Double literacy = (Double)stats.getObject("Literacy");

    System.out.println("locale = " + locale.getDisplayName() +
    ", gdp = " + gdp + ", population = " + population + ", literacy = " + literacy);
    }

    public static void main(String[] args)
    {
    Locale.setDefault(Locale.US);
    Locale[] locales =
    {
    new Locale("en", "CA"),
    new Locale("de", "DE"),
    new Locale("zh", "CN")
    };

    for (int i = 0; i < locales.length; i++)
    {
    displayValue(locales[i]);
    }
    }
    }
3. relative printing results as follows:

![](https://bigengzhe.github.io/images/20160206083133641)
Donate comment here