Search code examples
vue.jsvuejs2vuexnuxt.js

how to define global variables in Nuxt to be accessed anywhere


as i start to expand my app, i found a big problem!! i'm developing a multilingual bidirectional app without i18n. basically i have a language json file like bellow:

{
  "fa":{
    "dir": "rtl",
    // ....
  },
  "en":{
    "dir": "ltr",
    //....
  }
}

i store it in my vuex state lang on nuxtInitServer. but i have two problem.

first, how to access it in my scss file to change the font family?

second, how to access it in my plugins? as for plugins, here is my explanation: link to question

btw, is there any way to define a global variable in nuxt to be acessed anywhere, and of course be changable (not static like env). for example when i change language, be able to access current language in .js and .scss files.

UPDATE here is my actual plugin code that needs access to store:

import Vue from 'vue'
import { required, email , alpha , alpha_spaces , numeric , confirmed } from 'vee-validate/dist/rules'
import { extend, ValidationObserver, ValidationProvider, setInteractionMode } from 'vee-validate'
import { store } from 'vuex'

Vue.prototype.$something= function (){
    let lang = store.state.lang
}

setInteractionMode('eager')

extend('required', {
    ...required,
    message: `{_field_} ${$lang.error_required}` // this is were i'm gonna use my vuex state
})
extend('email', email)
extend('alpha', alpha)
extend('numeric', numeric)
extend('alpha_spaces', alpha_spaces)
extend('confirmed', confirmed)
extend("decimal", {
    validate: (value, { decimals = '*', separator = '.' } = {}) => {
        if (value === null || value === undefined || value === '') {
            return {
                valid: false
            };
        }
        if (Number(decimals) === 0) {
            return {
                valid: /^-?\d*$/.test(value),
            };
        }
        const regexPart = decimals === '*' ? '+' : `{1,${decimals}}`;
        const regex = new RegExp(`^[-+]?\\d*(\\${separator}\\d${regexPart})?([eE]{1}[-]?\\d+)?$`);

        return {
            valid: regex.test(value),
        };
    },
    message: '{_field_} ' + ''
})
Vue.component('ValidationProvider', ValidationProvider);
Vue.component("ValidationObserver", ValidationObserver);

Solution

    1. You can not access a javascript variable in Scss Code. But you could define a Css class for each locale and set the right class to a main div with a computed property inside your layout file.
    <template>
      <div :class="containerLangClass">
        <nuxt />
      </div>
    </template>
    <script>
    export default {
      computed: {
        containerLangClass() {
          return "container-" + this.$store.getters.lang;
        }
      }
    };
    </script>
    
    <style lang="scss">
    .container-fa {
      font-family: "Franklin Gothic Medium", "Arial Narrow", Arial, sans-serif;
    }
    .container-en {
      font-family: "Gill Sans", "Gill Sans MT", Calibri, "Trebuchet MS", sans-serif;
    }
    </style>
    
    1. You can import the vuex store in your plugin and use it in custom methods, directives and co. but I think you want to access the store values before the plugin is created.

    So you can't just import the store

    import {store} from './store';
    

    and use its values like

    store.getters.lang
    

    because at this point the store is not initialized.

    UPDATE Of course you can use store getters, actions etc. in a custom function like:

    import Vue from "vue";
    
    Vue.prototype.$something = function (){
                
    let lang = this.$store.getters.lang; //...etc
    
            }
    

    UPDATE 2 To use your store in your custom validation message, you could add a mixin where you add your validation in the mounted hook. At this point you have all access to your vuex store.

    plugin code:

    import Vue from "vue";
    import { extend } from "vee-validate";
    import { required } from "vee-validate/dist/rules";
    
    Vue.mixin({
      mounted() {
        extend("required", {
          ...required,
          message: fieldName => {
            return `${fieldName} ${this.$store.getters.$lang.error_required}`;
          }
        });
      }
    });
    
    

    Be aware that this code will get called everytime when mounted is called. So I would recommend just using this validation in the pages where you need it.