多言語化案件に携わることになり、Nuxt.js + i18nの導入を経験できたので備忘録的に残します。
ドキュメント
https://nuxt-community.github.io/nuxt-i18n/
要件
今回の要件は以下
- locale:
en
,ja
の2言語 - url:
/en
,/ja
( /へのアクセスはcookie制御、デフォルト/en
) - localeファイルはpage(component)ごとに管理
- メッセージはテンプレート方式で引数を与えられるようにする
導入手順
nuxt-i18n
のインストールnuxt-i18n.config.js
の作成- 言語ファイルの作成
nuxt.config.js
の設定- Template側での呼び出し
nuxt-i18n
のインストール
これはドキュメントの通り。
yarn add nuxt-i18n
or
npm i -S nuxt-i18n
nuxt-i18n.config.js
の作成
今回は、 ページごとにメッセージファイルを管理したいので、locales[].file
ではなく、 vueI18n.message
を使用します。
nuxt-i18n.config.js
import messages from './locales/message' <- これは次項で説明
export default {
strategy: 'prefix',
locales: [
{ code: 'en', iso: 'en_US' }, <- fileプロパティは使用しない
{ code: 'ja', iso: 'ja_JP' }
],
defaultLocale: 'en',
vueI18n: {
fallbackLocale: 'en',
messages
},
rootRedirect: 'en',
detectBrowserLanguage: {
useCookie: true,
cookieKey: 'i18n_locale'
}
}
言語ファイルの作成
要件#3のページごとにlocaleファイルを分けるために、このようなディレクトリ構造で管理します。
各localeごとにページ単位のjsファイルを用意して、message.jsでそれらをがっちんこしてexport。
それを nuxt-i18n.config.js
でimport。
./locales
├── en
│ ├── top.js
│ └── sub.js
├── ja
│ ├── top.js
│ └── sub.js
└── message.js
./locales/ja/top.js
export default {
top_title: 'TOPページへようこそ',
top_title_service: 'サービス概要',
top_label_service: 'サービス {index}: {name}',
top_service_price: '{0} 円',
top_service_description: 'こんなサービスです。詳しくは<a herf="{0}">こちら</a>までどうぞ!'
}
./locales/en/top.js
export default {
top_title: 'Welcome to TOP page',
top_title_service: 'Services'
top_label_service: 'Service {index}: {name}',
top_service_price: 'USD {0}',
top_service_description: 'This is the service description. For more information, please reach out ot us <a herf="{0}">here</a>.'
}
./locales/message.js
import localeENTop from './en/top'
import localeENSub from './en/sub'
import localeJATop from './ja/top'
import localeJASub from './ja/sub'
export default {
en: {
...localeENTop,
...localeENASub
},
ja: {
...localeJATop,
...localeJASub
}
}
これでページが量産されても管理しやすくなります。
nuxt.config.js
の設定
作成した i18n.config.js
を利用して、nuxt.config.js
のi18n設定を行います。
import i18n from './nuxt-i18n.config'
export default {
...
modules: [
...
[ 'nuxt-i18n, i18n ]
]
}
Template側での呼び出し
こんな感じで利用します。$message()
の引数にはオブジェクトの指定も可能。
<template>
<div>
<h2>{{ $t('top_title') }}</h2>
<section>
<h3>{{ $t('top_title_service') }}</h3>
<div v-for="(item, i) in services" :key="item.id">
<h4>{{ $t('top_label_service', { index: i + 1, name: item.name }) }}<h4>
...
<p>{{ $t('top_service_price', [item.price.toLocaleString()]) }}</p>
<p v-html="$t('top_service_description', [localePath({ path: '/contact' })])" />
</div>
</section>
</div>
</template>
...
Cookie制御とか自前で実装しようとしていたけど、これ使えばバッチリでした。