SpringBoot - SpringBoot整合i18n实现消息国际化

这篇具有很好参考价值的文章主要介绍了SpringBoot - SpringBoot整合i18n实现消息国际化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在我们开发WEB项目的时候,项目可能涉及到在国外部署或者应用,也有可能会有国外的用户对项目进行访问,那么在这种项目中, 为客户展现的页面或者操作的信息就需要根据客户系统的环境来使用不同的语言,这就是我们所说的项目国际化。

1. MessageSource源码

Spring中定义了一个MessageSource接口,以用于支持信息的国际化和包含参数的信息的替换,MessageSource接口源码如下:

public interface MessageSource {

   /**
    * 解析code对应的信息进行返回,如果对应的code不能被解析则返回默认信息defaultMessage。
    *
    * @param code 需要进行解析的code,对应资源文件中的一个属性名
    * @param args 当对应code对应的信息不存在时需要返回的默认值
    * @param defaultMessage 需要用来替换code对应的信息中包含参数的内容,如:{0},{1,date},{2,time}
    * @param locale 对应的Locale
    * @return 国际化翻译值
    */
   @Nullable
   String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);

   /**
    * 解析code对应的信息进行返回,如果对应的code不能被解析则抛出异常NoSuchMessageException
    *
    * @param code 需要进行解析的code,对应资源文件中的一个属性名
    * @param args 当对应code对应的信息不存在时需要返回的默认值
    * @param locale 需要用来替换code对应的信息中包含参数的内容,如:{0},{1,date},{2,time}
    * @return 国际化翻译值
    * @throws NoSuchMessageException 如果对应的code不能被解析则抛出该异常
    */
   String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;

   /**
    * 通过传递的MessageSourceResolvable对应来解析对应的信息
    *
    * @param resolvable  MessageSourceResolvable
    * @param locale 对应的Locale
    * @return 国际化翻译值
    * @throws NoSuchMessageException 如不能解析则抛出该异常
    */
   String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;

}

2. 项目环境搭建

1. 创建项目服务auth

① 创建一个服务auth,导入常用依赖,项目整体结构为:

SpringBoot - SpringBoot整合i18n实现消息国际化

② SpringBoot配置文件

server:
  port: 8080

spring:
  datasource:
    druid:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/storage?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: root
      password: root
  # 资源信息
  messages:
    encoding: utf-8
    # 国际化资源文件路径(配置文件路径)
    basename: i18n/messages

mybatis:
  mapper-locations: classpath:mapper/*.xml
2. 工具类 I18nUtils
// @Autowired 自动装配仅在托管类中有效(例如,注释为@ Component,@ Service或在应用程序上下文xml中定义)。
@Component
@Slf4j
public class I18nUtils {
    
    // 如果当前bean不加@Component注解,则messageSource无法注入,始终为null
    private static MessageSource messageSource;

    @Autowired
    public 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...)
     */
    @NonNull
    public static String tryI18n(@NonNull String source, @NonNull Object... args) {
        String res;
        try {
            res = i18n(source, args);
        } catch (Exception ignored) {
            res = source;
        }
        return res;
    }
}
3. 自定义异常 CommonException
public class CommonException extends RuntimeException {

    public CommonException(String i18eCode) {
        // 根据资源文件的属性名以及当前语言环境,获取国际化信息
        super(I18nUtils.tryI18n(i18eCode));
    }

    public CommonException(String i18eCode, Object... args) {
        // 根据资源文件的属性名,属性值中的参数以及当前语言环境,获取国际化信息
        // args用来替换资源文件属性值中的占位符参数
        super(I18nUtils.tryI18n(i18eCode, args));
    }
}
4. 统一异常处理 GlobalExceptionHandler
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(CommonException.class)
    public ApiResponse<Object> handleCommonException(CommonException e) {
        log.error(e.getMessage(), e);
        return new ApiResponse<>(-1,"error",e.getMessage());
    }
}

3. 业务实现

1. 实体类 UserEntity
@Data
public class UserEntity {

    private Integer id;

    private String name;

    private String password;

    private Date createTime;
}
2. 请求实体 UserQo
@Data
public class UserQo {

    private Integer id;

    @ApiModelProperty("用户名")
    private String name;

    @ApiModelProperty("密码")
    private String password;
}
3. 控制层 UserController
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping("/add")
    public ApiResponse<Object> add(@Validated @RequestBody UserQo userQo){
        userService.insertUser(userQo);
        return new ApiResponse<>(0,"success");
    }
}
4. 业务逻辑层 UserService
@Service
public class UserService {

    @Resource
    private 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.repeat",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.data.to.db");
        }
    }
}
5. 将异常信息写入i18n资源文件

messages.properties:

exception.name.can.not.repeat=exception name can not repeat,the name is {0}
exception.insert.data.to.db=exception insert data to db

messages_zh_CN.properties:

exception.name.can.not.repeat=用户名不能为重复,用户名为:{0}
exception.insert.data.to.db=新增数据到数据库异常
6. 项目测试

用户名重复时抛出异常CommonException,异常会被捕获并进行统一异常处理:

SpringBoot - SpringBoot整合i18n实现消息国际化

添加数据到数据库中时抛出异常CommonException,异常会被捕获并进行统一异常处理:

SpringBoot - SpringBoot整合i18n实现消息国际化

4. 多服务下使用 i18n

1. 调整项目结构

将原来的 auth 服务拆分为为 auth-model和 auth-core 服务,他们都在auth服务下:

SpringBoot - SpringBoot整合i18n实现消息国际化

其中auth-model模块主要请求Qo,响应Vo,实体类Entity,在响应的依赖中导入对应的服务即可。

2. 父模块 auth

pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.6</version>
        <relativePath/>
    </parent>

    <artifactId>auth</artifactId>
    <groupId>com.hh</groupId>
    <version>1.0-SNAPSHOT</version>

    <packaging>pom</packaging>

    <modules>
        <module>auth-core</module>
        <module>auth-model</module>
    </modules>

</project>
3. 子模块 auth-core

① pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>auth</artifactId>
        <groupId>com.hh</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>auth-core</artifactId>
    
    <dependencies>
        <!--依赖auth-module模块-->
        <dependency>
            <groupId>com.hh</groupId>
            <artifactId>auth-model</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        
         <!--省略.....-->
    </dependencies>
</project>

② SpringBoot 配置:

server:
  port: 8080

spring:
  datasource:
    druid:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/storage?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: root
      password: root
  # 资源信息
  messages:
    encoding: utf-8
    # 国际化资源文件路径,需要配置当前模块和依赖模块的资源文件路径
    basename: i18n/core,i18n/module

mybatis:
  mapper-locations: classpath:mapper/*.xml

③ 抛出异常信息,并对消息进行国际化处理:

@Service
public class UserService {

    @Resource
    private 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.repeat",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.data.to.db");
        }
    }
}

④ 因为是auth-core模块抛出的异常消息,因此需要写在i18n/core下面的资源文件中,如果是auth-model模块抛出的异常,则写在auth-model服务i18n/model下面的资源文件中。文章来源地址https://www.toymoban.com/news/detail-434956.html

4. 子模块 auth-model
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>auth</artifactId>
        <groupId>com.hh</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>auth-model</artifactId>
    
    <dependencies>
        <!--省略.....-->
    </dependencies>
</project>

到了这里,关于SpringBoot - SpringBoot整合i18n实现消息国际化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Spring之国际化:i18n

    Spring之国际化:i18n

    学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。各位小伙伴,如果您: 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持,想组团高效学习… 想写博客但无从下手,急需写作干货注入能量… 热爱写作,愿意让自己成为更好

    2024年02月03日
    浏览(16)
  • Vue - i18n 国际化的使用

    参考网址: 使用: https://huaweicloud.csdn.net/638f133edacf622b8df8eb26.html?spm=1001.2101.3001.6650.1utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Eactivity-1-125181861-blog-123845480.235%5Ev38%5Epc_relevant_anti_t3_basedepth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Ea

    2024年02月11日
    浏览(13)
  • 用i18n 实现vue2+element UI的国际化多语言切换详细步骤及代码

    用i18n 实现vue2+element UI的国际化多语言切换详细步骤及代码

    这个地方要注意自己的vue版本和i1n8的匹配程度,如果是vue2点几,记得安装i18n的@8版本,不然会自动安装的最新版本,后面会报错哦,查询了下资料,好像最新版本是适配的vue3。 在src下面新建i18n文件夹,然后在里面新建index.js,里面的内容如下 新建i18n文件夹里面新建config文

    2024年02月14日
    浏览(13)
  • spring6-国际化:i18n | 数据校验:Validation

    spring6-国际化:i18n | 数据校验:Validation

    1.1、i18n概述 国际化也称作i18n,其来源是英文单词 internationalization的首末字符i和n,18为中间的字符数。由于软件发行可能面向多个国家,对于不同国家的用户,软件显示不同语言的过程就是国际化。通常来讲,软件中的国际化是通过配置文件来实现的,假设要支撑两种语言,

    2024年02月08日
    浏览(17)
  • 微信小程序-切换语言(国际化i18n)的方法封装

    微信小程序-切换语言(国际化i18n)的方法封装

    最近做的一个小程序的项目, 涉及到了 多语言的切换 , 就想到了之前vue用的多语言插件i18n, 就尝试着在微信开放社区搜了一下, 没有具体的实现, 但是提供了大致的实现思路, 如下: 又结合了很多大佬的分享经验, 试着去封装了一个微信的i18n方法 首先, 我们需要明确一下需要实

    2024年02月05日
    浏览(13)
  • 如何在Vue3中配置国际化语言i18n

    1. 安装 vue-i18n 2. 创建一个i8n的配置文件 如:i18nConfig.js 3. 新建语言文件 zh-CN.js 和 en-US.js zh-CN.js 文件 en-US.js 文件 CONFIG.js 文件 4. 在 main.js 里面全局配置 通过上面四步即可配置完毕 下面说一下如何使用,分三种情况 在 .vue 组件中的 template 使用 在 .vue 组件中的 script 中使用 在

    2024年02月09日
    浏览(18)
  • Vue3中,国际化插件vue-i18n使用记录,配合VSCode自动化翻译插件i18n Ally

    Vue3中,国际化插件vue-i18n使用记录,配合VSCode自动化翻译插件i18n Ally

    说明文档: vue-i18n 版本说明: vue: 3.0.0+ vue-i18n: 9.x版 src 目录下新建目录 lang ,存放 i18n 的配置。 新建目录名称: lang (语言)、 locales (语系设定)、 i18n ,这些名称都可被VSCode图标插件( vscode-icons )检测到并美化。 lang 目录下,新建 index.js 文件,引入 vue-i18n 。 语言的配置信

    2024年02月12日
    浏览(15)
  • Vue实现多语言(i18n)

    Vue实现多语言(i18n)

    安装i18n插件。 在src目录下,创建一个【language】文件夹,并创建两个语言包js文件。 中文语言包:【zh.js】 英文语言包:【en.js】 完善en.js文件和zh.js文件。两个文件的结构要相同。如果用Element-UI,这里导入。 en.js zh.js 在main.js引入插件。 在页面上使用和切换。 使用: 切换

    2024年02月15日
    浏览(31)
  • i18n多国语言Internationalization的实现

    i18n多国语言Internationalization的实现

    i18n 是\\\"Internationalization”的缩写,这个术语来源于英文单词中首尾字母“”和“n”以及中间的字符数(共计18个字符) 当我们需要开发不同语言版本时,就可以使用i18n多国语言的一个操作处理,i18n主要实现那一方面的内容呢?例如: 文本内容本地化、日期/时间格式、货币与度

    2024年01月16日
    浏览(10)
  • Next实现 i18n 传递 locales 给 getStaticPaths

    在 Next.js 中实现国际化( i18n )时,可以通过配置 next.config.js 文件来传递 locales 给 getStaticPaths 函数。下面是一个示例代码,演示如何在 next.config.js 中配置 locales ,并在 getStaticPaths 中获取并使用这些 locales : 1、配置 next.config.js 文件: 2、在页面组件中使用 getStaticPaths : 在

    2024年04月24日
    浏览(12)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包