Gregor Voinov
Gregor Voinov

Reputation: 2263

Multiple translations files per language with vue-i18n and nuxtjs

I use nuxtjs and i18n to build a static website with multiple languages. At the moment I have one json file per language. For better structure i want to split the file in multiple files per language. How can i do that? Is there a way where i can tell i18n explicit which json file it should use for a page? Or do I have to concatenatet the jsons files to one?

I used this exmaple to build my translations https://nuxtjs.org/examples/i18n/

Upvotes: 9

Views: 5329

Answers (3)

Den15
Den15

Reputation: 21

For splitting translations into multiple files, I decided to leverage "Multiple files lazy loading" feature mentioned in Nuxt I18n docs. Although it may not exactly intended for this purpose according the docs, it works pretty well.

"lang" directory structure:

lang
├ de
│ ├ common.json
│ ├ main.json
│ └ pages.json
├ en
│ ├ common.json
│ ├ main.json
│ └ pages.json
└ ru
  ├ common.json
  ├ main.json
  └ pages.json

config/i18n.config.ts:

const fileNames = [
    'main',
    'common',
    'pages',
]

function getFileList(locale: string) {
    return fileNames.map(name => `${locale}/${name}.json`)
}

export default {
    legacy: false,
    locales: [
        { code: 'en', files: getFileList('en') },
        { code: 'ru', files: getFileList('ru') },
        { code: 'de', files: getFileList('de') },
      ],
    lazy: true,
    langDir: 'lang',
    defaultLocale: 'en',
}

nuxt.config.ts:

import i18nConfig from './config/i18n.config'

export default defineNuxtConfig({
  // ...

  modules: ['@nuxtjs/i18n'],
  i18n: i18nConfig
})

From the nuxtjs/i18n docs:

@nuxtjs/i18n will load locale messages with lazy loading in the order of the array specified in "files". It then overrides the locale messages in the order in which they were loaded.

So if you don't have same key:value pairs at the top level of your jsons, no keys will be overridden, and this is exactly behavior I need.

Upvotes: 1

DarthCanard
DarthCanard

Reputation: 1

Late reply, but I have the exact same needs :) Only work-around I have so far is to use the in-component feature of NuxtI18n

As shown in the doc :

<script setup lang="ts">
const { t } = useI18n({
  useScope: 'local'
})
</script>

<template>
  <p>{{ t('hello') }}</p>
</template>

<i18n lang="json">
{
  "en": {
    "hello": "hello world!"
  },
  "ja": {
    "hello": "こんにちは、世界!"
  }
}
</i18n>

It should at least only render with the page, but is not taking advantage of file structure, so it's a meh solution, but it is what I have got... I would love to hear if you got a solution !

Upvotes: 0

alperk01
alperk01

Reputation: 343

// i18n.js plugin
import Vue from 'vue'
import VueI18n from 'vue-i18n'

Vue.use(VueI18n)

export default ({ app, store }) => {
  app.i18n = new VueI18n({
    locale: store.state.locale,
    fallbackLocale: 'en-US',
    messages: {
      en: Object.assign({}, require('~/locales/en.json'), require('~/locales/en.settings.json')),
      tr: Object.assign({}, require('~/locales/tr.json'), require('~/locales/tr.settings.json')),
    },
    silentTranslationWarn: true,
  })
}

Upvotes: 3

Related Questions