Springで使うメッセージプロパティの多言語ファイル作成ツールを作ってみた

# 概要
Spring Bootを最近触り始めた中で、多言語対応の部分を簡略化できないかと考えました。
また、外部APIも取り込んだものを触ってみたい気持ちも合わさり、ノリと勢いで作成をしてみたため記事に残してみます。

## 本記事の対象
- Spring Bootを最近始めた方
- Spring Bootで多言語化してみたい人

# Spring Bootの多言語化について
まず今回作成したツールの話の前にSpring Bootにおいての通常の多言語対応についてお伝えいたします。
(すでにご存知な方は飛ばしていただけますと幸いです)
Spring Bootではメッセージプロパティというものであらかじめテキストを定義しておくことで、ブラウザの言語設定に合わせて自動でHTMLのテキストを変更してくれます。
また、メッセージプロパティを使用しておきますとテキストに変更が必要な際もHTMLファイルを触らずに対応できるのも強みですね。

## メッセージプロパティ使用例
手順としては簡単で、messages.propertiesというファイルを各言語分作成しておく形になります。

以下に例として昔Python(Flask)で作成したものを、前にSpringで作り直したものベースで紹介します。
[Flaskで作成したときの記事](https://qiita.com/strawberryjam/items/710a21329db109f62084)
[Spring版](https://github.com/murajo/RandomGreetingSpring.git)

まずHTML側で表示したいテキストを以下例のように用意しておきます。

```messages_ja.properties
# 日本語用

greeting.heading1=☆三種の挨拶☆
greeting.description=ボタンをクリックするたびに三種類の挨拶から一つ出力されるぞ！
greeting.button=挨拶
greeting.item=挨拶：
greeting.instructions=上のボタンを押してね
```
```messages_en.properties
# 英語用

greeting.heading1=☆Three types of greetings☆
greeting.description=Each time you click the button, one of three types of greetings will be output!
greeting.button=greeting
greeting.item=GREETING：
greeting.instructions=press the button above
```

あとは上記で定義した内容に合わせてHTML側に組み込みます。
組み込み方は以下のような形で記載します。
```html
<タグ th:text="#{定義した変数名}"><タグ>
```
```greeting.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
  layout:decorate="~{layout/layout}">

<head>
  <title>RandomGreeting</title>
  <script th:src="@{/js/greeting/greeting.js}" defer></script>
</head>

<body>
  <div layout:fragment="content">
    <h1 th:text="#{greeting.heading1}"></h1>
    <p th:text="#{greeting.description}"></p>
    <button id="btn-search" type="button" th:text="#{greeting.button}"></button>
    <br>
    <span th:text="#{greeting.item}"></span>
    <span id="greeting" th:text="#{greeting.instructions}"></span>
    <br>
    <img id="greetingImage" width="256" height="256" src="http://urx3.nu/Zlxt">
    <p hidden id=greetingId th:text="#{greeting.defaultId}"></p>
  </div>
</body>

</html>
```

では多言語対応の準備ができましたので、実際に確認してみます。
まずはブラウザの言語設定を日本語にした状態で見てみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/28b46a80-5fa2-4a5c-5c37-e5841955fc73.png)

日本語で表示されているのが確認できました。
それではブラウザの言語を英語にして再度アクセスしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/94fb3f85-3924-7af8-023a-7127f8df0fe1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/fcc9e063-7d5f-f445-3428-9103a2529a64.png)
そうしますと英語で表示されたのが確認できました。
このようにあらかじめmessages.propertiesというファイルを作成しておくことで、ブラウザの言語設定に合わせて自動で表示するテキストを変更することができます。

## 感じた課題
ただしこのmessages.propertiesですが複数言語を作っていくとなるとかなり手間がかかると思います。
例のものはテキスト量がかなり少なく、日本語と英語のみですが実際にはもっと多く表示する必要があるシステムもあります。
そこでベースとなる1言語のmessages.propertiesから多言語版を自動作成するツールを作成してみましたので紹介する形になります。
（めんどくさいと思ったことは自動化!!）

# 作成したツールの紹介
## 今回使用したもの
- Spring Boot
- H2 Database
- Deepl API
※ 他ライブラリ等は気になられる方は後述のgithubリンクよりpom.xmlを拝見して見てください。

### Spring Boot
Springアプリの開発を簡単に始めることができるフレームワークになります。
Springは初期設定でxmlファイルの作成などが大変でした。
一方pring Bootを利用すると使う機能を選択するだけで、必要な初期設定を行ってくれます。
また、設定変更もプロパティの値を変更するだけで後から簡単に行うことができます。

> Spring Boot を使用すると、「実行」可能なスタンドアロンの本番レベルの Spring ベースアプリケーションを簡単に作成できます。
Spring プラットフォームとサードパーティのライブラリに対して、Spring Boot の規約に従うことにより、最小限の手間で始めることができます。ほとんどの Spring Boot アプリケーションは、Spring の設定が不要です。
[引用元](https://spring.pleiades.io/projects/spring-boot)

### H2 Database
Java環境上で動作可能なインメモリ型のデータベースです。
インストールなども不要で簡単に組み込んで利用できます。
永続的にデータを保持する必要がない場合などに利用できます。

> 特徴
> - 非常に高速なオープン ソースの JDBC API
> - 埋め込みモードとサーバー モード。ディスクベースまたはインメモリ データベース
> - トランザクションのサポート、複数バージョンの同時実行
> - ブラウザベースのコンソール アプリケーション
> - 暗号化されたデータベース
> - 全文検索
> - フットプリントが小さい Pure Java: 約 2.5 MB の jar ファイル サイズ
> - ODBC ドライバー
[引用元](https://www.h2database.com/html/main.html)

### Deepl API
翻訳を行ってくれるAPIになります。
今回作るアプリケーションにおいては翻訳の機能が必要となるため、外部APIとしてDeepl APIを利用することにしました。

> DeepL APIでは、プログラムを使ってDeepLの機械翻訳技術にアクセスし、ウェブサイトやアプリを直接、高精度に翻訳できます。
[引用元](https://www.deepl.com/ja/docs-api)

## ソースコード
ソースコードは以下gitリポジトリにあげております。
H2 Databaseを使っておりますので、cloneすればそのまま使えます。

https://github.com/murajo/SpringMultilingualCreater.git


## 簡単な構成図
画面としてはAPI(Deepl)登録用の画面とメッセージプロパティを作成する画面の2つが用意されております。
あとは翻訳等の処理を実施するREST APIが2つある形になります。
（びっくりするぐらい雑な図で恐縮です。。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/4f9d54f5-9bd2-135f-33b7-e6be435b7b1a.png)

## 使い方
実際に実行してホスト名にアクセスをするとAPI Keyの登録画面に飛ばされます。
（API Keyが登録済みの場合は、メッセージプロパティ作成画面へリダイレクト）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/b4821c7e-f8b4-3313-5f2e-ab38450aa30d.png)

API Keyを入力して登録に成功すると、メッセージプロパティ作成画面へリダイレクトがされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/30377b68-b54d-9bd6-740c-1d1a7dc13ef1.png)

メッセージプロパティ作成画面では1つ元のmessages.propertiesの情報と、作成したい言語を指定します。
※今回試作のため、作成できる言語は「日本語、英語、中国語」にしております。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/de826d23-56a3-a60c-d023-7255a6afa5da.png)

それでは試しに本ツールの日本語のmessages.propertiesから英語版および中国版を作成してみようと思います。
まず本ツールの日本語のmessages.propertiesは以下のようになっております。
```messages_ja.properties
title=SpringMultilingualCreater
languageAuto=自動検出
languageJa=日本語
languageEn=英語
languageZh=中国語

register.heading1=API KEY 登録画面
register.description=APIキーを登録してください
register.button=登録

translate.heading1=メッセージプロパティ作成ツール
translate.description=1つのmessages.propertiesから他の言語版を作成します
translate.sourceLang=翻訳元の言語
translate.targetLang=翻訳後の言語
translate.targetTextPlace=翻訳元のメッセージプロパティを入力してください
translate.button=実行
```

実際にこちらの入力を行い実行してみると以下のように結果が返ってきます。
表示されるものは、作成するファイル名とその内容になります。
※表示された内容が元のものと比較して順番がバラバラになっているのが気になります。。（いつか原因みます）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/39c8b380-6640-c7c9-c243-32f6e47ba8bf.png)

それではお試しがてら英語版を本ツールに組み込んで確認してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/1ff09b5b-a387-fe48-1820-381539bfc741.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406495/611fc330-3c9e-762a-9aa4-927dbd7c1bc2.png)

無事に英語になったのが確認できました。
このようにmessages.propertiesを1言語分作成さえできれば残りを自動で作成することができるツールとなります。

# まとめ
本記事ではSpring Bootを使って外部APIのDeepl APIと連携したアプリケーションを紹介してみました。

実は気づきとして、Javaのクラス内変数とJsonのKey名を紐づけることができることを初めて知りました。
Deeplでは戻り値のJsonがスネークケースで返ってきます。
そのため、Jsonを直接Javaのクラスへ変換しようと思うと、Javaのクラス内変数を変えなければならないかと最初は思いました。
ただし、アノテーションで「@JsonProperty("○○_○○")」と書いておくことでJsonをクラスへ変換する際にJsonのKeyとクラス内変数を紐づけることができると知りました。
これで外部APIがスネークケースの場合もJava側はキャメルを守れそうです。

また、今回は自分用に作ったこともあり、例外的な入力などの処理等ほとんどできていないので今後はきちんと行えるように学習しておきます。（UIももう少し頑張ります。。）

まだSpring Bootは勉強し始めたばかり（Java自体もほぼ初心者）のため、今後も自動化できそうな部分があったら新たな気づきを得るチャンスと思いチャレンジしてみようと思います。