Nuxt.jsでメッセージの外出し＆国際化対応

# vue-i18nとnuxt-i18nがあるけど...
### <font color="red">nuxt-i18n</font> を使用します
- nuxt-i18nの方が更新が活発なのでこちらを使っていこうという単純な理由です。
- もう1つ、[nuxt-community/nuxt-i18n](https://github.com/nuxt-community/nuxt-i18n)のREADMEの通りにやってもいいのですが<font color="salmon">メンテがしにくい</font>と思い、`プラグインとして登録`し、メッセージを定義したjsonファイルを読み込むようにします。（+ 言語として日本語を設定）

# インストール
- 2019年11月23日現在の最新6.4.0をインストール

```
npm install --save nuxt-i18n@6.4.0
```
- package.json確認

```javascript:package.json
//省略
"dependencies": {
    //省略
    "nuxt-i18n": "^6.4.0",
    //省略
  },
```

#プラグインを作成する
- [nuxt-community/nuxt-i18n](https://github.com/nuxt-community/nuxt-i18n)のREADMEの通りにやってもいいのですが、メンテがしにくいと思い`プラグインとして登録`し、メッセージを定義したjsonファイルを読み込むようにします。（+ 言語として日本語を設定）
- `plugins/nuxt-i18n.ts`を作成。`locales/ja.json`に定義されているメッセージを読み込む設定。

```javascript:nuxt-i18n.ts
import Vue from 'vue'
import VueI18n from 'vue-i18n'

Vue.use(VueI18n)

export default ({ app, store }) => {
  // Set i18n instance on app
  // This way we can use it in middleware and pages asyncData/fetch
  app.i18n = new VueI18n({
    locale: store.state.locale,
    fallbackLocale: 'ja',
    messages: {
      ja: require('~/locales/ja.json')
    }
  })
}

export const i18n = new VueI18n({
  locale: 'ja',
  messages: {
    ja: require('~/locales/ja.json')
  }
})

```

# メッセージ定義ファイル（`ja.json`）を作成
- 一部抜粋してますが、`error`、`info`などでIDのprefixを分けるとメンテがしやすいと思います。

```json:ja.json
{
  "error": {
    "E-0001": "[0] の参照権限がありません。",
    "E-0002": "[0] の編集権限がありません。",
    "E-0003": "[0] は入力必須です。",
    "E-0004": "[0] は選択必須です。"
  },
  "warn": {
    "W-0001": "表示対象[0] が[1] 以上存在します。",
    "W-0002": "メール通知に失敗しました。自ら通知メールを送ってください。"
  },
  "info": {
    "I-0001": "[0] が完了しました。",
    "I-0002": "メール通知に成功しました。"
  },
  "confirm": {
    "C-0001": "[0] します。よろしいですか。",
    "C-0002": "編集内容は保存されていません。編集内容を破棄してよろしいですか。",
    "C-0003": "同一名の[0]が存在します。更新してもよろしいですか。"
  },
  "placeHolder": {
    "P-0001": "パスワード",
    "P-0002": "E-mail",
    "P-0003": "10文字以上で入力下さい。",
    "P-0004": "100文字以内で入力下さい。"
  },
  "tooltip": {}
}

```

# nuxt.config.tsの編集

```javascript:nuxt.config.ts
plugins: [
    '@/plugins/nuxt-i18n.ts'
  ],
```

# 使用する
- importして`i18n.tc`で対象のメッセージを指定するだけ。
- 例えばユーザ登録後にログイン画面に遷移させた際のメッセージの出力を例にすると...以下の通り。

```vue:login.vue
<script lang="ts">
import { Component, Mixins } from 'vue-property-decorator'
//省略
import { i18n } from '~/plugins/nuxt-i18n'

@Component({})
export default class Login extends Vue {
  //省略
  created() {
    if (CommonModule.SignUpJobDone) {
      this.message = i18n.tc('info.I-0003')  //ココ
    }
  }
}
```

# 結果の確認
<img width="1128" alt="スクリーンショット 2019-11-24 9.31.15.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303093/f9bdec9a-ced8-8082-8737-06161d94046b.jpeg">

# パラメータがあるとき
- メッセージの動的部分を文字配列の値で置き換え、置き換えた後のメッセージを返却する関数を自作します。

```typescript:common-message.ts

/**
 * @param baseMessage メッセージ
 * @param args 文字配列
 * @param original メッセージ返却フラグ
 * @example baseMessage："[0]しました。", args["ログイン"] ＝＞ "ログインしました。"
 * @returns 置き換えた後のメッセージ
 */
export function editMessage(
  baseMessage: string,
  args: string[],
  original: boolean = false
): string {
  if (isNotParam(baseMessage)) {
    return ''
  }

  if (isNotParam(args) || args.length === 0) {
    if (original) {
      return baseMessage
    } else {
      return ''
    }
  }

  let rtnMessage: string = baseMessage
  for (let i = 0; i < args.length; i++) {
    rtnMessage = rtnMessage.replace('[' + i + ']', args[i])
  }

  return rtnMessage
}

/**
 * 引数に値が設定されていないかの判定。
 *
 * @param value チェック対象
 * @returns 結果(true:設定なし、false：設定あり)
 */
function isNotParam(value: any): boolean {
  let rtn: boolean = false

  if (value === null || value === '') {
    rtn = true
  }
  return rtn
}

```

- lacaleのjsonの方は以下のようになります。

```json:ja.json
"info": {
    "I-0001": "[0] が完了しました。",
    "I-0002": "メール通知に成功しました。",
    "I-0003": "ユーザの登録が完了しました。[0]してください。",
    "I-0004": "ログインしました。",
    "I-0005": "[0]しました。"
  },
```

### pagesで使う
- importして使います。

```javascript:login.vue
//template省略
import * as CommonMessage from '~/utils/common-message'


created() {
    this.isAlert = false
    if (CommonModule.SignUpJobDone) {
      this.isAlert = true
      this.type = 'success'
      this.message = CommonMessage.editMessage(i18n.tc('info.I-0005'), [
        'ログイン'
      ])
    }
  }
```

### 結果確認
<img width="1680" alt="スクリーンショット 2019-11-26 23.36.37.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303093/c602ed75-94fe-221d-454f-a88ffa1daa89.jpeg">

# OK!!以上！！