国际化处理的作用是使当前应用程序能够根据用户地区或者语言设置的不同向用户显示不同的语言。
TCSF中定义一个应用程序中需要进行国际化处理的主要分为两个部分:数据部分和界面静态显示部分。
对界面静态显示部分进行国际化
界面静态显示部分通常都是直接将文字写入在界面布局文件如jsp、html文件上,而数据部分则是存储在数据库或者说是由程序动态生成的文字。
在TCSF中,最终使用的是Spring所提供的国际化功能,TCSF中开发者需要在src/main/resources/i18n目录下的messages_*.properties定义国际化资源(通过键值对的形式进行存放)。
例如下面的国际化文件messages_en.properties定义:
hello=english{0}{1}
对于界面静态显示部分,在TCSF中是直接使用Spring message标签进行处理,如下填写国际化资源code和参数:
<spring:message code="hello" arguments="111,222" argumentSeparator=",">
对数据部分进行国际化
在数据部分,TCSF则通过I18nUtil来处理。
I18nUtil工具类提供了5个方法,包括2个通过code获取国际化资源的方法以及2个处理bean国际化的方法。
通过code获取国际化资源
2个通过code获取国际化资源方法介绍:
/**
* 根据language参数进行国际化
* 在推送中使用
* @author Unicorn Lien
* 2016年9月16日 下午5:03:17 创建
* @param code 国际化文字的键名(国际化文字常量)
* @param language 语言(en/zh-cn),空或空字符串默认为zh-cn
* @param params 文本格式化处理的填充参数
* @return 国际化结果字符串
*/
public static String getMessage(String code, String language, Object ... params);
/**
* 根据HttpRequest进行国际化
* 在http请求响应中使用
* @author Unicorn Lien
* 2016年9月16日 下午5:05:35 创建
* @param request 请求
* @param code 国际化文字的键名(国际化文字常量)
* @param params 文本格式化处理的填充参数
* @return 国际化结果字符串
*/
public static String getMessage(HttpServletRequest request, String code, Object ... params);
这两个方法的区别在于,一个需要手动指定语言,而另外一个方法通过request自动获取语言。在普通的请求中,你可以获取到request对象就可以使用第二个方法直接处理国际化。但在主动推送消息到客户端的情况下,由于你无法获取到request对象,需要事先获取客户端的语言,然后通过第一个方法手动设置语言来获取国际化资源。
I18nUtil.getMessage(I18nUtil.LANGUAGE_ENGLISH, "hello", "Unicorn", "Lien");
对javabean字段进行国际化处理
I18nUtil提供了2个方法来处理bean字段的国际化。
/**
* 对List进行国际化处理
* 需要配合I18n注解
* @param list 对象列表
* @param request request对象
*/
public static void processAnnotation(List list,HttpServletRequest request);
/**
* 对bean对象进行国际化处理
* @param request request对象
* @param obj 对象列表
*/
public static void processAnnotation(HttpServletRequest request, Object obj);
对javabean对象字段的国际化处理仅支持通过request参数,不支持通过code。
对于需要进行国际化处理的bean有要求:
1. 需要国际化的bean字段必须是String类型;
2. 在字段上必须注明I18n注解。
之所以说是对于bean字段进行注解,是因为I18nUtil目前不支持对于Getter的注解。
如下为I18n注解源码:
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface I18n {
String module() default "";
String value() default "";
String domain() default "";
String field() default "";
}
假设目前需要处理一个Person类的gender字段,gender取值范围为Male(男)和Female(女)。
通过在gender字段上配置注解 @I18n,在调用I18n.processAnnotation方法时,将会自动到messages_*.properties文件查找 Person.gender.Male或Person.gender.Female
配置@I18n(value="mygender") 将会查找mygender.Male或mygender.Female
配置@I18n(module="core",domain="Cat",field="birthday") 将会查找 core.Cat.birthday.Male或core.Cat.birthday.Female
结合上面三个示例的规律,讲解一下I18n的具体用法。I18n注解在没有进行参数配置情况下,默认按照 类名.字段名.取值 到文件中查找,如果需要修改类名,可以配置domain,修改字段名配置field,取值是不能修改的。I18n为了避免命名冲突问题,增加了前缀module,你可以配置module来分隔开。
你也可以直接使用value来进行指定。之所以允许开发者使用这种配置方式,主要目的是在于资源的复用,例如SysUser和AppUser两个类都用gender字段,并且取值范围都是一样的,那么可以配置为同一个国际化资源。
前面说到国际化字段必须是String类型,原因是I18nUtil在处理时会将处理结果直接赋值到这个字段上,所以如果需要国际化,建议一些Boolean类型的字段也设置为字符串类型,虽然可能浪费一些存储空间,但是这里主要的目的在于提高开发效率,对于服务端开发项目前期来说,这点存储空间不算什么,重要的是快速上线拓展市场。