OutSystemsのReactive Web Appで多言語化対応する

__2021/5/12追記：正式な多言語対応機能の発表に伴い、下記Forgeコンポーネントは2021/6/5でdiscontinuedになります。今後は正式な多言語機能の方を使ったほうがいいです。__


2019/10に追加されたReactive Web Appでは、これまでのWebアプリケーション(Traditional Web)にあったMultilingual Localesによる多言語対応機能が使えません。

[OutSystemsのProduct DesignerによるForumの投稿](https://www.outsystems.com/forums/discussion/52761/reactive-web-the-next-generation-of-web-apps/#Post197456)によると、やがて対応されそうですが、少なくとも2019/11/2時点では未対応です。
> Regarding multilingual, you are right, this is similar to mobile. We might improve this in the future.

モバイルでも同様の問題があって、モバイルアプリケーションを多言語化対応させるForgeコンポーネントが作られています。最近、そのコンポーネントがバReactive Web Appでも使えるようになったので動作確認してみます。

以前ブログの方に書いた以下の記事は、モバイルアプリケーション対象で同じコンポーネントを用いて多言語化対応する手順を確認しています。
[複数言語対応(3)モバイル](https://blog.house-soft.info/archives/1307)

# サンプル
Forgeコンポーネント：https://www.outsystems.com/forge/Component_Overview.aspx?ProjectId=7086
Multilingual Screenを参照してください。

# 環境
Personal Environment(Version 11.0.606.0)
Service Studio(Version 11.6.6)
Multilingual Component(Version 2.0.3)

# Multilingual Component
[ForgeのVersionsの記述](https://www.outsystems.com/forge/component-versions/1784)によると、Version2.0.2から、Reactive Web Appに対応したとのこと。

モジュールの種類が、新たに作成されたLibraryになっています。
よってこのモジュールはこれまでのモバイルからだけでなく、Reactive Web Appからも参照できることになります。
![qReactiveML1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/71d17f64-1485-147b-0cb5-39ff3ba83eb0.png)

参照追加もしておきます。Manage Dependenciesから、MultiLingualの全要素を選択しておきます。
![qReactiveML2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/9603d4c2-0b59-09d1-fa28-04c091b51354.png)

# テスト画面用意
「Bulk Actions」Screen Templateを使ってScreenを用意します。
Screen Templateをベースに作った画面はテキストが全部英語です。これを日本語に変換できるようにします。ロケールを日本語と英語で切り替えるため、画面上にSwitch Widgetを配置しておきます。
![qReactiveML3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/113dbafc-c573-8877-bf42-389ffec47f76.png)

# 翻訳データを用意する
データはJSONで用意。
翻訳先のロケールごとに翻訳データをオブジェクトにし、その配列として作成します。
localeプロパティに翻訳先のロケール、translationsには、キーに対する翻訳後の文言をオブジェクトとして設定。キーはアプリケーション内で一意でなければいけません。

```json
[
    {
        "locale": "ja-JP",
        "isRightToLeft": false,
        "translations": {
            "A001": "製品リスト",
            "A002": "選択した製品を削除",
            "A003": "製品を追加",
            "A004": "名前",
            "A005": "カテゴリー",
            "A006": "価格",
            "A007": "最大在庫",
            "A008": "在庫閾値"
        }
    }   
]
```

これを.jsonファイルにし、Resourcesに配置します。
Deploy ActionをDeploy to Target Directoryに。
![qReactiveML4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/99d38872-c150-cc1f-c9f8-178f1dd00947.png)

# 翻訳処理を追加
## まずはResourceをロード
翻訳Functionを呼び出す前にMultiLingual Componentに含まれるAddTranslatinonsFromResourceを呼び出しておきます。

翻訳処理はScreen内で呼び出すので、確実にScreen処理より早く動くタイミングにします。
ここでは、Client Actionsを右クリック => Add System EventからOnApplicationReadyのイベントハンドラーを作成し、その中にAddTranslationsFromResourceを配置することにします。

このActionはResourceに翻訳データ(JSONファイル)があることを前提に、そのパスをResourceUrlに要求します。
配置したResourceのJSONファイルのRuntime Pathをコピーして設定すればいいですね。

## Screenに翻訳処理を設定
翻訳処理は、Functionとして定義されています。
翻訳処理を行いたい場所に、MultiLingualのGetTranslation呼び出しを設定してください。

Function呼び出しなのでText WidgetはExpression WidgetにConvertしてから。
GetTranslationの第一引数は、用意しておいた翻訳データのキーを指定。第二引数はデフォルト文言。該当なしの場合にこの値が返ってきます。デフォルトロケール用の文言を設定しておくといいと思います。
![qReactiveML5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/de5cb4be-a778-4c23-3e53-47b646f5ab7e.png)

# ロケール設定
画面に追加したスイッチがオンになったとき、ロケールを日本語(ja-JP)にします。
Switch WidgetのOn Change Eventに以下のScreen Actionを設定しておきます。
これで、スイッチがオンになったら日本語、オフになったらデフォルトロケールに。
![qReactiveML6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/f583b112-a81a-3f26-75e9-a862d24ab563.png)

SetLocaleに渡しているInput Paramete:
`If(BooleanVar, "ja-JP", "")`

切り替えたあと、新しいロケールで翻訳文言を再取得するため、同じ画面を開き直しています(Destination)。
そこで、画面のOn Initialize Event(画面遷移直前に発生するイベント)でMultiLingualのGetLocaleで現在のロケールを判定してスイッチを適切に設定しないといけません。

![qReactiveML7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/b5cf1bd5-6bef-59be-e46f-b21ade8fe3d0.png)

# 動作確認
スイッチをオンにした状態。
Screen Templateで固定テキストだった部分を翻訳対応してあります。

![qReactiveML8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/8db32144-bb00-a2f3-a35b-01fba85c1cd3.png)