Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to import multiple locale json files in Vue 3 + i18n?

Tags:

This is my code, that works without problems:

import { createI18n } from 'vue-i18n'
import messages from './components/json/foo/foo_messages.json'

const app = createApp(App)
installI18n(app)

const i18n = createI18n({
  locale: 'ru',
  messages
})

app
  .use(i18n)
  .use(vuetify)
  .mount('#app')

Now I need to load messages also from ./components/json/bar/bar_messages.json. I tried to do this way:

import { createI18n } from 'vue-i18n'
import foo_msg from './components/json/foo/foo_messages.json'
import bar_msg from './components/json/bar/bar_messages.json'

const app = createApp(App)
installI18n(app)

const i18n = createI18n({
  locale: 'ru',
  messages: {foo_msg, bar_msg}
})

app
  .use(i18n)
  .use(vuetify)
  .mount('#app')

But it didn't work. Could anyone say how to do it?

EDIT: This is my foo json file

{
  "ru": {
    "header": {
      "hello": "Привет"
    }
  },
  "en": {
    "header": {
      "hello": "Hello"
    }
  }
}

and this is bar json file

{
  "ru": {
    "footer": {
      "bye": "Пока"
    }
  },
  "en": {
    "footer": {
      "bye": "Goodbye"
    }
  }
}
like image 303
Pavel_K Avatar asked Jan 03 '22 15:01

Pavel_K


1 Answers

What you are trying to do is not very scalable. Given the format of the i18n JSON messages, you need to merge the input files to something like this:

{
  "ru": {
    "header": {
      "hello": "Привет"
    },
    "footer": {
      "bye": "Пока"
    }
  },
  "en": {
    "header": {
      "hello": "Hello"
    },
    "footer": {
      "bye": "Goodbye"
    }
  }
}

...this is definitely possible with JS but you must still import the JSON file for each component in your main.js which is tedious and error prone

Did you consider using vue-i18n custom blocks in your components? You can even keep the translations in external JSON files and use a custom block like <i18n src="./myLang.json"></i18n>

this is much better approach but if you stil want to use yours, here is a simple code how to merge all translation files (objects imported from JSON) into a single object usable by vue-i18n:

// import foo_msg from './components/json/foo/foo_messages.json'
const foo_msg = {
  "ru": {
    "header": {
      "hello": "Привет"
    }
  },
  "en": {
    "header": {
      "hello": "Hello"
    }
  }
}

// import bar_msg from './components/json/bar/bar_messages.json'
const bar_msg = {
  "ru": {
    "footer": {
      "bye": "Пока"
    }
  },
  "en": {
    "footer": {
      "bye": "Goodbye"
    }
  }
}

const sources = [foo_msg, bar_msg]
const messages = sources.reduce((acc, source) => {
  for(key in source) {
    acc[key] = { ...(acc[key] || {}), ...source[key] }
  }
  return acc
},{})

console.log(messages)
like image 170
Michal Levý Avatar answered Oct 06 '22 00:10

Michal Levý