Framework/Spring Boot

[Spring boot] 다국어 처리하기

시크맥스 2021. 1. 5. 17:31

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에 대한 파일이 없는 경우,

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

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