[how to] Implement i18next in quasar



  • Hello all

    I recently implemented i18next in my Quasar project.
    Here I will try to show you all how it was done.

    My use case

    The project is a multi language static site.
    I have a simple button with a popover to select languages.
    My language files go in ‘/src/statics/i18n/’ folder.
    I am using these packages: i18next, vue-i18next, i18next-xhr-backend

    Getting started

    Install basic packages
      $  npm install --save i18next  @panter/vue-i18next
    

    This will install the core i18next library, as well as the vue-i18next plugin.

    Boot up i18next

    
    // src/main.js
    
    // import libraries
    import i18next from 'i18next'
    import VueI18Next from '@panter/vue-i18next'
    
    ....
    
    // init i18next
    i18next
      .init({
        debug: false, // set this to true for now. Will give som interesting output in console
        lng: 'en', // default language
        resources: {  // fixed resources for now. may be useful to keep critical messages here. 
          en: { // language
            translations: { // Namespace. Default namespace is 'translations'
              key: 'value'  // your translations go here.
            }
          }
        }
      }, (err, t) => {
        if (DEV && err) {
          // if there is an error on init, log it
          console.log(err)
        }
      })
    
    // plug Vuei18Next into Vue,
    Vue.use(VueI18Next)
    // use your instace of i18next with vue
    const i18n = new VueI18Next(i18next)
    
    // init quasar 
    Quasar.start(() => {
      /* eslint-disable no-new */
      new Vue({
        el: '#q-app',
        i18n, // pass i18n: i18n
        .....
        // other arguments here as usual
      })
    })
    

    With this, you should be set up. try the following in any .vue component

    {{$t('key')}}
    

    If everything is working, this should render as ‘value’. Try adding a few more.

    Changing language

    First update your main.js i18next resources to look like so to look like so

    
        resources: {
          en: {
            translations: {
              hello: 'Hello World!' 
            }
          },
          es: {
            translations: {
              hello: 'Hola Mundo!' 
            }
          },
          fr: {
            translations: {
              hello: 'Bonjour Monde!' 
            }
          }
        }
    
    

    Now add {{$t('hello)}} in a .vue component.

    You should be able to change language with the following:

    
    changeLanguage (lng) {
      // where lng is one of 'es', 'fr', 'en'
      this.$i18n.i18next.changeLanguage(lng)
    }
    
    

    Accessing the current language

    This can be useful for choosing an icon representing the current language.

    
      this.$i18n.i18next.language 
    
    

    Using a xHR backend

    Having all your language data in main.js only works for the smallest of apps.
    Here is a way to pull language data from static .json files

    Add the following files

    /src/statics/i18n/en/translations.json

    {
      "hello": "Hello from backend"
    }
    

    /src/statics/i18n/es/translations.json

    {
      "hello": "Hola desde statics"
    }
    
    Install the XHR backend
      $  npm install --save i18next-xhr-backend
    

    src/main.js

    
    import i18next from 'i18next'
    import VueI18Next from '@panter/vue-i18next'
    import XHR from 'i18next-xhr-backend' // import xhr backend
    
    ....
    
    i18next
      .use(XHR) // Add  xhr backend to i18next 
      .init({
        debug: true,
        lng: 'en',
        ns: 'translations',
        backend: { // backend config
          loadPath: '/statics/i18n/{{lng}}/{{ns}}.json', // load path based on language and namespaces
          parse: data => JSON.parse(data) // parse data
        }
      }, (err, t) => {
        if (DEV && err) {
          console.log(err)
        }
      })
    
    

    This should set up the backend.

    Additional configuration options

    
    import i18next from 'i18next'
    import VueI18Next from '@panter/vue-i18next'
    import XHR from 'i18next-xhr-backend' // import xhr backend
    
    ....
    
    i18next
      .use(XHR)
      .init({
        debug: true,
        returnObjects: true, // this is very useful if you want translations to return an array on which you can use v-for
        lng: 'en',
        fallbackLng: 'en', // language to fallback to if current language is unavailable 
        ns: 'translations',
        defaultNS: 'translations',
        fallbackNS: 'translations' //  namespace to fallback to if current namespace is unavailable 
        backend: { // add backend
          loadPath: '/statics/i18n/{{lng}}/{{ns}}.json', // load path based on namespaces and language
          parse: data => JSON.parse(data) // parse data
        }
      }, (err, t) => {
        if (DEV && err) {
          console.log(err)
        }
      })
    
    

    And now in any .vue file, configure local namespaces for said file

    export default {
      .....
      i18nOptions: {
        namespaces: 'translations' // either string or array of strings. The corresponding files will be loaded
      }
      .....
    }
    
    Hope this helped

    I’m tired now. Will edit later. Please post if you spot any mistakes. Thanks you



  • I’ll try your method soon, and I will then plug my own i18next-firebase-backend instead, which I’ll opensource once all is well.
    Stay tuned