SpringBoot实现i18n国际化配置(超详细之跟着走就会系列)

2年前 (2022) 程序员胖胖胖虎阿
349 0 0

一、新增国际化资源文件

在resources文件下新建i18n文件,并新建国际化资源文件。如图:
SpringBoot实现i18n国际化配置(超详细之跟着走就会系列)
点击新增Resource Bundle文件。
SpringBoot实现i18n国际化配置(超详细之跟着走就会系列)
我们在Resource bundle base name处填写国际化文件的名称,笔者此处填“messages”。并点击中间偏右的“+”号,新增国际化语言,此处新增两个语言“zh_CN”,“en_US”。SpringBoot实现i18n国际化配置(超详细之跟着走就会系列)
点击ok保存,看到这样的文件结构,就表示创建成功了:SpringBoot实现i18n国际化配置(超详细之跟着走就会系列)
分别在两个文件中添加
zh_CN:

A00001=你好,世界
A00002=你好,JAVA

en_US:

A00001=Hello World
A00002=Hello JAVA

二、添加国际化配置

2.1 添加配置文件

spring:
  messages:
    basename: i18n/messages

注意:此处的basename填的messages是填Resource bundle base name时填的值。

2.2 添加配置类

MyLocaleResolver:

/**
 * @Description: 自定义LocaleResolver
 * @author Felix.Du
 * @Date: 2022/3/30 21:25
 */
@Configuration
public class MyLocaleResolver implements LocaleResolver {

    @Autowired
    private HttpServletRequest request;

    public Locale getLocal() {
        return resolveLocale(request);
    }

    /**
     * 从HttpServletRequest中获取Locale
     *
     * @param httpServletRequest    httpServletRequest
     * @return                      语言Local
     */
    @Override
    public Locale resolveLocale(HttpServletRequest httpServletRequest) {
        //获取请求中的语言参数
        String language = httpServletRequest.getParameter("lang");
        //如果没有就使用默认的(根据主机的语言环境生成一个 Locale
        Locale locale = Locale.getDefault();
        //如果请求的链接中携带了 国际化的参数
        if (!StringUtils.isEmpty(language)){
            //zh_CN
            String[] s = language.split(Constant.CONNECTOR);
            //国家,地区
            locale = new Locale(s[0], s[1]);
        }
        return locale;
    }

    /**
     * 用于实现Locale的切换。比如SessionLocaleResolver获取Locale的方式是从session中读取,但如果
     * 用户想要切换其展示的样式(由英文切换为中文),那么这里的setLocale()方法就提供了这样一种可能
     *
     * @param request               HttpServletRequest
     * @param httpServletResponse   HttpServletResponse
     * @param locale                locale
     */
    @Override
    public void setLocale(@NonNull HttpServletRequest request, @Nullable HttpServletResponse httpServletResponse, @Nullable Locale locale) {

    }
}

添加i18n工具类,I18nUtil:

@Slf4j
@Component
public class I18nUtil {

    @Value("${spring.messages.basename}")
    private String basename;

    private final MyLocaleResolver resolver;

    private static MyLocaleResolver customLocaleResolver;

    private static String path;


    public I18nUtil(MyLocaleResolver resolver) {
        this.resolver = resolver;
    }


    @PostConstruct
    public void init() {
        setBasename(basename);
        setCustomLocaleResolver(resolver);
    }

    /**
     * 获取 国际化后内容信息
     *
     * @param code 国际化key
     * @return 国际化后内容信息
     */
    public static String getMessage(String code) {
        Locale locale = customLocaleResolver.getLocal();
        return getMessage(code, null, code, locale);
    }

    /**
     * 获取指定语言中的国际化信息,如果没有则走英文
     *
     * @param code 国际化 key
     * @param lang 语言参数
     * @return 国际化后内容信息
     */
    public static String getMessage(String code, String lang) {
        Locale locale;
        if (StringUtils.isEmpty(lang)) {
            locale = Locale.US;
        } else {
            try {
                var split = lang.split("-");
                locale = new Locale(split[0], split[1]);
            } catch (Exception e) {
                locale = Locale.US;
            }
        }
        return getMessage(code, null, code, locale);
    }

    /**
     * 获取站内信指定语言 目前只支持 中文与英文两类 默认英文
     *
     * @param code 国际化 key
     * @param lang 语言参数
     * @return 国际化后内容信息
     */
    public static String getStationLetterMessage(String code, String lang) {
        Locale locale = Objects.equals(lang, I18nConstant.ZH_CN) ? Locale.SIMPLIFIED_CHINESE : Locale.US;
        return getMessage(code, null, code, locale);
    }


    public static String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setDefaultEncoding(StandardCharsets.UTF_8.toString());
        messageSource.setBasename(path);
        String content;
        try {
            content = messageSource.getMessage(code, args, locale);
        } catch (Exception e) {
            log.error("国际化参数获取失败===>{},{}", e.getMessage(), e);
            content = defaultMessage;
        }
        return content;

    }

    public static void setBasename(String basename) {
        I18nUtil.path = basename;
    }

    public static void setCustomLocaleResolver(MyLocaleResolver resolver) {
        I18nUtil.customLocaleResolver = resolver;
    }

}

三、测试

FirstUserController:

@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
@Slf4j
public class FirstUserController {

    private final HttpServletRequest request;

    @GetMapping("/i18n")
    public String i18n() {
        String message1 = I18nUtil.getMessage("A00001", request.getHeader("lang"));
        String message2 = I18nUtil.getMessage("A00002", request.getHeader("lang"));
        return message1 + message2;
    }
}

因为此处截取的是请求头的lang参数,那么我们在请求的时候添加一个lang参数。
SpringBoot实现i18n国际化配置(超详细之跟着走就会系列)
SpringBoot实现i18n国际化配置(超详细之跟着走就会系列)
注意:此处lang传的值是zh-CN、en-US并非zh_CN、en_US,因为在MyLocaleResolver中解析参数是通过分隔符“-”解析的,而并不是“”。当然你也可以传zh_CN、en_US,只需要在MyLocaleResolver类的resolveLocale方法将解析符号换为“”即可。

相关文章

暂无评论

暂无评论...