什么是I8n

国际化(I18n)指的是设计和开发产品的过程,使得它们能够适应多种语言和文化环境,而不需要进行大量的代码更改。这通常涉及到创建一个基础版本的产品,然后通过配置和资源文件来添加对不同语言和地区的支持。

这样,当产品需要在新的地理区域或语言环境中使用时,只需要添加或更新相应的资源文件,而不需要修改产品本身的代码。

"I18n" 是 "Internationalization" 的缩写形式,之所以是 "I18n" 而不是 "Int" 或者其他缩写,是因为 "Internationalization" 这个词的第一个字母是 "I",最后一个字母是 "n",而在这两个字母之间有 18 个字符。因此,"I18n" 成为了一个流行的缩写方式,类似的还有 "K8s" 。

Spring Boot I18n

I8n体现在Java后端比较常见的就是错误提示,而SpringBoot本身就提供了对I8n的支持。使用也非常简单,可以参考一下官方文档

添加国际化资源文件

SpringBoot默认会读取classpath/resource下的messages目录里的国际化资源文件,可以通过下面这个配置更改:

spring.messages.basename=messages

咱们先通过Idea 创建国际化资源文件,方法如下:



创建完成后在reources目录下能看到这些国际化资源文件,图中为了演示,定义了咱们开发中比较常见的登录错误提示信息。


创建工具类

创建工具类的目的是方便咱们获取国际化信息

public class I18nUtil {
 public static String getI18nMessage(String code) {
         try {
           // SpringBoot提供有一个MessageSource的默认实现
             MessageSource messageSource = SpringUtils.getBean("messageSource");
             // 从SpringBoot中获取请求上下文 语言
             Locale locale = LocaleContextHolder.getLocale();
             // 因为我项目只有中文和英文,所以判断一下除了指定中文,否则默认使用英文  
             // 这里对简体中文的定义,Locale[] SIMPLIFIED_CHINESE = {Locale.CHINESE, Locale.CHINA, Locale.SIMPLIFIED_CHINESE, Locale.PRC};
             if (Arrays.stream(LocaleUtils.SIMPLIFIED_CHINESE).toList().contains(locale)) {
                 locale = Locale.SIMPLIFIED_CHINESE;
             } else {
                locale = Locale.US;
             }
            return messageSource.getMessage(code, null, locale);
         } catch (Exception e) {
             log.error("获取国际化内容异常", e);
             // 如果获取国际化信息失败就返回原内容
             return code;
         }
     }
}

定义接口统一返回类

@Data
public class RestResult<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    /** 状态标识码 */
    private String code;

    /** 描述信息 */
    private String message;

    /** 数据 */
    private T data;
    
    public String getMessage(){
     if (StrUtil.isNotEmpty(this.code)) {
       // 获取I8n
      return I18nUtil.getI18nMessage(this.code)
     }
     return this.message;
    }
    
    // 省略其他方法。。。
}

请求头添加语言编码

curl -H "Accept-Language: zh-CN" http://example.com

Spring Cloud 配置I8n

上面是一个简单的是SpringBoot项目配置I8n的流程,但是在Spring Cloud下通常会有多个服务(SpringBoot项目)。按照我们的习惯一般有一个公共项目(common),用于封装POJO 和一些通用的工具类、常量类之类的功能,然后把这个项目打成jar包,其他业务服务都会依赖这个项目,达到功能复用的目的。通用我们也会将一些通用的错误信息(比如:用户Id不能为空)放到common项目里面,那么怎么把这些通用错误信息配置成I8n呢?

按照上面所说,我们把common项目打成jar包供其他业务服务使用,那么当其他服务引入common依赖以后,common就和业务服务同处于一个Spring容器,这时候上面的I8n配置就无法读取到common里面的I8n配置了(上面讲过了SpringBoot默认读取的是项目classpath/resource下的配置文件)。因此我们需要自定义一个MessageSource 然后读取common下的I8n配置就可以了。

  1. 首先,我们在commonresource下创建I8n配置文件,方法和上面一样,因为和业务服务同处一个Spring容器,所以我们需要将资源名称区分开,我们暂且就叫common_messages, 如下图所示:

Untitled
  1. 然后,我们配置一个自定义MessageSource Bean,并且读取我们设置的common_messages
@Bean(name = "commonMessageSource")
public ResourceBundleMessageSource resourceBundleMessageSource() throws IOException {
    ResourceBundleMessageSource source = new ResourceBundleMessageSource();
    source.setDefaultEncoding(StandardCharsets.UTF_8.displayName());
    source.setBasename("common_messages");
    return source;
}
  1. 最后,调整I8nUtil逻辑,先读取业务服务自己的I8n,如果没有再从common I8n获取,如果还没有则返回原code
public class I18nUtil {
 public static String getI18nMessage(String code) {
         try {
           // SpringBoot提供有一个MessageSource的默认实现
             MessageSource messageSource = SpringUtils.getBean("messageSource");
             // 从SpringBoot中获取请求上下文 语言
             Locale locale = LocaleContextHolder.getLocale();
             // 因为我项目只有中文和英文,所以判断一下除了指定中文,否则默认使用英文  
             // 这里对简体中文的定义,Locale[] SIMPLIFIED_CHINESE = {Locale.CHINESE, Locale.CHINA, Locale.SIMPLIFIED_CHINESE, Locale.PRC};
             if (Arrays.stream(LocaleUtils.SIMPLIFIED_CHINESE).toList().contains(locale)) {
                 locale = Locale.SIMPLIFIED_CHINESE;
             } else {
                locale = Locale.US;
             }
            try{
              // 先读取业务服务自己配置的I8n
             return messageSource.getMessage(code, null, locale);
            }catch (NoSuchMessageException e) {
                // 如果没有获取到,再从common里面读取I18n
              ResourceBundleMessageSource commonMessageSource = SpringUtils.getBean("commonMessageSource");
                return commonMessageSource.getMessage(code, null, locale);
            }
         } catch (Exception e) {
             log.error("获取国际化内容异常", e);
             // 如果获取国际化信息失败就返回原内容
             return code;
         }
     }
}

本文使用 markdown.com.cn 排版

Spring Cloud微服务下如何配置I8n的更多相关文章

  1. Spring Cloud微服务下的权限架构调研

    随着微服务架构的流行,系统架构调整,项目权限系统模块开发提上日程,需要对权限架构进行设计以及技术选型.所以这段时间看了下相关的资料,做了几个对比选择. 一.架构图 初步设想的架构如下,结构很简单:eu ...

  2. spring cloud微服务下手动回滚事务

    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 这里使用的场景是,跨服务调用接口,比如:用户信息和用户积分 ...

  3. Spring Cloud微服务Sentinel+Apollo限流、熔断实战总结

    在Spring Cloud微服务体系中,由于限流熔断组件Hystrix开源版本不在维护,因此国内不少有类似需求的公司已经将眼光转向阿里开源的Sentinel框架.而以下要介绍的正是作者最近两个月的真实 ...

  4. Spring Cloud微服务限流之Sentinel+Apollo生产实践

    Sentinel概述 在基于Spring Cloud构建的微服务体系中,服务之间的调用链路会随着系统的演进变得越来越长,这无疑会增加了整个系统的不可靠因素.在并发流量比较高的情况下,由于网络调用之间存 ...

  5. Servlet+MyBatis项目转Spring Cloud微服务,多数据源配置修改建议

    一.项目需求 在开发过程中,由于技术的不断迭代,为了提高开发效率,需要对原有项目的架构做出相应的调整. 二.存在的问题 为了不影响项目进度,架构调整初期只是把项目做了简单的maven管理,引入spri ...

  6. Spring Cloud微服务系列文,服务调用框架Feign

    之前博文的案例中,我们是通过RestTemplate来调用服务,而Feign框架则在此基础上做了一层封装,比如,可以通过注解等方式来绑定参数,或者以声明的方式来指定请求返回类型是JSON.    这种 ...

  7. 一张图了解Spring Cloud微服务架构

    Spring Cloud作为当下主流的微服务框架,可以让我们更简单快捷地实现微服务架构.Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟.经得起实际考验的服务框架组合起来 ...

  8. 如何优化Spring Cloud微服务注册中心架构?

    作者: 石杉的架构笔记 1.再回顾:什么是服务注册中心? 先回顾一下什么叫做服务注册中心? 顾名思义,假设你有一个分布式系统,里面包含了多个服务,部署在不同的机器上,然后这些不同机器上的服务之间要互相 ...

  9. Dubbo和Spring Cloud微服务架构比较

    Dubbo 出生于阿里系,是阿里巴巴服务化治理的核心框架,并被广泛应用于中国各互联网公司:只需要通过 Spring 配置的方式即可完成服务化,对于应用无入侵,设计的目的还是服务于自身的业务为主. 微服 ...

  10. Dubbo 和 Spring Cloud微服务架构 比较及相关差异

    你真的了解微服务架构吗?听听八年阿里架构师怎样讲述Dubbo和Spring Cloud微服务架构. 微服务架构是互联网很热门的话题,是互联网技术发展的必然结果.它提倡将单一应用程序划分成一组小的服务, ...

随机推荐

  1. Springboot 项目集成 PageOffice V6 最简单代码

    本文描述了PageOffice产品在Springboot项目中如何集成调用.(本示例使用了Thymeleaf模板引擎) 新建Springboot项目:pageoffice6-springboot2-s ...

  2. WPF登录界面样例

    XAML文件内容如下 1 <Window x:Class="ERP.Views.Login" 2 xmlns="http://schemas.microsoft.c ...

  3. 5款超好用的AI换脸软件,一键视频直播换脸(附下载链接)

    随着AIGC的火爆,AI换脸技术也被广泛应用于娱乐.广告.电影制作等领域,本期文章系统介绍了市面上超火的5款AI软件 换脸整合包收录了全部5款AI工具,请按照需要选择下载: 百度网盘:https:// ...

  4. Vue——Ajax请求的基本使用

    1.get方法发送Ajax请求 // 直接在 URL 上添加参数 ID=12345 axios.get('/user?ID=12345') .then(function (response) { co ...

  5. centos7下启动Django项目报错(sqlite错误)

    报错内容如下: [root@localhost project]# python3 manage.py runserver Watching for file changes with StatRel ...

  6. 工作流Activiti 迁移 Camunda

    后端操作 意思就是: ①更改maven②改包名.类名③改bpmn model中语法④检查迁移后有哪些功能缺失了 1.更改maven 改为 2.换包名.类名 意思就是将  org.activiti.*  ...

  7. Js实现任意位置缩放图片,深入理解背后原理

    前言 本文将用一个简单的例子详细讲解如何用原生JS一步步实现完整的任意位置缩放图片功能,无任何第三方依赖,指针事件 进行多端统一的事件监听,干货满满. 完整代码 为提升阅读体验,正文中代码展示有部分省 ...

  8. Mp4V2与ffmpeg静态库符号冲突问题解决

    一.为什么静态符号会冲突 无论macho二进制类型,还是Windows上的PE格式,还是Linux上的ELF格式,里面都是按照特定格式存放的一个程序的代码和数据 比如Linux下的可执行文件格式,大致 ...

  9. 30万奖金池鼓励工控人,AIRIOT智慧物联应用场景创新大赛等你来战!

    随着工业和智慧领域数智化发展步伐的逐步加快,智慧物联应用场景越来越广泛,涵盖了智慧城市.智能园区.智慧能源.智慧电力.智能制造.工业物联网等多个领域.航天科技控股集团股份有限公司举办[AIRIOT智慧 ...

  10. 网页唤起qq加群

    今天在网上大浪淘沙了一番,90%的教程都是使用的鹅厂官方的加群组件,但是有个致命bug就是这个加群组件只能唤起自己创建的群,这就很尴尬了,后来偶然发现在qq群资料那边就可以直接获取到加群的链接,害得我 ...