Reputation: 2263
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
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
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
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