JavaScript
vue.js
nuxt.js
vue-i18n

Nuxt.jsでいい感じにi18nを使う

More than 1 year has passed since last update.

Nuxt 国際化(i18n)
https://ja.nuxtjs.org/examples/i18n/

上記ページのサンプルは、 /en やら /fr みたいなパスベースで切り替える感じだけど、あんま好きくないのでブラウザの設定ベースで言語を切り替えるようにする。

パスベースじゃないのでサンプルにある vue-routermiddleware/i18n.js は不要。

vue-i18n はイケてるけど英語の設定で最初の1文字目を大文字にしたい〜みたいなところは特に標準では対応してないので適当にfunctionを追加。

というわけで僕が考えた最強のNuxtの plugins/vue-i18n.js

plugins/vue-i18n.js
import _ from 'lodash';
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import changeCase from 'change-case';

Vue.use(VueI18n);

// 各種大文字/小文字切り替え用のfunctionを用意する
Vue.mixin({
  methods: {
    // camelCaseにする
    $tcc(path) {
      return changeCase.camelCase(this.$t(path));
    },
    // 1文字目をupperCaseにする
    $tucf(path) {
      return changeCase.upperCaseFirst(this.$t(path));
    },
    // 1文字目をlowerCaseにする
    $tlcf(path) {
      return changeCase.lowerCaseFirst(this.$t(path));
    },
    // 全部upperCaseにする
    $tuc(path) {
      return changeCase.upperCase(this.$t(path));
    },
    // 全部lowerCaseにする
    $tlc(path) {
      return changeCase.lowerCase(this.$t(path));
    }
  }
});

export default ({ app, req, isClient }) => {
  // 標準はja
  let locale = 'ja';
  if (isClient) {
    // browserから取る場合はnavigator経由で取得
    const navigator = _.get(window, 'navigator', {});
    locale = (_.head(navigator.languages) || navigator.language || navigator.browserLanguage || navigator.userLanguage).substr(0, 2);
  } else if (req) {
    // ssrの場合はrequestから取得
    locale = req.headers['accept-language'].split(',')[0].toLocaleLowerCase().substr(0, 2);
  }
  app.i18n = new VueI18n({
    locale: locale || 'ja',
    fallbackLocale: 'ja',
    messages: {
      'en': require('~/locales/en.json'),
      'ja': require('~/locales/ja.json'),
    },
  });
}

これで以下のように使う場所に応じて大文字・小文字を切り替えられる。

locales/en.json
{"app": {"brand": "my application"}}
locales/ja.json
{"app": {"brand": "僕のアプリ"}}
components/Header.vue(テンプレート内に書く場合)
<template>
  <div class="navbar-header">
    <nuxt-link to="/" class="navbar-brand">{{$tuc('app.brand')}}</nuxt-link>
  </div>
</template>
components/Header.vue(jsから渡す場合)
<template>
  <div class="navbar-header">
    <nuxt-link to="/" class="navbar-brand">{{brand}}</nuxt-link>
  </div>
</template>
<script>
export default {
  data() {
    return {
      brand: this.$tuc('app.brand'),
    };
  },
};
</script>

たぶんこんな感じのやつで、英語なら「MY APPLICATION」ってなるし日本語「僕のアプリ」って表示されるはず。

参考