2016년 8월 18일 목요일

Spring Boot에서 header의 accept language를 이용한 i18n 처리

서버 Locale 설정


스프링에서 web을 사용하면 LocaleContextHolder를 통한 Locale 관리가 이루어진다.

이 LocaleContext에 Locale을 설정하기 위해 spring에서는 LocaleResolver를 제공한다.

spring에서는 LocaleResolver의 구현체를 4가지 제공하는데 아래와 같다.

  • FixedLocaleResolver
  • SessionLocaleResolver
  • CookieLocaleResolver
  • AcceptHeaderLocaleResolver

Spring Boot의 WebMvcProperties는 위 4가지중 Fixed와 AcceptHeader에 대한 설정을 지원하며 기본 설정은 acceptHeader이다.

다만 기본 설정으로 사용하는 경우 AcceptHeaderLocaleResolver의 supportedLocale 설정에 대한 WebMvcProperties의 설정 지원이 없기 때문에 모든 Locale을 받아들이게 된다.

만약 특정 Locale만 처리가 가능하도록 원한다면 별도로 bean을 선언해주는 것이 좋다.
@Bean
public LocaleResolver localeResolver() {
    AcceptHeaderLocaleResolver acceptHeaderLocaleResolver = new AcceptHeaderLocaleResolver();
    acceptHeaderLocaleResolver.setDefaultLocale(Locale.getDefault());
    List localeList = new ArrayList<>();
    localeList.add(Locale.KOREAN);
    localeList.add(Locale.CHINESE);
    localeList.add(Locale.ENGLISH);
    acceptHeaderLocaleResolver.setSupportedLocales(localeList);
    return acceptHeaderLocaleResolver;
}


restTemplate의 Locale 설정

restTemplate에서 요청하는경우 accept-language header에 locale 정보를 담아 보내면 된다.

accept-language 를 header에 담기 위해 쓸 수 있는 HttpHeaderInterceptor가 있다
이 interceptor를 restTemplate에 선언하면 client에서 오는 header정보를 그대로 담아 전달한다.

다만 이렇게 쓰는 경우 localeResolver를 통해 변경한 locale은 담을 수 없다.

localeResolver를 통해 변경된 locale은 response header의 content-language 정보이기 때문에 request header의 accept-language를 전달하는 HttpHeaderInterceptor가 아닌 별도의 Interceptor를 구현해야한다.


/**
 * Locale별 응답 에러 메세지처리를 위한 interceptor
  *
 */
public class AcceptLanguageClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        request.getHeaders().set(HttpHeaders.ACCEPT_LANGUAGE, LocaleContextHolder.getLocale().toLanguageTag());
        return execution.execute(request, body);
    }
}
주의 해야할 점은 header에 보낼 locale정보는 toLanguageTag 메소드로 보내야 한다는 점이다.

java에서 쓰이는 Locale은 ko_KR과 같은 형태이지만 request header의 accept-langauge의 형태는 ko-kr 과 같은 형태이기 때문에 header에서 쓰이는 형태로 전송하지 않으면 정상적으로 language를 전달받지 못한다.


댓글 없음:

댓글 쓰기