springboot 使用i18n实现国际化(二)

springboot 使用i18n实现国际化(二)

业务场景

之前文章中已经描述了具体的业务场景,可以点击此处查看。现在完成上篇文章中业务场景3(对需要返回给前端的实体表或者VO实体中含有需要切换语言的字段进行切换语言)

实现步骤

1、定两个注解I18nModel,I18nModelProperty

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
** 这个注解在实体类上使用 用来标记哪些实体是需要转换的
**/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface I18nModel {
    String value() default "";
}

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 多语言转换属性注解,用在字段上面
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface I18nModelProperty {
    /**
     * 目标字段
     */
    String target();

    /**
     * 当前字段语言
     */
    String language() default "zh-CN";

}

2、接着我们使用aop对spring的ResponseBody返回对象进行统一处理


import com.ljz.xd.easyadmincommon.annotation.I18nModel;
import com.ljz.xd.easyadmincommon.annotation.I18nModelProperty;
import com.ljz.xd.easyadmincommon.result.model.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.reflect.Field;

@ControllerAdvice
public class ResultBodyAdvice implements ResponseBodyAdvice {
    private static Logger logger = LoggerFactory.getLogger(ResultBodyAdvice.class);
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        //只对自定义封装的实体做处理
        if(body instanceof R){
            //获取返回数据,并判断是否是需要转换的实体
            Object data = ((R<?>) body).getData();
            if(data != null && data.getClass().isAnnotationPresent(I18nModel.class)){
                //如果是的话接着,判断那些字段需要转换
                Field[] fields = data.getClass().getDeclaredFields();
                for(Field field : fields){
                    if(field.isAnnotationPresent(I18nModelProperty.class)){
                        //获取注解对应的参数
                        I18nModelProperty i18nModelProperty = field.getAnnotation(I18nModelProperty.class);
                        String currentLanguage = LocaleContextHolder.getLocale().toLanguageTag();
                        //判断是否是当前语言
                        if(currentLanguage.equals(i18nModelProperty.language())){
                            try {
                                field.setAccessible(true);
                                //获取字段属性值
                                Object o = field.get(data);
                                //替换到目标位置
                                Field targetField = data.getClass().getDeclaredField(i18nModelProperty.target());
                                targetField.setAccessible(true);
                                targetField.set(data, o);
                            } catch (IllegalAccessException e) {
                                logger.error("获取i18nProperty值的时候失败",e);
                            } catch (NoSuchFieldException e) {
                                logger.error("i18nProperty替换指定字段的值的时候失败",e);
                            }
                        }
                    }
                }
            }
        }
        return body;
    }
}

3、上面这样就可以了,下面展示下效果和使用


import com.ljz.xd.easyadmincommon.annotation.I18nModel;
import com.ljz.xd.easyadmincommon.annotation.I18nModelProperty;

/**
 * 登录用户信息实体类
 *
 * @author ljz
 * @date 2023/1/9 10:14
 */
 @Data
 @toString
@I18nModel
public class LoginUser {
    //用户id
    private Long userId;
    //用户姓名 
    private String userName;
    //用户密码
    private String password;
    //登录账号
    private String loginAccount;
	//这边是不同语言的查找出来的值,设置上目标字段名和当前字段对应的语言code
    @I18nModelProperty(target = "userName",language = "en-US")
    private String userNameEn;

    
}
 @PostMapping("test")
    public R<LoginUser> test(){
        LoginUser user = new LoginUser();
        user.setUserNameEn("testUser");
        user.setUserName("测试用户");
        return R.ok(user);
    }

postman请求时当zh-CN的时候
在这里插入图片描述
请求当en-US时
在这里插入图片描述
可以看到上面的返回值中userName会根据语言返回不同的值,这样未来要是新增语言时前端就不用重新绑定字段

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot中,可以使用Spring框架内置的国际化支持来实现控制器(Controller)的国际化。 首先,在application.properties或application.yml中配置国际化相关的属性,如下: application.yml ``` spring: messages: basename: i18n/messages fallback-to-system-locale: true ``` 其中,basename指定了国际化资源文件的位置和名称,这里的i18n/messages表示在src/main/resources目录下的i18n子目录中,使用messages.properties和messages_XX.properties文件来存储不同语言的翻译内容。fallback-to-system-locale设置为true表示如果没有匹配的语言资源,则使用系统默认语言。 接着,在控制器(Controller)中注入MessageSource对象,并在方法中使用该对象获取对应的国际化消息,如下: ```java @RestController public class UserController { @Autowired private MessageSource messageSource; @GetMapping("/hello") public String hello(@RequestParam(required = false, defaultValue = "en") String lang) { Locale locale = LocaleContextHolder.getLocale(); if ("zh".equals(lang)) { locale = Locale.CHINESE; } String message = messageSource.getMessage("hello.world", null, locale); return message; } } ``` 在上述代码中,我们通过LocaleContextHolder获取当前的Locale对象,然后根据请求参数lang的值来判断是否需要切换为中文Locale对象。接着,使用MessageSource的getMessage方法获取对应的国际化消息。其中,第一个参数是消息的key,第个参数是替换占位符的值,第三个参数是Locale对象。 最后,我们可以在messages.properties和messages_zh.properties文件中定义不同语言的翻译内容,如下: messages.properties ``` hello.world=Hello, World! ``` messages_zh.properties ``` hello.world=你好,世界! ``` 这样,在访问/hello接口时,根据不同的lang参数值,我们可以得到不同的国际化消息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值