React + Polyglot で多言語化対応をおこなう

# はじめに
今のチームでは、多言語化対応をおこなう際、Airbnb製のライブラリである`node-polyglot`を使っています。

Reactの多言語化でポピュラーなライブラリとして`react-intl`があります。
しかし我々の場合は、フロントエンドにReactを採用したのは最近のため、これまで利用していたライブラリを継続して使う形で開発をしています。

今回はその使い方を簡単にまとめました。

# 開発で用いる環境の構築
ここでは、`create-react-app`で環境を構築しています。
動作確認のための環境なので、 tslint のエラーが出ないように少し設定をいじっています。
`tslint.json`の`rules`は以下の通りです。

```json
"rules": {
  "no-var-requires": false,
  "interface-name": [true, "never-prefix"],
  "no-empty-interface": false,
  "jsx-no-lambda": false,
  "no-console": false,
  "member-access": false
}
```

# コードの実装方法
ライブラリをインポートし、変換用のファイルを読み込みます。

```javascript
import * as Polyglot from 'node-polyglot';
import * as React from 'react';

const jaTranslations = require('../locales/ja.json');
const enTranslations = require('../locales/en.json');
const polyglot = new Polyglot({ phrases: jaTranslations, locale: 'ja' });
const defaultLocale = 'ja';

/***** 略 *****/
```

言語を切り替えるボタンを押したさいに呼ぶ関数を定義します。
引数で渡される言語によって、`polyglot`の locale を変更します。
それだけだと画面に再レンダリングがされないため、`this.state.locale`を更新しています。
（もっとうまい方法がありそうですが、探せていません）

```javascript
setLocale = (locale?: string): void => {
  const selectedLocale = locale || defaultLocale;

  let translations = jaTranslations;
  switch (selectedLocale) {
    case 'ja':
      translations = jaTranslations;
      break;
    case 'en':
      translations = enTranslations;
      break;
  }

  polyglot.locale(selectedLocale);
  polyglot.replace(translations);
  this.setState({ locale: selectedLocale })
};

```

表示は以下のように実装します。

```javascript
const formStyle = {
  display: 'flex',
  height: 20,
  justifyContent: 'space-between',
  width: '50%',
} as React.CSSProperties;

return (
  <div>
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
      <div style={formStyle}>
        <label>{polyglot.t('username')}</label>
        <input type="text" />
      </div>
      <div style={formStyle}>
        <label>{polyglot.t('email')}</label>
        <input type="email" />
      </div>
      <div style={formStyle}>
        <label>{polyglot.t('password')}</label>
        <input type="password" />
      </div>
      <div style={formStyle}>
        <label>{polyglot.t('passwordConfirm')}</label>
        <input type="password" />
      </div>
      <div>
        <button
          type="submit"
          onClick={e => { console.log(e); }}
        >
          {polyglot.t('buttonApply')}
        </button>
      </div>
      <div>
        <button
          type="button"
          onClick={() => { this.setLocale('ja'); }}
        >
          {polyglot.t('buttonJa')}
        </button>
        <button
          type="button"
          onClick={() => { this.setLocale('en'); }}
        >
          {polyglot.t('buttonEn')}
        </button>
      </div>
    </div>
  </div>
);

```


# 言語設定ファイル
言語設定ファイルの中身は以下の通りです。

`ja.json`

```json

{
  "username": "ユーザー名",
  "email": "メールアドレス",
  "password": "パスワード",
  "passwordConfirm": "パスワード（確認）",
  "buttonApply": "無料登録",
  "buttonJa": "日本語",
  "buttonEn": "英語",
  "hello": "こんにちは"
}
```

`en.json`

```json

{
  "username": "username",
  "email": "email address",
  "password": "password",
  "passwordConfirm": "password(confirmation)",
  "buttonApply": "sign up",
  "buttonJa": "Japanese",
  "buttonEn": "English",
  "hello": "hello"
}
```

# 実際の動作
以下のような動作になります。

![polyglot_sample.gif](https://qiita-image-store.s3.amazonaws.com/0/43625/8f078313-7194-0794-de25-30e4ea2d6c6e.gif)

# おわりに
コード内に直接日本語を埋め込んでしまうと、将来の運用・調査時に余計な手間を増やすことになりかねません。

日本語を直に埋め込んだケースよりも、こちらの方がコードをきれいに保つことができます。
１言語しか使わないサービスでも導入の価値はあると考えています。

もっとよいライブラリなどがあれば、ぜひ教えていただけると幸いです。