JQuery i18n?

다국어 지원?

요즘 웹 페이지를 구성하는데 있어서 다국어를 지원하는 비중이 점점 커지고있다. 인터넷이 빨라짐에 따라서 자국어의 언어만으로 검색하기보다는 다른 언어를 이용해 검색하는 일이 빈번하기 때문이다.

이런 다국어 처리를 하기위해서 외부 javascript 파일을 사용하기에는 골치가 아프고 모든 요청을 서버사이드에서 처리하기에는 너무 부담이 크고 불가능한 경우도 많다. 그렇기 때문에 jQuery에서 제공하는 jQuery.i18n.properties를 사용하게 되었다. Github의 주소는 아래와 같다. (참고로 라이브러리 이름 중간에 들어가는 i18ninternationalization을 줄인 단어이다. in사이에 18글자가 있다는 뜻. 나도 세어봤는데 진짜 18글자다.)

https://github.com/jquery-i18n-properties/jquery-i18n-properties


적용법

Spring에서 사용하기 위한 적용법을 살펴보자.

  1. 인코딩 설정
  2. application-servlet.xml 설정
  3. 서버 사이드에서 요청을 받을 Controller 작성
  4. 설정된 Locale을 확인하는 클래스 작성
  5. 메세지를 언어 설정에 따라서 가져오는 클래스
  6. javascript용 파일 생성
  7. 사용하기(javascript, java, jsp)

위와 같은 순서로 적용을 하면된다. 순서대로 살펴보자.


인코딩 설정

우선, web.xml에 인코딩 필터를 추가한다. 그냥 복사 붙여넣기해서 추가해도된다.

1
2
3
4
5
6
7
8
9
10
11
12
<filter>
   <filter-name>encodingFilter</filter-name>
   <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
   <init-param>
     <param-name>encoding</param-name>
     <param-value>UTF-8</param-value>
   </init-param>
</filter>
<filter-mapping>
   <filter-name>encodingFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>


application-servlet.xml 설정

Spring에서 텍스트 메세지를 처리하기 위한 MessageSource를 빈으로 등록한다.(디폴트 ko)

1
2
3
4
5
6
7
8
9
10
11
12
13
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
  <property name="defaultEncoding" value="UTF-8"/>
  <property name="basenames">
    <list>
      <value>classpath:/com/test/mydomain/message</value>
    </list>
  </property>
  <property name="fallbackToSystemLocale" value="false"/>
  <property name="cacheSeconds" value="60"/>
</bean>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
  <property name="defaultLocale" value="ko" />
</bean>

MessageSource는 인터페이스로 세 개의 메소드를 정의하고 있다.

1
2
3
4
5
6
7
8
* String getMessage(String code, Object[] args, String default, Locale locale);
  //특정 로케일 내에서 발견되는 메세지가 없다면 디폴트 메세지를 반환
  
* String getMessgae(String code, Object[] args, Locale locale);
  //기본적인 기능은 위의 메소드와 비슷하지만 디폴트 메세지가 없어서 메세지가 없는경우 NoSuchMessageException 을 던짐.
  
* String getMessage(MessageSourceResolvable resolvable, Locale locale);
  //위 메소드의 모든 프로퍼티를 MessageSourceResolvable에 설정해 사용한다.

자세한 내용은 아래의 블로그를 참고하자.

http://jjaeko.tistory.com/18

다시 돌아와서, 빈으로 등록한 MessageSource를 사용하기 위해서는 classpath로 등록한 /com/test/mydomain/ 위치에 다국어를 포함하는 파일을 넣으면 된다. 파일명은 message_ko.property와 같이 Locale명을 중간에 넣는 식으로 만들면 된다. 파일의 내용은

1
test.message=안녕하세요.test.hello={0}, 안녕하세요. {1}

과 같은 방식으로 작성한다. 여기서 {0}{1}은 치환될 영역이다.


Controller 작성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Controller
public class LocaleController {
    
    @RequestMapping(value = "/changeLocale")
    public String changeLocale(HttpServletRequest request, HttpServletResponse response, @RequestParam(required = false) String locale) {
        HttpSession session = request.getSession();
        Locale lo = null;
        
        //step. Parameter에 따라서 Locale 생성, 기본은 KOREAN.
        if (locale.matches("en")) {
            lo = Locale.ENGLISH;
        } else {
            lo = Locale.KOREAN;
        }

        // step. Locale을 새로 설정한다.
        session.setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, lo);
        
        // step. 해당 컨트롤러에게 요청을 보낸 주소로 돌아간다.
        String redirectURL = "redirect:" + request.getHeader("referer");
        return redirectURL;
    }
}

요청을 받아 사용자의 Locale을 변환하는 Controller이다.


설정된 Locale을 확인하는 클래스 작성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class LocaleUtil {

    //기본 로케일을 리턴한다. 기본은 한글이다. 
    public static Locale getDefaultLocale() {
        return Locale.KOREAN;
    }

    //HttpServletRequest 를 받아서 저장되어 있를 locale 값을 리턴한다. 
    //없는 경우는 기본 로케일을 리턴한다. 
    public static Locale getLocale(HttpServletRequest request) {
        Locale locale = null;
        HttpSession session = request.getSession(); 
        locale = (Locale)session.getAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME);

        if (locale == null ) {
            locale = getDefaultLocale();
        }
        return locale;
    }
}