Mestar 国际化方案和整改指导

1 Java 国际化方案

1.1. 原理介绍

Java 程序的国际化思路是将程序中的标签、提示信息等放在资源文件中,程序需要支持国家 / 语言环境,则必须提供对应的资源文件。资源文件是 key-value 对,每个资源文件中的 key 不变,但 value 随不同的国家 / 语言变化。

 

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

Java.util.ResourceBundle: 用于加载资源包,即对应的资源文件
Java.util.Locale: 本地化对象,对应一个特定的语言环境、国家 / 地区,包含“语言类型”和“国家 / 地区的类型。

Java.text.MessageFormat: 用于将消息格式化,用户动态消息传入。

 

资源文件: 为了实现程序的国际化,必须先提供程序所需要的资源文件。资源文件的内容是很多的 key-value 对,其中 key 是程序使用的部分,而 value 是程序的显示部分。资源文件的命名可以是如下 3 种形式:
  baseName_language_country.properties
  baseName_language.properties
  baseName.properties

其中 baseName 是资源文件的基本名称,用户可以自由定义,而 language 和 country 都不可随意变化,必须是 Java 所支持的语言和国家。事实上,Java 不可能支持所有的国家和语言,可以通过 Locale 类的 getAvailableLocale 方法获取支持的,该方法返回一个 Locale 数组,该数组中包含了所有支持的国家和语言。

Locale [] locales = Locale.getAvailableLocales();

 

小知识:

i18N ,现在才知道原来 i18N 就是 Internationalization,因为以 i 开头,以 N 结尾,共 18 个字母,也就是国际化的意思。

 

1.2. 操作过程及代码示例:

(1)、首先编写两个资源文件,例如:
  resource_zh_CN.properties
title= 标题

resource_en_US.properties
title=title

(2)、中文的可以使用 jdk 的 native2ascii 命令进行转码 Unicode 编码。

命令格式:native2ascii [-reverse] [-encoding encoding] [inputfile [outputfile]]

示例: native2ascii resource_zh_CN.properties teme.properties,然后在将转好的编码拷贝替换到 resource_zh_CN.properties, 替换后是:
title=\u6807\u9898

(3)、java 代码实现

Locale locale = Locale.getDefault();

// 可以使用 Local 的常量设置具体的语言环境 

//Locale locale = Locale.US; 

// 根据地区不同加载不同的资源文件 

ResourceBundle rb = ResourceBundle.getBundle(“resource”, locale); 

// 根据 key 获得 value 值 

String title = rb.getString(“title”); 

注意:由于 ResourceBundle**** 内部的缓存机制,修改资源文件需要重启进程。

(4)、占位符实现

以上在资源文件配置的消息都是简单的消息,假如消息中含有参数,即有参数占位,我们需要使用 MessageFormat 类的 format 方法, 用后面多个参数值填充前面 pattern 字符串,其中 pattern 字符串就是一个带占位符的字符串:

format(String pattern,Object… values)

例如下面消息:
英文:hello=Hello,{0}!Today is {1}.
中文:hello= 你好,{0}! 今天是 {1}.

Locale locale = Locale.getDefault(); 

ResourceBundle rb = ResourceBundle.getBundle(“resource”, locale);

String hello = rb.getString(“hello”); 

String result = MessageFormat.format(hello, “Bob”,new Date()); 

 

  1. Struts 2 标签化的国际化方案
    ====================

2.1. JSP 方案

2.1.1. fmt 标签库原理

JSP 使用 JSTL 辅助标签库 (fmt) 支持国际化功能,这些标记利用在 java.util 和 java.text 包中实现的 Java 语言的国际化 API。

JSP 将文件中的字符串信息提取出来,放置到 properties 文件中。我们可以为不同语言环境定义不同的属性文件,如 welcome.properties(英语 / 默认)、welcome_zh_CN.properties(简体中文) 等。

HTTP 协议通过 Accept-Language 请求头将本地化信息从浏览器传递至服务器。Servlet 规范通过 javax.servlet.ServletRequest 类的 getLocale()和 getLocales() 方法自动地利用 HTTP 协议的这一功能。JSTL fmt 库中的定制标记又会利用这些方法来自动地确定用户的语言环境,从而相应地调整它们的输出。另外,我们也可以显式的定义页面的语言环境。

 

2.1.2. fmt 使用的要点说明:

(a) 引入 fmt 库:<%@ taglib prefix=“fmt” uri=“http://java.sun.com/jstl/fmt” %>

(b) 设置语言环境:<fmt:setLocale value=“zh_CN” scope=“application” /> 。可以使用 Accept-Language 请求头的语言环境,也可以通过显式设置供用户手动切换语言环境

(c) 绑定资源文件:<fmt:bundle basename=“resources.welcome”> 。注意:资源文件一定要放置在 WEB-INF/classes 目录下

(d) 从资源文件中获取指定 key 的信息:<fmt:message key=“gobs”/>

2.1.3. fmt 标签示例

<%@taglib prefix=“fmt” uri=“http://java.sun.com/jstl/fmt” %>  

<%@page contentType=“text/html” pageEncoding=“UTF-8”%>  

**  

  

    fmt:setLocale** value="en_US" scope="application" **/  

    fmt:bundle** basename="resources.welcome"**  

          

            <meta http-equiv=“Content-Type” content=“text/html; charset=UTF-8”>

            <a href="fmt:message** key="title"**/">fmt:message** key="title"**/</a>  

          

        <body >  

          <Span style=“font-size:16px”>

** fmt:message** key="description"**/**

** **  

  

** </fmt:bundle>**  

  

 

2.2. Struts 2 方案

Struts 2 国际化也是建立在 Java 国际化的基础之上,一样也是通过提供不同国家 / 语言环境的消息资源,然后通过 ResourceBundle 加载指定 Locale 对应的资源文件,再取得该资源文件中指定 key 对应的消息,整个过程与 Java 程序的国际化完全相同,只是 Struts2 框架对 Java 程序国际化进行了进一步封装,从而简化了应用程序的国际化。

 

2.2.1. Struts 2 中加载全局资源文件

Struts 2 提供了很多加载国际化资源文件的方式,最简单. 最常用的就是加载全局的国际化资源文件,加载全局的国际化资源文件的方式通过配置常量来实现。不管在 struts.xml 文件中配置常量,还是在在 struts.properties 文件中配置常量,只需要配置 struts.custom.i18n.resources 常量即可。

2.3. Struts 2 中语言及编码设置

同样,struts 中的语言设置也只需要配置 struts 常量:struts.locale,当此常量未配置时读取操作系统默认语言。但是 Struts 在每一个 action 中会按照如下顺序读取 local

url 中 request_locale 查询参数 -> session 中 WW_TRANS_I18N_LOCALE 变量 -> Accept-Language 请求头 ->struts 配置文件中 struts.locale 变量

代码详解:

I18nInterceptor.java line:119

public String intercept(ActionInvocation invocation)

 

ActionContext.java line:225

public Locale getLocale()

2.4. Struts 2 访问国际化资源

Struts2 即可以在 JSP 页面中通过标签输出国际化消息,也可以在 Action 类中输出国际化消息。

1) 为了在 JSP 页面中输出国际化消息,可以使用 Struts2 标签, 在标签中指定了国际化资源文件中的 key.

示例:
<s:text name=“login.title”></s:text>

<s:textfield name=“username” key=“login.username”></s:textfield>

还可以输出带占位符的信息。如,有一个 login.welcome = 你好 {0},那么可以用下面这种方式来显示:

<s:text name=“login.welcome”><s:param><s:property value=“username”/></s:param></s:text>

 

2) 为了在 Action 类中访问国际化消息, 可以使用 ActionSupport 类的 getText 方法, 该方法可以接受一个 name 参数, 该参数指定了国际化资源文件中的 key,该方法有多个重载版本可以使用,适用于不同输出要求。

注意:默认所有的 action类继承自ActionSupport**,可以直接使用该方法。**

示例:

getText(“login.username”);

还可以使用带占位符的信息。如,有一个 login.welcome = 你好 {0},那么可以用下面这种方式来显示:

String params[] = {“张三”};

String welcome = getText(“login.welcome”, params);

  

  1. MESTAR 国际化方案扩展
    ================

3.1. 语言配置参数

当前语言获取的优先级:request parameter > cookie/session > application default

详细说明:

request 参数 request_lang:表示语言切换。

cookie 参数 lang:表示当前正在使用的语言,是真正使用的语言参数。

为什么使用 cookie? cookie 具有延续性,只依赖浏览器环境,不依赖后台,即使用户退出或 session 超时依然有效。

application 参数 lang:系统默认语言,非 http 请求环境下使用。

 

代码详解

3.2. 资源文件存储

平台自动加载 resources\i18n 目录下所有文件.properties 文件,文件名可自定义,平台和产品分析。包含两类文件,一:普通 key=value 资源文件,中英文分开保存,中文需使用 Unicode 编码;二:菜单翻译映射文件,保存内容格式为 中文 = 英文,用于菜单名直接翻译成英文。

 

代码详解

 

3.3. 资源解析过程及 java api

3.3.1. java 代码资源获取 API

方式一:

Action 里面使用 ActionSupport 类的 getText 实例方法:

getText(resourceKey)

 

方式二:

使用 I18nHelper 类的 i18nMessage 静态方法:

I18nHelper.i18nMessage(resourceKey)

I18nHelper.i18nMessage(resourceKey, Object…)

 

代码详解

 

注意:语言参数全部自动获取,不对接口体现。

3.3.2. JSP EL 自定义解析器原理

http 请求过程:

http 请求 -> Tomcat connector 接受连接请求 -> 请求任务池 -> 各种 standard pipeline -> standard wrapper -> filter -> action -> ModleAndView -> forward -> jsp servlet -> 编译生成 *_jsp.java -> _jspService -> 标签解析 -> out.write ()

 

自定义 EL 解析器:

代码详解

 

注意:资源字符串必须以 i8n_ 开头

 

3.3.3. EL 表达式和 ajax 方法使用

a)jsp 文件直接在对应字符显示位置填入 ${i18n_****} 即可。

 

b) js 文件不经过后台解析,需要由 jsp 传递传递国际化字符串,可以使用全局变量,也可以通过函数参数传递。

window.i18nMsg= window.i18nMsg|| {};

 

c) 无 jsp 环境的页面,使用 sysutil.js 的 getI18nResource 方法获取资源,该方法使用 AJAX 从后台获取资源。

var messageKesy=new Array(“logged_out”,“expired_message”,“login_again”)

var resobj = $.su.getI18nResource(messageKesy);

document.title = resobj.logged_out;

附件:
Mestar 国际化方案和整改指导.docx