多语言支持改造

中英文

Posted by 就是我啦 on March 21, 2022

多语言支持改造

语言资源包的引入

改造比较琐碎

最近的客户突然要求支持中英文两个版本。以前的客户都是国内,基本没有这方面的需求,所以系统一直是单一语言的。既然这次客户有这个需要,正好对系统进行多语言支持的改造。

首先需要引入一个全局变量:language。

image-20220321092957586

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

image-20220321093529485

从大的角度看,系统资源分为动态和静态两种:

1. 静态

静态资源包括freemarker模板文件、引入的第三方JS包等

1.1 Freemarker模板文件

系统使用freemarker模板生成前端页面。在模板目录下设置语言目录,除中文外,其他语言自动转到相应的语言目录下的模板

image-20220321093754405

image-20220321094009737

image-20220321094059613

1.2 第三方JS

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

image-20220321094344883

2. 动态

动态资源比较多,包括菜单、表单、字典、提示信息、后台返回信息、自定义按钮等

我们做了一个语言资源包表:

image-20220321094804286

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 表中数据的中英文转换

类似于这个:

image-20220321101238963

物料名称想变成英文显示。没有好的办法,实在需要的话,再加一列”英文物料名称“吧。

总结

  • 引入语言资源包

  • 引入language全局变量

  • 总体解决方案还是比较优雅的