No More Posting New Topics!

If you have a question or an issue, please start a thread in our Github Discussions Forum.
This forum is closed for new threads/ topics.

Navigation

    Quasar Framework

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

    [0.15] Access plugin component outside of Vue instance (e.g. from router navigation guards)?

    Help
    4
    9
    3571
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      sarndt last edited by

      Hello,

      I’m a bit new to Vue and Quasar, so please help me understand how to accomplish the following:

      I wish to use the vue-i18n plugin to translate something in a Dialog that is created in a vue-router beforeEach navigation guard, i.e.:

      import Vue from 'vue';
      import VueRouter from 'vue-router';
      import { Dialog } from 'quasar';
      import routes from './routes';
      
      
      const Router = new VueRouter({
        /*
         * NOTE! Change Vue Router mode from quasar.conf.js -> build -> vueRouterMode
         *
         * If you decide to go with "history" mode, please also set "build.publicPath"
         * to something other than an empty string.
         * Example: '/' instead of ''
         */
      
        // Leave as is and change from quasar.conf.js instead!
        mode: process.env.VUE_ROUTER_MODE,
        base: process.env.VUE_ROUTER_BASE,
        scrollBehavior: () => ({y: 0}),
        routes
      });
      
      Router.beforeEach((to, from, next) => {
        if (to.matched.some(record => record.meta.someProp) &&
          !from.matched.some(record => record.meta.someProp)) {
          Dialog.create({
            // The following does not work :(
            title: Vue.t('some.translation.key'),
            form: {
                   ...
              }
            },
            buttons: [
                  ...
            ]
          });
        }
        else {
          next();
        }
      });
      
      export default Router;
      

      Before, I could just import the i18n instance, but since the thing is now initialized as a plugin to the Vue system, how can I access it from router, which has no this to use? Stuff like Vue.t or Vue.$i18n.t doesn’t work.

      I’m sure I’m missing some core concept here, please help me out.

      1 Reply Last reply Reply Quote 0
      • J
        jgalmes last edited by

        Hello sarndt,

        I was a little stuck also with this problem. My solution was:

        MUST KNOW BEFORE SOLUTION:
        If you use this.$q.i18n.<quasar-label> is the label of QUASAR, this is only for components as DataTable.
        If you want to use your own translations you must to do: this.$i18n.<your-custom-label>

        SOLUTION:
        1- To do your own translations after install Vue WITH i18n you must change src/i18n and add your own languages and then change index.js inside this folder. In my case, I have 4 languages:

        import en from ‘./en’
        import de from ‘./de’
        import ca from ‘./ca’
        import es from ‘./es’

        export default {
        en,de,ca,es
        }

        2- Inside your layout (default.vue) yo can declare this:

        in your HTML:

        <q-btn @click=“changeLanguage(‘en’)”>EN</q-btn>
        <q-btn @click=“changeLanguage(‘de’)” >DE</q-btn>
        <q-btn @click=“changeLanguage(‘ca’)” >CA</q-btn>
        <q-btn @click=“changeLanguage(‘es’)”>ES</q-btn>

        in your script:

        methods: {
        openURL,
        changeLanguage (lng) {
        //DANGER!!!
        //this.$q.i18n -> International QUASAR
        //this.$i18n -> International local files
        console.log(‘Change lang:’,lng);
        this.$i18n.locale=lng;
        }
        }

        I hope you help with this solution.

        1 Reply Last reply Reply Quote 0
        • benoitranque
          benoitranque last edited by benoitranque

          You can pass vm: this to the store when dispatching an action. Then you can do everything there

          Edit:

          You can access the vue from the store instance using this._vm

          S 1 Reply Last reply Reply Quote 0
          • S
            sarndt @benoitranque last edited by

            @benoitranque said in [0.15] Access plugin component outside of Vue instance (e.g. from router navigation guards)?:

            You can pass vm: this to the store when dispatching an action. Then you can do everything there

            Edit:

            You can access the vue from the store instance using this._vm

            My problem is that I’m not having a store instance to work with, I’m in a Router.beforeEach() guard, so that I don’t have any vue instance at this point either. I would really just like to know how to access the i18n plugin from the general Vue object that I can import with import Vue from 'vue';

            1 Reply Last reply Reply Quote 0
            • benoitranque
              benoitranque last edited by

              I would suggest you create a plugin for your router.beforeEach() guard, and add it after i18n plugin has been initiated

              1 Reply Last reply Reply Quote 0
              • S
                sarndt last edited by

                That doesn’t sound too bad, I’ll see if that works. Haven’t written plugins for vue yet, but maybe that’s the right way to go about it

                1 Reply Last reply Reply Quote 0
                • benoitranque
                  benoitranque last edited by

                  You can(should) init a quasar plugin using quasar new plugin <name>

                  S 1 Reply Last reply Reply Quote 0
                  • S
                    sarndt @benoitranque last edited by sarndt

                    @benoitranque
                    Yep, that actually did the trick, just wanted to write this down here in case someone else comes around with the same problem.
                    NB: The plugin order doesn’t matter actually, as the guard is only used once all plugins are initialized.

                    In my case, using a plugin, I could reference my i18n instance via app.i18n and thus just add a navigation guard like this:

                    import {Dialog, Notify} from 'quasar';
                    
                    export default ({app, router, store}) => {
                      router.beforeEach((to, from, next) => {
                        if (to.matched.some(record => record.meta.someProperty) {
                          // Do something here like creating a dialogue
                          Dialog.create({
                            title: app.i18n.t('some.i18n.key'),
                            ok: true,
                            cancel: true,
                            preventClose: true,
                            prompt: {
                              model: ''
                            }
                          }).then(data => {
                            // Handle okay
                          }).catch(() => {
                            // Handle cancel
                            Notify.create(app.i18n.t('some.other.i18n.key'));
                          });
                        }
                        else {
                          next();
                        }
                      });
                    };
                    
                    1 Reply Last reply Reply Quote 0
                    • a47ae
                      a47ae last edited by

                      I would agree with @benoitranque on your use case.
                      However if you run in the problem that you really need i18n access from external files (e.g. pure JS files that are imported in your component) I have come up with the following solution.

                      1. Set up your i18n instance in a seperate file (for example src/i18n/i18n.js) with the following conent:
                      import Vue from 'vue'
                      import VueI18n from 'vue-i18n'
                      import locales from 'src/i18n'
                      
                      Vue.use(VueI18n)
                      
                      const i18n = new VueI18n({
                        locale: 'en',
                        messages: locales
                      })
                      
                      export default i18n
                      
                      
                      1. Create a Quasar plugin for i18n (or use the default one) with the following content:
                      import i18n from 'src/i18n/i18n'
                      
                      export default ({ app, Vue }) => {
                        app.i18n = i18n
                      }
                      
                      

                      This way you can use this.$t in your Vue components, but you are also able to use it like this in pure JS:

                      import i18n from `src/i18n/i18n.js`
                      
                      // whatever code
                      
                      i18n.t('my-string')
                      
                      1 Reply Last reply Reply Quote 2
                      • First post
                        Last post