多语言翻译
1、多语言介绍
一般情况下,多语言系统包含用户界面多语言和后台消息多语言。在企业级业务系统中,为了方便跨国公司、多语言用户访问相同的数据,还需要支持数据多语言,如国家名称、活动名称、计量单位名称等等。
在 OpenMeta 中,标准的界面元素和消息模板采用统一的译文,界面元素如新增、编辑、删除、导入、导出等的按钮名称,消息模板如分别由前端多语言和后端多语言实现。而像菜单名称、模型名称和字段名称这类存储在数据库中的元数据,会从数据多语言层面进行支持。
因此,当新增一种语言支持时,需要同时翻译前端多语言和后端多语言,同时也需要便捷的数据多语言翻译工具。
另外,多语言的标志应该具有地域无关性,比如不应该简化成国家名、不适合用国旗代表语言选项。
2、后台消息多语言
后台消息多语言,主要用于服务端数据校验、异常提示等消息内容,消息的内容、参数由代码决定,因此这些消息的多语言使用标准化翻译,翻译文件存储在后端多语言资源文件中。可以通过扩展语言文件增加新的语种支持。
为了统一后台消息多语言的使用机制,同时使开发过程和翻译过程分离,OpenMeta 在异常消息中仍然保留原文,而在翻译文件中,原文直接对应译文。
2.1 多语言翻译
使用 <module>.<language>.json
格式的 JSON 文件定义代码中的翻译文本。其中,JSON 文件中 original
表示原文,translation
对应译文。
2.2 自定义消息
抛出异常或提示消息时,直接使用原文定义。
throw new BusinessException("The operator {0} does not exist", name);
其中,异常消息支持占位符参数,通过数字序号标识参数顺序,以应对不同语言环境的译文语序不同。
2.3 手动获取译文
在消息渲染、手动拼接文本、邮件渲染等场景下,可以通过调用 I18n.java
工具类的静态方法获取当前语言或指定语言的译文。
I18n.get("Hello world!");
I18n.get("Hello world!", Locale.SIMPLIFIED_CHINESE);
I18n.get("Hello {0} {1}", firstName, lastName)
2.4 语言优先级
-
优先使用用户 Profile 语言设置,作为当前请求的语言。
-
当用户语言未配置,或者匿名用户访问场景下,获取客户端语言,作为当前语言。首先获取
Accept-Language
header 参数,如无该 Header 参数,比如某些 API 调用场景,则可以通过 URL 参数传递语言参数,如language=zh-CN
。 -
未识别语言参数时,全局默认使用
en-US
英文语言。
2.5 译文优先级
- 优先使用当前语言的译文。
- 当前语言无对应译文时,返回原文。根据全局默认语言设置,原文一般为英文。
2.6 注意事项
依赖组件抛出的异常消息,可能仍然是原始文本,此类异常消息,多数情况下仅用于排错,不需要抛给客户端/用户,一般需要返回给用户的消息,才需要进行多语言翻译。
3、数据多语言
3.1 Create
- Create 原文,同时插入翻译表(包括默认语言和非默认语言情况)
- 至少两条SQL语句
3.2 Read
- Join 翻译表,加载翻译表
SELECT *, COALESCE(NULLIF(trans.column_name, ''), t.column_name) AS t.column_name
FROM business_data t
LEFT JOIN business_data_trans trans ON t.id = trans.row_id AND trans.language_code = ?
WHERE t.id in (?,?)
3.3 Search
- Join 翻译表,读取译文 SELECT * FROM business_data t LEFT JOIN business_data_trans trans ON t.id = trans.row_id WHERE trans.language_code = ? AND trans.name = ? AND t.xxx = ?
3.4 Update
- 多语言字段,同时Update 翻译表
- 两条SQL语句
3.5 Delete
- 物理删除时,删除翻译表数据,同时打包译文,一起发送到changelog使用
- 两条SQL语句
3.6 Changelog
- Create、Update、Delete时,一起携带当时发生变化的语言数据,作为Changelog的dataBeforeChange、dataAfterChange 中translation多语言属性值
- 查询时,自动包含translation 属性值。
3.7 预定义数据
- 业务数据:preId = xxx, model = Business.Data, field = xxx
- 翻译表数据:model = Business.Data.Trans, languageCode = xxx, preId, field = xxx