![JAVA 实现多语言](http://img.jiangsulong.com/230202/1I2495F9-0.png)
文章插图
国际化是产品、应用程序或文档内容的设计和开发,它可以为不同文化、地区或语言的目标受众轻松实现本地化 。国际化(Internationalization)通常用英文写成 i18n,其中 18 是英文单词中 i 和 n 之间的字母数 。
任何一个面向全世界的软件都会面临多语言国际化的问题,尤其是跨境电商行业,在做自研系统必不可少的要实现多语言功能,就是在数据展示给用户之前,替换成用户可识别的语言,这里以spring i18n 国际化来介绍一下 。
SpringBoot下Application.ymlbasename:以逗号分隔的基名列表(本质上是一个完全限定的类路径位置),每个基名都遵循 ResourceBundle 约定,对基于斜杠的位置提供宽松的支持,它将从类路径根目录解析 。
cache-duration:加载的资源包文件缓存的持续时间 。如果没有设置,捆绑包将被永久缓存 。如果没有指定持续时间后缀,将使用秒 。
spring:# 资源信息messages:encoding: utf-8# 国际化资源文件路径(配置文件路径),多模块也可以用逗号分隔basename: i18n/messages
将异常信息写入i18n资源文件messages.propertiesexception.name.can.not.null=exception name can not null,the name is {0}exception.insert=exception insert
messages_zh_CN.propertiesexception.name.can.not.null=用户名不能为空,用户名为:{0}exception.insert=新增异常
工具类 I18nUtils@Component@Slf4jpublic class I18nUtils {// 如果当前bean不加@Component注解,则messageSource无法注入,始终为nullprivate static MessageSource messageSource;@Autowiredpublic void setMessageSource(MessageSource messageSource) {I18nUtils.messageSource = messageSource;}/*** 解析code对应的信息进行返回,如果对应的code不能被解析则抛出异常NoSuchMessageException** @param code 需要进行解析的code,对应资源文件中的一个属性名* @param args 当对应code对应的信息不存在时需要返回的默认值* @return 国际化翻译值*/public static String i18n(String code, Object... args) {return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());}/*** 解析code对应的信息进行返回,如果对应的code不能被解析则返回默认信息defaultMessage 。** @param code 需要进行解析的code,对应资源文件中的一个属性名* @param defaultMessage 当对应code对应的信息不存在时需要返回的默认值* @param args 需要用来替换code对应的信息中包含参数的内容,如:{0},{1,date},{2,time}* @return 对应的Locale*/public static String i18nOrDefault(String code, String defaultMessage, Object... args) {return messageSource.getMessage(code, args, defaultMessage, LocaleContextHolder.getLocale());}/*** 因为i18n方法如果获取不到对应的键值,会抛异常NoSuchMessageException* 本方法是对i18n方法的封装 。当报错时并不抛出异常,而是返回source** @param source 模板* @param args参数* @return 返回I18n(正常结束)或者source(抛出异常)* @see #i18n(String, Object...)*/@NonNullpublic static String tryI18n(@NonNull String source, @NonNull Object... args) {String res;try {res = i18n(source, args);} catch (Exception ignored) {res = source;}return res;}}
自定义异常@RestControllerAdvice@Slf4jpublic class GlobalExceptionHandler {@ExceptionHandler(CommonException.class)public ApiResponse<Object> handleCommonException(CommonException e) {log.error(e.getMessage(), e);return new ApiResponse<>(-1,"error",e.getMessage());}}
应用@Servicepublic class UserService {@Resourceprivate UserDao userDao;public void insertUser(UserQo userQo){UserEntity userEntity = userDao.findByName(userQo.getName());if(Objects.nonNull(userEntity)){// i18n带有参数String name = userQo.getName();throw new CommonException("exception.name.can.not.null",name);}userEntity = new UserEntity();BeanUtils.copyProperties(userQo,userEntity);userEntity.setCreateTime(new Date());int count = userDao.insert(userEntity);if(count==1){// i18n不带有参数throw new CommonException("exception.insert");}}}
结论这里只是简单的演示了 spring i18n 的功能,可以满足一些简单场景的需求,可以适当扩展,比如:如果使用了 nacos 等配置中心,则需要去注册中心手动拉取 i18n 的 properties 文件内容,并加载到应用程序的内存里 。【JAVA 实现多语言】
推荐阅读
- 24个JavaScript循环遍历方法,你都知道吗?
- MySQL MaxCompute与AnalyticDB实现数据处理与转换过程
- 5寸蛋糕是多少磅~~5寸蛋糕是多大是什么?
- 别人问你工资多少,高情商会这么回答,既不伤人,也给自己留余地
- 不管谁向你借钱,直接问“借多少”你就输了,聪明人都这样回答
- 自媒体怎么赚钱,自媒体真实收入介绍
- 麦斯数学多少钱一节课,麦斯数学的教学特色及课程收费标准介绍
- wps没有a3纸张大小——a三纸多大尺寸是多少?
- 钓鱼|天选打工人不少,天选钓鱼人更多,其中原因你知道吗?
- 儿童耐克13c是多大码?34码耐克是几c?