nuxt vue-i18n

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

参考　[国際化（i18n） - Nuxt.js](https://ja.nuxtjs.org/examples/i18n/#codefund_ad)

※ 要所のファイルしか載せてないので他気になる箇所は[国際化（i18n） - Nuxt.js](https://ja.nuxtjs.org/examples/i18n/#codefund_ad)を見てください。

```sh
yarn add vue-i18n -D
```

nuxt.config.ts
   
```js 
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

```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

```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

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

~/locales/en.json

```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

```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

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

~/pages/_lang/index.vue

```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>
```