#MessageResourceでメッセージをYAMLファイルから読み出す
##動機
messages.properties
のメンテ面倒くさいんですけおお!!
Eclipseで触ると勝手にnative2ascii
してくれちゃって困るし!!11!!1
だからYAML
で書こうね
##目的
SpringFrameworkを使ったアプリケーションでi18n対応をする場合、messages.properties
のようなリソースファイル(拡張子が.properties
なプロパティファイル)を使用することになる。
こういうやつだ
message_ja.properties
#階層構造で書けないんですか?やだー!
site.title=サイトタイトル
site.description=サイトの説明
page.header.links.index=サイトトップ
page.header.links.gettingstart=はじめる
page.header.links.document=ドキュメント
page.header.links.community=コミュニティ
これをこう書きたい。2
message_ja.yaml
#階層構造で書けるんですか?native2asciiしなくていいんですか?やったー!
site:
title: "サイトタイトル"
description: "サイトの説明"
page:
header:
links:
index: "サイトトップ"
gettingstart: "はじめる"
document: "ドキュメント"
community: "コミュニティ"
ググってもそのものズバリの実装例が見つからなかったのでこうやって記事にしておく。
##プロジェクト構成例
メッセージリソースをYAML対応させるためのプロジェクトの構成例。3
Yamlファイルからの読み出しにはYamlResourceBundleを使用している。4
各ファイルの内容は以下の通り。
やってる事は単純なので読めば分かると思う。なので細かい解説は省略。
build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.springframework.boot:spring-boot-gradle-plugin:2.0.2.RELEASE'
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
bootJar {
baseName = 'exercise1'
version = '0.0.1-SNAPSHOT'
}
repositories {
mavenCentral()
}
dependencies {
compile 'org.springframework.boot:spring-boot-devtools'
compile 'org.springframework.boot:spring-boot-starter-web'
compile 'org.springframework.boot:spring-boot-starter-thymeleaf'
compile 'net.rakugakibox.util:yaml-resource-bundle:1.1'
}
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
ext['mainClass'] = 'pkg.exercise1.App'
ext['thymeleaf.version'] = '3.0.9.RELEASE'
ext['thymeleaf-layout-dialect.version'] = '2.3.0'
config/application.yml
spring:
thymeleaf:
mode: "HTML"
messages:
basename: "i18n/messages"
encoding: "UTF-8"
i18n/messages.yml
site:
title: "Excercise"
description: "このメッセージはYAMLリソースファイルから出力していますよ"
templates/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title data-th-text="#{site.title}">Title</title>
</head>
<body>
<div>
<article>
<h1 data-th-text="#{site.title}">Title</h1>
<p data-th-text="#{site.description}">This is Index page. Yeah!</p>
<hr />
<h2>API</h2>
<ul>
<li><a href="#" data-th-href="@{/api/hello}">/api/hello</a></li>
</ul>
</article>
</div>
</body>
</html>
pkg/exercise1/App.java
package pkg.exercise1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class App {
public static void main(String... args) {
SpringApplication.run(App.class, args);
}
}
pkg/exercise1/configurations/MessageSourceConfig.java
package pkg.exercise1.configurations;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import net.rakugakibox.util.YamlResourceBundle;
@Configuration
public class MessageSourceConfig {
@Bean("messageSource")
public MessageSource messageSource(
@Value("${spring.messages.basename}") String basename,
@Value("${spring.messages.encoding}") String encoding
) {
YamlMessageSource ms = new YamlMessageSource();
ms.setBasename(basename);
ms.setDefaultEncoding(encoding);
ms.setAlwaysUseMessageFormat(true);
ms.setUseCodeAsDefaultMessage(true);
ms.setFallbackToSystemLocale(true);
return ms;
}
}
class YamlMessageSource extends ResourceBundleMessageSource {
@Override
protected ResourceBundle doGetBundle(String basename, Locale locale) throws MissingResourceException {
return ResourceBundle.getBundle(basename, locale, YamlResourceBundle.Control.INSTANCE);
}
}
pkg/exercise1/controllers/IndexController.java
package pkg.exercise1.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class IndexController {
@RequestMapping("/")
String home() {
return "index";
}
}
##ブラウザ表示
SpringBootアプリケーションを起動してhttp://localhost:8080にアクセスしてみる。
やったぜ。5