提示语国际化

199 阅读2分钟

参数校验提示语国际化(language由参数给定)

创建国际化资源文件:在 src/main/resources 下创建 i18n 文件夹,并在其中创建语言文件,例如 messages.propertiesmessages_zh.properties

# messages.properties (default English)
sms.logId.notNull=Log ID cannot be null
sms.mobile.notNull=Mobile number cannot be null
sms.channelId.notNull=Channel ID cannot be null
sms.apiTemplateId.notNull=API Template ID cannot be null

# messages_zh.properties (Chinese)
sms.logId.notNull=短信日志编号不能为空
sms.mobile.notNull=手机号不能为空
sms.channelId.notNull=短信渠道编号不能为空
sms.apiTemplateId.notNull=短信 API 的模板编号不能为空

配置国际化支持:在 Spring Boot 中配置国际化支持,包括 MessageSourceLocaleResolver

@Configuration
public class InternationalizationConfig {

    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("i18n/messages");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }

    @Bean
    public LocaleResolver localeResolver() {
        AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
        localeResolver.setDefaultLocale(Locale.ENGLISH);
        return localeResolver;
    }

    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
        localeChangeInterceptor.setParamName("lang");
        return localeChangeInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeChangeInterceptor());
    }
}

SmsSendMessage 类中使用国际化消息:修改 SmsSendMessage 类,使用 @NotNull 注解的 message 属性来引用国际化消息。

import javax.validation.constraints.NotNull;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.MessageSource;
import org.springframework.beans.factory.annotation.Autowired;

@Data
public class SmsSendMessage {

    @NotNull(message = "{sms.logId.notNull}")
    private Long logId;

    @NotNull(message = "{sms.mobile.notNull}")
    private String mobile;

    @NotNull(message = "{sms.channelId.notNull}")
    private Long channelId;

    @NotNull(message = "{sms.apiTemplateId.notNull}")
    private String apiTemplateId;

    private List<KeyValue<String, Object>> templateParams;
}

在控制器中获取语言参数并设置 Locale:在需要的地方获取 Headers 中的语言参数,并设置 Locale。

@RestController
@RequestMapping("/sms")
public class SmsController {

    @Autowired
    private MessageSource messageSource;

    @PostMapping("/send")
    public ResponseEntity<String> sendSms(@RequestHeader(value = "Accept-Language", defaultValue = "en") String lang, @Valid @RequestBody SmsSendMessage message) {
        LocaleContextHolder.setLocale(Locale.forLanguageTag(lang));
        // Your logic to send SMS
        return ResponseEntity.ok("SMS sent successfully");
    }
}

自定义异常类提示语, language从Headers的Accept-Language中获取:

1. 配置 MessageSource 以支持国际化

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

@Configuration
public class ValidationConfig {

    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasenames("messages");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }

    @Bean
    public LocalValidatorFactoryBean getValidator() {
        LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
        bean.setValidationMessageSource(messageSource());
        return bean;
    }
}

2. 配置国际化拦截器

配置 LocaleChangeInterceptorLocaleResolver 以从头部获取语言信息:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;

import java.util.Locale;

@Configuration
public class LocaleConfig implements WebMvcConfigurer {

    @Bean
    public LocaleResolver localeResolver() {
        AcceptHeaderLocaleResolver resolver = new AcceptHeaderLocaleResolver();
        resolver.setDefaultLocale(Locale.ENGLISH);
        return resolver;
    }

    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
        interceptor.setParamName("Accept-Language");
        return interceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeChangeInterceptor());
    }
}

3. 定义自定义异常

定义一个自定义异常类,用于携带国际化消息的键和参数:

public class CustomException extends RuntimeException {
    private final String messageKey;
    private final Object[] args;

    public CustomException(String messageKey, Object... args) {
        super(messageKey);
        this.messageKey = messageKey;
        this.args = args;
    }

    public String getMessageKey() {
        return messageKey;
    }

    public Object[] getArgs() {
        return args;
    }
}

4. 创建异常处理器

使用 @ControllerAdvice 创建全局异常处理器,以捕获异常并返回国际化的错误消息:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;

import java.util.Locale;

@ControllerAdvice
public class GlobalExceptionHandler {

    @Autowired
    private MessageSource messageSource;

    @ExceptionHandler(CustomException.class)
    public ResponseEntity<ErrorResponse> handleCustomException(CustomException ex, WebRequest request) {
        Locale locale = request.getLocale();
        String message = messageSource.getMessage(ex.getMessageKey(), ex.getArgs(), locale);
        ErrorResponse errorResponse = new ErrorResponse(HttpStatus.BAD_REQUEST.value(), message);
        return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
    }

    // 其他异常处理方法
}

5. 定义错误响应类

定义一个类来表示错误响应:

public class ErrorResponse {
    private int status;
    private String message;

    public ErrorResponse(int status, String message) {
        this.status = status;
        this.message = message;
    }

    // getters and setters
}

6. 抛出自定义异常

在你的业务逻辑中,遇到错误时抛出 CustomException

import org.springframework.stereotype.Service;

@Service
public class SmsService {

    public void sendSms(SmsSendMessage smsSendMessage) {
        if (smsSendMessage.getMobile() == null) {
            throw new CustomException("sms.mobile.notNull");
        }
        // 其他逻辑
    }
}