Nuxt.js, nuxt-i18n で VeeValidate の多言語対応

[Nuxt.js](https://nuxtjs.org/), [nuxt-i18n](https://nuxt-community.github.io/nuxt-i18n/), [VeeValidate](https://baianat.github.io/vee-validate/) で多言語対応する方法を検索すると、自前で plugin を設置するものが多いのですが、最新（2019年06月28日現在）の [nuxt-validate](https://www.npmjs.com/package/nuxt-validate) を使ってもできるようにしてあるので、やり方をまとめます。

:warning: VeeValidate がバージョン3になる前の記事なので最新のVeeValidateでは動作しないコードが含まれています。

## インストール

Nuxt.js などはインストールしてある前提です。

```bash
npm i --save nuxt-validate nuxt-i18n
```

nuxt-validate は 1.0.0 以降のものが nuxt-i18n 対応版です。

## nuxt.config.js の編集

modules に nuxt-i18n, nuxt-validate の追加と、設定を書きます。
注意するところとしては、`nuxt-validate`に`nuxti18n`オプションを指定すること、`nuxt-validate`を`nuxt-i18n`より前に記述すること、`nuxt-i18n`とのlocale名の対応に気をつけることです。
`nuxti18n: true`と設定した場合、`nuxt-i18n`で設定したlocale codeと同名のファイルを、[VeeValidateのlocale](https://github.com/baianat/vee-validate/tree/master/locale)からロードします。
なので、 ja, en, fr など言語コードのみの場合は問題ないですが、ポルトガル語（ポルトガル、ブラジル）や中国語（繁体、簡体）などは、`nuxt-i18n`でのlocale codeをVeeValidate側に合わせるか、以下のようにlocale名の対応を取るための設定値を記述する必要があります。（変換が必要でない場合は記述する必要はありません。）

```js:nuxt.config.js
modules: [
  // nuxt-validateの設定（nuxt-i18nより前に書く）
  // https://github.com/lewyuburi/nuxt-validate#configuration
  [
    "nuxt-validate",
    {
      nuxti18n: {
        locale: {
          // nuxt-i18n と VeeValidate のlocale名の差分を埋めるための設定
          // nuxt-i18n の locale : VeeValidate の locale
          "pt-BR": "pt_BR"
        }
      }
    }
  ],
  // nuxt-i18nの設定
  // https://nuxt-community.github.io/nuxt-i18n/options-reference.html
  [
    "nuxt-i18n",
    {
      locales: [
        "ja", "en", "pt-BR"
      ],
      defaultLocale: "ja",
      vueI18n: {
        fallbackLocale: "ja",
      }
    }
  ],
  //
],
```

## 要素名の多言語化

```vue
<input v-validate="'required'" name="myinput" type="text">
<span>{{ errors.first('myinput') }}</span>
```

上記の対応をしてバリデーションエラーがあった場合、以下の出力がされます。

> myinputは必須項目です

この myinput の部分も多言語化したい場合は、いくつかやり方があります。

### `data-vv-as` を利用する方法

https://baianat.github.io/vee-validate/guide/localization.html#aliases

```vue
<template>
  <div>
    <input v-validate="'required'" :data-vv-as="myinput" name="myinput" type="text">
    <span>{{ errors.first('myinput') }}</span>
  </div>
</template>

<script>
export default {
  computed: {
    myinput() {
      if (this.$i18n.locale === "ja") {
        return "マイインプット"
      }
      // ...
      return "MyInput"
    }
  }
}
</script>
```

> マイインプットは必須項目です

### plugin を設置する方法

https://baianat.github.io/vee-validate/guide/localization.html#aliases

nuxt-validate は app context に Validator API を inject してあるので、 plugin で使用することができます。

```js:nuxt.config.js
  plugins: [
    "@/plugins/attributes.js"
  ],
```

```js:plugins/attributes.js
export default ({ app }, inject) => {
  app.validator.localize({
    ja: {
      attributes: {
        myinput: "マイインプット"
      }
    },
    en: {
      attributes: {
        myinput: 'MyInput'
      }
    },
    // ...
  })
}
```

```vue
<template>
  <div>
    <input v-validate="'required'" name="myinput" type="text">
    <span>{{ errors.first('myinput') }}</span>
  </div>
</template>
```

> マイインプットは必須項目です

## 関連記事

- [Nuxt.js + nuxt-i18n + VeeValidate する](https://qiita.com/keiichi-hikita/items/9d5742f1cc06fd0d5707)
- [TypeScriptなNuxt.jsでVeeValidateを使ってみる - くらげになりたい。](https://www.memory-lovers.blog/entry/2019/06/16/100000)
- [Nuxt.js と vee-validate でエラーメッセージは日本語でバリデーションするメモ - 牌語備忘録 -pygo](https://cortyuming.hateblo.jp/entry/2018/10/15/231238)