LoginSignup
13
13

More than 5 years have passed since last update.

Vue.JS + Nuxt で i18n (yaml使用) 対応

Last updated at Posted at 2018-11-15

Install

npm i -S vue-i18n
npm i -S @kazupon/vue-i18n-loader
npm i -S yaml-loader

下記ファイルの追加

modules/vue-i18n.js
module.exports = function () {
  this.extendBuild(config => {
    const rule = config.module.rules.find(el => el.loader === 'vue-loader')
    rule.options.preLoaders = rule.options.preLoaders || {}
    rule.options.preLoaders.i18n = 'yaml-loader'
    rule.options.loaders.i18n = '@kazupon/vue-i18n-loader'
  })
}
plugins/vue-i18n.js
import Vue from 'vue'
import VueI18n from 'vue-i18n'

Vue.use(VueI18n)

export default ({ app }) => {
  app.i18n = new VueI18n({
    locale: navigator.language  // ブラウザの設定を利用
  })
}

nuxt.config.js に下記の項目を追加。

nuxt.config.js
module.exports = {
  plugins: [
    { src: '@/plugins/vue-i18n.js', ssr: false },
  ],
  modules: [
    '@/modules/vue-i18n.js',
  ],
  build: {
    vendor: ['vue-i18n'],
  },
}

多言語の指定

通常

<i18n>
en:
  ppap:
    1: "This is a pen."
    2: "This is an apple."
  "これは何?": "What is this?"
</i18n>

<template>
  <div>
    <div>{{$t('ppap.1')}}</div>
    <div>{{$t('ppap.2')}}</div>
    <div>{{$t('これは何?')}}</div>
  </div>
</template>

パラメータ渡す

<i18n>
en:
  ppap: "This is a {item}."
</i18n>

<template>
  <p>{{ $t('ppap', { item: 'pen' }) }}</p>
</template>

i18n を別ファイルに切り出す

messages/en/global.yml
en:
  ppap:
    1: "This is a pen."
    2: "This is an apple."
  "これは何?": "What is this?"
<i18n src="../../messages/en/global.yml"></i18n>

言語名のclassを有効化する

<div :class="{[`lang-${$i18n.locale}`]: true}">

# locale = en の場合の output
<div class="lang-en">

script の中で使う場合

data() {
  const $t = this.$t.bind(this)
  return {
    ppap: $t('ppap.1'),
  }
},

文言の中にタグが含まれるなど複雑な分を使う

<i18n> タグ使う。

<i18n>
en:
  'aaa': 'There are {a}, {b} and {c}.'
  'りんご': 'Apple'
</i18n>

<template>
  <div>
    <i18n path="aaa" tag="p" :places="{a: 'バナナ'}">
      <span place="b">パイナップル</span>
      <a place="c" href="/url">{{ $t('りんご') }}</a>
    </i18n>
  </div>
</template>

# 出力
<div>
  <p>
    There are バナナ, パイナップル and Apple.
  </p>
</div>

v-t を使う方法

<p v-t="ppap1"></p>
<p v-t="{path: 'ppap2', locale: 'ja', args: {item: 'pen'}}"></p>

リアルタイムで変える必要がないなら v-t を使った方が良さそうだが、パフォーマンスにさほど影響がないなら可読性の高い $t でも良さそう。

  • v-t
    • メリット: パフォーマンス。vue-i18n-extensions を使えば事前翻訳も。
    • デメリット: 柔軟ではない。dom の textContent に保存される。
  • $t
    • メリット: 柔軟。
    • デメリット: 再描画のたびに計算される翻訳コスト。

言語セレクター

<template>
  <div class="locale-changer">
    <select v-model="$i18n.locale">
      <option v-for="(lang, i) in langs" :key="`Lang${i}`" :value="lang">{{ lang }}</option>
    </select>
  </div>
</template>

<script>
export default {
  name: 'locale-changer',
  data () {
    return { langs: ['ja', 'en'] }
  }
}
</script>

クエリパラメータで locale 注入

middleware/i18n-locale.js
export default async function ({route, app}) {
  if (route.query['locale']) {
    console.log('locale', route.query['locale'])
    app.i18n.locale = route.query['locale']
  }
}
nuxt.config.js
module.exports = {
  router: {
    middleware: ['i18n-locale'],
  },
}
13
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
13