Link Search Menu Expand Document

메시지, 국제화

메시지, 국제화 소개

메시지

  • 다양한 메시지를 아래와 같이 하나의 파일에서 관리할 수 있음
  • messages.properties
item=상품
item.id=상품 ID
item.itemName=상품명
item.price=가격
item.quantity=수량
  • addForm.html: <label for="itemName" th:text="#{item.itemName}"></label>
  • editForm.html: <label for="itemName" th:text="#{item.itemName}"></label>

국제화

  • 사용자 언어에 따라 다른 메시지를 제공할 수 있음
  • messages_en.properties
item=Item
item.id=Item ID
item.itemName=Item Name
item.price=price
item.quantity=quantity
  • messages_ko.properties
item=상품
item.id=상품 ID
item.itemName=상품명
item.price=가격
item.quantity=수량

스프링 메시지 소스 설정

직접 등록

@Bean
public MessageSource messageSource() {
    ResourceBundleMessageSource messageSource = new
    ResourceBundleMessageSource();
    messageSource.setBasenames("messages", "errors");
    messageSource.setDefaultEncoding("utf-8");
    return messageSource;
}
  • basenames: 설정 파일의 이름을 지정
    • messages로 지정하면 messages.properties 파일을 사용
    • 추가로 국제화 기능을 적용하려면 messages_en.properties, messages_ko.properties 와 같이 파일명 마지막에 언어 정보를 줌. 만약 찾을 수 있는 국제화 파일이 없으면 messages.properties (언어정보가 없는 파일명)를 기본으로 사용
    • 파일의 위치는 /resources/messages.properties
    • 여러 파일을 한번에 지정할 수 있음
  • defaultEncoding: 인코딩 정보를 지정한다. utf-8 을 사용

스프링 부트

  • 스프링 부트를 사용하면 스프링 부트가 MessageSource 를 자동으로 스프링 빈으로 등록

스프링 부트 메시지 소스 설정 스프링 부트를 사용하면 application.properties에서 메시지 소스를 설정

spring.messages.basename=messages,config.i18n.messages

스프링 부트 메시지 소스 기본 값 spring.messages.basename=messages

  • MessageSource를 스프링 빈으로 등록하지 않고, 스프링 부트와 관련된 별도의 설정을 하지 않으면 messages라는 이름으로 기본 등록
  • messages_en.properties, messages_ko.properties, messages.properties 파일만 등록하면 자동으로 인식

메시지 파일 만들기

  • messages.properties
    hello=안녕
    hello.name=안녕 {0}
    

스프링 메시지 소스 사용

package hello.itemservice.message;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.MessageSource;

import static org.assertj.core.api.Assertions.*;

@SpringBootTest
public class MessageSourceTest {
  
    @Autowired
    MessageSource ms;
  
    @Test
    void helloMessage() {
        String result = ms.getMessage("hello", null, null);
        assertThat(result).isEqualTo("안녕");
    }
}
  • ms.getMessage("hello", null, null)
    • code: hello
    • args: `null
    • locale: null
  • locale 정보가 없으면 basename에서 설정한 기본 이름 메시지 파일을 조회
  • basename으로 messages를 지정 했으므로 messages.properties 파일을 조회

MessageSourceTest 추가 - 메시지가 없는 경우, 기본 메시지

@Test
void notFoundMessageCode() {
    assertThatThrownBy(() -> ms.getMessage("no_code", null, null))
    .isInstanceOf(NoSuchMessageException.class);
}

@Test
void notFoundMessageCodeDefaultMessage() {
    String result = ms.getMessage("no_code", null, "기본 메시지", null);
    assertThat(result).isEqualTo("기본 메시지");
}
  • 메시지가 없는 경우에는 NoSuchMessageException
  • 메시지가 없어도 기본 메시지( defaultMessage )를 사용하면 기본 메시지가 반환

MessageSourceTest 추가 - 매개변수 사용

@Test
void argumentMessage() {
    String result = ms.getMessage("hello.name", new Object[]{"Spring"}, null);
    assertThat(result).isEqualTo("안녕 Spring");
}
  • 다음 메시지의 {0} 부분은 매개변수를 전달해서 치환
  • hello.name=안녕 {0} → Spring 단어를 매개변수로 전달 → 안녕 Spring

국제화 파일 선택

  • locale 정보를 기반으로 국제화 파일을 선택, 구체적인 것 우선
  • Locale이 en_US 의 경우
    • messages_en_USmessages_enmessages 순서

MessageSourceTest 추가 - 국제화 파일 선택1

@Test
void defaultLang() {
    assertThat(ms.getMessage("hello", null, null)).isEqualTo("안녕");
    assertThat(ms.getMessage("hello", null, Locale.KOREA)).isEqualTo("안녕");
}
  • ms.getMessage("hello", null, null) : locale 정보가 없으므로 messages 를 사용
  • ms.getMessage("hello", null, Locale.KOREA) : locale 정보가 있지만, message_ko 가 없으므로 messages 를 사용

MessageSourceTest 추가 - 국제화 파일 선택2

@Test
void enLang() {
    assertThat(ms.getMessage("hello", null,     Locale.ENGLISH)).isEqualTo("hello");
}
  • ms.getMessage("hello", null, Locale.ENGLISH) : locale 정보가 Locale.ENGLISH 이므로 messages_en 을 찾아서 사용

웹 애플리케이션에 메시지 적용하기

  • 타임리프 메시지 표현식: #{...}
  • 파라미터 사용
    • hello.name=안녕 {0}
    • <p th:text="#{hello.name(${item.itemName})}"></p>

웹 애플리케이션에 국제화 적용하기

스프링의 국제화 메시지 선택

  • 스프링은 언어 선택시 기본으로 Accept-Language 헤더의 값을 사용

LocaleResolver

  • 스프링은 Locale 선택 방식을 변경할 수 있도록 LocaleResolver 라는 인터페이스를 제공
  • 스프링 부트는 기본으로 Accept-Language 를 활용하는 AcceptHeaderLocaleResolver 를 사용한다