2023. 12. 14. 00:01ㆍspring
과제
애너테이션을 이용해 다국어를 지원하는 애플리케이션을 작성하세요.
해결책
MessageSource 인터페이스에는 리소스 번들 메시지를 처리하는 메서드가 몇 가지 정의되어 있다.
ResourceBundleMessageSource는 가장 많이 쓰이는 MessageSource 구현체로, 로케일별로 분리된 리소스 번들 메시지를 해석한다.ResourceBundleMessageSource POJO를 구현하고 자바 구성 파일에서 @Bean을 붙여 선언하면 애플리케이션에서 필요한 i18n 데이터를 가져다 쓸 수 있다.
풀이
미국(로케일)의 영어(언어)에 해당하는 message_en_US.properties 리소스 번들을 예로 들겠다. 리소스 번들은 클래스패스 루트에서 읽으므로 이 경로에 파일이 있는지 확인하고 다음과 같이 키-값을 기재한다.
alert.checkout=A shopping cart has been checked out.
alert.inventory.checkout=A shopping cart with {0} has been checked out at {1}
리소스 번들 메시지를 구분 처리하려면 ReloadableResourceBundleMessageSource 빈 인스턴스를 자바 구성 파일에 정의한다.
@Configuration
@PropertySource("classpath:discounts.properties")
@ComponentScan("com.spring.study.chapter02.shop")
public class ShopConfiguration {
@Value("classpath:banner.txt")
private Resource banner;
@Bean
public ReloadableResourceBundleMessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource =
new ReloadableResourceBundleMessageSource();
//자바 클래스패스에서 이름이 messages로 시작하는 파일들을 찾도록 설정
messageSource.setBasename("classpath:messages");
//캐시 주기는 1초로 설정해서 쓸모없는 메시지를 다시 읽지 않는다.
messageSource.setCacheSeconds(1);
return messageSource;
}
.
.
.
}
빈 인스턴스는 반드시 messageSource라고 명명해야 애플리케이션 컨텍스트가 알아서 감지한다.
빈 정의부에서 setBasenames() 메서드에 가변 문자열 인수를 넘겨 ResourceBundleMessageSource 번들 위치를 지정한다.
이렇게 MessageSource를 정의하고 영어가 주 언어인 미국 로케일에서 텍스트 메시지를 찾으면 message_en_US.properties 리소스 번들 파일이 제일 먼저 잡힌다.
만약 이런 이름을 가진 파일이 클래스패스에 없거나 해당 메시지를 찾지 못하면 언어(영어)에 맞는 mesages_en.properties 파일을 잡고 이 파일마저 없으면 전체 로케일의 기본 파일 messages.properties를 선택한다.
애플리케이션 컨텍스트를 구성해서 getMessage() 메서드로 메시지를 해석할 수 있다.
첫 번째 인수 : 메시지 키
두 번째 인수 : 메시지 매개변수 배열
세 번째 인수 : 대상 로케일
public class MessageExample {
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(ShopConfiguration.class);
String alert = context.getMessage("alert.checkout", null, Locale.US);
String alert_inventory = context.getMessage("alert.inventory.checkout",
new Object[] {"[DVD-RW 3.0]", new Date()}, Locale.US);
System.out.println("The I18N message for alert.checkout is: " + alert);
System.out.println("The I18N message for alert.inventory.checkout is: " +
alert_inventory);
}
}
=>
The I18N message for alert.checkout is: A shopping cart has been checked out.
The I18N message for alert.inventory.checkout is: A shopping cart with [DVD-RW 3.0] has been checked out at 12/13/23, 11:52 PM
MessageExample 클래스는 애플리케이션 컨텍스트를 직접 가져올 수 있으므로 텍스트 메시지를 해석할 수 있지만 텍스트 메시지를 해석하는 빈에는 MessageSource 구현체를 넣어야 한다.
@Component
public class Cashier {
@Autowired
private MessageSource messageSource;
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
public void checkout(ShoppingCart cart) {
String alert = messageSource.getMessage("alert.inventory.checkout",
new Object[]{cart.getItems(), new Date()}, Locale.US);
System.out.println(alert);
}
}
'spring' 카테고리의 다른 글
스프링 레시피 CH2.9 후처리기를 만들어 POJO 검증/수정하기 (0) | 2023.12.16 |
---|---|
스프링 레시피 CH2.8 애너테이션을 이용해 POJO 초기화/폐기 커스터마이징하기 (0) | 2023.12.14 |
스프링 레시피 CH2.6 외부 리소스(텍스트, XML, 프로퍼티, 이미지 파일)의 데이터 사용하기 (1) | 2023.12.12 |
스프링 레시피 CH2.4 @Resource와 @Inject를 붙여 POJO 자동 연결 하기 (0) | 2023.12.11 |
스프링 레시피 CH2.3 POJO 레퍼런스와 자동 연결을 이용해 다른 POJO와 상호 작용하기 (0) | 2023.12.10 |