4.8. 国際化¶
4.8.1. Overview¶
国際化とは、アプリケーションで表示するラベルやメッセージを、特定の言語のみに固定せず、ロケール(Locale)と呼ばれる言語や国・地域を表す単位の指定により、複数言語の切り替えに対応させることである。
本節では、画面に表示するメッセージを国際化する方法について説明する。
国際化するためには、以下の対応が必要となる。
画面内のテキスト要素(コード値の名称、メッセージ、GUIコンポーネントのラベルなど)は、プログラム内でハードコードせずに、プロパティファイルなどの外部定義から取得する。
クライアントからLocaleを指定する仕組みを提供する。
クライアントからLocaleを指定する方法は以下の通りである。
標準のリクエストヘッダを使用する。(ブラウザの言語設定で指定)
リクエストパラメータを使用してCookieに保存する。
リクエストパラメータを使用してSessionに保存する。
Localeの切り替えイメージを以下に示す。
Note
Codelistの国際化方法については、コードリストを参照されたい。
Note
エラー画面を国際化する必要がある場合、Spring MVCのControllerを使用してエラー画面に遷移すること。
Spring MVCを介さずエラー画面に直接遷移した場合、メッセージが意図した言語で出力されない場合がある。
詳細については国際化が適用されない場合の対処方法を参照されたい。
Tip
国際化はi18nという略称が広く知られている。
i18n という記述は、internationalization の先頭の i と語尾の n の間に nternationalizatio の18文字があることに起因する。
4.8.2. How to use¶
4.8.2.1. メッセージ定義の設定¶
画面に表示するメッセージを国際化する場合は、メッセージを管理するためのコンポーネント(MessageSource
)として、
org.springframework.context.support.ResourceBundleMessageSource
org.springframework.context.support.ReloadableResourceBundleMessageSource
のどちらかを使用する。
ここでは、ResourceBundleMessageSource
を使用する場合の設定例を紹介する。
ApplicationContextConfig.java
@Bean("messageSource")
public MessageSource messageSource() {
ResourceBundleMessageSource bean = new ResourceBundleMessageSource();
bean.setBasenames("i18n/application-messages"); // (1)
return bean;
}
項番
|
説明
|
---|---|
(1)
|
プロパティファイルの基底名として、
i18n/application-messages を指定する。国際化対応を行う場合、i18nディレクトリ配下にメッセージプロパティファイルを格納することを推奨する。
MessageSource の詳細や定義方法は、メッセージ管理を参照されたい。 |
applicationContext.xml
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>i18n/application-messages</value> <!-- (1) -->
</list>
</property>
</bean>
項番
|
説明
|
---|---|
(1)
|
プロパティファイルの基底名として、
i18n/application-messages を指定する。国際化対応を行う場合、i18nディレクトリ配下にメッセージプロパティファイルを格納することを推奨する。
MessageSource の詳細や定義方法は、メッセージ管理を参照されたい。 |
プロパティファイルの格納例
プロパティファイルは、以下のルールに則って作成する。
Locale毎のファイル名は、
application-messages_XX.properties
という形式で作成する。(XX部分はLocaleを指定)application-messages.properties
は必ず作成する。もし存在しない場合、MessageSource
からメッセージを取得できず以下の様な状態となる。JSPにメッセージを設定する際に
JspTagException
が発生する。Thymeleafでは、
MessageSource
からメッセージを取得できず、??メッセージID??
という形式でメッセージIDが出力される。
application-messages.properties
に定義するメッセージは、デフォルトで使用する言語で作成する。
上記ルールに則ってプロパティファイルを作成すると、以下のような動作になる。
クライアントのLocaleがzhの場合、
application-messages_zh.properties
が使用される。クライアントのLocaleがjaの場合、
application-messages_ja.properties
が使用される。クライアントのLocaleに対応するプロパティファイルが存在しない場合、デフォルトとして、
application-messages.properties
が使用される。(ファイル名に”_XX”部分が存在しないファイル)
Note
Localeの判別方法は、以下の順番で該当するLocaleのプロパティファイルが発見されるまで、Localeを確認していくことである。
クライアントから指定されたLocale
アプリケーションサーバのJVMに指定されているLocale(設定されていない場合あり)
アプリケーションサーバのOSに指定されているLocale
よく間違える例として、 クライアントから指定されたLocaleのプロパティファイルが存在しない場合、デフォルトのプロパティファイルが使用されるとの誤解が挙げられる。
実際は、次にアプリケーションサーバに指定されているLocaleを確認して、それでも該当するLocaleのプロパティファイルが見つからない場合に、デフォルトのプロパティファイルが使用されるので注意する。
Tip
メッセージプロパティファイルの記載方法については、メッセージ管理を参照されたい。
4.8.2.2. Localeをブラウザの設定により切り替える¶
4.8.2.2.1. AcceptHeaderLocaleResolverの設定¶
ブラウザの設定を使用してLocaleを切り替える場合は、AcceptHeaderLocaleResolver
を使用する。
SpringMvcConfig.java
// (1)
@Bean("localeResolver")
public AcceptHeaderLocaleResolver localeResolver() {
AcceptHeaderLocaleResolver bean = new AcceptHeaderLocaleResolver();
bean.setDefaultLocale(Locale.ENGLISH); // (2)
List<Locale> locales = new ArrayList<Locale>();
locales.add(Locale.ENGLISH);
locales.add(Locale.JAPANESE);
bean.setSupportedLocales(locales); // (3)
return bean;
}
項番
|
説明
|
---|---|
(1)
|
org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver をbean定義する。この
LocaleResolver を使用すると、リクエスト毎に設定されるHTTPヘッダー(”accept-language”)に指定されているLocaleが使用される。 |
(2)
|
デフォルトのLocaleを設定するため、
defaultLocale プロパティを設定する。上記の例では、アプリケーションがサポートしていないLocaleがリクエストされた場合、Localeは”en”に設定される。
|
(3)
|
アプリケーションがサポートするLocaleを設定するため、
supportedLocales プロパティを設定する。リクエストが要求するLocaleと、サポートするLocaleが一致する場合はそのLocaleが使用される。
国と言語を組み合わせたLocale(例:ja_JP)が要求され、サポートするLocaleと一致しない場合、対応する言語のみのLocale(例:ja)で一致を確認する。
上記の例では、アプリケーションがサポートするLocaleとして、”en”と”ja”を指定している。
|
spring-mvc.xml
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver"> <!-- (1) -->
<property name="defaultLocale" value="en" /> <!-- (2) -->
<property name="supportedLocales"> <!-- (3) -->
<list value-type="java.util.Locale">
<value>en</value>
<value>ja</value>
</list>
</property>
</bean>
項番
|
説明
|
---|---|
(1)
|
beanタグのid属性”localeResolver”に
org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver を指定する。この
LocaleResolver を使用すると、リクエスト毎に設定されるHTTPヘッダー(”accept-language”)に指定されているLocaleが使用される。 |
(2)
|
デフォルトのLocaleを設定するため、
defaultLocale プロパティを設定する。上記の例では、アプリケーションがサポートしていないLocaleがリクエストされた場合、Localeは”en”に設定される。
|
(3)
|
アプリケーションがサポートするLocaleを設定するため、
supportedLocales プロパティを設定する。リクエストが要求するLocaleと、サポートするLocaleが一致する場合はそのLocaleが使用される。
国と言語を組み合わせたLocale(例:ja_JP)が要求され、サポートするLocaleと一致しない場合、対応する言語のみのLocale(例:ja)で一致を確認する。
上記の例では、アプリケーションがサポートするLocaleとして、”en”と”ja”を指定している。
|
Note
LocaleResolver
が設定されていない場合、デフォルトでorg.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
が使用されるため、LocaleResolver
の設定は、省略することもできる。
4.8.2.2.2. メッセージの設定¶
以下に、メッセージの設定例を示す。
application-messages.properties
title.admin.top = Admin Top
application-messages_ja.properties
title.admin.top = 管理画面 Top
4.8.2.2.3. 実装¶
include.jsp(インクルード用の共通jspファイル)
<%@ page session="false"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%> <!-- (1) -->
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec"%>
<%@ taglib uri="http://terasoluna.org/functions" prefix="f"%>
<%@ taglib uri="http://terasoluna.org/tags" prefix="t"%>
項番
|
説明
|
---|---|
(1)
|
JSPで出力する場合、Springのタグライブラリを用いてメッセージ出力を行うため、カスタムタグを定義する必要がある。
<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> を定義すること。 |
Note
インクルード用の共通jspファイルの詳細はインクルード用の共通JSPの作成を参照されたい。
画面表示用JSPファイル
<spring:message code="title.admin.top" /> <!-- (2) -->
項番
|
説明
|
---|---|
(2)
|
JSPでは、Springのタグライブラリである、
<spring:message> を用いてメッセージ出力を行う。code属性に、プロパティで指定したキーを設定する。
本例では、Localeがjaの場合”管理画面 Top”、それ以外のLocaleの場合”Admin Top”が出力される。
|
テンプレートHTMLファイル
<span th:text="#{title.admin.top}"></span> <!-- (1) -->
項番
|
説明
|
---|---|
(1)
|
メッセージ式
#{} を用いてメッセージ出力を行う。本例では、Localeがjaの場合”管理画面 Top”、それ以外のLocaleの場合”Admin Top”が出力される。
|
4.8.2.3. Localeを画面操作等で動的に変更する¶
Localeを画面操作等で動的に変更する方法は、ユーザ端末(ブラウザ)の設定に関係なく、特定の言語を選択させたい場合に有効である。
画面操作でLocaleを変更する場合のイメージを以下に示す。
ユーザが使用する言語を選択する場合は、org.springframework.web.servlet.i18n.LocaleChangeInterceptor
を用いることで実現する事ができる。
LocaleChangeInterceptor
は、リクエストパラメータに指定されたLocaleの値を、org.springframework.web.servlet.LocaleResolver
のAPIを使用してサーバ又はクライアントに保存するためのインタセプターである。
使用するLocaleResolver
の実装クラスを、以下の表から選択する。
No |
実装クラス |
Localeの保存方法 |
---|---|---|
|
サーバーに保存(
HttpSession を使用) |
|
|
クライアントに保存(
Cookie を使用) |
Note
LocaleResolver
にorg.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
を使用する場合、
org.springframework.web.servlet.i18n.LocaleChangeInterceptor
を使用してLocaleを動的に変更することはできない。
4.8.2.3.1. LocaleChangeInterceptorの設定¶
リクエストパラメータを使用してLocaleを切り替える場合は、LocaleChangeInterceptor
を使用する。
SpringMvcConfig.java
@EnableAspectJAutoProxy
@EnableWebMvc
@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// omitted
registry.addInterceptor(localeChangeInterceptor()).addPathPatterns("/**") // (1)
.excludePathPatterns("/resources/**");
}
// (1)
@Bean("localeChangeInterceptor")
public LocaleChangeInterceptor localeChangeInterceptor() {
return new LocaleChangeInterceptor();
}
項番
|
説明
|
---|---|
(1)
|
Spring MVCのインタセプターに、
org.springframework.web.servlet.i18n.LocaleChangeInterceptor を定義する。この設定により、”リクエストURL?locale=xx”で使用可能となる。
|
spring-mvc.xml
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/resources/**" />
<bean
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"> <!-- (1) -->
</bean>
<!-- omitted -->
</mvc:interceptor>
</mvc:interceptors>
項番
|
説明
|
---|---|
(1)
|
Spring MVCのインタセプターに、
org.springframework.web.servlet.i18n.LocaleChangeInterceptor を定義する。この設定により、”リクエストURL?locale=xx”で使用可能となる。
|
Note
Localeを指定するリクエストパラメータ名の変更方法
@Bean("localeChangeInterceptor") public LocaleChangeInterceptor localeChangeInterceptor() { LocaleChangeInterceptor bean = new LocaleChangeInterceptor(); bean.setParamName("lang"); // (2) return bean; }
項番 説明 (2)paramName
プロパティにリクエストパラメータ名を指定する。上記例では、”リクエストURL?lang=xx”となる。<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"> <property name="paramName" value="lang"/> <!-- (2) --> </bean>
項番 説明 (2)paramName
プロパティにリクエストパラメータ名を指定する。上記例では、”リクエストURL?lang=xx”となる。
Note
LocaleChangeInterceptor
はSpring MVCのControllerの処理実行時に呼ばれるインターセプタであるため、Controllerを経由しない遷移の場合は適用されないことに注意されたい。
なお、LocaleChangeInterceptor
だけでなくViewResolver(ThymeleafViewResolver
など)も同様にControllerを経由しない遷移の場合は適用されない。
詳細は「ブランクプロジェクトの設定」を参照されたい。
Note
リクエストパラメータにLocaleとして使用できない文字(半角スペース、ハイフン、アンダースコア、英数字以外)を含む値が指定された場合、例外がスローされる。この時、前回のリクエストまでのLocaleが継続して有効になる。例外については、ignoreInvalidLocale
プロパティにtrue
を指定することでスローされなくなる。
リクエストパラメータにLocaleとして指定された値はJDKでサポートされないLocaleでも、そのままLocaleとして有効になる。LocaleChangeInterceptor
にはAcceptHeaderLocaleResolver
のsupportedLocales
のように、サポートするLocaleを限定する仕組みはないため、注意されたい。
空文字が指定された場合はLocaleResolver
に予め設定されたdefaultLocale
が有効になる。defaultLocale
が設定されていない場合はユーザ端末(ブラウザ)に設定されたLocaleが有効になる。
このため、defaultLocale
を設定することを推奨する。
4.8.2.3.2. SessionLocaleResolverの設定¶
Localeをサーバに保存する場合は、SessionLocaleResolver
を使用する。
SpringMvcConfig.java
// (1)
@Bean("localeResolver")
public SessionLocaleResolver localeResolver() {
SessionLocaleResolver bean = new SessionLocaleResolver();
bean.setDefaultLocale(Locale.ENGLISH); // (2)
return bean;
}
項番
|
説明
|
---|---|
(1)
|
org.springframework.web.servlet.LocaleResolver をBean定義する。本例では、セッションにLocaleを保存する
org.springframework.web.servlet.i18n.SessionLocaleResolver を指定している。bean名は”localeResolver”と設定すること。
この設定により、
LocaleChangeInterceptor 内の処理でSessionLocaleResolver が使用される。 |
(2)
|
defaultLocale プロパティにLocaleを指定する。セッションからLocaleが取得できない場合、value の設定値が有効になる。Note
|
spring-mvc.xml
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"> <!-- (1) -->
<property name="defaultLocale" value="en"/> <!-- (2) -->
</bean>
項番
|
説明
|
---|---|
(1)
|
beanタグのid属性を”localeResolver”で定義し、
org.springframework.web.servlet.LocaleResolver を実装したクラスを指定する。本例では、セッションにLocaleを保存する
org.springframework.web.servlet.i18n.SessionLocaleResolver を指定している。beanタグのid属性は”localeResolver”と設定すること。
この設定により、
LocaleChangeInterceptor 内の処理でSessionLocaleResolver が使用される。 |
(2)
|
defaultLocale プロパティにLocaleを指定する。セッションからLocaleが取得できない場合、value の設定値が有効になる。Note
|
4.8.2.3.4. メッセージの設定¶
以下に、メッセージの設定例を示す。
application-messages.properties
i.xx.yy.0001 = changed locale
i.xx.yy.0002 = Confirm change of locale at next screen
application-messages_ja.properties
i.xx.yy.0001 = Localeを変更しました。
i.xx.yy.0002 = 次の画面でのLocale変更を確認
4.8.2.3.5. 実装¶
画面表示用JSPファイル
<a href='${pageContext.request.contextPath}?locale=en'>English</a> <!-- (1) -->
<a href='${pageContext.request.contextPath}?locale=ja'>Japanese</a>
<spring:message code="i.xx.yy.0001" />
項番
|
説明
|
---|---|
(1)
|
Localeを切り替えるためのパラメータを送信する。
リクエストパラメータ名は、
LocaleChangeInterceptor のparamName プロパティに指定した値となる。(上記例では、デフォルトのパラメータ名を使用している)上記例の場合、Englishリンクで英語Locale、Japaneseリンクで日本語Localeに変更している。
以降は、選択したLocaleが有効になる。
英語Localeは”en”用のプロパティファイルが存在しないため、デフォルトのプロパティファイルから読み込まれる。
|
Tip
インクルード用の共通jspにSpringのタグライブラリを定義する必要がある。
インクルード用の共通jspファイルの詳細はインクルード用の共通JSPの作成を参照されたい。
テンプレートHTMLファイル
<a th:href="@{/(locale='en')}">English</a> <!-- (1) -->
<a th:href="@{/(locale='ja')}">Japanese</a>
<span th:text="#{i.xx.yy.0001}"></span>
項番
|
説明
|
---|---|
(1)
|
Localeを切り替えるためのパラメータを送信する。
リクエストパラメータ名は、
LocaleChangeInterceptor のparamName プロパティに指定した値となる。(上記例では、デフォルトのパラメータ名を使用している)上記例の場合、Englishリンクで英語Locale、Japaneseリンクで日本語Localeに変更している。
以降は、選択したLocaleが有効になる。
英語Localeは”en”用のプロパティファイルが存在しないため、デフォルトのプロパティファイルから読み込まれる。
|
4.8.2.3.6. 国際化が適用されない場合の対処方法¶
LocaleChangeInterceptor
はSpring MVCのController
の処理実行時に呼ばれるインターセプタであるため、Controller
を経由しない遷移の場合は国際化が適用されないことに注意されたい。
Controller
が使用されない。Controller
を作成し、エラー画面への遷移に使用することでLocaleChangeInterceptor
が使用されるように設定する必要がある。設定方法について、Spring Securityの認可の実装を例に以下に示す。
LocaleChangeInterceptorが適用されないエラー画面への遷移例
SpringSecurityConfig.java
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// omitted
http.exceptionHandling(ex -> ex.accessDeniedHandler(
accessDeniedHandler()));
return http.build();
}
@Bean("accessDeniedHandler")
public AccessDeniedHandler accessDeniedHandler() {
LinkedHashMap<Class<? extends AccessDeniedException>, AccessDeniedHandler> errorHandlers = new LinkedHashMap<>();
// omitted
AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl();
accessDeniedHandler.setErrorPage(
"/WEB-INF/views/common/error/accessDeniedError.jsp"); // (1)
return new DelegatingAccessDeniedHandler(errorHandlers, accessDeniedHandler);
}
項番 |
説明 |
---|---|
(1)
|
AccessDeniedHandlerImpl クラスに認可エラー用のエラー画面をJSPで指定する。 |
spring-security.xml
<sec:http request-matcher="ant">
<!-- omitted -->
<sec:access-denied-handler
error-page="/WEB-INF/views/common/error/accessDeniedError.jsp" /> <!-- (1) -->
<!-- omitted -->
</sec:http>
項番 |
説明 |
---|---|
(1)
|
<sec:access-denied-handler> タグのerror-page 属性に認可エラー用のエラー画面をJSPで指定する。 |
LocaleChangeInterceptorが適用されるエラー画面への遷移例
SpringSecurityConfig.java
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// omitted
http.exceptionHandling(ex -> ex.accessDeniedHandler(
accessDeniedHandler()));
return http.build();
}
@Bean("accessDeniedHandler")
public AccessDeniedHandler accessDeniedHandler() {
LinkedHashMap<Class<? extends AccessDeniedException>, AccessDeniedHandler> errorHandlers = new LinkedHashMap<>();
// omitted
AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl();
accessDeniedHandler.setErrorPage(
"/common/error/accessDeniedError"); // (1)
return new DelegatingAccessDeniedHandler(errorHandlers, accessDeniedHandler);
}
項番 |
説明 |
---|---|
(1)
|
AccessDeniedHandlerImpl クラスに認可エラー用のエラー画面のパスを設定する。 |
spring-security.xml
<sec:http request-matcher="ant">
<!-- omitted -->
<sec:access-denied-handler
error-page="/common/error/accessDeniedError" /> <!-- (1) -->
<!-- omitted -->
</sec:http>
項番 |
説明 |
---|---|
(1)
|
<sec:access-denied-handler> タグのerror-page 属性に認可エラー用のパスを設定する。 |
Controllerクラス
@Controller
@RequestMapping("/common/error") // (1)
public class ErrorController {
@RequestMapping(value = "accessDeniedError", method = { RequestMethod.GET,
RequestMethod.POST }) // (1)
public String accessDeniedError() {
return "common/error/accessDeniedError"; // (2)
}
}
項番 |
説明 |
---|---|
(1)
|
エラー画面へ遷移するためにリクエストマッピングを定義する。
|
(2)
|
遷移するエラー画面のView名を返却する。
|
Warning
一般的に、エラー画面にはGETリクエストだけでなくPOSTリクエストからも遷移する可能性があるため、<mvc:view-controller>
は使用しないことを推奨する。
<mvc:view-controller>
使用時の留意点については HTMLを応答するを参照されたい。