티스토리 뷰
12.1 다국어 처리의 개요
다국어 처리는 웹 브라우저의 로케일에 따라 다양한 언어를 지원하는 서비스이다.
다양한 언어와 지역적 차이에 따라 웹 애플리케이션의 코드를 수정할 필요 없이 웹 브라우저의 로케일을 기준으로 각 언어에 해당하는 메시지로 변경하는 서비스이다.
즉 선택적으로 변경할 수 있다는 말이다.
- 로케일
로케일은 프로그램이 세계적으로 사용되면서 사용자의 나라 혹은 환경에 따라 결정되는 요소들을 의미한다.
예를 들어 나라별로 언어, 글자, 날짜나 시간의 양식, 통화 기호, 문자열 정렬 순서 등이 다른 요소들을 의미한다.
다국어 처리를 하려면 사용자가 언어를 설정할 수 있도록 MessageSource를 적용해야 한다.
MessageSource를 이용하면 화면에 출력할 메시지를 가져와 화면에 다국어로 표현할 수 있다.
MessageSource를 기반으로하는 LocaleResolver와 LocaleChangeInterceptor를 이용하면 웹 애플리케이션에서 원하는 언어를 자유롭게 선택하거나 변경하도록 할 수 있다.
12.2 MessageSource를 이용한 다국어 처리
MessageSource는 다양한 언어로 작성된 메시지 리소스 파일을 읽어 웹 브라우저의 로케일에 따라 각 언어에 해당하는 메시지로 설정할 수 있다.
12.2.1 메시지 리소스 파일 작성
프로젝트에 지원 가능한 각 언어에 대해 메시지 리소스 파일(*.properties)을 생성해 출력할 메시지를 작성한다. 메시지 리소스 파일에는 key=value 쌍으로 구성되고 참조시 key를 선택하여 참조한다.
기본 언어의 메시지 리소스 파일은 '파일 이름.properties' 형태로 작성한다.
특정 언어에 대한 메시지 리소스 파일이름은 '파일 이름_언어코드.proeprties' 형태로 작성한다.
또한 메시지 리소스 파일은 src/main/resources 폴더에 위치해야한다.
파일 형식 | 설명 |
파일 이름.properties | 시스템의 언어 및 지역에 맞는 리소스 파일이 없을 떄 사용한다. |
파일 이름_ko.properties | 시스템 언어 코드가 한국어일 때 사용한다. |
파일 이름_en.properties | 시스템 언어 코드가 영어일 때 사용한다. |
파일 이름_en_UK.properties | 시스템 언어 코드가 영어고 영구(국가 코드)일 때 사용한다. |
파일 이름_ja.properties | 시스템 언어 코드가 일본어일 때 사용한다. |
12.2.2 MessageSource 환경 설정
스프링 MVC은 웹 브라우저의 로케일에 따라 다양한 언어의 메시지를 출력할 수 있도록 MessageSource 인터페이스를 제공한다.
스프링에서 빈 객체의 생성, 관계 설정, 사용, 제거 등의 기능을 담당하는 컨테이너 중 하나인 애플리케이션 컨텍스트는 MessageSource 인터페이스의 구현체를 빈 객체로 등록해 (MessageSource 인터페이스) 접근하여 원하는 메시지를 가져올 수 있다.
<bean id="messageSource" class="org.springframework.context.support.MessageSource 구현체">
<property name="basename" value="메시지 리소스 파일" />
<porperty name="defaultEncoding" value="인코딩" />
...
</bean>
* id 속성 값은 messageSource가 되어야만 디스패처 서블릿이 인식한다.
MessageSource 구현체의 유형
유형 | 설명 |
ResourceBundleMessageSource | ResourceBundel과 MessageFormat 클래스 기반으로 만드러옂ㅆ으며 특정 이름으로 메시지에 접근할 수 있다. |
ReloadableResourceBundleMessageSource | <property name="cacheSeconds" value="2" /> 프로퍼티 설정으로 다시 시작하지 않고 애플리케이션 실행 도중에 메시지 정의를 다시 로드할 수 있다. |
MessageSOurce 구현체의 빈 객체를 스프링 MVC 설정 파일인 servlet-context.xml에 등록하는 예시
<beans:bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<beans:property name="basename" value="messages"/>
</beans:bean>
프로퍼티 설정에서 value 속성 값이 messages로 설정되었기 때문에 메시지 리소스 파일 messages.properteis로 실제 출력할 메시지를 가져온다.
12.2.3 뷰 페이지에 메시지 출력
메시지 리소스 파일에서 메시지를 가져왔는데 그것을 뷰 페이지에 출력하려면 뷰 페이지 위 쪽에 스프링의 태그 라이브러리를 선언하기 위해 메시지 태그를 사용해야 한다.
<%@ taglib preifx="spring" uri="http://www.springframework.org/tags" %>
<spring:message> 태그를 사용해 메시지 리소스 파일에서 메시지를 가져와 뷰 페이지에 출력한다.
<spring:message> 태그의 속성
속성 | 설명 |
arguments | 부가적인 인자를 넘겨준다. 콤마로 구분된 문자열, 객체 배열, 객체 하나를 넘긴다. |
argumentSeparator | 넘겨줄 인자의 구분자를 설정한다. 기본값은 콤마이다. |
code | 추출할 메시지의 키를 지정한다. 지정하지 않으면 text 속성에 입력한 값이 출력된다. |
htmlEscape | HTML의 기본 escape 속성을 오버라이딩한다. 기본값은 false이다. |
javaScriptEscape | 기본 값은 false이다. |
message | 스프링 MVC에서 유효성 검사를 거친 오류 메시지를 간단하게 보여줄 떄 사용한다. |
scope | 결과 값을 변수에 지정할 때 변수 범위(page, request, session, application)를 정한다. |
text | 해당 code 속성에서 가져온 값이 없을 때 기본으로 보여 주는 문자열이다. 빈 값이면 null을 출력한다. |
var | 결과 값을 정할 떄 사용한다. 빈 값이면 jsp에 그대로 출력된다. |
12.2.4 MessageSoure를 이용하여 다국어 처리
MessageSource로 메시지 리소스 파일을 가져오고 가져온 메시지를 <spring:message> 태그를 사용해 뷰 페이지가 출력한다.
servlet-context.xml
<!-- 12.2.4 다국어 처리 -->
<beans:bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<beans:property name="basename" value="messages"/>
<beans:property name="defaultEncoding" value="utf-8"/>
</beans:bean>
MessageSource 구현체의 빈 객체를 등록한다.
ReousrceBundelMessageSource 클래스를 등록한다.
메시지 리소스 파일이름은 messeges.properties가 된다. (value="messages")
messages_ko.properties
addBook.form.title.label = \uB3C4\uC11C \uB4F1\uB85D
addBook.form.subtitle.label = \uC2E0\uADDC \uB3C4\uC11C \uB4F1\uB85D
addBook.form.bookId.label = \uB3C4\uC11CID
addBook.form.name.label = \uB3C4\uC11C\uBA85
addBook.form.unitPrice.label = \uAC00\uACA9
addBook.form.author.label = \uC800\uC790
addBook.form.description.label = \uC0C1\uC138\uC815\uBCF4
addBook.form.publisher.label = \uCD9C\uD310\uC0AC
addBook.form.category.label = \uBD84\uB958
addBook.form.unitsInStock.label = \uC7AC\uACE0\uC218
addBook.form.releaseDate.label = \uCD9C\uD310\uC77C
addBook.form.condition.label = \uC0C1\uD0DC
addBook.form.bookImage.label = \uB3C4\uC11C\uC774\uBBF8\uC9C0
addBook.form.button.label = \uB4F1\uB85D
messages_en.properties
addBook.form.title.label = Book Addition
addBook.form.subtitle.label = New Book Registration
addBook.form.bookId.label = Book ID
addBook.form.name.label = Name
addBook.form.unitPrice.label = Unit Price
addBook.form.author.label = Author
addBook.form.description.label = Description
addBook.form.publisher.label = Publisher
addBook.form.category.label = Category
addBook.form.unitsInStock.label = Units in Stock
addBook.form.releaseDate.label = Release Date
addBook.form.condition.label = Condition
addBook.form.bookImage.label = Book Image
addBook.form.button.label = Addition
addBook.jsp
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<spring:message code="addBook.form.subtitle.label" />
...
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="<c:url value="/resources/css/bootstrap.min.css"/>"rel="stylesheet" />
<title>도서 등록</title>
</head>
<body>
<nav class="navbar navbar-expand navbar-dark bg-dark">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="./home">Home</a>
</div>
</div>
</nav>
<div class="jumbotron">
<div class="container">
<!-- <h1 class="display-3">도서 등록</h1> -->
<h1 class="display-3">
<spring:message code="addBook.form.title.label" />
</h1>
</div>
</div>
<div class="container">
<div class="float-right">
<form:form action="${pageContext.request.contextPath }/logout" method="post">
<input type="submit" class="btn btn-sm btn-success" value="Logout" />
</form:form>
</div>
<br><br>
<form:form modelAttribute="NewBook" action="./add?${_csrf.parameterName }=${_csrf.token }" class="form-horizontal" enctype="multipart/form-data">
<fieldset>
<%-- <legend>${addTitle}</legend> --%>
<legend><spring:message code="addBook.form.subtitle.label" /></legend>
<div class="form-group row">
<label class="col-sm-2 control-label">
<!-- <label class="col-sm-2 control-label">도서ID</label> -->
<spring:message code="addBook.form.bookId.label" />
</label>
<div class="col-sm-3">
<form:input path="bookId" class="form-control" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<!-- <label class="col-sm-2 control-label">도서명</label> -->
<spring:message code="addBook.form.name.label" />
</label>
<div class="col-sm-3">
<form:input path="name" class="form-control" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<!-- <label class="col-sm-2 control-label">가격</label> -->
<spring:message code="addBook.form.unitPrice.label" />
</label>
<div class="col-sm-3">
<form:input path="unitPrice" class="form-control" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<!-- <label class="col-sm-2 control-label">저자</label> -->
<spring:message code="addBook.form.author.label" />
</label>
<div class="col-sm-3">
<form:input path="author" class="form-control" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<!-- <label class="col-sm-2 control-label">상세정보</label> -->
<spring:message code="addBook.form.description.label" />
</label>
<div class="col-sm-5">
<form:textarea path="description" cols="50" rows="2" class="form-control" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<!-- <label class="col-sm-2 control-label">출판사</label> -->
<spring:message code="addBook.form.publisher.label" />
</label>
<div class="col-sm-3">
<form:input path="publisher" class="form-control" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<!-- <label class="col-sm-2 control-label">분야</label> -->
<spring:message code="addBook.form.category.label" />
</label>
<div class="col-sm-3">
<form:input path="category" class="form-control" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<!-- <label class="col-sm-2 control-label">재고수</label> -->
<spring:message code="addBook.form.unitsInStock.label" />
</label>
<div class="col-sm-3">
<form:input path="unitsInStock" class="form-control" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<!-- <label class="col-sm-2 control-label">출판일</label> -->
<spring:message code="addBook.form.releaseDate.label" />
</label>
<div class="col-sm-3">
<form:input path="releaseDate" class="form-control" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<!-- <label class="col-sm-2 control-label">상태</label> -->
<spring:message code="addBook.form.condition.label" />
</label>
<div class="col-sm-3">
<form:radiobutton path="condition" value="New" />New
<form:radiobutton path="condition" value="Old" />Old
<form:radiobutton path="condition" value="E-Book" />E-Book
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 control-label">
<!-- <label class="col-sm-2 control-label">도서이미지</label> -->
<spring:message code="addBook.form.bookImage.label" />
</label>
<div class="col-sm-7">
<form:input path="bookImage" type="file" class="form-control" />
</div>
</div>
<div class="form-group row">
<div class="col-sm-offset-2 col-sm-10">
<!-- <input type="submit" class="btn btn-primary" value="등록" /> -->
<input type="submit" class="btn btn-primary" value="<spring:message code="addBook.form.button.label" />" />
</div>
</div>
</fieldset>
</form:form>
<hr>
<footer>
<p>© BookMarket</p>
</footer>
</div>
</body>
</html>
<sprng:message>태그를 사용해 뷰 페이지에 출력한다.
12.3 LocaleResolver와 LocaleChangeInterceptor를 이용한 다국어 변경
LocaleResolver은 다양한 언어로 작성된 메시지 리소스 파일을 읽어 웹 브라우저의 로케일에 따라 각 언어에 해당하는 메시지로 설정할 수 있다.
LocaleChangeInterceptor은 다양한 언어를 자유롭게 선택해 변경할 수 있다.
12.3.1 LocaleResolver 환경 설정
스프링 MV는 LocaleResolver로 웹 브라우저의 로케일을 추출해 알맞은 언어를 선택하여 메시지를 출력한다.
디스패처 서블릿은 웹 요청이 들어오면 LocaleResolver를 검색한다. 로케일 객체가 검색되면 이것을 이용해 로케일을 설정한다.
<beans:bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<beans:property name="defaultLocale" value="로케일 언어" />
</beans:bean>
* 구현체란 인터페이스 객체를 구현한 클래스를 말한다.
(ex) class b implement a 일때 클래스 b를 말한다.)
* 로케일 언어에는 ko, en 등이 들어간다.
LocaleResolver 구현체의 유형
유형 | 설명 |
AcceptHeader:ocaleResolver | 웹 브라우저에 설정된 기본 로케일 정보를 사용한다. HTTP 요청의 aceept-language 헤더에 지정된 기본 로케일을 사용한다. |
CookieLocaleResolver | 쿠키를 이용한 로케일 정보를 사용한다. 사용자 지정 로케일, 표준 시간대 정보를 브라우저 쿠키로 유지하낟. |
SessionLocaleResolver | 세션을 이용한 로케일 정보를 사용한다. 사용자 세션에 locale 속성을 사용해 지정된 기본 로케일 또는 요청의 accept-header 로케일로 대체한다. |
FixedLocaleResolver | 특정 로케일을 지정한다. 항상 고정된 기본 로케일을 반환하고 선택적으로 시간대를 반환한다. |
* CookieLocaleResolver와 SessionLocaleResolver는 웹 브라우저의 로케일에 따라 원하는 언어를 선택해 서비스할 수 있다.
* FixedLocaleResolver는 웹 브라우저의 로케일과 상관 없이 지정된 언어만 서비스한다.
12.3.2 LocaleChangeInterceptor를 이용한 로케일 변경
LocaleChangeInterceptor 클래스는 로케일을 변경하는 별도의 컨트롤러 클래스를 구현할 필요 없이 메시지를 해당 언어로 변경할 수 있다.
웹 요청의 매개변수를 사용해 로케일로 바꾸는 방법이다.
LocaleChangeInterceptor 클래스는 HandlerInterceptor로 <interceptors> 요소에 등록하면 디스패처 서블릿이 컨트롤러에 접근할 때 응답은 가로채 LocaleChangeInterceptor를 적용할 수 있다.
<interceptors>
<beans:bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<beans:property name="paramName" value="language" />
</beans:bean>
</interceptors>
12.3.3 LocaleResolver와 LocaleChangeInterceptor 를 이용하여 다국어 변경하기
servlet-context.xml
<interceptors>
<beans:bean class="com.springmvc.interceptor.MonitoringInterceptor"/>
<!-- <beans:bean class="com.springmvc.interceptor.AuditingInterceptor"/> -->
<beans:bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<beans:property name="paramName" value="language" />
</beans:bean>
</interceptors>
<beans:bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<beans:property name="defaultLocale" value="ko" />
</beans:bean>
<!-- 12.2.4 다국어 처리 -->
<beans:bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<beans:property name="basename" value="messages"/>
<beans:property name="defaultEncoding" value="utf-8"/>
</beans:bean>
</beans:beans>
SessionLocaleResolver은 기본으로 제공할 로케일을 지정한다.
addBook.jsp
<div class="float-right" style="padding-right:30px">
<a href="?language=ko">Korean</a>|<a href="?language=en">English</a>
</div>
a 태그를 클릭하면 파라미터로 ?language=ko를 들고 간다.
이때 url이 따로 지정되어 있지 않는데 지정되어 있지 않으므로 현재 url을 사용한다.
그러므로 books/add에서 a 클릭하면 현재 url 뒤로 +되어 표기한다.
아무것도 입력하지 않은채로 add에 접속하면 ko로 넘어가는데 이것은 defaultLocale의 value가 ko로 지정되어 있기 때문에 기본 페이지가 ko로 지정되어 있다.
'코딩 > spring' 카테고리의 다른 글
spring & jsp 객체 & 애너테이션 정리 (0) | 2024.01.29 |
---|---|
[16주 5일차] 유효성 검사 (0) | 2024.01.26 |
[16주 4일차] 로그 순서 (1) | 2024.01.25 |
[16주 4일차] 로그 (2) (0) | 2024.01.25 |
[16주 3일차] 로그 기록 : 로그 기록 만들기 (1) | 2024.01.24 |
- Total
- Today
- Yesterday