根据数据的类型不同,国际化分为2类:静态数据国际化和动态数据的国际化。
静态数据,包括 “标题”、“用户名”、“密码”这样的文字数据。
动态数据,包括日期、货币等可以动态生成的数据。
国际化涉及到java.util.Locale和java.util.ResourceBundle类。
java.util.Locale
A Locale object represents a specific geographical, political, or cultural region.
Locale对象代表了一定的地理、政治、文化区域。
java.util.ResourceBundle
Resource bundles contain locale-specific objects. When your program needs a locale-specific resource, a String for example, your program can load it from the resource bundle that is appropriate for the current user's locale. In this way, you can write program code that is largely independent of the user's locale isolating most, if not all, of the locale-specific information in resource bundles.
ResouceBundle,由两个单词组成Resouce和Bundle,合在一起就是“资源包”的意思。ResouceBundle是包含不同区域(Locale)资源的集合,只要向ResouceBundle提供一个特定的Locale对象,ResouceBundle就会把相应的资源返回给你。
1、静态数据国际化
静态数据国际化的步骤:
(1).建立资源文件,存储所有国家显示的文本的字符串
a)文件: .properties
b)命名: 基础名_语言简称_国家简称.properties
例如: msg_zh_CN.properties 存储所有中文
msg_en_US.properties 存储所有英文
(2).程序中获取
ResourceBundle类,可以读取国际化的资源文件!
Locale类,代表某一区域,用于决定使用哪一个国际化的资源。
1.1、Locale的API
static Locale getDefault() 得到JVM中默认的Locale对象
String getCountry() 得到国家名称的简写
String getDisplayCountry() 得到国家名称的全称
String getLanguage() 得到当前语言的简写
String getDisplayLanguage() 得到语言的全称
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package com.rk.i18n.demo; import java.util.Locale; public class Demo01 { public static void main(String[] args) { //本地化对象:Locale // 封装语言、国家信息的对象,由java.util提供 // Locale locale = Locale.CHINA; // Locale locale = Locale.US; Locale locale = Locale.getDefault(); String country = locale.getCountry(); String displayCountry = locale.getDisplayCountry(); String language = locale.getLanguage(); String displayLanguage = locale.getDisplayLanguage(); System.out.println(country); // CN System.out.println(displayCountry); // 中国 System.out.println(language); // zh System.out.println(displayLanguage); // 中文 } } |
1.2、ResourceBundle的API
static ResourceBundle getBundle(String baseName,Locale locale) 获取ResourceBundle实例
String getString(String key) 根据key获取资源中的值
1.3、示例
(1)建立properties文件:msg_zh_CN.properties和msg_en_US.properties
msg_zh_CN.properties
1 2 | uname=\u59D3\u540D pwd=\u5BC6\u7801 |
msg_en_US.properties
1 2 | uname=User Name pwd=Password |
(2)代码获取
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 | package com.rk.i18n.demo; import java.util.Locale; import java.util.ResourceBundle; // 国际化 - 静态数据 public class Demo02 { public static void main(String[] args) { // 中文语言环境 Locale locale = Locale.US; // 创建工具类对象ResourceBundle ResourceBundle bundle = ResourceBundle.getBundle( "com.rk.i18n.demo.msg" , locale); // 根据key获取配置文件中的值 String uname = bundle.getString( "uname" ); String pwd = bundle.getString( "pwd" ); //输出 System.out.println(uname); System.out.println(pwd); } } |
1.4、关于ResourceBundle的资源文件properties
文件命名:基础名、语言简称
Resource bundles belong to families whose members share a common base name, but whose names also have additional components that identify their locales. For example, the base name of a family of resource bundles might be "MyResources". The family can then provide as many locale-specific members as needed, for example a German one named "MyResources_de".
文件命名:国家简称
If there are different resources for different countries, you can make specializations: for example, "MyResources_de_CH" contains objects for the German language (de) in Switzerland (CH). If you want to only modify some of the resources in the specialization, you can do so.
文件命名:默认的Resource Bundle
The family should have a default resource bundle which simply has the same name as its family - "MyResources" - and will be used as the bundle of last resort if a specific locale is not supported.
文件内容:属于同一个family的resource bundle要包含相同的items内容。
Each resource bundle in a family contains the same items, but the items have been translated for the locale represented by that resource bundle. For example, both "MyResources" and "MyResources_de" may have a String that's used on a button for canceling operations. In "MyResources" the String may contain "Cancel" and in "MyResources_de" it may contain "Abbrechen".
Java代码:获取Resource Bundle
When your program needs a locale-specific object, it loads the ResourceBundle class using the getBundle method:
ResourceBundle myResources = ResourceBundle.getBundle("MyResources", currentLocale);
2、动态数据国际化
动态国际化则主要涉及到数字、货币、百分比和日期
例如:
中文:1987-09-19 ¥1000
英文: Sep/09 1987 $100
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | package com.rk.i18n.demo; import java.text.DateFormat; import java.text.NumberFormat; import java.text.ParseException; import java.util.Date; import java.util.Locale; import org.junit.Test; public class Demo03 { // 国际化 - 动态文本 - 0. 概述 public void testI18N() { // 国际化货币 NumberFormat.getCurrencyInstance(); // 国际化数字 NumberFormat.getNumberInstance(); // 国际化百分比 NumberFormat.getPercentInstance(); // 国际化日期 // DateFormat.getDateTimeInstance(dateStyle, timeStyle, aLocale) } // 国际化 - 动态文本 - 1. 国际化货币 @Test public void testI18NCurrency() { // 模拟语言环境 Locale locale = Locale.CHINA; // 数据准备 double number = 100 ; // 工具类 NumberFormat nf = NumberFormat.getCurrencyInstance(locale); // 国际化货币 String str = nf.format(number); // 输出 System.out.println(str); } //面试题: 代码计算: $100 * 10 @Test public void testCurrency() throws ParseException { String str = "$100" ; int num = 10 ; // 1. 分析str值是哪一国家的货币 Locale locale = Locale.US; // 2. 国际化工具类 NumberFormat nf = NumberFormat.getCurrencyInstance(locale); // 3. 解析str Number number = nf.parse(str); //4.进行计算 int value = number.intValue() * num; //5.格式化输出 str = nf.format(value); System.out.println(str); } // 国际化 - 动态文本 - 2. 国际化数值 @Test public void testI18NNumber() { Locale locale = Locale.CHINA; NumberFormat nf = NumberFormat.getNumberInstance(locale); String str = nf.format( 1000000000 ); System.out.println(str); } // 国际化 - 动态文本 - 3. 国际化百分比 @Test public void testI18NPercent() { Locale locale = Locale.CHINA; NumberFormat nf = NumberFormat.getPercentInstance(locale); String str = nf.format( 0.325 ); System.out.println(str); } // 国际化 - 动态文本 - 4. 国际化日期 /* * 日期 * FULL 2015年3月4日 星期三 * LONG 2015年3月4日 * FULL 2015年3月4日 星期三 * MEDIUM 2015-3-4 * SHORT 15-3-4 * * 时间 * FULL 下午04时31分59秒 CST * LONG 下午04时32分37秒 * MEDIUM 16:33:00 * SHORT 下午4:33 * * */ @Test public void testI18NDate() { int dateStyle = DateFormat.FULL; int timeStyle = DateFormat.FULL; Locale locale = Locale.CHINA; DateFormat df = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale); String date = df.format( new Date()); System.out.println(date); } // 面试2: 请将时间值:09-11-28 上午10时25分39秒 CST,反向解析成一个date对象。 @Test public void testDate() throws ParseException { String str = "09-11-28 上午10时25分39秒 CST" ; int dateStyle = DateFormat.SHORT; int timeStyle = DateFormat.FULL; Locale locale = Locale.CHINA; // 创建DateFormat工具类,国际化日期 DateFormat df = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale); Date date = df.parse(str); System.out.println(date); } } |
3、JSP页面国际化
数值,货币,时间,日期等数据由于可能在程序运行时动态产生,所以无法像文字一样简单地将它们从应用程序中分离出来,而是需要特殊处理,有的Java培训机构讲的不错。Java 中提供了解决这些问题的 API 类(位于 java.util 包和 java.text 包中)
3.1、准备工作:建立properties资源
建立2个properties文件:message_en_US.properties和message_zh_CN.properties。
message_zh_CN.properties
1 2 3 4 | title=\u4F60\u597D\uFF0C\u8BF7\u767B\u5F55 uname=\u7528\u6237\u540D pwd=\u5BC6\u7801 submit=\u63D0\u4EA4 |
message_en_US.properties
1 2 3 4 | title=Plean Log In uname=User Name pwd=Password submit=Submit\! |
3.2、使用JSP脚本进行国际化
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 | <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> < html > < head > <% ResourceBundle bundle = ResourceBundle.getBundle("com.rk.i18n.resource.message", request.getLocale()); %> < title ><%=bundle.getString("title") %></ title > < meta http-equiv = "pragma" content = "no-cache" > < meta http-equiv = "cache-control" content = "no-cache" > < meta http-equiv = "expires" content = "0" > </ head > < body > < table border = "1" > < tr > < td ><%=bundle.getString("uname") %></ td > < td >< input type = "text" name = "uname" /></ td > </ tr > < tr > < td ><%=bundle.getString("pwd") %></ td > < td >< input type = "password" name = "pwd" /></ td > </ tr > < tr > < td ></ td > < td >< input type = "submit" value = "<%=bundle.getString(" submit") %>"/></ td > </ tr > </ table > </ body > </ html > |
3.3、使用JSTL进行国际化
JSTL标签:
核心标签库
国际化与格式化标签库
数据库标签库(没用)
函数库
<fmt:setLocale value=""/> 设置本地化对象
<fmt:setBundle basename=""/> 设置工具类
<fmt:message></fmt:message> 显示国际化文本
格式化数值:<fmt:formatNumber pattern="#.##" value="100.99"></fmt:formatNumber>
格式化日期:<fmt:formatDate pattern="yyyy-MM-dd" value="${date}"/>
需要注意的一点是:HttpServletRequest有一个方法是getLocale(),可以获取当前request中的Locale信息,在EL表达式中可以使用${pageContext.request.locale}获取
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 | <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%--引入jstl国际化与格式化标签库 --%> <%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> < html > < head > <!-- 一、设置本地化对象 --> < fmt:setLocale value = "${pageContext.request.locale }" /> <!-- 二、设置工具类 --> < fmt:setBundle basename = "com.rk.i18n.resource.message" var = "msg" /> < title >< fmt:message bundle = "${msg }" key = "title" ></ fmt:message ></ title > < meta http-equiv = "pragma" content = "no-cache" > < meta http-equiv = "cache-control" content = "no-cache" > < meta http-equiv = "expires" content = "0" > </ head > < body > < table border = "1" > < tr > < td >< fmt:message bundle = "${msg }" key = "uname" ></ fmt:message ></ td > < td >< input type = "text" name = "uname" /></ td > </ tr > < tr > < td >< fmt:message bundle = "${msg }" key = "pwd" ></ fmt:message ></ td > < td >< input type = "password" name = "pwd" /></ td > </ tr > < tr > < td ></ td > < td >< input type = "submit" value = "<fmt:message bundle=" ${msg }" key = "submit" ></ fmt:message >"/></ td > </ tr > </ table > </ body > </ html > |
格式化数值和日期
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 | <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> < html > < head > < title >格式化</ title > < meta http-equiv = "pragma" content = "no-cache" > < meta http-equiv = "cache-control" content = "no-cache" > < meta http-equiv = "expires" content = "0" > < body > <!-- 格式化金额 格式: 0.00 保留2为小数,会自动补0 #.## 保留2为小数,不自动补0 --> < fmt:formatNumber pattern = "0.00" value = "100" ></ fmt:formatNumber > < br > < fmt:formatNumber pattern = "#.##" value = "100" ></ fmt:formatNumber > < br > < fmt:formatDate pattern = "yyyyMMdd" value="<%=new Date() %>"/> < br > <% request.setAttribute("date", new Date()); %> < fmt:formatDate pattern = "yyyy-MM-dd" value = "${date }" /> < br > </ body > </ html > |