spring boot国际化(i18n)


配置

新增自定义i18n国际化拦截器

url参数优先,代码如下

public class CustomLocaleChangeInterceptor implements HandlerInterceptor {

    /**
     * 语言默认参数名
     */
    public static final String DEFAULT_PARAM_NAME = "locale";

    private String paramName = DEFAULT_PARAM_NAME;

    @Nullable
    private String[] httpMethods;

    private boolean ignoreInvalidLocale = false;

    /**
     * 设置语言参数名
     *
     * @param paramName: 参数名
     **/
    public void setParamName(String paramName) {
        this.paramName = paramName;
    }

    /**
     * 获得语言参数名
     *
     * @return java.lang.String
     **/
    public String getParamName() {
        return this.paramName;
    }

    /**
     * 设置支持的请求方法
     *
     * @param httpMethods: 请求方法列表
     **/
    public void setHttpMethods(@Nullable String... httpMethods) {
        this.httpMethods = httpMethods;
    }

    /**
     * 获得支持的请求方法
     *
     * @return java.lang.String[]
     **/
    @Nullable
    public String[] getHttpMethods() {
        return this.httpMethods;
    }

    /**
     * 设置是否忽略无效语言
     *
     * @param ignoreInvalidLocale: 是否忽略无效语言
     **/
    public void setIgnoreInvalidLocale(boolean ignoreInvalidLocale) {
        this.ignoreInvalidLocale = ignoreInvalidLocale;
    }

    /**
     * 获得是否忽略无效语言
     *
     * @return boolean
     **/
    public boolean isIgnoreInvalidLocale() {
        return this.ignoreInvalidLocale;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (!checkHttpMethod(request.getMethod())) {
            return true;
        }
        String newLocale = request.getParameter(getParamName());
        if (newLocale == null) {
            setLocale(request, response, request.getLocale());
            return true;
        }
        setLocale(request, response, StringUtils.parseLocale(newLocale));
        // Proceed in any case.
        return true;
    }

    /**
     * 设置语言
     *
     * @param request: 请求对象
     * @param response: 返回对象
     * @param locale:  语言
     **/
    private void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
        LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
        if (localeResolver == null) {
            throw new IllegalStateException(
                    "No LocaleResolver found: not in a DispatcherServlet request?");
        }
        try {
            localeResolver.setLocale(request, response, locale);
        } catch (IllegalArgumentException ex) {
            if (isIgnoreInvalidLocale()) {
                System.out.println("Ignoring invalid locale value [" + locale.toString() + "]: " + ex.getMessage());
            } else {
                throw ex;
            }
        }
    }

    /**
     * 检查http请求
     *
     * @param currentMethod:当前请求
     * @return boolean
     **/
    private boolean checkHttpMethod(String currentMethod) {
        String[] configuredMethods = getHttpMethods();
        if (ObjectUtils.isEmpty(configuredMethods)) {
            return true;
        }
        for (String configuredMethod : configuredMethods) {
            if (configuredMethod.equalsIgnoreCase(currentMethod)) {
                return true;
            }
        }
        return false;
    }
}

webMvc配置

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    /**
     * 默认解析器 其中locale表示默认语言
     */
    @Bean
    public LocaleResolver localeResolver() {
        SessionLocaleResolver localeResolver = new SessionLocaleResolver();
        localeResolver.setDefaultLocale(Locale.US);
        return localeResolver;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //自定义国际化拦截器
        CustomLocaleChangeInterceptor localeInterceptor = new CustomLocaleChangeInterceptor();
        localeInterceptor.setParamName("lang");
        registry.addInterceptor(localeInterceptor);
    }
}

application.yml

spring:
  messages:
    basename: i18n/messages

resources/i18n/messages.properties

service.customExecption=自定义错误,参数:{0}
service.i18nDemo=你好,世界。{0}

resources/i18n/messages_en_US.properties

service.customExecption=Custom error, parameter {0}
service.i18nDemo=Hello, world {0}

resources/i18n/messages_zh_CN.properties

service.customExecption=自定义错误,参数:{0}
service.i18nDemo=你好,世界。{0}

新增国际化工具类

@Component
public class MessageUtils {

    private static MessageSource messageSource;

    public MessageUtils(MessageSource messageSource) {
        MessageUtils.messageSource = messageSource;
    }

    /**
     * 获取单个国际化翻译值
     *
     * @param msgKey: 键
     * @param args:   参数
     * @return java.lang.String
     **/
    public static String get(String msgKey, Object[] args) {
        try {
            return messageSource.getMessage(msgKey, args, LocaleContextHolder.getLocale());
        } catch (Exception e) {
            e.printStackTrace();
            return msgKey;
        }
    }
}

使用

@RestController
@RequestMapping("/i18n/")
public class I18nController {

    /**
     * 国际化测试
     *
     * @return java.lang.String
     **/
    @RequestMapping(value = "/message")
    public String message() {
        return MessageUtils.get("service.i18nDemo", new Object[]{"哈哈哈"});
    }

    /**
     * 国际化测试
     *
     * @return java.lang.String
     **/
    @RequestMapping(value = "/throw_execption")
    public String throwExecption() {
        if(true){
            throw new ServiceException("{service.customExecption}","测试参数");
        }
        return "ok";
    }
}

在异常处理中使用国际化

自定义异常处理类

public class ServiceException extends RuntimeException {

    private int code;
    private String message;
    private static final String MESSAGE_START_WITH = "{";
    private static final String MESSAGE_END_WITH = "}";
    private static MessageUtils messageUtils;

    /**
     * 初始化国际化配置
     *
     * @param messageSource: 国际化消息
     **/
    public static void initI18n(MessageSource messageSource) {
        messageUtils = new MessageUtils(messageSource);
    }

    public ServiceException(int code, String message) {
        this.code = code;
        this.message = parseMessage(message);
    }

    public ServiceException(String message, Object... args) {
        this.code = 502;
        this.message = parseMessage(message, args);
    }

    /**
     * 格式化消息
     *
     * @param message: 消息
     * @param args:    参数
     * @return java.lang.String
     **/
    private String parseMessage(final String message, Object... args) {
        if (message.startsWith(MESSAGE_START_WITH) && message.endsWith(MESSAGE_END_WITH)) {
            final String msgKey = message.substring(1, message.length() - 1);
            return messageUtils.get(msgKey, args);
        }
        return String.format(message, args);
    }

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }
}

使用

@RestController
@RequestMapping("/i18n/")
public class I18nController {

    /**
     * 国际化测试
     *
     * @return java.lang.String
     **/
    @RequestMapping(value = "/throw_execption")
    public String throwExecption() {
        if(true){
            throw new ServiceException("{service.customExecption}","测试参数");
        }
        return "ok";
    }
}

示例

https://gitee.com/luoye/examples/tree/main/springboot-i18n


文章作者: Ming Ming Liu
文章链接: https://www.lmm.show/9/
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Ming Ming Liu !
  目录