Nuxt.js + nuxt-i18n + VeeValidate する

表題の環境を作るのに意外とハマったので備忘録的に書いておく。

## やりたかったこと

1. nuxt-i18nで多言語化したい
2. この仕組を(多分)活かしつつ、VeeValidateのメッセージも多言語に対応させておきたい
3. 上記2で翻訳したメッセージ内に、フィールドの name がそのままの表示されてしまうのをなんとかしたい

## この記事で書かないこと

VeeValidatorそのもののHTML内での使い方。

[こちら](https://baianat.github.io/vee-validate/guide/syntax.html#rules-parameters) をみていただくほうが詳しいので。

## 前提

yarn とかで ``vee-validate`` は入れておく。

## 1. nuxt-i18nでのi18n

・・・についてはここに書いたので省略。
https://qiita.com/keiichi-hikita/items/b3cd955a35260b399097

## 2. VeeValidateの多言語化

プラグインを作ります。

ちなみに読み込み方はこう。

### nuxt.config.js

```javascript
  plugins: [{ src: '~plugins/vee-validate/i18n.js' }],
```


Nuxt.jsの世界では `~` はプロジェクトトップを意味しますが、

`~/plugins` の下に、こういう構造を作ってあります。

```
plugins/
└── vee-validate
    ├── attributes.js
    └── i18n.js <-- プラグインとして直接読み込むのはこれ
```

ファイルが２つありますね。

まず ``i18n.js`` についてだけ内容を書きます。
（もう１つのファイルについては後述します)

### i18n.js

```javascript
import Vue from 'vue'

import messageEn from 'vee-validate/dist/locale/en'
import messageJa from 'vee-validate/dist/locale/ja'

import attributes from './attributes' // --- (*)

import VeeValidate, { Validator } from 'vee-validate'

export default function({ app }) {
  Vue.use(VeeValidate)

  Validator.localize('en', messageEn)

  Validator.localize('ja', messageJa)
  Validator.localize(attributes)  // --- (*)

  Validator.localize('en') // -- (1)
  if (['en', 'ja'].includes(app.i18n.loadedLanguages[0])) {
    Validator.localize(app.i18n.loadedLanguages[0])
  }
}
```

この中の(*) の部分は一旦無視。（これはやりたいことの3に関係するので)

この状態にしておくとブラウザの言語設定に連動してバリデーションメッセージが ``en`` , ``ja`` で切り替わります。
（日英のみ対応にしてます）

(1) の部分は nuxt-i18n のフォールバック言語に設定を合わせればよいかと思います。

メッセージの翻訳の元ファイルに相当するのは以下の２点。

```javascript
import messageEn from 'vee-validate/dist/locale/en'
import messageJa from 'vee-validate/dist/locale/ja'
```

これはVeeValidateの中に入っているのでそのまま使わせてもらいました。

### で、ここで問題が

このままだと日本語にした時に、

```
nameは必須項目です
```

これは、name=nameな（わかりますよね?)フィールドに `v-validate="'required'"` した時のものです。

なんとも突っ込みたくなるメッセージになってしまいます。
そこで最後にやりたいことです。

### 3. 翻訳したメッセージ内に、フィールドの name がそのままの表示されてしまうのをなんとかしたい

このために必要なのが、前述の (*) の部分です。

再掲します。

```javascript
import Vue from 'vue'

import messageEn from 'vee-validate/dist/locale/en'
import messageJa from 'vee-validate/dist/locale/ja'

import attributes from './attributes' // --- (ここと)

import VeeValidate, { Validator } from 'vee-validate'

export default function({ app }) {
  Vue.use(VeeValidate)

  Validator.localize('en', messageEn)

  Validator.localize('ja', messageJa)
  Validator.localize(attributes)  // --- (ここ)

  Validator.localize('en')
  if (['en', 'ja'].includes(app.i18n.loadedLanguages[0])) {
    Validator.localize(app.i18n.loadedLanguages[0])
  }
}
```

先ほど紹介しませんでしたが、上記で参照している `attributes.js` はこうなっています。

```javascript
export default {
  ja: {
    attributes: {
      name: '名前',
      description: '説明',
    },
  },
  en: {
    attributes: {
      name: 'Name',
      description: 'Description',
    },
  },
}
```

ここで `バリデーションメッセージに name=name なものを出すときは、 "名前" と読み替えてね` ということを書いてます。
他にも少々書いてますが、意図は伝わると信じますｗ

この設定が入ると、先程のバリデーションメッセージが、

```
名前は必須項目です
```

のように変わります。

とりあえずこれでやりたいことの80%は出来ました。

最後にカスタムルールを足して、そのメッセージをブラウザ言語設定に合わせて切り替える方法を今調べてます。

初めてまともに使う分野は進むとすぐに壁にぶち当たりますねぇ。
そこが楽しいところなんですけどね。