3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

nuxt vue-i18n

Last updated at Posted at 2019-03-12

nuxt-i18nもう使えるらしいのでやろうとしたらエラーでたのでとりあえずvue-i18nでドキュメントみて実装しました。

参考 国際化(i18n) - Nuxt.js

※ 要所のファイルしか載せてないので他気になる箇所は国際化(i18n) - Nuxt.jsを見てください。

yarn add vue-i18n -D

nuxt.config.ts

const config = {
  head: {
    title: '...',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: '...' }
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
  },
  loading: { color: '#3B8070' },
// 追加 //////////////////////////////////////////////////////////////////
  router: {
    middleware: 'i18n'
  },
  generate: {
    routes: [
      '/',
      '/en'
    ]
  },
/////////////////////////////////////////////////////////////////////////
  css: [
    ...
  ],
  build: {
    ...
  },
// 追加 //////////////////////////////////////////////////////////////////
  plugins: [
    '~/plugins/i18n.js'
  ],
//////////////////////////////////////////////////////////////////////////
  modules: [
    ...
  ]
}

export default config

~/plugins/i18n.js

import Vue from 'vue'
import VueI18n from 'vue-i18n'

Vue.use(VueI18n)

export default ({ app, store }) => {
  // Set i18n instance on app
  // This way we can use it in middleware and pages asyncData/fetch
  app.i18n = new VueI18n({
    locale: store.state.locale,
    fallbackLocale: 'ja',
    messages: {
      'en': require('~/locales/en.json'),
      'ja': require('~/locales/ja.json')
    }
  })

  app.i18n.path = (link) => {
    if (app.i18n.locale === app.i18n.fallbackLocale) {
      return `/${link}`
    }

    return `/${app.i18n.locale}/${link}`
  }
}

~/middleware/i18n.js

export default function ({ isHMR, app, store, route, params, error, redirect }) {
  const defaultLocale = app.i18n.fallbackLocale
  // If middleware is called from hot module replacement, ignore it
  if (isHMR) return
  // Get locale from params
  const locale = params.lang || defaultLocale
  if (store.state.locales.indexOf(locale) === -1) {
    return error({ message: 'This page could not be found.', statusCode: 404 })
  }
  // Set locale
  store.commit('SET_LANG', locale)
  app.i18n.locale = store.state.locale
  // If route is /<defaultLocale>/... -> redirect to /...
  if (locale === defaultLocale && route.fullPath.indexOf('/' + defaultLocale) === 0) {
    const toReplace = '^/' + defaultLocale + (route.fullPath.indexOf('/' + defaultLocale + '/') === 0 ? '/' : '')
    const re = new RegExp(toReplace)
    return redirect(
      route.fullPath.replace(re, '/')
    )
  }
}

~/locales/ja.json

{
  "links": {
    "home": "トップ",
    "message": "ご挨拶",
    "info": "企業情報",
    "english": "English",
    "japanese": "Japanese"
  },
  "home": {
    "title": "ようこそ",
    "introduction": "これはトップページです。"
  },
  "message": {
    "title": "ご挨拶",
    "introduction": "これはご挨拶ページです。"
  },
  "info": {
    "title": "企業情報",
    "introduction": "これは企業情報ページです。"
  }
}

~/locales/en.json

{
  "links": {
    "home": "Home",
    "message": "Message",
    "info": "Info",
    "english": "英語",
    "japanese": "日本語"
  },
  "home": {
    "title": "Home",
    "introduction": "This is the home page."
  },
  "message": {
    "title": "Message",
    "introduction": "This is the message page."
  },
  "info": {
    "title": "Info",
    "introduction": "This is the info page."
  }
}

~/layouts/Header.vue

<template>
  <header class="header">
    <nav class="nav">
      <NuxtLink :to="$i18n.path('')" class="header__link" exact>
        {{ $t('links.home') }}
      </NuxtLink>
      <NuxtLink :to="$i18n.path('message')" class="header__link" exact>
        {{ $t('links.message') }}
      </NuxtLink>
      <NuxtLink :to="$i18n.path('info')" class="header__link" exact>
        {{ $t('links.info') }}
      </NuxtLink>

      <NuxtLink v-if="$i18n.locale === 'ja'" :to="`/en` + $route.fullPath" class="header__link" active-class="none" exact>
        {{ $t('links.english') }}
      </NuxtLink>
      <NuxtLink v-else :to="$route.fullPath.replace(/^\/[^\/]+/, '')" class="header__link" active-class="none" exact>
        {{ $t('links.japanese') }}
      </NuxtLink>
    </nav>
  </header>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'

@Component({
})
export default class HeaderLayout extends Vue {}
</script>

<style lang="scss" scoped>
.header {
}
.nav {
  .header__link {
  }
}
</style>

~/pages/index.vue

<script>
import Index from '~/pages/_lang/index'
export default Index
</script>

~/pages/_lang/index.vue

<template>
  <div>
    <section>
      <h1>{{ $t('home.title') }}</h1>
    </section>
    <p>{{ $t('home.sentence1') }}</p>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'

@Component({
  components: {
  }
})
export default class IndexPage extends Vue {}
</script>

<style lang="scss" scoped>
</style>
3
4
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
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?