반응형

메시지, 국제화 소개

1. 메세지

• 상품명이라는 단어를 모두 상품이름으로 고쳐야할 경우 여러 화면에 있는 상품명을 찾아가면서 수동으로 모두 변경해야 함

• HTML 파일에 메시지가 하드코딩 되어 있기 때문인데 이런 다양한 메시지를 한 곳에서 관리하도록 하는 기능을 메시지 기능이라 함.

 

• 적용 방법

 - messages.properties메시지 관리용 파일 생성 후 해당 데이터를 key 값으로 불러서 사용

ex) messages.properties메시지

item=상품
item.id=상품 ID
item.itemName=상품명
item.price=가격
item.quantity=수량

ex) 적용

addForm.html
editForm.html
<label for="itemName" th:text="#{item.itemName}"></label>

 

 

2. 국제화

• 메시지에서 설명한 메시지 파일(messages.properties)을 각 나라별로 별도로 관리하면 서비스를 국제화 할 수 있음

ex) messages_en.properties메시지

item=Item
item.id=Item ID
item.itemName=Item Name
item.price=price
item.quantity=quantity

ex) messages_ko.properties메시지

item=상품
item.id=상품 ID
item.itemName=상품명
item.price=가격
item.quantity=수량

• 영어를 사용하는 사람이면 messages_en.properties를 사용하고, 한국어를 사용하는 사람이면 messages_ko.properties를 사용하게 개발하면 사이트를 국제화 할 수 있음

• 한국어로 표현할지 영어에 표현할지 판단하는 방법은 HTTP accept-language 해더 값을 사용하거나 사용자가 직접 언어를 선택하도록 하고, 쿠키 등을 사용해서 처리하면 됨

• 메시지와 국제화 기능을 직접 구현할 수도 있겠지만, 스프링은 기본적인 메시지와 국제화 기능을 모두 제공함.

타임리프도 스프링이 제공하는 메시지와 국제화 기능을 편리하게 통합해서 제공함

 

 

스프링 메시지 소스 설정

1. 메세지 관리 빈 직접 등록

@Bean
public MessageSource messageSource() {
	ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
	messageSource.setBasenames("messages", "errors");
	messageSource.setDefaultEncoding("utf-8");
	return messageSource;
}

 MessageSource를 스프링 빈으로 등록하면 되는데, MessageSource는 인터페이스임

 따라서 구현체인 ResourceBundleMessageSource를 스프링 빈으로 등록하면 됨.

 

messageSource.setBasenames("messages", "errors")

 - basenames : 설정 파일의 이름을 지정

 - 여러 파일을 한번에 지정 가능(messages , errors)

 - messages로 지정하면 messages.properties 파일을 읽어서 사용

 -

추가로 국제화 기능을 적용하려면 messages_en.properties , messages_ko.properties와 같이 파일명 마지막에 언어 정보를 주면됨

 - 만약 찾을 수 있는 국제화 파일이 없으면 messages.properties (언어정보가 없는 파일명)를 기본으로 사용.
 - 파일의 위치는 /resources/messages.properties에 두면 됨.


 defaultEncoding : 인코딩 정보 지정 utf-8 사용

 

2. 스프링 부트 메세지 소스 설정

2.1 MessageSource 설정

 스프링 부트를 사용하면 스프링 부트가 application.properties를 읽어 MessageSource를 자동으로 스프링 빈으로 등록

 

2.2 application.properties 설정

 spring.messages.basename=messages,errors

 - 위의 basenames설정과 같음

 

※ 스프링 부트 메시지 소스 기본 값

 - spring.messages.basename=messages

※ MessageSource를 스프링 빈으로 등록하지 않고, 스프링 부트와 관련된 별도의 설정을 하지 않으면 messages 라는 이름으로 기본 등록

※ messages_en.properties , messages_ko.properties , messages.properties 파일만 등록하면 자동으로 인식.

 

 

3. 메세지 파일 만들기

 /resources/messages.properties 파일 생성

hello=안녕
hello.name=안녕 {0}

 

 /resources/messages_en.properties 파일 생성

hello=hello
hello.name=hello {0}

 

 

스프링 메세지 소스 사용

1. MessageSource 인터페이스

public interface MessageSource {
	String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
	String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;

 코드를 포함한 일부 파라미터로 메시지를 읽어오는 기능을 제공

 

 

2. 등록한 메세지 프로퍼티스 테스트 소스

2.1 단순한 메세지 조회 테스트 소스

@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 정보가 없으면 Locale.getDefault()을 호출해서 시스템의 기본 로케일을 사용하여 메시지 파일을 조회

locale 정보에 맞는 messages_xx.properties가 없다면 기본 messages.properties조회

application.properties에서 basename으로 messages를 지정 했으므로 messages.properties 파일에서 데이터 조회

 

 

2.2 메시지가 없는 경우, 기본 메세지 테스트 소스

@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 )를 사용하면 기본 메시지가 반환됨

 

 

2.3 매개변수를 사용 하는 메세지 테스트 소드

@Test
void argumentMessage() {
	String result = ms.getMessage("hello.name", new Object[]{"Spring"}, null);
	assertThat(result).isEqualTo("안녕 Spring");
}

hello.name=안녕 {0} → Spring 단어를 매개변수로 전달  안녕 Spring

 

 

3. 국제화 파일 선택

3.1 국제화 파일 선택 하는 메세지 테스트 소스 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 를 사용

 

 

3.2 국제화 파일 선택 하는 메세지 테스트 소스 2

@Test
void enLang() {
	assertThat(ms.getMessage("hello", null,
	Locale.ENGLISH)).isEqualTo("hello");
}

 ms.getMessage("hello", null, Locale.ENGLISH) : locale 정보가 Locale.ENGLISH이므로 messages_en을 찾아서 사용

 

 

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

1. 메세지 등록

 messages.properties에 메세지 추가

label.item=상품
label.item.id=상품 ID
label.item.itemName=상품명
label.item.price=가격
label.item.quantity=수량

page.items=상품 목록
page.item=상품 상세
page.addItem=상품 등록
page.updateItem=상품 수정

button.save=저장
button.cancel=취소

 

2. 타임리프에 메세지 적용

타임리프의 메세지 표현식 : #{ ... }

2.1 페이지 이름에 적용

<h2 th:text="#{page.addItem}">상품 등록</h2>

 

2.2 레이블에 적용

<label for="itemName" th:text="#{label.item.itemName}">상품명</label>
<label for="price" th:text="#{label.item.price}">가격</label>
<label for="quantity" th:text="#{label.item.quantity}">수량</label>

 

2.3 버튼에 적용

<button type="submit" th:text="#{button.save}">저장</button>
<button type="button" th:text="#{button.cancel}">취소</button>

 

2.4 파라미터에 사용하는 방법

<p th:text="#{hello.name(${item.itemName})}"></p>

 

 

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

1. messages_en.properties에 메세지 추가

label.item=Item
label.item.id=Item ID
label.item.itemName=Item Name
label.item.price=price
label.item.quantity=quantity

page.items=Item List
page.item=Item Detail
page.addItem=Item Add
page.updateItem=Item Update

button.save=Save
button.cancel=Cancel

 

2. 웹으로 확인하기

 웹 브라우저의 언어 설정 값을 변경하면서 국제화 적용을 확인가능
크롬 브라우저 설정 언어를 검색하고, 우선 순위를 변경하면 됨

 웹 브라우저의 언어 설정 값을 변경하면 요청시 Accept-Language 의 값이 변경
 Accept-Language 는 클라이언트가 서버에 기대하는 언어 정보를 담아서 요청하는 HTTP 요청 헤더임

 

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

 메시지 기능은 Locale 정보를 알아야 언어를 선택할 수 있음
스프링도 Locale 정보를 알아야 언어를 선택할 수 있는데, 스프링은 언어 선택시 기본으로 Accept-Language 헤더의 값을 사용함.

 

4. LocaleResolver

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

 

 LocaleResolver 인터페이스

public interface LocaleResolver {
	Locale resolveLocale(HttpServletRequest request);
	void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale);
}


 LocaleResolver 변경
 - Locale 선택 방식을 변경하려면 LocaleResolver의 구현체를 변경해서 쿠키나 세션 기반의 Locale 선택 기능을 사용할 수 있음

 - 고객이 직접 Locale을 선택하도록 변경가능

반응형

+ Recent posts