티스토리 뷰

Framework/Spring

MessageSource 다국어 처리

Seogineer 2022. 6. 15. 22:14

i18n

internationalization의 축약형

총 20자리 글자 중에 맨 앞 i와 맨 뒤 n을 제외한 나머지가 18글자가 있다고 해서 i18n 이다. 

 

MessageSource란?

국제화(i18n)를 지원하는 스프링 인터페이스

하나의 메세지에 대해서 다국어로 표시해주는 기능 제공

 

Entity 생성

@Entity
@Getter
@Setter
public class Languages {
    @Id @GeneratedValue
    private Integer id;
    private String locale;
    private String messageKey;
    private String messageContent;
}

 

sample data 생성 쿼리 작성

src/main/resources 경로에 data.sql 파일명으로 파일을 생성하고 아래 query로 데이터를 추가한다.

INSERT INTO languages (id, locale, message_key, message_content) VALUES
    (1, 'en', 'home.welcome','Hello, world'),
    (2, 'ko', 'home.welcome','안녕, 세계'),
    (3, 'es', 'home.welcome','Hola, mundo'),
    (4, 'en', 'home.lang.en','English'),
    (5, 'en', 'home.lang.ko','Korean'),
    (6, 'en', 'home.lang.es','Spanish'),
    (7, 'ko', 'home.lang.en','영어'),
    (8, 'ko', 'home.lang.ko','한국어'),
    (9, 'ko', 'home.lang.es','스페인어'),
    (10, 'es', 'home.lang.en','inglés'),
    (11, 'es', 'home.lang.ko','Coréano'),
    (12, 'es', 'home.lang.es','Español');

 

application.yml

spring:
  profiles:
    active: local

---
spring:
  config:
    activate:
      on-profile: local
  datasource:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:mem:testdb
    username: sa
    password:
  jpa:
    defer-datasource-initialization: true
    show-sql: true
    hibernate:
      ddl-auto: create-drop
  h2:
    console:
      enabled: true
  sql:
    init:
      data-locations: classpath:data.sql

 

WebConfig.java

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Bean
    public LocaleResolver localeResolver() {
        return new CookieLocaleResolver();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
        localeChangeInterceptor.setParamName("lang");
        registry.addInterceptor(localeChangeInterceptor);
    }
}

LocaleResolver

  • 스프링은 LocaleResolver를 통해서 클라이언트의 Locale 정보를 추출한다.

LocaleResolver 종류

  • AcceptHeaderLocaleResolver : Http 헤더의 Accept-Language의 값을 사용한다. (기본값)
  • CookieLocaleResolver : 쿠키의 값을 저장하여 사용한다.
  • SessionLocaleResolver : 세션에 값을 저장하여 사용한다.
  • FixedLocaleResolver : 요청과 관계없이 default locale 사용한다.

LocaleChangeInterceptor

  • Locale 값이 변경되면 인터셉터가 동작한다.
  • querystring에 지정한 값이 들어올 때 동작한다.
    • ex) http://localhost:8080?lang=ko

 

LanguageRepository.java

public interface LanguageRepository extends JpaRepository<Languages, Integer> {
    Languages findByMessageKeyAndLocale(String messageKey, String locale);
}

 

DBMessageSource

@Component("messageSource")
public class DBMessageSource extends AbstractMessageSource {
    @Autowired
    private LanguageRepository languageRepository;

    private static final String DEFAULT_LOCALE_CODE = "en";

    @Override
    protected MessageFormat resolveCode(String key, Locale locale) {
        Languages message = languageRepository.findByMessageKeyAndLocale(key, locale.getLanguage());
        if (message == null) {
            message = languageRepository.findByMessageKeyAndLocale(key, DEFAULT_LOCALE_CODE);
        }
        return new MessageFormat(message.getMessageContent(), locale);
    }
}

@Component("messageSource")

  • MessageSource 인스턴스로 구현하도록 스프링에 지시한다.

 

index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>multi language test</title>
</head>
<body>
    <span th:text="#{home.welcome}"></span>

    <ul>
        <li><a href="?lang=en" data-th-text="#{home.lang.en}"></a></li>
        <li><a href="?lang=ko" data-th-text="#{home.lang.ko}"></a></li>
        <li><a href="?lang=es" data-th-text="#{home.lang.es}"></a></li>
    </ul>
</body>
</html>

 

실행 결과

 

전체 소스

https://github.com/seogineer/spring-boot-multi-language

 

 

참고

 

i18n 이 뭔가요? SW 국제화가 뭔가요? 현지화가 뭔가요?

Database-Stored Messages for I18n in Spring Boot

댓글
Total
Today
Yesterday
링크
Apple 2023 맥북 프로 14 M3, 스페이스 그레이, M3 8코어, 10코어 GPU, 512GB, 8GB, 한글