笔记:国际化

国际化英文单词为:Internationalization,又称I18N,I为因为单词的第一个字母,18为这个单词的长度,而N代表这个单词的最后一个字母。国际化又称本地化(Localization,L10N)。

Java国际化主要通过如下3个类完成

  • java.util.ResourceBundle:用于加载一个资源包
  • java.util.Locale:对应一个特定的国家/区域、语言环境。
  • java.text.MessageFormat:用于将消息格式化

为实现程序的国际化,必须提供程序所需要的资源文件。资源文件的内容由key-value对组成,资源文件的命名可以有3种格式:

  • basename_language_country.properties
  • basename_language.properties
  • basename_properties

若资源文件包含非西方字符,则需要用JDK自带的工具来处理:native2ascii,这个工具的语法格式如下:

native2ascii 资源文件名 目标资源文件名

如:

native2ascii mess_zh_XXX.proerties mess_zh_CN.proerties

Locale类可获取各国区域环境(如:Locale.ENGLISH、Locale.CHINESE,这些常量返回一个Locale实例),也可以获取当前系统所使用的区域语言环境,也可以使用语言和区域来创建Locale对象,Java的本地语言使用的时国际化标准组织(ISO)所定义的编码,本地语言由小写的两个字母的代码表示,遵循ISO-639-1;国家代码由大写的两个字母的代码组成,遵循ISO-3166-1,下表为常用的代码:


语言


代码


国家


代码


Chinese


zh


China


CN


English


en


United
States


US


Japanese


ja


Japan


JP

可以使用Locale的静态方法 getAvailableLocales 来获取所支持的语言和国家,该方法返回一个Locale数组,该数组里包含了java所支持的语言和国家,代码如下:

Locale[] availableLocales = Locale.getAvailableLocales();

????????for (Locale l : availableLocales) {

??????????????System.out.println("Locale DisplayName=" + l.getDisplayName() + " Country=" + l.getCountry() + " Language="

+ l.getLanguage());

}

  1. 数字格式

    数字和货币的格式时高度依赖与Locale的,Java类库提供了一个格式器(formatter)对象的集合,可以对java.text包中的数字值进行格式化和解析,可以通过下面的步骤来对特定的Locale的数字进行格式化:

  • 获取Locale对象
  • 使用工厂方法获取格式器对象,工厂方法时
    NumberFormat
    类的静态方法,接受一个Locale
    类型的参数,有三个工厂方法:getNumberInstance(数字)、getCurrencyInstance(货币)

    getPercentInstance(百分比)
  • 使用这个格式器对象来完成格式化和解析工作

格式化示例代码:

Locale deLocale = new
Locale("de", "DE");

NumberFormat currFmt = NumberFormat.getCurrencyInstance(deLocale);

double amt = 123878.34;

String formatResult = currFmt.format(amt);

System.out.println("amt=" + amt + " Format=" + formatResult);

如果想要读取一个按照某个Locale的惯用法而输入或存储的数字,那边就需要使用
parse
方法。

解析示例代码:

Localede Locale=newLocale("de","DE");

NumberFormat currFmt=NumberFormat.getCurrencyInstance(deLocale);

Number input=currFmt.parse(formatResult);

double parseAmt=input.doubleValue();

System.out.println("FormatAmt="+formatResult+"ParseAmt="+parseAmt);

  1. 日期和时间

    当格式化日期和时间时,需要考虑4个与Locale相关的问题,例如:月份和星期应该用本地语言来表示;年月日的顺序要符合本地习惯;公历可能不是本地首选的日期表示方法;必须要考虑本地时区。Java
    使用
    DateFormat
    类来处理这些问题,和
    NumberFormat
    类很类似,调用
    DateFormat
    类的静态方法,并传入
    Locale
    来实例化,还需要设置日期或时间的格式化值,DateFormat
    有如下三个工厂方法:

    DateFormat.getDateInstance(dateStyle,loc);

    DateFormat.getTimeInstance(timeStyle,loc);

    DateFormat.getDateTimeInstance(dateStyle,timeStyle,loc);

    其日期和时间的风格使用
    DateFormat
    的静态常量来表示,常用的静态常量如下:

    DateFormat.DEFAULT

    DateFormat.FULL

    DateFormat.LONG

    DateFormat.MEDIUM

    DateFormat.SHORT

    示例代码如下:

    String fmt = "";

    Date nowDate = new
    Date();

    DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, zhLocale);

    fmt = dateFormat.format(nowDate);

    System.out.println("Short style date string " + fmt);

    ?
    ?

    dateFormat = DateFormat.getTimeInstance(DateFormat.MEDIUM, zhLocale);

    fmt = dateFormat.format(nowDate);

    System.out.println("MEDIUM style time string " + fmt);

    ?
    ?

    dateFormat = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, zhLocale);

    fmt = dateFormat.format(nowDate);

    System.out.println("FULL style date FULL style time string " + fmt);

    如果要解析一个用户输入的日期,可以使用
    DateFormat
    类的
    parse
    方法,但其输入的格式必须和创建
    DateFormat
    对象设置的风格一致,如果不一致则会抛出
    IllegalArgumentException
    异常,默认支持宽松的转换,比如日期
    2017年2月30日,会被解析为 2017年3月2日,如果希望关闭宽松的转换,需要设置 lenient 标识,示例代码如下:

    dateFormat.setLenient(false);

    Date convertDate = dateFormat.parse(fmt);

    System.out.println("parse string " + fmt + " convertDate " + convertDate);

  2. 字符串排序

    Java
    中的排序时用Unicode字符来决定顺序的,比如小写字母的Unicode值比大写的大,有重音符的字母的值甚至更大,这样将使结果失去意义,如果需要定义排序的强度,可以使用Locale对象来创建
    Collator
    类,该类继承了
    Comparator接口,因此可以将该对象传递给
    Collections.soft
    方法来进行排序,示例代码如下:

    List<String> list = new LinkedList<>();

    list.add("America");

    list.add("Zulu");

    list.add("able");

    list.add("zebra");

    ?
    ?

    Collator collator = Collator.getInstance(zhLocale);

    // 设置排序强度

    collator.setStrength(Collator.PRIMARY);

    Collections.sort(list, collator);

    可以设置排序强度来选择不同的排序行为,字符间的差别可以被分为首要的(primary)、其次的(secndary)和再次的(tertiary)。比如,在英语中,A 和 Z 之间的差异被归类为首要的;A 和 ?
    (重音符)之间的差异是其次的;A 和 a 之间是再次的,可以使用方法 setStrength 来设置排序强度,Collator.PRIMARY 表示首要的、Collator.SECONDARY
    表示其次的、
    Collator.TERTIARY
    表示再次的,而Collator.IDENTICAL 则表示不允许有任何差异。

    偶尔我们会碰到一个字符或字符序列在描述成Unicode时,可以有多种方式,例如,字母序列"ffi"可以用代码U+FB03描述成单个字符"拉丁小连字ffi",Unicode 标准对字符串定义了四种范式形式:D、KD、C和KC,其中 D 和 KD 时用于排序的,在范化形式 D 重,重音字符被分解为基字符和组合重音符;范化形式 KD 更进一步将兼容性字符也进行了分解,例如 ffi 连字符或商标符号TM,我们可以选择排序器所使用的范化程度:Collator.NO_DECOMPOSITION表示不对字符串做任何范化;Collator.CANONICAL_DECOMPOSITION
    使用范化形式 D;Collator.FULL_DECOMPOSITION 使用范化形式 KD。可以使用方法 setDecomposition 来设置分解模式

  3. 消息格式化

    Java
    类库中有一个
    MessageFormat
    类,用来格式化带变量的文本,就像这样:"今天
    {0} 是个好日子,{1} 公司给我发了工资 {2} 元",括号中的数字是一个占位符,可以用实际的名字和值来替换他,使用静态的 MessageFormat.format 方法,该方法使用当前系统的 Locale 对值进行格式化,如果需要用指定的 Locale 来进行格式化,需要使用 MessageFormat 实例的 format 方法,示例代码如下:

    String mfString = "今天 {0} 是个好日子,{1} 公司给我发了工资 {2} 元";

    String formatString = MessageFormat.format(mfString, new
    Date(), "汇元1", 50000);

    System.out.println(formatString);

    ?
    ?

    MessageFormat mf = new
    MessageFormat(mfString, zhLocale);

    formatString = mf.format(new Object[]{new Date(), "汇元2", 50000});

    System.out.println(formatString);

    如果还想在指定占位符的同时设置类型和样式,可以按照如下格式:

    String mfString = "今天 {0,date,long} 是个好日子,{1} 公司给我发了工资 {2,number,currency} 元";

    mf = new
    MessageFormat(mfString, zhLocale);

    formatString = mf.format(new Object[]{new Date(), "汇元3", 50000});

    System.out.println(formatString);

    输出内容

    今天 2017年5月26日 是个好日子,汇元3 公司给我发了工资 ¥50,000.00 元

    占位符索引后面可以跟一个类型和样式,之间用逗号隔开,类型可以是number、time、date、choice,如果类型是 number 则样式有 integer、currency、percent;如果类型是 time 或 date,那么样式有 short、medium、long、full 或者是一个日期模式(yyyy-MM-dd);choice
    表示希望消息跟随占位符的值而变化,选项格式是由一个序列对构成的,每个序列对包含一个下限和一个格式化字符串,下限和字符串使用#号分隔,对于对之间用 | 分隔,示例如下:

    mfString = "今天 {0,date,yyyy-MM-dd} 是个好日子,{1,choice,0#汇元|1#汇元1|2#汇元2} 公司给我发了工资 {2,number,currency} 元";

    mf.applyPattern(mfString);

    formatString = mf.format(new Object[]{new Date(), 1, 50000});

    System.out.println(formatString);

    可以使用 < 符号或

    符号
    来替换
    #
    ,则表示值小于或者小于等于下限值,示例代码如下:

    // choice说明: 这个表示 小于 1000
    并且
    1001-5000 的使用"可怜" ,5001-50000 的使用"不够",50001 以上为"正好"

    mfString = "今天 {0,date,yyyy-MM-dd} 是个好日子,{1} 公司给我发了工资 {2,number,currency} 元,{2,choice,1000<可怜|5000<不够|50000<正好}";

    mf.applyPattern(mfString);

    formatString = mf.format(new Object[]{new Date(), "汇元4", 60000});

    System.out.println(formatString

    输入内容

    今天 2017-05-26 是个好日子,汇元4 公司给我发了工资 ¥60,000.00 元,正好

  4. 资源包

    当本地化一个应用时,可能会有大量的消息字符串、按钮标签和其他的东西需要被翻译,为了能灵活的完成这项任务,你会希望外部定义消息字符串,通常称之为资源(resource),翻译人员不需要接触程序源代码就可以很容易的编辑资源文件,在Java
    中使用属性文件来设定字符串资源,并未其他类型的资源实现相应的类。

    当本地化一个应用时,会制造出很多资源包(resource
    bundle),每一个包都是一个属性文件或者一个描述了玉locale相关的项的类,对于每一个包,都要为所有你想要支持的locale提供相应的版本,并需要对这些包使用一种统一的命名规则,例如,为中国定义的资源放在一个名为"包名_zh_CN"的文件中,而为所有使用中文简体的国家所共享的资源则放在名为"包名_zh"的文件中,一般来说,使用

    包名_语言_国家

    来命名所有和国家相关的资源,使用

    包名_语言

    来命名所有和语言相关的资源,最后,作为后备,可以把默认资源放到一个没有后缀的文件中,可以使用下面的代码加载一个包:

    ResourceBundle resourceBundle = ResourceBundle.getBundle(bundleName, locale);

    getBundle
    方法加载包的顺序如下:

    1. 包名_当前locale的语言_当前locale的国家_当前locale的变量
    2. 包名_当前locale的语言_当前locale的国家
    3. 包名_当前locale的语言
    4. 包名_默认locale的语言_默认locale的国家_默认locale的变量
    5. 包名_默认locale的语言_默认locale的国家
    6. 包名_默认locale的语言
    7. 包名
    8. 抛出
      MissingResourceException
      异常

    一旦getBundle
    方法定位了一个包,比如,"包名_zh_CN" ,他还会继续查找"包名_zh"和"包名"这二个包,如果这些包也存在,他们在资源层次中就称为了"包名_zh_CN"的父包,以后查找资源的时候,如果在当前包中没有找到,就会去查找其父包。

    1. 属性文件

      属性文件是为了提供字符串资源常用的文件,每行存放一个键-值对的文本文件,比如,MyProgramStrings.properties 就是一个属性文件,存储属性文件都是ASCII文件,然后可以使用
      native2ascii
      工具来产生MyProgramStrings_语言_国家.properties 文件,示例如下:

      native2ascii MyProgramStrings.properties MyProgramStrings_zh_CN.properties

      要查找一个具体的字符串,可以调用:

      String resourceText= resourceBundle.getString("show.text");

      示例资源文件内容:

      show.text=\u8fd9\u4e2a\u662f\u8d44\u6e90\u6587\u4ef6\u7684\u5185\u5bb9

    2. 包类

      为了提供字符串以外的资源,需要定义类,必须继承
      ResourceBundle
      类(简单的方法是继承
      ListResourceBundle类),应该使用标准的命名规则来命名类,比如:

      MyProgramResource.java

      MyProgramResource_zh.java

      MyProgramResource_zh_CN.java

      可以使用与加载属性文件相同的
      getBundle
      方法来加载这个类,其
      bundleName

      资源包类的完整命名(包名和类名):

      ResourceBundle resourceBundle1Class =

      ????????????????????????????????ResourceBundle.getBundle("locale.MyProgramResource", Locale.SIMPLIFIED_CHINESE);

      要查找一个字符串或其他类型资源可以调用:

      resourceText = resourceBundle1Class.getString("resourceClass.show.text");

      Object resourceObj = resourceBundle1Class.getObject("resourceClass.show.obj");

      如果一个Key同时存在属性文件和包类,则包类的优先。

      ?
      ?

时间: 2024-10-20 01:43:54

笔记:国际化的相关文章

iOS 读书笔记-国际化

吐槽一下:国际化-我想说学习的这个工程好痛苦. 或许是百度的原因,总是不能找到自己想要东西.找到的内容不是不详细就是时间有点久了.让我这种小白很头痛. 下面记录一下整个过程. 国际化是什么 ? 说白了就是在不同的语言上APP上显示不同的文字,也就是说如果你是美国人系统语言是英语,那么APP就显示英语,如果你是中国人,那么APP就显示汉语. 我们首先来做国际化准备. 为了方便我们下面的演示,只添加一个简体中文就行了. 跳出下面界面 点击finish就行了,至于我们上面选对号的两个文件我们下面说.

java学习笔记—国际化(41)

国际化:internationalization即I18N. 举例: 本科高校的网站,一般的都有中文和英文两种页面风格.因此将这种根据不同用户群体显示不同的页面风格的方式称之为页面的国际化. 翻译 VS 国际化 翻译:Chrome 国际化:主要做的是页面的显示信息的国际化,至于文件等其他的资源是无法进行国际化. 1  国际化的原理 获取用户的本地信息 Locale通过静态属性获取区域对象. 准备不同区域国家的需要显示的资源 全部使用properties配置文件进行实现.但是文件名需要按照指定的规

ZendFramework2学习笔记 国际化、多语言

ZF2的网站语言配置项是module.config.hp中的"translator"项: <span style="font-size:18px;"> 'translator' => array( 'locale' => 'zh_CN',//中文简体是zf_CN,英文是en_US 'translation_file_patterns' => array( array( 'type' => 'gettext', 'base_dir'

开源TMS团队协作web系统

TMS(Teamwork Management System) TMS 是一款开源的团队协作(沟通.博文.国际化翻译)Web 系统(响应式界面设计.移动端适配). oschina推荐上榜的国产软件: https://www.oschina.net/p/tmsgitosc repo: https://git.oschina.net/xiweicheng/tmsgithub repo: https://github.com/xiweicheng/tms 试玩: http://tms000.sh1.n

.Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化

原文:.Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化 我们知道资源被注册到R.java我们通过R.java就可以读取到界面中的组件.跟我们.net一样,通过ID来读取组件 知识点: 通过R.java读取组件 MainActivity.java通过findViewById方法查找组件 在Layout中用@string查找字符串,这个跟我们MVC中国际化基本相识,通过xml这种资源引用进行中文和英文切换 加入中文和英文本地化 双击fragment_main.xml设计视图

[原创]java WEB学习笔记51:国际化 概述,API 之 locale类,dataFormat类,numberFormat类, MessageFormat类,ResourceBundle 类

本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 ---------------------------------

[原创]java WEB学习笔记52:国际化 fmt 标签,国际化的总结

本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 ---------------------------------

笔记02 文件上传、文件下载、类型转换器、国际化的支持

Struts2的上传 1. Struts2默认采用了apache commons-fileupload  2. Struts2支持三种类型的上传组件 3. 需要引入commons-fileupload相关依赖包 * commons-io-1.3.2.jar * commons-fileupload-1.2.1.jar 4. 表单中需要采用POST提交方式,编码类型需要使用:multipart/form-data 5. Struts2的Action     取得文件名称->>规则:输入域的名称+

SPRING IN ACTION 第4版笔记-第六章RENDERING WEB VIEWS-003- SPRING的GENERAL TAG LIBRARY简介及用&lt;s:message&gt;和ReloadableResourceBundleMessageSource实现国际化

一. SPRING支持的GENERAL TAG LIBRARY 1. 二.用<s:message>和ReloadableResourceBundleMessageSource实现国际化 1.配置ReloadableResourceBundleMessageSource,它能it has the ability to reload message properties without recompiling or restarting the application. 1 package spi