1. MessageSource

국제화 서비스를 위해서는 사용자 언어에 맞는 페이지가 번역되어 보여져야 합니다.

그런데 서비스 되는 언어마다 html 파일을 작성하여, 요청 언어에 따라 응답 페이지를 분기시키는 것은 매우 비효율적이고, 유지보수를 어렵게 만듭니다.

  • ko : main_ko.html
  • jp : main_jp.html
  • cn : main_cn.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에 대한 파일이 없는 경우,

  • 설정값 true : system locale 사용
  • 설정값 false : messages.properties 파일을 사용
 spring.messages.use-code-as-default-message false

 메시지를 찾지 못했을 때, 예외 처리 대신 메시지 코드를 그대로 반환





이상으로 다국어를 처리하는 방법에 대해 알아보았습니다.


[ 참고 자료 ]

https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html

https://www.baeldung.com/spring-boot-internationalization

https://lahuman.jabsiri.co.kr/87