1、国际化开发概述
(1)软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相应的、符合来访者阅读习惯的页面或数据。
(2)国际化又称为 i18n:internationalization
2、合格的国际化软件
软件实现国际化,需具备哪些特征:
(1)对于程序(页面)中固定使用的文本元素,例如菜单栏、导航条等中使用的文本元素、或错误提示信息,状态信息等,需要根据来访者的地区和国家,选择不同语言的文本为之服务。
(2)对于程序动态产生的数据,例如(日期,货币等),软件应能根据当前所在的国家或地区的文化习惯进行显示。
3、固定文本元素的国际化
(1)对于软件中的菜单栏、导航条、错误提示信息,状态信息等这些固定不变的文本信息,可以把它们写在一个properties文件中,并根据不同的国家编写不同的properties文件。这一组properties文件称之为一个资源包。
(2)在JavaAPI中提供了一个ResourceBundle 类用于描述一个资源包,并且 ResourceBundle类提供了相应的方法getBundle,这个方法可以根据来访者的国家地区自动获取与之对应的资源文件予以显示。
package com.itheima.i18n;
import java.util.Locale;
import java.util.ResourceBundle;
public class Demo1 {
public static void main(String[] args) {
ResourceBundle bundle = ResourceBundle.getBundle("conf",Locale.US);
String value = bundle.getString("username");
System.out.println(value);
}
}
4、创建资源包和资源文件
(1)一个资源包中的每个资源文件都必须拥有共同的basename基名。除了基名,每个资源文件的名称中还必须有标识其本地信息的附加部分。例如:一个资源包的基名是“myproperties”,则与中文、英文环境相对应的资源文件名则为:
“myproperites_zh.properties” “myproperites_en.properties”
(2)每个资源包都应有一个默认资源文件,这个文件不带有标识本地信息的附加部分。若ResourceBundle对象在资源包中找不到与用户匹配的资源文件,它将选择该资源包中与用户最相近的资源文件,如果再找不到,则使用默认资源文件。例如:
Myproperites.properties
5、语言和国别代码
6、资源文件的书写格式
(1)资源文件的内容通常采用“关键字=值”的形式,软件根据关键字检索值显示在页面上。一个资源包中的所有资源文件的关键字必须相同,值则为相应国家的文字。
(2)并且资源文件中采用的是properties格式文件,所以文件中的所有字符都必须是ASCII字码,对于像中文这样的非ACSII字符,须先进行编码。(java提供了一个native2ascII命令用于编码)。例:
属性文件是不能保存中文的
7、编程实现固定文本的国际化
(1)加载src下properties文件
ResourceBundle bundle = ResourceBundle.getBundle(basename);
(2)读取properties文件中内容
String value = bundle.getString(key);
(3)在读取properties文件时,可以传入一个Locale 实例对象,用于代表一个特定的地理,政治、文化区域
ResourceBundle bundle =
ResourceBundle.getBundle(basename, currentLocale);
(4)如果与该locale对象匹配的资源包子类找不到。一般情况下,则选用操作系统默认资源文件予以显示
(5)如果与该locale对象匹配的资源包子类找不到。一般情况下,则选用操作系统默认资源文件予以显示
(6)案例:制作国际化登陆页面
ResourceBundle bundle = ResourceBundle.getBundle("test", new Locale("ar"));
String prop = bundle.getString("prop1");
System.out.println(prop);
<fmt:setLocale value='en'/>
<fmt:setBundle basename="test" scope="page" var="t"/>
<fmt:message key="prop1" bundle="${t}"></fmt:message>
8、DateFormat类(国际化日期)
(1)DateFormat 类可以将一个日期/时间对象格式化为表示某个国家地区的日期/时间字符串。
(2)DateFormat 类除了可按国家地区格式化输出日期外,它还定义了一些用于描述日期/时间的显示模式的 int 型的常量,包括FULL, LONG, MEDIUM, DEFAULT, SHORT,实例化DateFormat对象时,可以使用这些常量,控制日期/时间的显示长度。
(3)Date date = new Date();
// 只需要显示 日期
// style 就可以 FULL LONG MEDIUM SHORT
DateFormat df1 = DateFormat.getDateInstance(DateFormat.FULL,
Locale.CHINA);
System.out.println(df1.format(date));
// 只需要显示时间
DateFormat df2 = DateFormat.getTimeInstance(DateFormat.LONG,
Locale.CANADA);
System.out.println(df2.format(date));
// 既需要日期也需要时间
DateFormat df3 = DateFormat.getDateTimeInstance(DateFormat.FULL,
DateFormat.FULL, Locale.GERMAN);
System.out.println(df3.format(date));
9、实例化DateFormat类
实例化DateFormat类有九种方式,以下三种为带参形式,下面列出的三种方式也可以分别不带参,或只带显示样式的参数。
(1)getDateInstance(int style, Locale aLocale):以指定的日期显示模式和本地信息来获得DateFormat实例对象,该实例对象不处理时间值部分。
(2)getTimeInstance(int style, Locale aLocale):以指定的时间显示模式和本地信息来获得DateFormat实例对象,该实例对象不处理日期值部分。
(3)getDateTimeInstance(int dateStyle, int timeStyle, Locale aLocale):以单独指定的日期显示模式、时间显示模式和本地信息来获得DateFormat实例对象。
package com.itheima.i18n;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import org.junit.Test;
public class DataFormatTest {
@Test
//将Date对象转换为指定样式指定语言环境的字符串时间表示形式
public void test1(){
Date date = new Date();
DateFormat format = DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL, Locale.CHINA);
String dateStr = format.format(date);
System.out.println(dateStr);
}
//2013年7月27日 星期六 下午03时57分45秒 CST
@Test
public void test2() throws ParseException{
String dateStr = "2013年7月27日 星期六 下午03时57分45秒 CST";
DateFormat format = DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL,Locale.CHINA);
Date date = format.parse(dateStr);
System.out.println(date);
}
@Test
public void test3() throws ParseException{
String dateStr = "2013~~~09@@@@09,16?00+00";
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy~~~MM@@@@dd,HH?mm+ss");
Date date = dateFormat.parse(dateStr);
System.out.println(date);
}
@Test
public void test4(){
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("MM~~~yyyy~~~~dd:mm~~~ss+HH");
String dateStr = dateFormat.format(date);
System.out.println(dateStr);
}
}
10、NumberFormat类
(1)实例化NumberFormat类时,可以使用locale对象作为参数,也可以不使用,下面列出的是使用参数的。
(2)getNumberInstance(Locale locale):以参数locale对象所标识的本地信息来获得具有多种用途的NumberFormat实例对象
(3)getIntegerInstance(Locale locale):以参数locale对象所标识的本地信息来获得处理整数的NumberFormat实例对象
(4)getCurrencyInstance(Locale locale):以参数locale对象所标识的本地信息来获得处理货币的NumberFormat实例对象
(5)getPercentInstance(Locale locale):以参数locale对象所标识的本地信息来获得处理百分比数值的NumberFormat实例对象
public void demo4() {
// 请将0.78654321,输出百分比格式,保留两位小数
double d = 0.78654321;
double d2 = 0.543;
NumberFormat numberFormat = NumberFormat.getPercentInstance();
numberFormat.setMaximumFractionDigits(2);
numberFormat.setMinimumFractionDigits(2);
System.out.println(numberFormat.format(d));
System.out.println(numberFormat.format(d2));
}
public void demo3() throws ParseException {
// 请将整数198,输出为货币形式:$198,并将¥198反向解析成整数198。
int n = 198; // 输出美元
NumberFormat format1 = NumberFormat.getCurrencyInstance(Locale.US);
format1.setMaximumFractionDigits(0);// 不要小数
System.out.println(format1.format(n));
String s = "¥198";
NumberFormat format2 = NumberFormat.getCurrencyInstance(Locale.CHINA);
Number m = format2.parse(s);
System.out.println(m);
}
package com.itheima.i18n;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
import org.junit.Test;
public class NumberFormatTest {
//100 ---> ¥100
@Test
public void test1(){
double num = 100.00;
NumberFormat format = NumberFormat.getCurrencyInstance(Locale.US);
String str = format.format(num);
System.out.println(str);
}
//¥100.00 -- > 100.00
@Test
public void test2() throws ParseException{
String str = "¥100.00";
NumberFormat format = NumberFormat.getCurrencyInstance(Locale.CHINA);
double num = format.parse(str).doubleValue();
System.out.println(num);
}
//99.1% --0.991
@Test
public void test3() throws ParseException{
String str = "99.1%";
NumberFormat format = NumberFormat.getPercentInstance(Locale.CHINA);
double num = format.parse(str).doubleValue();
System.out.println(num);
}
//0.8812 ---> 88.12%
@Test
public void test4(){
double num = 0.8812;
NumberFormat format = NumberFormat.getPercentInstance(Locale.GERMAN);
format.setMinimumFractionDigits(3);
String str = format.format(num);
System.out.println(str);
}
}
11、MessageFormat(动态文本)
(1)如果一个字符串中包含了多个与国际化相关的数据,可以使用MessageFormat类对这些数据进行批量处理。
(2)例如:
At 12:30 pm on jul 3,1998, a hurricance destroyed 99 houses and caused $1000000 of damage
以上字符串中包含了时间、数字、货币等多个与国际化相关的数据,对于这种字符串,可以使用MessageFormat类对其国际化相关的数据进行批量处理。
(3)MessageFormat 类如何进行批量处理呢?
1.MessageFormat类允许开发人员用占位符{0}{1}{2}…替换掉字符串中的敏感数据(即国际化相关的数据)。
2.MessageFormat类在格式化输出包含占位符的文本时,messageFormat类可以接收一个参数数组,以替换文本中的每一个占位符。
12、格式化模式字符串
(1)模式字符串:
On {0}, a hurricance destroyed { 1} houses and caused { 2} of damage.
(2)MessageFormat类
默认Locale
format(String pattern, Object... arguments) static
pattern 模式字符串
arguments 参数数组
自定义Locale
MessageFormat(String pattern, Locale locale)
format(Object obj)
String s = "At {0} on {1}, a hurricance destroyed {2} houses and caused {3} of damage";
Object[] args = { "12:30 pm", "jul 3,1998", "99", "$1000000" };
System.out.println(MessageFormat.format(s, args));
13、模式字符串与占位符
位符有三种方式书写方式:
(1){argumentIndex}: 0-9 之间的数字,表示要格式化对象数据在参数数组中的索引号
(2){argumentIndex,formatType}: 参数的格式化类型
(3){argumentIndex,formatType,FormatStyle}: 格式化的样式,它的值必须是与格式化类型相匹配的合法模式、或表示合法模式的字符串。
formatType:
number
date
time
choice
fomatStyle
short
medium
long
full
integer
currency
percent
Subformatpattern
String pattern = "At {0,time,short} on {0,date,medium},a destroyed {1}
houses and caused {2,number,currency} of damage."
Calendar calendar = Calendar.getInstance();
calendar.set(1998, 6, 3, 12, 30, 0);
Date date = calendar.getTime();
Object []msgArgs = {date, 99, 1000000};
String result = MessageFormat.format(pattern,msgArgs); // 默认国家
System.out.println(result);
// 动态文本高级应用
String s = "At {0,time,short} on {0,date,medium}, a hurricance destroyed {1,number,integer} houses and caused {2,number,currency} of damage";
// 第一个参数 日期对象12:30 pm on jul 3,1998
Calendar calendar = Calendar.getInstance();// 日历类
// 所有日期月份从0开始
calendar.set(1998, 6, 3, 12, 30, 0);
Date date = calendar.getTime();
// 第二个参数 99
int n = 99;
// 第三个参数 $1000000
int m = 1000000;
// 指定locale 是美国
MessageFormat messageFormat = new MessageFormat(s, Locale.US);
System.out.println(messageFormat.format(new Object[] { date, n, m }));
package com.itheima.i18n;
import java.text.MessageFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import org.junit.Test;
public class MessageFormatTest {
//At 12:30 pm on jul 3,1998, a hurricance destroyed 99 houses and caused $1000000 of damage
@Test
public void test1(){
String str = "At {0,date,full} {1,time,full}, a hurricance destroyed {2,number} houses and caused {3,number,currency} of damage";
MessageFormat format = new MessageFormat(str,Locale.CHINA);
Calendar c = Calendar.getInstance();
c.set(1998, 6, 3, 12, 30, 0);
Date date = c.getTime();
Object [] objs = {date,date,99,1000000};
String result = format.format(objs);
System.out.println(result);
}
}