Vue – Vue I18n プラグインで多言語対応する方法

目次

概要

Vue を使ったアプリケーションで多言語対応を行う方法について解説します。

Vue I18n

Vue I18n は Vue アプリケーションを多言語対応するためのプラグインです。

使い方

1. プロジェクトを作成する

チュートリアル用に作成したサンプルをベースに使用します。

git clone https://github.com/nekobean/vue2-minimum-sample.git
cd vue2-minimum-sample

ディレクトリ構造は vue-cli で生成したもので、以下のようになっています。

├─ .gitignore
├─ babel.config.js
├─ jsconfig.json
├─ LICENSE
├─ package-lock.json
├─ package.json
├─ public
│  ├─ favicon.ico
│  └─ index.html
├─ README.md
├─ src
│  ├─ App.vue
│  ├─ assets
│  ├─ components
│  └─ main.js
└─ vue.config.js

2. Vue I18n をインストールする

npm i vue-i18n@8

3. ロケールデータを定義する

main.js に以下の記述を追加します。

import VueI18n from 'vue-i18n'
Vue.use(VueI18n)

また、言語コードごとに、キーとそれに対応する文字列を定義したオブジェクトを作成します。 言語コードは ISO 639-1コード一覧 で確認できます。 以下の例では、英語 (言語コード en) では、キー message.hello に「Hello World」、日本語 (言語コード ja) では、キー message.hello に「こんにちは世界」が定義されています。 このオブジェクトを VueI18n オブジェクトを作成する際のコンストラクタに渡します。

/src/main.js

import Vue from 'vue'
import App from './App.vue'
import VueI18n from 'vue-i18n'

Vue.use(VueI18n)
Vue.config.productionTip = false

const messages = {
    en: {
        message: {
            hello: 'hello world'
        }
    },
    ja: {
        message: {
            hello: 'こんにちは、世界'
        }
    }
}

const i18n = new VueI18n({
    locale: 'ja',
    messages: messages,
})

new Vue({
    i18n,
    render: h => h(App)
}).$mount('#app')

4. ロケールデータを使用する

$t(キー) で先程定義したキーに対応する文字列が得られます。

/src/App.vue

<template>
  <div>
    <Home />
  </div>
</template>

<script>
import Home from "./components/Home";

export default {
  name: "App",

  components: {
    Home,
  },
};
</script>

/src/components/Home.vue

<template>
  <p>{{ $t("message.hello") }}</p>
</template>

<script>
export default {
  name: "Home",
};
</script>

出力

こんにちは世界

単一のコンポーネントでのみ使用するロケールデータを定義する

最初の例では、main.js 内にロケールデータを定義し、VueI18n のコンストラクタに渡しました。このロケールデータは、すべてのコンポーネントから参照できます。 あるコンポーネントでしか使用しないロケールデータは、そのコンポーネント内でロケールデータを定義することもできます。 main.js で定義したロケールデータとコンポーネントで定義したロケールデータで同じキーがある場合、コンポーネントで定義したロケールデータが優先されます。

コード

/src/main.js

import Vue from 'vue'
import App from './App.vue'
import VueI18n from 'vue-i18n'

Vue.use(VueI18n)
Vue.config.productionTip = false

const messages = {
    en: {
        message: {
            hello: 'hello world (global)'
        }
    },
    ja: {
        message: {
            hello: 'こんにちは、世界 (global)'
        }
    }
}

const i18n = new VueI18n({
    locale: 'ja',
    messages: messages,
})

new Vue({
    i18n,
    render: h => h(App)
}).$mount('#app')

/src/App.vue

<template>
  <div>
    <Home />
  </div>
</template>

  <script>
import Home from "./components/Home";

export default {
  name: "App",

  components: {
    Home,
  },
};
</script>

/src/components/Home.vue

<template>
  <div>
    <p>{{ $t("message.hello") }}</p>
    <p>{{ $t("message.hoge") }}</p>
  </div>
</template>

  <script>
export default {
  name: "Home",

  i18n: {
    messages: {
      en: {
        message: {
          hello: "hello world (component)",
          hoge: "hoge (component)",
        },
      },
      ja: {
        message: {
          hello: "こんにちは、世界 (component)",
          hoge: "ほげ (component)",
        },
      },
    },
  },
};
</script>

出力

こんにちは、世界 (component)
ほげ (component)

複数のコンポーネントで使用するロケールデータを定義する

複数のコンポーネントで使用するロケールデータは、別ファイルでロケールデータを定義し、それを import してsharedMessages プロパティに設定します。

コード

/src/main.js

import Vue from 'vue'
import App from './App.vue'
import VueI18n from 'vue-i18n'

Vue.use(VueI18n)
Vue.config.productionTip = false

const i18n = new VueI18n({
    locale: 'ja'
})

new Vue({
    i18n,
    render: h => h(App)
}).$mount('#app')

/src/App.vue

<template>
  <div>
    <Home />
  </div>
</template>

  <script>
import Home from "./components/Home";

export default {
  name: "App",

  components: {
    Home,
  },
};
</script>

/src/locales/common.js

export default {
    en: {
        message: {
            hello: 'hello world'
        }
    },
    ja: {
        message: {
            hello: 'こんにちは、世界'
        }
    }
}

./components/Home.vue

<template>
  <div>
    <p>{{ $t("message.hello") }}</p>
  </div>
</template>

  <script>
import commonMessages from "../locales/common";

export default {
  name: "Home",

  i18n: {
    sharedMessages: commonMessages,
  },
};
</script>

出力

こんにちは、世界 (component)

言語を動的に切り替える

使用する言語の初期値は VueI18n のコンストラクタの locale プロパティの値が使用されます。 あとから言語を変更する場合は $i18n.locale の言語コードを変更します。

/src/main.js

import Vue from 'vue'
import App from './App.vue'
import VueI18n from 'vue-i18n'

Vue.use(VueI18n)
Vue.config.productionTip = false

const messages = {
    en: {
        message: {
            hello: 'hello world'
        }
    },
    ja: {
        message: {
            hello: 'こんにちは、世界'
        }
    }
}

const i18n = new VueI18n({
    locale: 'ja',
    messages: messages,
})

new Vue({
    i18n,
    render: h => h(App)
}).$mount('#app')

/src/App.vue

<template>
  <div>
    <Home />
  </div>
</template>

<script>
import Home from "./components/Home";

export default {
  name: "App",

  components: {
    Home,
  },
};
</script>

/src/components/Home.vue

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

    <p>{{ $t("message.hello") }}</p>
  </div>
</template>

<script>
export default {
  name: "Home",

  data() {
    return { langs: ["ja", "en"] };
  },
};
</script>

出力

こんにちは世界

コメント

コメントする

目次