[Spring boot] 다국어 처리하기
1. MessageSource
국제화 서비스를 위해서는 사용자 언어에 맞는 페이지가 번역되어 보여져야 합니다.
그런데 서비스 되는 언어마다 html 파일을 작성하여, 요청 언어에 따라 응답 페이지를 분기시키는 것은 매우 비효율적이고, 유지보수를 어렵게 만듭니다.
- ko : index_ko.html
- jp : index_jp.html
- cn : index_cn.html
- en : index_en.html
- ...
그래서 하나의 템플릿만 만들어 놓고 다국어가 처리된 파일을 작성해주면, SpringBoot가 알아서 텍스트를 다국어 처리 할 수 있게끔 해주는 것이 MessageSource입니다.
즉, SpringBoot에서는 src/main/resources/messages.properties를 찾았을 때 자동으로 MessageSource를 구성하고,
해당 파일에 다국어를 작성해주기만 하면, SpringBoot가 알아서 사용자 언어를 확인한 후 메시지를 변환해줍니다.
2. 구현하기
프로젝트 구조
1) 컨트롤러
src/main/java/com/victolee/i18n/controller/i18nController.java
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class i18nController {
@GetMapping("/test")
public String test() {
return "test";
}
}
2) 템플릿
src/main/resources/templates/test.html
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>i18n 테스트</h1>
<p th:text="#{product}"></p>
<p th:text="#{product.category}"></p>
</body>
</html>
thymeleaf에서 MessageSource의 메시지를 가져오기 위해서는 #{속성명}을 작성해주면 됩니다.
즉, product, product.category는 messages.properties 파일에서 언어별로 텍스트를 정의해줄 것입니다.
3) messages.properties
다음으로 messages_{언어코드}_{국가코드}.properties 파일에 번역 텍스트를 작성해줍니다.
messages.properties 파일은 사용자 언어 환경에 맞는 properties 파일이 없을 경우, 기본 값으로 보여지는 파일입니다.
각 properties 파일에서 텍스트를 작성하기 전에 IDE에서 *.properties 파일의 인코딩을 UTF-8로 설정해주도록 합니다.
그렇지 않으면 한글 등의 문자가 깨짐 현상이 발생합니다.
src/main/resources/messages.properties
product=some product
product.category=some category
src/main/resources/messages_en_US.properties
product=us product
product.category=us category
src/main/resources/messages_ko_KR.properties
product=한국 상품
product.category=한국 카테고리
각각의 파일은 이렇게 bundle로 묶여지면 손쉽게 관리할 수도 있습니다.
여담이지만.. properties 파일이 아닌 yml을 사용하고 싶은데, 현재 다른 포맷을 지원하고 있지 않다고 합니다. ( 참고 )
4) application.java
src/main/java/com/victolee/i18n/I18nApplicationjava
package com.victolee.i18n;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import java.util.Locale;
@SpringBootApplication
public class I18nApplication {
public static void main(String[] args) {
SpringApplication.run(I18nApplication.class, args);
}
/*
* 사용자 언어 환경을 설정해주기 위한 bean 설정
*/
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
sessionLocaleResolver.setDefaultLocale(Locale.US); // <---- 해당 값을 수정하여 언어 결정
return sessionLocaleResolver;
}
}
테스트를 하려면 사용자 언어 환경을 셋팅해줘야 하기 때문에 bean을 추가합니다.
즉, Locale.US로 설정했으면 messages_en_US.properties에 작성된 텍스트가 보여집니다.
아래의 테스트는 해당 값을 바꿔가며 진행됩니다.
5) 테스트
Locale.US로 설정
messages_en_US.properties 파일에 명시된 텍스트가 의도된대로 노출됩니다.
Locale.JAPAN로 설정
messages_ja_JP.properties 파일은 작성하지 않았기 때문에, 기본 값인 messages.properties 파일의 텍스트가 보여질 것이라 예상할 수 있습니다.
그러나 messages_ko_KR.properties 텍스트가 노출되었는데, 이는 spring.messages.fallback-to-system-locale 설정과 관련이 있습니다.
기본 값이 false이므로 messages_ja_JP.properties 파일을 찾지 못했을 경우, 시스템의 locale을 따라가게 됩니다.
즉, messages_ko_KR.properties 에서 텍스트를 가져오는 것이죠.
( 설정에 대한 내용은 뒤에서 다루겠습니다. )
같은 상황에서 spring.messages.fallback-to-system-locale = false 를 해주면 아래와 같이 messages.properties에서 텍스트를 가져옵니다.
6) 설정
예제에서는 다루지 않았지만, MessageSource와 관련된 설정들을 application.yml 파일에 작성할 수 있습니다. ( 참고 )
key |
기본값 |
설명 |
spring.messages.always-use-message-format |
false |
MessasgeFormat을 전체 메시지에 적용할 것인지 여부 |
spring.messages.basename |
messages |
message 파일을 여러개 사용할 경우 콤마로 구분해서 여러개의 basename을 설정할 수 있다. |
spring.messages.cache-duration |
|
캐시 주기 설정, 기본 값 forever |
spring.messages.encoding |
UTF-8 |
인코딩 방식 |
spring.messages.fallback-to-system-locale |
true |
감지된 locale에 대한 파일이 없는 경우,
|
spring.messages.use-code-as-default-message | false |
메시지를 찾지 못했을 때, 예외 처리 대신 메시지 코드를 그대로 반환 |