0.15.3 quasar vs local i18n



  • Hello,

    I have followed the example in the quasar documentation to get components internationalized dynamically:
    http://quasar-framework.org/components/internationalization.html

    This works fine but I am encountering difficulties to get my own application translations working.

    During my projects initialization, I selected that I wanted i18n support. From what I understand, this creates the file i18n.js in the folder src/plugins and adds an english translation file in src/i18n (as a side note, shouldn’t it be “en-us” and not “en” ?).
    I added a couple of keys with their english translation and added other counties in src/i18n with their corresponding translation.

    I am stuck with getting the local translations in my vues. I have tried the following:
    {{$t(‘test’)}}
    {{$i18n.t(‘test’)}}

    I get the following error:
    Cannot translate the value of keypath ‘test’. Use the value of keypath as default.

    What should I use?

    If I use quasar components labels, it works fine. Example:
    {{$q.i18n.label.close}}

    Thanks.



  • I have managed to get ride of the “Cannot translate the value of keypath ‘test’. Use the value of keypath as default.” message.

    The problem was that setting the locale to “en-us” inside src/plugin/i18n.js didn’t find my translation in src/i18n/en-us. So I set the default locale to ‘en’ inside the plugin declaration as follows:

    import VueI18n from 'vue-i18n'
    import messages from 'src/i18n'
    
    export default ({ app, store, Vue }) => {
      Vue.use(VueI18n)
    
      // Set i18n instance on app
      app.i18n = new VueI18n({
        locale: 'en',
        fallbackLocale: 'en',
        messages
      })
    }
    

    This manages to get the correct value with either {{ $t(‘test’) }} or {{ $i18n.t(‘test’) }}

    Now, the problem is that I am unable to dynamically change the language.

    I have a language selection component as follows:

    <template>
      <q-select
        stack-label="Language"
        :options="[
          { label: 'English',      value: 'en' },
          { label: 'English (US)', value: 'en-us' },
          { label: 'English (UK)', value: 'en-uk' },
          { label: 'Français',     value: 'fr' },
          { label: 'Deutsche',     value: 'de' },
          { label: 'Español',      value: 'es' }
        ]"
        v-model="lang"
      />
    </template>
    
    <script>
    export default {
      data () {
        return {
          lang: this.$q.i18n.lang
        }
      },
      watch: {
        lang (lang) {
          // dynamic import, so loading on demand only
          import(`quasar-framework/i18n/${lang}`).then(lang => {
            this.$q.i18n.set(lang.default)
          })
          // dynamic import, so loading on demand only
          import(`src/i18n/${lang}`).then(lang => {
            this.i18n.set(lang.default)
          })
        }
      }
    }
    </script>
    

    This correctly selects the quasar components language but not my own local translations.

    What is the correct call?

    Cheers.



  • You probably want these docs



  • @benoitranque Thank you for the link. I am new not only to quasar but also vue and all its underpinnings…

    I managed to get it working 🙂

    The thing is, since quasar uses “en-us” and “en-uk” and not only “en” like in the default example, I had to split “en” in “-us” and “-uk” versions inside src/i18n and then convert from snake case to camel case in my language selection component (cf. snakeToCamel() ).

    // language selection component
    <template>
      <q-select
        stack-label="Language"
        :options="[
          { label: 'English (US)', value: 'en-us' },
          { label: 'English (UK)', value: 'en-uk' },
          { label: 'Français',     value: 'fr' },
          { label: 'Deutsche',     value: 'de' },
          { label: 'Español',      value: 'es' }
        ]"
        v-model="lang"
      />
    </template>
    
    <script>
    export default {
      data () {
        return {
          lang: this.$q.i18n.lang
        }
      },
      watch: {
        lang (lang) {
          // Update application specific i18n
          this.$i18n.locale = snakeToCamel(lang)
          // Update quasar components i18n
          // (dynamic import, so loading on demand only)
          import(`quasar-framework/i18n/${lang}`).then(lang => {
            this.$q.i18n.set(lang.default)
          })
        }
      }
    }
    function snakeToCamel (str) {
      return str.replace(/(-\w)/g, m => { return m[1].toUpperCase() })
    }
    </script>`
    

    And set “en-us” (ie. “enUs”) as default in the ars/plugins/i18n.js :

    // src/plugins/i18n.js
    import VueI18n from 'vue-i18n'
    import messages from 'src/i18n'
    
    export default ({ app, store, Vue }) => {
      Vue.use(VueI18n)
    
      // Set i18n instance on app
      app.i18n = new VueI18n({
        locale: 'enUs',
        fallbackLocale: 'enUs',
        messages
      })
    }
    

    It works but is this the correct way to do this?

    Cheers



  • Looks good to me. You must remember quasar i18n is not the same as whatever i18n plugin you end up using



  • Thanks a lot for this @PeterHewat ! I was having the exact same problem and solved it with your instructions.