多语言支持改造
语言资源包的引入
改造比较琐碎
最近的客户突然要求支持中英文两个版本。以前的客户都是国内,基本没有这方面的需求,所以系统一直是单一语言的。既然这次客户有这个需要,正好对系统进行多语言支持的改造。
首先需要引入一个全局变量:language。

登录时,用户选择语言,此变量同时保存在前后台的session中,保证随时可用。

从大的角度看,系统资源分为动态和静态两种:
1. 静态
静态资源包括freemarker模板文件、引入的第三方JS包等
1.1 Freemarker模板文件
系统使用freemarker模板生成前端页面。在模板目录下设置语言目录,除中文外,其他语言自动转到相应的语言目录下的模板



1.2 第三方JS
这个简单,在引入的时候根据language引入不同的语言包即可

2. 动态
动态资源比较多,包括菜单、表单、字典、提示信息、后台返回信息、自定义按钮等
我们做了一个语言资源包表:

2.1 菜单
在生成菜单的时候,根据中文资源和language变量的值查找语言资源包,优先查找”menu“特殊标记的。
public List<SysMenu> findAll(String module) {
Object language = CommonKit.getSession().getAttribute("language");
List<SysMenu> findAll = null;
if(null == language || language.toString().length() ==0 || "chinese".equalsIgnoreCase(String.valueOf(language))){
findAll = find("select * from sys_menu where module=? order by order_num asc ", module);
}else{
findAll = find("SELECT lan.RES_LANG,lan.SPEC_FLAG ,sm.* FROM hzcore.SYS_MENU sm " +
"LEFT JOIN hzcore.SYS_LANG_RES lan ON lan.RES_NAME =sm.MENU_NAME AND lan.LANG =? " +
" where module=? "
, language, module);
}
// wangdongchao-2018/9/27-修改
// 解决首页菜单无法显示问题
return uppderToLower(LanguageUtil.parsetObject(findAll, "MENU_NAME", "menu"));//SysMenu.dao.findByRoleIds
}
2.2 在线表单
在线表单和菜单类似,根据中文资源和language变量的值查找语言资源包,优先查找”field“特殊标记的。
public List<CapmsField> findByHeadId(int headId) {
Object language = CommonKit.getSession().getAttribute("language");
if(null == language || language.toString().length() ==0 || "chinese".equalsIgnoreCase(String.valueOf(language))){
return find("select f.*,nvl(nvl(f.ff_int4,order_num),id) search_order from capms_field f where head_id=? order by order_num", headId);
}else{
List<CapmsField> capmsFields = find("select lan.RES_LANG,lan.SPEC_FLAG ,f.*,nvl(nvl(f.ff_int4,order_num),f.id) search_order " +
" from capms_field f LEFT JOIN HZCORE.SYS_LANG_RES lan " +
"ON f.COLUMN_NAME =lan.RES_NAME AND lan.LANG =? " +
" where head_id=? order by order_num", language, headId);
return LanguageUtil.parsetObject(capmsFields, "COLUMN_NAME", "field");
}
}
2.3 弹窗
和2.2类似,优先查找”find“特殊标记的。
public List<SysFindCri> findByProgCode(String progCode) {
Object language = CommonKit.getSession().getAttribute("language");
if(null == language || language.toString().length() ==0 || "chinese".equalsIgnoreCase(String.valueOf(language))){
return find("select * from sys_find_cri c where c.prog_code=? order by c.seq_no", progCode);
}else{
List<SysFindCri> sysFindCris = find("select lan.RES_LANG,lan.SPEC_FLAG ,c.* from sys_find_cri c " +
" LEFT JOIN HZCORE.SYS_LANG_RES lan ON c.DESC_CH =lan.RES_NAME AND lan.LANG =? " +
" where c.prog_code=? order by c.seq_no", language, progCode);
return LanguageUtil.parsetObject(sysFindCris, "DESC_CH", "find");
}
}
2.4 后台返回信息
后台信息原来都是返回中文的msg,现在也是经过资源包转一下,优先查找”render“特殊标记的。
private String getLanguageData(String msg){
Object language = CommonKit.getSession().getAttribute("language");
if(null == language || language.toString().length() ==0 || "chinese".equalsIgnoreCase(String.valueOf(language))){
return msg;
}else{
DbPro use = Db.use("capms_base");
List<Record> records = use.find("SELECT * FROM HZCORE.SYS_LANG_RES lan WHERE lan.RES_NAME =? AND lan.LANG =?",
msg, language);
String renderMsg = null;
boolean flag = true;
for (Record record : records) {
String res_name = record.getStr("RES_NAME");// 中文
String res_lang = record.getStr("RES_LANG");// 其它
String spec_flag = record.getStr("SPEC_FLAG");//
String tempMsg = null!=res_lang && res_lang.trim().length()!=0 ? res_lang : res_name;;
// 每次都判断
if(null != spec_flag && spec_flag.trim().length()>0 && "render".equalsIgnoreCase(spec_flag)){
renderMsg = tempMsg;
flag = false;
continue;
}
// 如果flag=true,则永远不走这个判断
if( flag && (null == spec_flag || spec_flag.trim().length()==0 )){
renderMsg = tempMsg;
}
}
return renderMsg==null ? msg : renderMsg ;
}
}
2.5 自定义按钮
自定义按钮也是经过资源包转一下,优先查找”btn“特殊标记的。
public List<CapmsHeadBtn> findByHeadId(int headId) {
Object language = CommonKit.getSession().getAttribute("language");
if(null == language || language.toString().length() ==0 || "chinese".equalsIgnoreCase(String.valueOf(language))){
return find("select * from capms_head_btn where head_id=? order by order_num,id", headId);
}else{
List<CapmsHeadBtn> list = find("select lan.RES_LANG,lan.SPEC_FLAG ,btn.* from HZCORE.capms_head_btn btn " +
" LEFT JOIN HZCORE.SYS_LANG_RES lan ON btn.BTN_NAME =lan.RES_NAME AND lan.LANG =? " +
" where btn.head_id=? order by order_num,btn.id", language, headId);
return LanguageUtil.parsetObject(list, "BTN_NAME", "btn");
}
}
2.6 表中数据的中英文转换
类似于这个:

物料名称想变成英文显示。没有好的办法,实在需要的话,再加一列”英文物料名称“吧。
总结
-
引入语言资源包
-
引入language全局变量
-
总体解决方案还是比较优雅的