728x90
1. 메시지, 국제화 소개
- messages.properties : key-value로 메시지 관리 file 생성
1.1. 메시지
- 메시지: 동일한 단어를 일일이 변경하는 까다로움을 해결하기 위해서 다양한 메시지를 한 곳에서 관리하도록 하는 기능
방식
- 경로: resources/messages.properties
hello=안녕
hello.name=안녕 {0}
- 사용: thymeleaf에서 메시지 key를 불러서 value를 사용 : #{messageKEY}
<label for="itemName" th:text="#{item.itemName}"></label>
1.2. 국제화
- 경로: resources/messages_en.properties
hello=hello
hello.name=hello {0}
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
- 경로: resources/messages_ko.properties
hello=안녕
hello.name=안녕 {0}
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=취소
- 한국어 영어 인식하는 방법
- http accept-language 헤더 값을 사용
- web Browser 설정
- 사용자가 직접 언어를 선택하도록 쿠키를 사용해서 처리하기 (구글링하면 많이 나옴)
- 메시지와 국제화 기능을 직접 구현 가능하지만 스프링이 기본적으로 제공함
2. 스프링 메시지 소스 설정
2.1. 직접 등록
- 스프링이 제공하는 MessageSource를 springBean으로 등록
- MessageSource
- interface
- MessageSource의 구현체인 ResourceBundleMessageSource를 스프링 빈으로 등록
// spring이 등록한 빈
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
// "messages" : messages.property
// "errors" : errors.property
messageSource.setBasenames("messages", "errors");
messageSource.serDefaultEncoding("utf-8);
return messageSource;
}
- setBasenames: 설정 파일의 이름 지정
- messages: messages.properties 파일을 읽어서 사용
-> 꼭 messages 로 파일 이름을 설정하지 않아도 된다. - 국제화 적용
파일명 마지막에 언어 정보 추가 ex)_en.properties , _ko.properties - 설정 파일 위치
/resources/messages.properties - 여러 파일을 한번에 설정 가능
messages, errors -> messages.properties, errors.properties 2개 설정 파일
- messages: messages.properties 파일을 읽어서 사용
- setDefaultEncoding: 인코딩 정보를 지정하는데 utf-8 사용
2.2. 스프링 부트
- MessageSource를 자동으로 스프링 빈으로 등록
- 스프링부트 메시지 소스 설정
- SetBasenames("file명", "file명") 과 같은 역할
- application.properties 에서 설정 변경
- default 값
- spring.messages.basename=messages
- value : utf-8
- SetBasenames("file명", "file명") 과 같은 역할
#파일 위치: application.properties
spring.messages.basename=messages, errors # <- errors.properties 추가
3. 메시지 소스 사용
- interface의 method 사용 소개
// MessageSource interface
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;
...
}
- MessageSource interface
- getMessage( basenames.properties KEY 명, Object 배열, 찾을 수 없을 때 defaultMessage, 국제화 )
# 2개 파일의 code를 한 코드 블럭에 넣음
/resources/messages.properties
hello=안녕
hello.name=안녕 {0}
/resources/messages_en.properties
hello=hello
hello.name=hello {0}
- {0}: Object 배열의 첫번째를 가지고 온다는 뜻
- 참고: thymeleaf에서는 #{hello.name(${item.itemName})} 형태로 사용
//사용 test code
@SpringBootTest
public class MessageSourceTest {
// 참고
// SpringBootTest여서 MessageSource가 자동으로 springBean 생성이 된다.
// @Test에서 MessageSource method를 직접 사용해서 test를 하기 위해서 의존관계 주입을 넣는다.
// 실제 spring에서 사용할때는 html에서 사용을 하기 때문에 thymeleaf의 문법을 통해서 더 간단하게 사용한다.
@Autowired
MessageSource ms;
@Test
void helloMessage() {
String result = ms.getMessage("hello", null, null);
// messages.proerties KEY명, object 배열 null, locale null
assertThat(result).isEqualTo("안녕");
}
// 메시지가 없는 경우
@Test
void notFoundMessageCode() {
assertThatThrownBy(() -> ms.getMessage("no_code", null, null)).isInstanceOf(NoSuchMessageException.class);
}
// 기본메시지
@Test
void notFoundMessageCodeDefaultMessage() {
String result = ms.getMessage("no_code", null, "기본 메시지", null);
// messages.proerties KEY명, object 배열 null, default message, locale null
assertThat(result).isEqualTo("기본 메시지");
}
// 매개변수 사용
@Test
void argumentMessage() {
String message = ms.getMessage("hello.name", new Object[]{"Spring"}, null);
// messages.proerties KEY명, object 배열, locale null
assertThat(message).isEqualTo("안녕 Spring");
}
// 국제화 파일 선택 1
@Test
void defaultLang() {
assertThat(ms.getMessage("hello", null, null)).isEqualTo("안녕");
assertThat(ms.getMessage("hello", null, Locale.KOREA)).isEqualTo("안녕");
}
// 국제화 파일 선택 2
@Test
void enLang() {
assertThat(ms.getMessage("hello", null, Locale.UK)).isEqualTo("hello");
// messages.proerties KEY명, object 배열 null, locale english
}
}
4. 웹 어플리케이션에 메시지 적용
- messages 파일 생성
# 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=취소
- 타임리프
<!--/*-->
thymeleaf 사용
#{basenames.key}
<!--*/-->
<h2 th:text="#{page.addItem}">상품 등록</h2>
<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>
<button class="w-100 btn btn-primary btn-lg" type="submit" th:text="#{button.save}">저장</button>
5. 웹 어플리케이션에서 국제화 적용
- messages 국제화
# 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
- web Browser 언어 설정 -> 우선순위변경
- request Accept-Language의 값이 변경됨
- request Accept-Language의 값이 변경됨
- LocaleResolver 이용
- 쿠키, 세션 등에 local 방식을 변경하도록 하는 방법
- 블로그보면 언어선택할 수 있는 란
- 스프링이 제공하는 인터페이스
- LocaleResolver 변경 - 쿠키나 세션 기반의 locale 선택 기능을 사용할 수 있다.
- LocaleResolver 구글링하면 예제 많으니 필요시 사용
// LocaleResolver.Interface
public interface LocaleResolver {
Locale resolveLocale(HttpServletRequest request);
void setLocale(HttpServletRequest request, @Nullable HttpServletResponseresponse, @Nullable Locale locale);
}
- LocalResolver 변경
- 만약 Locale 선택 방식을 변경하려면 LocalResolver의 구현체를 변경해서 쿠키나 세션 기반의 Locale 선택기능을 사용할 수 있다.
- 예) 고객인 직접 Locale을 선택하도록 한다.
- LocaleResolver를 검색하면 수 많은 예제가 나오니 필요한 사람들을 참고