博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java国际化学习(二)------示例
阅读量:4673 次
发布时间:2019-06-09

本文共 26686 字,大约阅读时间需要 88 分钟。

  Java编程语言是第一个设计成为全面支持国际化的语言。从一开始,它就具备了进行有效的国际化所必须的一个重要特征:使用Unicode来处理所有字符串。支持Unicode使得在Java编程语言中,编写程序来操作多种语言的字符串变得异常方便。多数程序员认为进行国际哈需要做的事情就是支持Unicode并在用户接口中对消息进行翻译。然而在实际的开发中,国际化一个程序所需要做的绝不仅仅是提供Unicode支持,它还包括日期、时间、货币和数字等格式上的差异。

    1.    Locales:
    需要依赖国际化的两个主要格式化类为NumberFormat和DateFormat,它们在通过工厂方法获取其实现子类时,都会依赖参数Locale来决定最终被实例化的子类,见如下代码:

1 publicstaticvoid main(String[] args) {
2 Locale loc =new Locale("de","DE"); 3 NumberFormat currFmt = NumberFormat.getCurrencyInstance(loc); 4 double amt =123456.78; 5 String result = currFmt.format(amt); 6 System.out.println("The result = "+ result); 7 } 8 /* 输出结果如下: 9 The result = 123.456,78 ? */

    从结果可以看出原有的货币格式被转换为德语的格式了。以上例子是从数字格式化为字符串,同样还可以通过字符串转换为数字,但是这要依赖parse方法,见如下代码:

1 publicstaticvoid main(String[] args) throws ParseException {
2 Locale loc =new Locale("de","DE"); 3 NumberFormat fmt = NumberFormat.getNumberInstance(loc); 4 String amt ="123.456,78"; 5 double result = fmt.parse(amt).doubleValue(); 6 System.out.println("The result = "+ result); 7 } 8 /* 输出结果如下: 9 The result = 123456.78 */

    在上面的代码中都是通过直接给出ISO定义的语言和地区代码缩写的方式来构造Locale对象的,事实上Java中提供了一组预定义的Locale静态对象来表示不同的语言和地区的Locale实例,如:

    Locale.CANADA
    Locale.CANADA_FRENCH
    Locale.CHINA
    Locale.FRANCE
    Locale.GERMANY
    Locale.ITALY
    Locale.JAPAN
    Locale.KOREA
    ...
    以下的仅设定了语言而没有设定位置:
    Locale.CHINESE
    Locale.ENGLISH
    Locale.FRENCH
    Locale.GERMAN
    Locale.ITALIAN
    ...
    以下再给出几个关于Locale的示例代码:

1 //设置缺省国际化Locale,注意:该操作只是修改当前应用程序的  2 //本地化,而不是修改当前操作系统的。  3 publicstaticvoid main(String[] args) {
4 Locale.setDefault(Locale.FRANCE); 5 DateFormat df = DateFormat.getInstance(); 6 NumberFormat nf = NumberFormat.getInstance(); 7 System.out.println(df.format(new Date())); 8 System.out.println(nf.format(123.4567)); 9 } 10 /* 输出结果如下: 11 26/08/11 23:28 12 123,457 */ 13 14 //获取当前机器支持语言的列表 15 publicstaticvoid main(String[] args) {
16 Locale[] locales = Locale.getAvailableLocales(); 17 for (Locale loc : locales) 18 System.out.println(loc.getDisplayName()); 19 }

    2.    数字格式:

1 //将数组中的数字转换为指定的美国本地化显示格式  2 publicstaticvoid main(String[] args) {
3 int data[] = { 100, 1000, 10000, 1000000 }; 4 NumberFormat nf = NumberFormat.getInstance(Locale.US); 5 for (int i =0; i < data.length; ++i) {
6 System.out.println(data[i] +"\t"+ nf.format(data[i])); 7 } 8 } 9 //格式化BigDecimal 10 publicstaticvoid main(String[] args) {
11 StringBuffer buffer =new StringBuffer(); 12 Locale it = Locale.ITALY; 13 Locale.setDefault(it); 14 BigDecimal rate =new BigDecimal(".03250000"); 15 BigDecimal months =new BigDecimal("12"); 16 BigDecimal monthlyRate = rate.divide(months, BigDecimal.ROUND_HALF_DOWN); 17 NumberFormat pf =new DecimalFormat("#,##0.00000%"); 18 buffer.append("Annual rate : "+ pf.format(rate.doubleValue()) +"\n"); 19 buffer.append("Monthly rate: "+ pf.format(monthlyRate.doubleValue()) +"\n"); 20 BigDecimal balance =new BigDecimal("10000.0000"); 21 NumberFormat nf = NumberFormat.getCurrencyInstance(); 22 for (int i =0; i <12; i++) {
23 BigDecimal interest = balance.multiply(monthlyRate); 24 balance = balance.add(interest); 25 buffer.append("Balance : "+ nf.format(balance.doubleValue()) +"\n"); 26 } 27 System.out.println(buffer.toString()); 28 } 29 //格式化数字格式中主要的3中表示方式:数字、货币和百分比 30 publicclass MyTest {
31 staticpublicvoid displayNumber(Locale currentLocale) {
32 Integer quantity =new Integer(123456); 33 Double amount =new Double(345987.246); 34 NumberFormat numberFormatter; 35 String quantityOut; 36 String amountOut; 37 numberFormatter = NumberFormat.getNumberInstance(currentLocale); 38 quantityOut = numberFormatter.format(quantity); 39 amountOut = numberFormatter.format(amount); 40 System.out.println(quantityOut +""+ currentLocale.toString()); 41 System.out.println(amountOut +""+ currentLocale.toString()); 42 } 43 44 staticpublicvoid displayCurrency(Locale currentLocale) {
45 Double currency =new Double(9876543.21); 46 NumberFormat currencyFormatter; 47 String currencyOut; 48 currencyFormatter = NumberFormat.getCurrencyInstance(currentLocale); 49 currencyOut = currencyFormatter.format(currency); 50 System.out.println(currencyOut +""+ currentLocale.toString()); 51 } 52 53 staticpublicvoid displayPercent(Locale currentLocale) {
54 Double percent =new Double(0.75); 55 NumberFormat percentFormatter; 56 String percentOut; 57 percentFormatter = NumberFormat.getPercentInstance(currentLocale); 58 percentOut = percentFormatter.format(percent); 59 System.out.println(percentOut +""+ currentLocale.toString()); 60 } 61 62 publicstaticvoid main(String[] args) {
63 Locale[] locales = { new Locale("fr", "FR"), 64 new Locale("de", "DE"), 65 new Locale("en", "US") }; 66 for (int i =0; i < locales.length; i++) {
67 System.out.println(); 68 displayNumber(locales[i]); 69 displayCurrency(locales[i]); 70 displayPercent(locales[i]); 71 } 72 } 73 }

    3.    日历格式:

1 //从不同的locale获取每周中的哪一天为周的第一天,并显示  2 //不同locale针对星期的显示名称。  3 publicstaticvoid main(String[] args) {
4 Locale usersLocale = Locale.getDefault(); 5 6 DateFormatSymbols dfs =new DateFormatSymbols(usersLocale); 7 String weekdays[] = dfs.getWeekdays(); 8 Calendar cal = Calendar.getInstance(usersLocale); 9 //获取不同地区定义的哪一天是每周的第一天 10 int firstDayOfWeek = cal.getFirstDayOfWeek(); 11 int dayOfWeek; 12 //根据不同的每周第一天,遍历并显示不同地区针对星期的名称。 13 for (dayOfWeek = firstDayOfWeek; dayOfWeek < weekdays.length; dayOfWeek++) 14 System.out.println(weekdays[dayOfWeek]); 15 16 for (dayOfWeek =0; dayOfWeek < firstDayOfWeek; dayOfWeek++) 17 System.out.println(weekdays[dayOfWeek]); 18 } 19 //比较日本时区时间和本地时区时间 20 publicstaticvoid main(String[] args) {
21 Calendar local = Calendar.getInstance(); 22 Calendar japanCal =new GregorianCalendar(TimeZone.getTimeZone("Japan")); 23 japanCal.setTimeInMillis(local.getTimeInMillis()); 24 int jpHour = japanCal.get(Calendar.HOUR); // 3 25 int jpMinutes = japanCal.get(Calendar.MINUTE); // 0 26 int jpSeconds = japanCal.get(Calendar.SECOND); // 0 27 System.out.println("Japan's time is Hour = "+ jpHour +"\tMinutes = " 28 + jpMinutes +"\tSeconds = "+ jpSeconds); 29 int localHour = local.get(Calendar.HOUR); // 3 30 int localMinutes = local.get(Calendar.MINUTE); // 0 31 int localSeconds = local.get(Calendar.SECOND); // 0 32 System.out.println("Local's time is Hour = "+ localHour +"\tMinutes = " 33 + localMinutes +"\tSeconds = "+ localSeconds); 34 }

    4.    日期格式:

1 //定义指定的日期格式化格式,再根据locale的不同,打印出不同的日期名称。  2 publicstaticvoid main(String[] args) {
3 Locale locale = Locale.ENGLISH; 4 //SimpleDateFormat对象的构造函数中,如果没有显示的传入locale对象, 5 //该对象在解析和格式化的过程中将使用缺省的本地化对象。 6 DateFormat formatter =new SimpleDateFormat("E, dd MMM yyyy", locale); 7 DateFormat formatter2 =new SimpleDateFormat("HH:mm:ss zzzz", locale); 8 System.out.println("Result = "+ formatter.format(new Date())); 9 System.out.println("Result2 = "+ formatter2.format(new Date())); 10 //定义指定格式的日期格式化对象,在结合Locale对象去格式化当前时间。 11 Date date =new Date(); 12 String s = DateFormat.getTimeInstance(DateFormat.SHORT, locale).format(date); 13 System.out.println(s); 14 15 //使用缺省的本地化locale格式化日期和数字,这里DateFormat和NumberFormat工厂方法 16 //将会根据不同的locale来实例化不同的DateFormat和NumberFormat的实现类,然而这些 17 //逻辑对使用者是完全透明的。 18 DateFormat df = DateFormat.getInstance(); 19 NumberFormat nf = NumberFormat.getInstance(); 20 System.out.println(df.format(new Date())); 21 System.out.println(nf.format(123.4567)); 22 } 23 //根据不同的时间Pattern、日期Pattern、日期时间Pattern,连同不同的Locale参数来 24 //构造出DateFormat的实现子类,在格式化指定的日期对象。 25 publicclass MyTest {
26 staticpublicvoid displayDate(Locale currentLocale) {
27 DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.DEFAULT, 28 currentLocale); 29 Date today =new Date(); 30 String dateOut = dateFormatter.format(today); 31 System.out.println(dateOut +""+ currentLocale.toString()); 32 } 33 34 staticpublicvoid showBothStyles(Locale currentLocale) {
35 int[] styles = { DateFormat.DEFAULT, DateFormat.SHORT, 36 DateFormat.MEDIUM, DateFormat.LONG, DateFormat.FULL }; 37 System.out.println("Locale: "+ currentLocale.toString()); 38 Date today =new Date(); 39 for (int k =0; k < styles.length; k++) {
40 DateFormat formatter = DateFormat.getDateTimeInstance(styles[k], styles[k], 41 currentLocale); 42 String result = formatter.format(today); 43 System.out.println(result); 44 } 45 } 46 47 staticpublicvoid showDateStyles(Locale currentLocale) {
48 Date today =new Date(); 49 int[] styles = { DateFormat.DEFAULT, DateFormat.SHORT, 50 DateFormat.MEDIUM, DateFormat.LONG, DateFormat.FULL }; 51 System.out.println("Locale: "+ currentLocale.toString()); 52 for (int k =0; k < styles.length; k++) {
53 DateFormat formatter = DateFormat.getDateInstance(styles[k], currentLocale); 54 String result = formatter.format(today); 55 System.out.println(result); 56 } 57 } 58 59 staticpublicvoid showTimeStyles(Locale currentLocale) {
60 Date today =new Date(); 61 int[] styles = { DateFormat.DEFAULT, DateFormat.SHORT, 62 DateFormat.MEDIUM, DateFormat.LONG, DateFormat.FULL }; 63 System.out.println("Locale: "+ currentLocale.toString()); 64 for (int k =0; k < styles.length; k++) {
65 DateFormat formatter = DateFormat.getTimeInstance(styles[k], currentLocale); 66 String result = formatter.format(today); 67 System.out.println(result); 68 } 69 } 70 71 staticpublicvoid main(String[] args) {
72 Locale[] locales = { Locale.CHINA,new Locale("en", "US") }; 73 for (int i =0; i < locales.length; i++) 74 displayDate(locales[i]); 75 showDateStyles(new Locale("en", "US")); 76 showDateStyles(Locale.CHINA); 77 showTimeStyles(new Locale("en", "US")); 78 showTimeStyles(Locale.CHINA); 79 showBothStyles(new Locale("en", "US")); 80 showBothStyles(Locale.CHINA); 81 } 82 }

    5.    字符排序:

    大多数程序员都知道如何使用String类中的compareTo方法对字符串进行比较。但是由于大小写字符的ASCII值之间的差异,既小写字符总是大于大写字符,因此很多时候排序的结果并非程序员所真正希望得到的。然而有些时候,排序的问题不仅仅被大小写的问题所困扰,使用不同的本地化(Locale)对象,得到的排序规则往往也是不同的,比如在有些语言中存在重音符,其值更是大于小写字符,基于这样的排序结果也就失去的排序的真正意义。在Java中提供了Collator对象(Comparator的实现类),因此在当需要对字符串进行排序时,可以使用该类的工厂方法针对不同的Locale生成一个Collator的子类,之后在传给如Collections.sort这样的排序方法来完成实际的排序,如下例:

1 staticpublicvoid main(String[] args) {
2 List
fruits =new ArrayList
(); 3 fruits.add("A"); 4 fruits.add("é"); 5 fruits.add("C"); 6 fruits.add("D"); 7 fruits.add("A"); 8 Collator collator = Collator.getInstance(Locale.US); 9 Collections.sort(fruits, collator); 10 for (int i =0; i < fruits.size(); i++) {
11 String fruit = fruits.get(i); 12 System.out.println("Fruit = "+ fruit); 13 } 14 } 15 /* 结果如下: 16 Fruit = A 17 Fruit = A 18 Fruit = C 19 Fruit = D 20 Fruit = é 21 */

    在Collator中提供了不同的排序强度,字符间的差别主要区分为PRIMARY、SECONDARY和TERTIARY三种,PRIMARY差别将主要关注字符间的主要差异,如A和Z之间就是主要的差异,而é和"É"(法语)之间的差别为SECONDARY,最后"A"和"a"之间的差异为TERTIARY。由此看出,排序强度越高,其区分字符间的差异性就越差,见下例:

1 staticpublicvoid main(String[] args) {
2 String s1 ="é"; 3 String s2 ="É"; 4 5 Collator frCollator = Collator.getInstance(Locale.FRANCE); 6 System.out.println("The current strength is PRIMARY."); 7 frCollator.setStrength(Collator.PRIMARY); 8 if (frCollator.compare(s1, s2) ==0) 9 System.out.println("s1 = s2"); 10 System.out.println("The current strength is SECONDARY."); 11 frCollator.setStrength(Collator.SECONDARY); 12 if (frCollator.compare(s1, s2) ==0) 13 System.out.println("s1 = s2"); 14 System.out.println("The current strength is TERTIARY."); 15 frCollator.setStrength(Collator.TERTIARY); 16 if (frCollator.compare(s1, s2) ==0) 17 System.out.println("s1 = s2"); 18 } 19 /* 输出结果如下: 20 The current strength is PRIMARY. 21 s1 = s2 22 The current strength is SECONDARY. 23 s1 = s2 24 The current strength is TERTIARY. 25 */

    从输出结果中可以看出,当排序强度将为TERTIARY时,这两个字符将被视为不同的字符了。

    6.    消息格式化:

1 //这里演示了MessageFormat的最基本用法:  2 // {0,time}: 0表示第0个占位符,time表示该占位符的格式为时间,如不指定style,按缺省格式显示。  3 // {1,number}: 1表示第1个占位符,number表示该占位符为数字。  4 staticpublicvoid main(String[] args) {
5 String pattern ="The time is {0,time} and your lucky number is {1,number}."; 6 MessageFormat format =new MessageFormat(pattern); 7 Object objects[] = {
new Date(),new Integer((int)(Math.random() *1000))}; 8 String formattedOutput = format.format(objects); 9 System.out.println(formattedOutput); 10 11 pattern ="The datetime is {0} and your lucky number is {1}."; 12 format =new MessageFormat(pattern); 13 //指定Locale 14 format.setLocale(Locale.US); 15 formattedOutput = format.format(objects); 16 System.out.println(formattedOutput); 17 format.setLocale(Locale.CHINA); 18 formattedOutput = format.format(objects); 19 System.out.println(formattedOutput); 20 } 21 /* 输出结果如下: 22 The time is 10:47:47 and your lucky number is 97. 23 The datetime is 8/28/11 10:47 AM and your lucky number is 97. 24 The datetime is 11-8-28 上午10:47 and your lucky number is 97. 25 */

    Java针对Message中占位符的type,不仅提供了常规的number、time和date,还提供了choice格式,见如下例句:

    String pattern = "On {2,date,long},{0} destroyed {1} houses and caused {3,number,currency} of damage";
    注意占位符{1},尽管没有明确标注,仍然可以推测出它是number类型的。这里存在的主要问题是{1}后面的houses是复数格式,因此如果参数设置为1,则不符合英文的语法1 houses。再有就是如果参数设置为0,则更加奇怪"0 houses"。根据英文的语法规则,我们期待的格式是如果数量>=2,显示n houses,如果等于1,显示1 house,如果<=0,显示no house。如何完成这个功能呢?这里我们可以利用Java中给占位符提供的另外一种type: choice。其语法规则如下:
    一个选择格式是由一个序列对组成,每一个对包括一个下限和一个格式字符串,下限和格式字符串由一个#符号分隔,对与对之间由符号|分隔。如:
    {1,choice,0#no house|1#one house|2#{1} houses}
     如果不使用选择格式,又希望实现刚刚说到的逻辑,就需要手工进行数量的判断,再根据数量的不同定义不同的pattern,如果使用选择格式,代码将会更加清晰明确,如:
    String pattern = "On {2,date,long},{0} destroyed {1,choice,0#no house|1#one house|2#{1} houses} houses and caused {3,number,currency} of damage";
     7.    字符集:
     在进行byte和char之间的转换时,不同编码方式的字符集提供了不同的编码(encode)和解码(decode)规则,见如下代码:

1 publicclass MyTest {
2 publicstaticvoid print(ByteBuffer bb) {
3 while (bb.hasRemaining()) 4 System.out.print(bb.get() +""); 5 System.out.println(); 6 bb.rewind(); 7 } 8 9 publicstaticvoid main(String[] args) {
10 ByteBuffer bb = ByteBuffer.wrap(newbyte[] { 0, 0, 0, 0, 0, 0, 0, 11 (byte) 'a' }); 12 System.out.println("Initial Byte Buffer"); 13 print(bb); 14 //提供了几种常用的字符集 15 Charset[] csets = { Charset.forName("UTF-16LE"), 16 Charset.forName("UTF-16BE"), Charset.forName("UTF-8"), 17 Charset.forName("US-ASCII"), Charset.forName("ISO-8859-1") }; 18 for (int i =0; i < csets.length; i++) {
19 System.out.println(csets[i].name() +":"); 20 //编码显示 21 print(csets[i].encode(bb.asCharBuffer())); 22 //解码用于下一次迭代 23 csets[i].decode(bb); 24 bb.rewind(); 25 } 26 } 27 } 28 //根据指定的字符集,将数据在CharBuffer和ByteBuffer之间做转换(编码和解码) 29 publicstaticvoid main(String[] args) throws CharacterCodingException {
30 //由于有中文的存在,因此这里需要是用UTF-8的字符集,如果使用其他 31 //的西方字符集会导致encode抛出异常。 32 Charset charset = Charset.forName("UTF-8"); 33 // An engine that can transform a sequence of bytes in a specific 34 // charset into a sequence of sixteen-bit Unicode characters. 35 // from byte to unicode 36 CharsetDecoder decoder = charset.newDecoder(); 37 // An engine that can transform a sequence of sixteen-bit Unicode 38 // characters into a sequence of bytes in a specific charset. 39 // from unicode to byte 40 CharsetEncoder encoder = charset.newEncoder(); 41 ByteBuffer bbuf = ByteBuffer.allocate(1024); 42 CharBuffer cbuf = CharBuffer.allocate(1024); 43 String tmp ="HelloWorld123你好"; 44 cbuf.put(tmp); 45 cbuf.flip(); 46 //或者直接给CharBuffer赋值,如: 47 //cbuf = CharBuffer.wrap("HelloWorld123你好"); 48 //该语句相当于上面3条语句的功能。 49 50 //注:在encode内部已经调用了bbuf.flip(),如果外部重复调用,会导致后面的 51 //decode返回空值。 52 bbuf = encoder.encode(cbuf); 53 byte[] buf = bbuf.array(); 54 String s =new String(buf,charset); 55 System.out.println("ByteBuffer = "+ s); 56 //注:在decode内部已经调用了cbuf.flip(),如果外部重复调用,会导致后面 57 //打印空值。 58 cbuf = decoder.decode(bbuf); 59 System.out.println("CharBuffer = "+ cbuf.toString()); 60 }

    8.    资源包:

    经常会遇到这样的情形,我们应用程序中的大量字符串信息需要被翻译成各种不同的语言,如英文、德文等。我们常用的方式是自定义包含各种不同语言信息的文件,并通过文件名来标识其所属的语种。我们的应用程序在根据当前不同的locale来选择不同的语言资源文件。在Windows的MFC中,是通过一种被称为字符表的资源来存储这些信息的。在Java中,JDK同样提供了其自身的支持--资源包。
    和我们想象的一样,JDK也是通过将不同语言的字符串信息存放在不同的资源文件中,同时也定义了语言资源文件的文件命名规则:包名_语言_国家,如MyProgramStrings_de_DE。如果locale = new Locale("de","DE");该资源文件将会被加载。既然Java已经为我们提供了这样的方法,我们还是应该充分的利用这一规则。事实上,和我们预想的非常相似,该资源文件也是以键值对的方式存储资源信息的,如下面的德文和英文资源文件:
    File: MessageBundle_en_US.properties
    planet = Mars
    template = At {2,time,short} on {2,date,long}, we detected {1,number,integer} spaceships on the planet {0}.
   
    File: MessageBundle_de_DE.properties
    planet = Mars
    template = Um {2,time,short} am {2,date,long} haben wir {1,number,integer} Raumschiffe auf dem Planeten Mars entdeckt.
    将以上两个文件copy到工程的bin目录下,再执行下面的示例代码:

1 publicclass MyTest {
2 staticvoid displayMessage(Locale currentLocale) {
3 System.out.println("currentLocale = "+ currentLocale.toString()); 4 //getBundle的第一个参数是资源文件的前缀,后缀则根据Locale来定义。 5 ResourceBundle messages = ResourceBundle.getBundle("MessageBundle",currentLocale); 6 Object[] messageArguments = { messages.getString("planet"), 7 new Integer(7), new Date() }; 8 MessageFormat formatter =new MessageFormat(""); 9 formatter.setLocale(currentLocale); 10 formatter.applyPattern(messages.getString("template")); 11 String output = formatter.format(messageArguments); 12 System.out.println(output); 13 } 14 15 publicstaticvoid main(String[] args) {
16 displayMessage(new Locale("en", "US")); 17 displayMessage(new Locale("de", "DE")); 18 } 19 } 20 /* 输出结果如下: 21 currentLocale = en_US 22 At 9:27 PM on August 29, 2011, we detected 7 spaceships on the planet Mars. 23 currentLocale = de_DE 24 Um 21:27 am 29. August 2011 haben wir 7 Raumschiffe auf dem Planeten Mars entdeckt. 25 */

     以下示例结合了ChoiceFormat和ResourceBundle,资源文件内容如下:

    File: ChoiceBundle_en_US.properties
    noFiles = are no files
    oneFile = is one file
    multipleFiles = are {2} files
    pattern = There {0} on {1}.
   
    File: ChoiceBundle_fr_FR.properties
    noFiles = n' y a pas des fichiers
    oneFile = y a un fichier
    multipleFiles = y a {2} fichiers
    pattern = Il {0} sur {1}.
    见代码如下:

1 publicclass MyTest {
2 staticvoid displayMessages(Locale currentLocale) {
3 System.out.println("currentLocale = "+ currentLocale.toString()); 4 //1. 根据Locale的不同,获取不同的资源文件 5 ResourceBundle bundle = ResourceBundle.getBundle("ChoiceBundle",currentLocale); 6 MessageFormat messageForm =new MessageFormat(""); 7 //2. 给MessageFormat对象设定locale,便于资源文件的定位。 8 messageForm.setLocale(currentLocale); 9 //3. 设定ChoiceFormat下限部分 10 double[] fileLimits = { 0, 1, 2 }; 11 //4. 从资源文件中读取指定的key/value,之后再初始化ChoiceFormat的选择部分。 12 String[] fileStrings = { bundle.getString("noFiles"), 13 bundle.getString("oneFile"), bundle.getString("multipleFiles") }; 14 ChoiceFormat choiceForm =new ChoiceFormat(fileLimits, fileStrings); 15 //5. 根据资源文件中“pattern”键值对来定义MessageFormat的pattern部分。 16 String pattern = bundle.getString("pattern"); 17 //6. 定义MessageFormat.pattern的格式信息。 18 Format[] formats = { choiceForm, null, NumberFormat.getInstance() }; 19 messageForm.applyPattern(pattern); 20 messageForm.setFormats(formats); 21 //7. 定义和formats对应的格式参数。 22 Object[] messageArguments = { null, "XDisk", null }; 23 for (int numFiles =0; numFiles <4; numFiles++) {
24 //8. 重新设定格式参数中第0个和第2个参数的值,该值为被ChoiceFormat利用, 25 //并根据该参数值的不同选择不同的Choice字符串来替换。 26 messageArguments[0] =new Integer(numFiles); 27 messageArguments[2] =new Integer(numFiles); 28 //9. 开始格式化了。 29 String result = messageForm.format(messageArguments); 30 System.out.println(result); 31 } 32 } 33 34 publicstaticvoid main(String[] args) {
35 displayMessages(new Locale("en", "US")); 36 displayMessages(new Locale("fr", "FR")); 37 } 38 } 39 /* 输出结果如下: 40 currentLocale = en_US 41 There are no files on XDisk. 42 There is one file on XDisk. 43 There are 2 files on XDisk. 44 There are 3 files on XDisk. 45 currentLocale = fr_FR 46 Il n' y a pas des fichiers sur XDisk. 47 Il y a un fichier sur XDisk. 48 Il y a 2 fichiers sur XDisk. 49 Il y a 3 fichiers sur XDisk. 50 */

    Java不仅提供了资源包文件的方式来包含不同语言的资源信息,还提供了资源包类的方式,其命名规则和资源包的规则一致,只是扩展名由".properties"替换为".java",其内容也从键值对的配置文件改为java的代码文件。资源包中定义的类必须是扩展自ResourceBundle类,使用方式和资源包配置文件的方式完全一致。见下面的示例代码:

1 //File: SimpleResourceBundle.java  2 publicclass SimpleResourceBundle extends ResourceBundle {
3 @Override 4 protected Object handleGetObject(String key) {
5 if (key.equals("AMMessage")) 6 return"早上好"; 7 if (key.equals("PMMessage")) 8 return"晚上好"; 9 returnnull; 10 } 11 @Override 12 public Enumeration getKeys() {
13 StringTokenizer keyTokenizer =new StringTokenizer(keys); 14 return keyTokenizer; 15 } 16 private String keys ="AMMessage PMMessage"; 17 } 18 //File: SimpleResourceBundle_en_US.java 19 publicclass SimpleResourceBundle_en_US extends ResourceBundle {
20 @Override 21 protected Object handleGetObject(String key) {
22 if (key.equals("AMMessage")) 23 return"Good morning"; 24 if (key.equals("PMMessage")) 25 return"Good evening"; 26 returnnull; 27 } 28 @Override 29 public Enumeration getKeys() {
30 StringTokenizer keyTokenizer =new StringTokenizer(keys); 31 return keyTokenizer; 32 } 33 private String keys ="AMMessage PMMessage"; 34 } 35 36 //调用类代码如下: 37 publicstaticvoid main(String[] args) {
38 try {
39 //由于使用缺省的locale,因此在定义资源包类的文件时,可以不包含locale相关的后缀。 40 ResourceBundle rb = ResourceBundle.getBundle("SimpleResourceBundle"); 41 System.out.println(rb.getString("AMMessage")); 42 System.out.println(rb.getString("PMMessage")); 43 //由于给ResourceBundle的工厂方法传入了Locale参数,因此会获取US的资源包绑定类。 44 ResourceBundle rb_US = ResourceBundle.getBundle("SimpleResourceBundle",Locale.US); 45 System.out.println(rb_US.getString("AMMessage")); 46 System.out.println(rb_US.getString("PMMessage")); 47 } catch (MissingResourceException mre) {
48 mre.printStackTrace(); 49 } 50 } 51 /* 输出结果如下: 52 早上好 53 晚上好 54 Good morning 55 Good evening 56 */

    在Java中还提供了另外一种更为方便的资源包绑定类的实现方式,既直接扩展ListResourceBundle类,ListResourceBundle让你把所有资源都放到一个对象数组并提供查询功能,见如下代码:

1 //File: SimpleResourceBundle_de_DE.java  2 publicclass SimpleResourceBundle_de_DE extends ListResourceBundle {
3 public Object[][] getContents() {
4 return contents; 5 } 6 7 privatestaticfinal Object[][] contents = { 8 {
"backgroundColor",Color.black}, 9 {
"defaultPaperSize",newdouble[]{
210,297}} 10 }; 11 } 12 //File: SimpleResourceBundle_en_US.java 13 publicclass SimpleResourceBundle_en_US extends ListResourceBundle {
14 public Object[][] getContents() {
15 return contents; 16 } 17 18 privatestaticfinal Object[][] contents = { 19 {
"backgroundColor",Color.blue}, 20 {
"defaultPaperSize",newdouble[]{
216,279}} 21 }; 22 } 23 //主程序文件 24 publicstaticvoid main(String[] args) {
25 try {
26 ResourceBundle rb = ResourceBundle.getBundle("SimpleResourceBundle",Locale.GERMANY); 27 Color bg = (Color)rb.getObject("backgroundColor"); 28 double[] paperSize = (double[])rb.getObject("defaultPaperSize"); 29 System.out.println("Germany Color is "+ bg); 30 System.out.println("Germany paperSize is x = "+ paperSize[0] +"\ty = "+ paperSize[1]); 31 ResourceBundle rb_US = ResourceBundle.getBundle("SimpleResourceBundle",Locale.US); 32 bg = (Color)rb_US.getObject("backgroundColor"); 33 paperSize = (double[])rb_US.getObject("defaultPaperSize"); 34 System.out.println("US Color is "+ bg); 35 System.out.println("US paperSize is x = "+ paperSize[0] +"\ty = "+ paperSize[1]); 36 } catch (MissingResourceException mre) {
37 mre.printStackTrace(); 38 } 39 } 40 /* 输出结果如下: 41 Germany Color is java.awt.Color[r=0,g=0,b=0] 42 Germany paperSize is x = 210.0 y = 297.0 43 US Color is java.awt.Color[r=0,g=0,b=255] 44 US paperSize is x = 216.0 y = 279.0 45 */

转载于:https://www.cnblogs.com/WayneZeng/archive/2012/09/23/2698763.html

你可能感兴趣的文章
springcloud配置动态更新
查看>>
Java中数据类型转换大全(个人总结)
查看>>
为Eclipse安装主题插件
查看>>
python-Django收集主机信息json格式
查看>>
51nod 1091 线段的重叠(贪心)
查看>>
jQuery Event 模块 源码浅解
查看>>
svn使用笔记
查看>>
vue.js基础知识篇(4):过滤器、class与style的绑定2
查看>>
flex 图片旋转(解决公转和自转问题)
查看>>
函数柯里化浅解
查看>>
C# 生成pdf
查看>>
迅速理解 XML
查看>>
BZOJ 1004: [HNOI2008]Cards [Polya 生成函数DP]
查看>>
笨方法学python(本文为阅读时从此书摘录的笔记) 第四天
查看>>
Interview
查看>>
window.event对象详尽解析
查看>>
如何高效检查一个数组中是否包含某个值?
查看>>
JAVA中如何判断一个输入是数字(小数和整数)还是字符串?
查看>>
【笔记】汇编..寄存器和地址的概述
查看>>
Commons- BeanUtils学习笔记(转)
查看>>