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'],
},
}