Tech/Spring

요청으로 들어온 language 값에 따른 GlobalExceptioner에서 다국어 처리 (i18n, yml) + spring validaiton 다국어처리

소프 2022. 5. 23.

기록용

직접 정의한 헤더값의 language값에 따른 예외처리 메시지 다중화 

 

applicaiton.yml

spring:
  messages:
    basename: i18n/exception
    encoding: UTF-8

 

resources/i18n/exception_eng.yml

※ 다른 포맷 사용시 그에 따른 값으로 변경

# exception_eng.yml
unKnown:
  code: "-9999"
  msg: "An unknown error has occurred. SadPepe :("
userNotFound:
  code: "-1000"
  msg: "This member not exist. SadPepe :("

resources/i18n/exception_kor.yml

※ 다른 포맷 사용시 그에 따른 값으로 변경

# exception_kor.yml
unKnown:
  code: "-9999"
  msg: "알 수 없는 오류가 발생하였습니다. SadPepe :("
userNotFound:
  code: "-1000"
  msg: "존재하지 않는 회원입니다. SadPepe :("

ISO_639 alpha-3 포맷 사용 : kor, eng

https://ko.wikipedia.org/wiki/ISO_639-1_%EC%BD%94%EB%93%9C_%EB%AA%A9%EB%A1%9D

 

ISO 639-1 코드 목록 - 위키백과, 우리 모두의 백과사전

ISO 639는 언어 분류를 위해 사용되는 표준화된 명명법이다. 각 언어는 2글자(639-1) 및 3글자(639-2, 639-3)로 할당된다. 어족 ISO 언어 이름 네이티브 이름 639-1 639-2/T 639-2/B 639-3 Northwest Caucasian Abkhazian а

ko.wikipedia.org

 

Locale 객체 변환 테스트 코드

exception 에러가 뜨지 않으면 정상

import org.apache.commons.lang3.LocaleUtils;
import org.junit.jupiter.api.Test;

import java.util.Locale;

public class LocaleUtilsTest {

    @Test
    void test() {
        Locale kor = LocaleUtils.toLocale("kor");
        System.out.println(kor);

        Locale eng = LocaleUtils.toLocale("eng");
        System.out.println(eng);
    }
}

 

MessageConfiguration.java

@Configuration
public class MessageConfiguration implements WebMvcConfigurer {

    @Bean // yml 파일을 참조하는 MessageSource 선언
    public MessageSource messageSource(
            @Value("${spring.messages.basename}") String basename,
            @Value("${spring.messages.encoding}") String encoding
    ) {
        YamlMessageSource ms = new YamlMessageSource();
        ms.setBasename(basename);
        ms.setDefaultEncoding(encoding);
        ms.setAlwaysUseMessageFormat(true);
        ms.setUseCodeAsDefaultMessage(true);
        ms.setFallbackToSystemLocale(true);
        return ms;
    }

    // locale 정보에 따라 다른 yml 파일을 읽도록 처리 (kor, eng [ISO_639 alpha-3 포맷]) 
    private static class YamlMessageSource extends ResourceBundleMessageSource {
        @Override
        protected ResourceBundle doGetBundle(String basename, Locale locale) throws MissingResourceException {
            return ResourceBundle.getBundle(basename, locale, YamlResourceBundle.Control.INSTANCE);
        }
    }

}

 

GlobalExceptionHandler.java

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ApplicationException.class)
    public ExceptionMessage handleApplicationException(ApplicationException e) {
        Locale locale = getLocaleByLanguage();
        return ExceptionMessage.of(
                getMessage("userNotFound.code", locale),
                getMessage("userNotFound.msg", locale)
        );

    private Locale getLocaleByLanguage() {
        String langCd = httpServletRequest.getHeader("langCd"); //직접 정의한 헤더값
        return LocaleUtils.toLocale(langCd);
    }
    
     // code 정보에 해당하는 메시지를 조회한다.
    private String getMessage(String code, Locale locale) {
        return messageSource.getMessage(code, null, locale);
    }

    // code 정보, 추가 argument로 현재 locale에 맞는 메시지를 조회한다.
    private String getMessage(String code, Object[] args, Locale locale) {
        return messageSource.getMessage(code, args, locale);
    }

}

 

+ spring validaiton 다국어 처리

현재까지 yml은 지원 X

@Getter
@Setter
public class MenuCreateRequest {

    @NotNull(message = "{name.notnull}")
    private String parentId;

}

 

/resources/messages/validation_eng.properties

name.notnull=sdaasd

/resources/messages/validation_kor.properties

name.notnull=한글이다

 

※ 스프링부트는 기본적으로 Accept-Language값에 따라 다국어 처리를 해줌

validaiton_en.properties, validaiton_kr.properties 형식으로 했으면

Accept-Language값이 없을경우 자동으로 Locale.getDefault()값을 기준으로 .properties를 찾음

 

나는 프론트에서 Accept-Language를 kor, eng 값 포맷으로 보내주길 원함

따라서 값이 없을경우 default로 한글(_kor.properteis)을 찾을 수 있께 설정 추가

 

MessageConfiguration.java

@Slf4j
@Configuration
public class MessageConfiguration implements WebMvcConfigurer {

    //Accept-Language값에 kor 혹은 eng가 없을때 기본값 kor로 설정
    @Bean
    public LocaleResolver localeResolver() {
        AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
        localeResolver.setDefaultLocale(LocaleUtils.toLocale("kor")); // ko_KR
        Locale.setDefault(LocaleUtils.toLocale("kor"));

        return localeResolver;
    }

    @Bean
    public MessageSource validationMessageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("classpath:/messages/validation");
        messageSource.setDefaultEncoding(Encoding.DEFAULT_CHARSET.toString());
        messageSource.setDefaultLocale(Locale.getDefault());
        messageSource.setCacheSeconds(600);
        return messageSource;
    }

    @Override
    public Validator getValidator() {
        LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
        bean.setValidationMessageSource(validationMessageSource());
        return bean;
    }

}

 

 

 

 

참고

https://zepinos.tistory.com/45

 

Spring Boot 에서 messages.properties 을 이용한 다국어 처리 (5)

2019/02/01 - [Programming/Spring Boot 시작하기] - Spring Boot 에서 messages.properties 을 이용한 다국어 처리 (4) Spring Boot 에서 messages.properties 을 이용해서 다국어를 쉽게 view 에서 사용할 수 있..

zepinos.tistory.com

https://pepega.tistory.com/28

 

springboot로 Rest api 만들기(7) MessageSource를 이용한 Exception 처리

전체 소스코드 https://github.com/GHGHGHKO/Springboot/tree/main/pepega_chapter_7 GitHub - GHGHGHKO/Springboot: 블로그에 업로드 된 소스코드 블로그에 업로드 된 소스코드. Contribute to GHGHGHKO/Springbo..

pepega.tistory.com

https://daddyprogrammer.org/post/499/springboot2-exception-handling-with-messagesource/

 

SpringBoot2로 Rest api 만들기(7) – MessageSource를 이용한 Exception 처리

이번 시간에는 Spring에서 메시지를 처리하는 방법에 대해 알아보고, MessageSource를 이용하여 Exception Message를 고도화해 보도록 하겠습니다. Spring에서는 다국어를 처리하기 위해 i18n 세팅을 지원하

daddyprogrammer.org

 

https://stackoverflow.com/questions/57619422/defaultlocale-of-acceptheaderlocaleresolver-is-not-working

 

defaultLocale of AcceptHeaderLocaleResolver is not working

I added AcceptHeaderLocaleResolver. @Configuration public class ApplicationContextConfig { @Bean public LocaleResolver localeResolver() { AcceptHeaderLocaleResolver localeResolver ...

stackoverflow.com

 

https://www.inflearn.com/questions/271842

 

인코딩 문제 - 인프런 | 질문 & 답변

addItemV3를 따라하다가 상품 등록은 괜찮은데 error메세지만 문자가 깨지는 일이 발생합니다. 설정도 validation 프로젝트 받아서 열었더니 차이가 없었는데 뭐가 문제인지 알고 싶습니다. 인코딩 설

www.inflearn.com

 

https://oingdaddy.tistory.com/266

 

Spring Validation Message properties 파일을 통해 관리하기

들어오는 Data에 대한 검증은 어디에서나 필요하다. @Data public class MemberDto { @NotNull(message="name must not be null") private String name; ... 후략 ... } 위와 같은 방식으로 DTO에 message를 하드..

oingdaddy.tistory.com

 

https://ifuwanna.tistory.com/291

 

[IntelliJ] properties 한글 설정 방법

Standard Java API에서 프로퍼티 파일들은 ISO 8859-1 인코딩을 사용하도록 설계되어 있는데 이때 한글 같이 ISO 8859-1에 정의되지 않은 문자는 이스케이프 시퀀스로 저장되기 떄문에 인텔리제이(IntelliJ

ifuwanna.tistory.com

 

댓글