数据库的数据,国际化可选的方案
方案5,所有有中文的表都增加一个lang列,每个语言都录入不同的数据。方案3,使用两套完全隔离的数据库,优点是简单,改动的地方少改动小,且稳定可控,缺点是需部署不同语言的服务器和数据库,费钱,运营麻烦,而且还有用户切换语言后,账号和数据之间不互通问题(切换语言后需重新注册登录),根据自身需求情况可以使用。方案2,数据库只存中文,在展示层(前端)国际化成英文(或其他语言),优点是简单,改动的地方少改
方案1
所有有中文的列都增加一个英文列(或其他语言),优点是稳定可控,翻译内容可以管理端随时调整,缺点是每增加一种语言就增加一个列,改动的地方太多,改动太大,加翻译需要修改代码和重新部署,除非是文本字段是富文本或超长文本类型,否则不推荐使用。
总结:加列实现多语言。
应用场景:用户协议表、文章表等超长文本类型,或者表中需要翻译的字段(列)小于3个。
方案2
数据库只存中文,在展示层(前端)国际化成英文(或其他语言),优点是简单,改动的地方少改动小,缺点是,不可控不稳定,很容易存在数据库录入的数据前端没有配置对应的翻译,加翻译需要修改代码和重新发布前端或APP,不推荐使用。
总结:加前端翻译配置实现多语言。
应用场景:短文本类型。
方案3
使用两套完全隔离的数据库,优点是简单,改动的地方少改动小,且稳定可控,缺点是需部署不同语言的服务器和数据库,费钱,运营麻烦,而且还有用户切换语言后,账号和数据之间不互通问题(切换语言后需重新注册登录),根据自身需求情况可以使用。
总结:加数据库实现多语言。
应用场景:有国内和国外不同国家并分开部署和运营的APP、网站,数据和账号完全隔离的情况。
方案4
将方案2改良,增加一个翻译字典表,前端在翻译时从翻译字典表查数据,这样就不会有遗漏的没被翻译的问题。优点:改动较少(相对方案1而言),稳定可控,翻译内容可以管理端随时调整,加翻译不需要修改代码和重新部署,推荐使用。
总结:加表实现多语言,前端初始化时查出该表作为翻译配置。
应用场景:短文本类型。
表结构设计如下:
CREATE TABLE `i18n` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`code` varchar(500) NOT NULL COMMENT '编码,同一段文字的不同语言翻译的code必须相同,code可以为中文',
`lang` varchar(20) NOT NULL COMMENT '语言',
`value` varchar(500) NOT NULL COMMENT '翻译值',
`create_by` bigint(20) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '录入时间',
`update_by` bigint(20) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `code` (`code`,`lang`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='翻译字典表';
--INSERT INTO `i18n` (`code`, `lang`, `value`) VALUES ('简介', 'zh_CN', '简介');如果将中文作为code则可以不录入中文数据
INSERT INTO `i18n` (`code`, `lang`, `value`) VALUES ('简介', 'en_US', 'Introduction');
INSERT INTO `i18n` (`code`, `lang`, `value`) VALUES ('简介', 'ja_JP', 'プロフィール');
INSERT INTO `i18n` (`code`, `lang`, `value`) VALUES ('my_name', 'zh_CN', '我的名字');
INSERT INTO `i18n` (`code`, `lang`, `value`) VALUES ('my_name', 'en_US', 'My name');
INSERT INTO `i18n` (`code`, `lang`, `value`) VALUES ('my_name', 'ja_JP', '私の名前です');
INSERT INTO `i18n` (`code`, `lang`, `value`) VALUES ('v.age', 'zh_CN', '年龄必须大于{ageN}岁');
INSERT INTO `i18n` (`code`, `lang`, `value`) VALUES ('v.age', 'en_US', 'Age must be greater than {ageN} years old');
INSERT INTO `i18n` (`code`, `lang`, `value`) VALUES ('v.age', 'ja_JP', '年齢は{ageN}歳より大きくなければなりません');
方案4 Plus
将方案4改良,依旧不动原数据表结构,增加一个翻译字典表但不需要传给前端,只需要在后台通过AOP编程统一翻译(使用翻译字典表来翻译)后再给前端。
总结:加表实现多语言,后台切面编程统一使用该表翻译。
应用场景:短文本类型。
java代码I18nUtils .java如下
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class I18nUtils {
private static final I18nMapper i18nMapper= SpringUtils.getBean(I18nMapper.class);
public static String trans(String code, Object... args) {
String lang=((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest().getHeader("Content-Language");
return trans(lang,code,args);
}
public static String trans(String lang,String code, Object... args) {
try{
LambdaQueryWrapper<I18n> lqw = Wrappers.lambdaQuery();
lqw.eq(I18n::getLang, lang);
lqw.eq(I18n::getCode, code);
I18n i18n= i18nMapper.selectOne(lqw);
String[] s = lang.contains("_")?lang.split("_"):(lang.contains("-")?lang.split("-"):new String[]{lang,""});
MessageFormat format=new MessageFormat(i18n.getValue(), new Locale(s[0].toLowerCase(),s[1].toUpperCase()));
String newValue=format.format(args);
return newValue;
}catch (Exception e){
return code;
}
}
}
方案5
所有有中文的表都增加一个lang列,每个语言都录入不同的数据。优点是稳定可控,翻译内容可以管理端随时调整,加翻译不需要修改代码和重新部署。缺点是改动量较多,运营麻烦(需录入和管理多个版本数据,即使大部分字段内容是不需要翻译的也需要录入两次),根据自身需求情况可以使用。
总结:加行实现多语言。
应用场景:用户协议表、文章表等超长文本类型,或者表中不需要翻译字段(列)小于3个的情况下使用。
其他:
可根据上述方案组合使用。如超过100个字符的,可采用方案1或方案5;小于100个字符的,可采用方案4;小于100个字符并且需要翻译的字段少于3个的,可采用方案1;小于100个字符并且需要翻译的字段大于3个的,可采用方案5。
国际化遵循的原则
谁污染谁治理:
1.前端定义的字符串,前端(前端包括web、app、小程序等)自己处理(前端的翻译字典配置可以存储在数据库)。
2.后台定义的字符串,后台必须翻译后再传给前端(后台的翻译字典配置可以存储在数据库)。
3.数据库录入的字符串,必须由数据库配置不同版本的数据或者翻译。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)