-
Spring 다국어 적용하기JAVA 2020. 5. 27. 15:04반응형
특정 사이트에서 다국어 서비스를 구현하기 위해 Message Source 를 활용하여 다국어를 적용하는 소스를 작성해보려고 한다.
화면단에서는
/common/messages.js
를 호출하여 마치 js 파일을 사용하는 듯 한 모습을 하지만 이는 Request Mapping을 통하여 서버에서 properties 파일을 읽어들이는 식으로 구성하고자 한다.- Controller
com/hailey/message/MessageController.java
package com.hailey.message.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.hailey.message.service.MessageResolveService; @Controller public class MessageController { @Autowired private MessageResolveService messageResolveService; @RequestMapping(value="/common/messages.js") public ModelAndView strings(HttpServletRequest request, HttpServletResponse response) { ModelAndView modelAndView = new ModelAndView("message/messages", "keys", messageResolveService.getMessages(LocaleContextHolder.getLocale())); modelAndView.addObject("content-type", "text/javascript"); String acceptEncoding = request.getHeader("Accept-Encoding"); if(acceptEncoding != null && acceptEncoding.indexOf("gzip") != -1) { response.addHeader("Content-Encoding", "gzip"); } return modelAndView; } }
- Bean
com/hailey/message/ExposedResourceBundleMessageSource.java
메시지 소스를 읽어오기 위함package com.hailey.message; import java.io.IOException; import java.util.Locale; import java.util.Properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.support.ReloadableResourceBundleMessageSource; import org.springframework.core.io.Resource; public class ExposedResourceBundleMessageSource extends ReloadableResourceBundleMessageSource { protected final Logger logger = LoggerFactory.getLogger(this.getClass()); @Override protected Properties loadProperties(Resource resource, String filename) throws IOException { logger.info("Load " + filename); return super.loadProperties(resource, filename); } /** * Gets all messages for presented Locale. * * @param locale user request's locale * @return all messages */ public Properties getMessages(Locale locale) { return getMergedProperties(locale).getProperties(); } }
- Service ( interface 클래스를 상속받으나 생략함 )
com/hailey/message/service/MessageResolveServiceImpl.java
package com.hailey.message.service; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.MessageSource; import org.springframework.context.NoSuchMessageException; import org.springframework.stereotype.Service; import org.springframework.web.context.support.XmlWebApplicationContext; import com.hailey.message.ExposedResourceBundleMessageSource; @Service public class MessageResolveServiceImpl implements MessageResolveService { protected final Logger logger = LoggerFactory.getLogger(this.getClass()); private MessageSource messageSource; @Override public String getMessage(String key, Object[] arguments, Locale locale) { String message = ""; try { message = messageSource.getMessage(key, arguments, locale); } catch (NoSuchMessageException e) { message = key; logger.warn("No message found: " + key); } return message; } @Override public Map<String, String> getMessages(Locale locale) { Properties properties = ((XmlWebApplicationContext) messageSource).getBean("messageSource", ExposedResourceBundleMessageSource.class).getMessages(locale); Map<String, String> messagesMap = new HashMap<String, String>(); for (Map.Entry<Object, Object> entry : properties.entrySet()) { if (entry.getKey() != null && entry.getValue() != null) { messagesMap.put(entry.getKey().toString(), entry.getValue().toString()); } } return messagesMap; } @Override public void setMessageSource(MessageSource messageSource) { logger.info("Messages i18n injected"); this.messageSource = messageSource; } }
- View (js 파일)
/WEB-INF/view/message/messages.jsp
<%@page language="java" contentType="text/javascript; charset=utf-8" pageEncoding="utf-8" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <% pageContext.setAttribute("newLineChar", "\n"); %> var messages = new Array(); <c:forEach var="map" items="${keys}"> messages["${map.key}"] = "${fn:replace(map.value, newLineChar,'\\n')}"; </c:forEach>
// Sample var messages = new Array(); messages["LABEL.JOIN"] = "회원가입"; messages["MSG.LOGIN.PWD"] = "비밀번호"; messages["MSG.ERROR.PWD_VALID"] = "비밀번호는 영문 + 숫자 + 특수문자 혼합 8자리 이상이어야 합니다.";
- 메시지 정의 파일
/WEB-INF/message/messages.properties
(Default)
각 언어 별로 파일명을 messages_en.properties , messages_kr.properties 등으로 구분한다.
Eclipse 툴을 이용하면 메시지 파일을 간단히 작성할 수 있고, KEY 값을 . 기호로 트리구조로 작성할 수 있다.#messages_en.properties #Generated by Eclipse Messages Editor (Eclipse Babel) LABEL.JOIN = Join MSG.LOGIN.PWD = Password MSG.ERROR.PWD_VALID = Your password must be a \ combination of alphabetic, \ numeric and special characters \ of at least 8 characters.
#messages_kr.properties #Generated by Eclipse Messages Editor (Eclipse Babel) # 이클립스 GUI에서 한글을 입력하면 아래와 같이 유니코드 문자로 변환하여 저장된다. LABEL.JOIN = \uD68C\uC6D0\uAC00\uC785 MSG.LOGIN.PWD = \uBE44\uBC00\uBC88\uD638 MSG.ERROR.PWD_VALID = \uBE44\uBC00\uBC88\uD638\uB294 \ \uC601\uBB38 + \uC22B\uC790 + \ \uD2B9\uC218\uBB38\uC790 \uD63C\ \uD569 8\uC790\uB9AC \ \uC774\uC0C1\uC774\uC5B4\uC57C \ \uD569\uB2C8\uB2E4.
- Spring Context 에 지정하기
/WEB-INF/spring/context-message.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="messageSource" class="com.hailey.message.ExposedResourceBundleMessageSource"> <property name="basenames"> <list> <!-- 메세지 파일의 위치를 지정합니다. message_언어.properties 파일을 찾습니다. --> <value>/WEB-INF/messages/message</value> </list> </property> <!-- 파일의 기본 인코딩을 지정합니다. --> <property name="defaultEncoding" value="UTF-8" /> <!-- properties 파일이 변경되었는지 확인하는 주기를 지정합니다. 60초 간격으로 지정했습니다. --> <property name="cacheSeconds" value="60" /> </bean> <!-- 언어 정보를 세션에 저장하여 사용합니다. --> <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"> <property name="cookieName" value="LOCALE" /> <property name="cookieMaxAge" value="2592000" /> </bean> </beans>
- 클라이언트 javascript 활용 예
화면에서 언어 설정은 쿠키를 사용하는데 위에 작성한
context-message.xml
에 명시한cookieName
을 사용해야 한다.// 창이 로드될 때 메시지 js 파일을 호출하여 캐시해놓고 사용한다. window.onload = function(){ jQuery.ajax({ dataType: 'script', callType: 'skip_success', cache: true, url: '/common/messages.js' /* Controller 에서 지정한 url */ }); }; // 메시지 읽어들일 때 아래와같이 함수를 정의하였다. function getMessage(key, default_value) { if(typeof messages == 'undefined') { return default_value || ''; } return nvl(messages[key]); } // 언어 변경 시 쿠키 값에 세팅해야 한다. 그래야 페이지 새로고침 시 message.js 파일에 영향이 있음. // context 에 지정한 60초 이내에는 바로 적용되지 않을 수 있음. function changeLocale(locale) { document.cookie = "LOCALE="+nvl(locale, 'kr'); } console.log( getMessage("LABEL.JOIN") ); // 회원가입
반응형'JAVA' 카테고리의 다른 글
Spring Controller에서 이미지 타입으로 리턴 (0) 2022.01.24 이클립스 속도 개선 eclipse.ini / Preference (0) 2021.01.08 Spring DAO DTO 사용하기 (0) 2020.05.12 Spring 커스텀 태그 활용 (0) 2020.05.12