I'm new to VueJS. I'm trying to make a SAP website with multilingual support. I'm using this helper plugin :
Vue-I18n
Based on this example:
vue-i18n/example/locale/src/App.vue
It works good, however how can I extend this to have the language available to multiple components (pages)? Do I really need to use a store for this, from Vuex?
I did the following and it works like a charm.
main.js:
import Vue from 'vue';
import router from '#/router';
import { store } from '#vue/store/index.js';
import i18n from '#vue/i18n.js'
import App from '#vue/components/App.vue';
Vue.config.productionTip = false;
new Vue({
store,
i18n,
router,
render: h => h(App),
}).$mount(`#app`);
#vue/i18n.js:
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import fr from '../json/fr.json';
import en from '../json/en.json';
Vue.use(VueI18n);
let format = function(lang) {
let messages = {};
lang.forEach(function(message)
{
messages[message.key] = message.text
})
return messages;
}
let populateTexts = function(lang) {
return { ui : format(lang[8]) }
}
let conf = {
locale: 'fr',
fallbackLocale: 'fr',
messages : {
fr: populateTexts(fr),
en: populateTexts(en)
}
}
const i18n = new VueI18n(conf)
export default i18n
You probably won't have the same JSON, so you won't need format and populateTexts.
Although it is late:
1- When using this package in a project it will be available for all components and pages.
2- Using store is not a must, but it is like data layer that all vars and data collected in and make data management easy.
Related
I'm using a helper file to import VueX modules:
const requireModule = require.context('.', false, /\.store\.js$/)
const modules = {}
requireModule.keys().forEach(filename => {
const moduleName = filename
.replace(/(\.\/|\.store\.js)/g, '')
.replace(/^\w/, c => c.toUpperCase())
modules[moduleName] = requireModule(filename).default || requireModule(filename)
})
export default modules
This lives in #/store/modules/index.js and is imported by #/store/index.js:
import Vue from 'vue'
import Vuex from 'vuex'
import modules from './modules'
Vue.use(Vuex)
export default new Vuex.Store({
modules,
actions: {
reset({commit}) {
Object.keys(modules).forEach(moduleName => {
commit(`${moduleName}/RESET`);
})
}
}
})
Imported in to Vue: #/main.js:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
Works great for all of my store modules! Each of which are namespaced:
const initialState = () => ({})
const state = initialState()
const mutations = {
RESET(state) {
const newState = initialState();
Object.keys(newState).forEach(key => {
state[key] = newState[key]
});
}
}
const getters = {}
const actions = {}
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
Now, I'm trying to import a package as a state module. Which I don't have any experience with. This might seem silly... but I'm not sure how to inject the namespace enablement into the package importation in #/store/modules/Auth.store.js:
import AmazonCognitoVuexModule from 'amazon-cognito-vuex-module';
const cognito = new AmazonCognitoVuexModule({
region: process.env.VUE_APP_COGNITO_REGION,
userPoolId: process.env.VUE_APP_COGNITO_USERPOOL_ID,
clientId: process.env.VUE_APP_COGNITO_CLIENT_ID,
})
export default cognito
So when I try to call the imported store module's actions with $store.dispatch('Auth/...') they're not found... because they're not namespaced. I want to namespace this module "Auth". I bet I'm overlooking something really simple. Any help appreciated.
My first try would be (based on the docs of this package on NPM):
// source: https://www.npmjs.com/package/amazon-cognito-vuex-module
const store = new Vuex.Store({
modules: {
cognito: new AmazonCognitoVuexModule({
region: '<region>',
userPoolId: '<user pool id>',
clientId: '<client id>'
})
}
});
The code above shows that you can import it as a module (they named it cognito, you want auth - that should make no difference; I use the naming in the official docs). So you need to update your code, like this:
import Vue from 'vue'
import Vuex from 'vuex'
import modules from './modules'
import cognito from './path/to/cognito'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
...modules,
cognito,
},
actions: {
reset({commit}) {
Object.keys(modules).forEach(moduleName => {
commit(`${moduleName}/RESET`);
})
}
}
})
I'm not sure this works, but this would be my first try :)
I'm new to Vue CLI, and I'm trying to build a small application. As part of this I want to generate some forms.
I've tested a few libraries, and NCForms seems to do all I need to do. (specifically, I need to handle capturing of multiple arrays).
I tried to initialize the library as described in the documentation - but it fails in the Template saying that it can't find some of the element-ui components.
I'm pretty sure that I've followed the instructions properly - but I must be missing something small.
My main.js file looks like this:
import 'ant-design-vue/lib/style/index.less' // antd core styles
import './#kit/vendors/antd/themes/default.less' // default theme antd components
import './#kit/vendors/antd/themes/dark.less' // dark theme antd components
import './global.scss' // app & third-party component styles
import Vue from 'vue'
import VuePageTitle from 'vue-page-title'
import NProgress from 'vue-nprogress'
import VueLayers from 'vuelayers'
import BootstrapVue from 'bootstrap-vue'
import VueFormulate from '#braid/vue-formulate'
// Form generator: Vue-Form-Generator: https://github.com/vue-generators/vue-form-generator
import VueFormGenerator from 'vue-form-generator'
import 'vue-form-generator/dist/vfg.css'
// Form generator: NCForms: https://github.com/ncform/ncform
import vueNcform from '#ncform/ncform'
// eslint-disable-next-line no-unused-vars
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import ncformStdComps from '#ncform/ncform-theme-elementui'
// REST Calls: Axios: https://github.com/axios/axios
import axios from 'axios'
// Local files
import App from './App.vue'
import router from './router'
import store from './store'
import { i18n } from './localization'
import './antd'
import './registerServiceWorker'
// mocking api
import './services/axios/fakeApi'
Vue.use(BootstrapVue)
Vue.use(VueLayers)
Vue.use(NProgress)
Vue.use(VuePageTitle, {
prefix: 'Nedbank PhishTank | ',
router,
})
// Form generator: Vue-Form-Generator
Vue.use(VueFormGenerator)
// Form generator: NCForms
Vue.use(vueNcform, { extComponents: ncformStdComps, lang: 'en' })
window.$http = Vue.prototype.$http = axios
Vue.use(VueFormulate)
Vue.config.productionTip = false
const nprogress = new NProgress({ parent: 'body' })
new Vue({
router,
store,
nprogress,
i18n,
render: h => h(App),
}).$mount('#app')
My template looks like this:
<template>
<div>
<ncform :form-schema="formSchema" form-name="settings-form" v-model="item" #submit="submit()"></ncform>
<el-button #click="submit()">Submit</el-button>
</div>
</template>
<script>
export default {
data() {
return {
formSchema: {
type: 'object',
properties: {
name: {
type: 'string',
},
},
},
item: {
name: 'Peter Pan',
},
}
},
methods: {
submit () {
this.$ncformValidate('settings-form').then(data => {
if (data.result) {
console.log(this.$data.formSchema.value)
// do what you like to do
alert('finally!!!')
}
})
},
},
}
</script>
The error is:
Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.
Am I missing something like registering the individual components? I thought this line would take care of it: Vue.use(vueNcform, { extComponents: ncformStdComps, lang: 'en' })
It feels like I should put something into the "new Vue()" statement - but I'm not sure what....
In main.js, you need to specify: Vue.use(Element);
I have been trying for some time to upgrade my app from vuetify 1.5 to 2, after a lot of thought I think the issue is that the way my app initializes causes the issue, I cannot put my finger on exactly what it is though, the issue is that when I run the app I get errors in the console that none of the vuetify components are recognized.
Attached is a screenshot of the error message.
My main.js file:
import 'babel-polyfill' // IE support
import VueI18n from 'vue-i18n'
import {localizationFactory} from "./localization";
import {apiFactory, apiPluginFactory} from './api/api';
import {storeFactory} from "./store/store";
import {configServiceFactory} from "./services/configService";
import {Services, Security, Utils} from 'em-common-vue';
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import {filtersFactory} from './filters/index';
import Vuetify from "vuetify/lib";
const appsService = new Services.appsService(process.env);
const loginDetails = {
loginHost: appsService.getLoginStorage()
};
Security.ServiceFactory(loginDetails).then($security => {
Vue.config.productionTip = false;
Vue.use(Utils.EventBusPlugin);
Vue.use($security);
var vInstance = new Vue();
const $api = apiFactory(vInstance, $security);
configServiceFactory($security, $api).then($config => {
Vue.use($config);
Vue.use(apiPluginFactory($api));
// for now
const store = storeFactory($api, null);
Vue.use(VueI18n);
filtersFactory($config.$service);
localizationFactory($config.$service).then(messages => {
const i18n = new VueI18n({
locale: 'en', // set locale
messages, // set locale messages
});
Vue.use(Vuetify);
let vuetify = new Vuetify({
icons: {
iconfont: 'mdiSvg',
},
});
new Vue({
router,
store,
i18n,
vuetify,
render: h => h(App),
computed: {
title: {
set(val) {
document.querySelector('title').innerText = val;
},
get(val) {
return document.querySelector('title').innerText;
}
}
},
mounted() {
if (!document.querySelector('title')) {
let title = document.createElement('title');
document.head.append(title);
}
this.title = this.$config.get().title;
}
}).$mount('#app')
});
});
}).catch(err => {
console.error(err);
if (err.loginUrl) {
const nextUrl = appsService.getLogin(window.location.href);
window.location.href = nextUrl;
} else { // for now
alert(err);
}
});
How might I change my code to load vuetify properly? Alternatively what might be a pattern that might work for my code?
TL;DR:
Replace import Vuetify from "vuetify/lib"; with import Vuetify from "vuetify";
Alternatively if you want to use vuetify-loader:
Add vuetify-loader to your project (if already present, update it)
If you're using webpack directly add the vuetify-loader plugin to your webpack plugins:
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin');
exports.plugins.push(new VuetifyLoaderPlugin());
If you used #vue/cli to setup your project, you can use the configureWebpack option in vue.config.js to add the plugin:
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin');
module.exports = {
configureWebpack: {
plugins: [
new VuetifyLoaderPlugin()
]
}
}
Why?
vuetify comes in two "flavors":
A-la-carte
All vuetify components will not be directly required, but only loaded when you explicitly import them.
This greatly reduces your final package size, since you only include the parts of the vuetify framework that you're actually using.
You're using A-la-carte if you're importing vuetify from vuetify/lib:
import Vue from "vue";
import Vuetify from "vuetify/lib";
Vue.use(Vuetify);
const vuetify = new Vuetify({ /* ... */});
new Vue({vuetify}).$mount('#root');
The downside of a-la-carte is that you need to manually import each vuetify component you want to use:
import {VIcon} from "vuetify/lib";
export default {
name: 'foo-component',
components: { VIcon },
template: '<v-icon>user</v-icon>'
};
To make this less a hassle, you can either:
use vuetify-loader, it will automatically add those imports for you if you set it up correctly.
globally load components you use a lot:
import Vue from 'vue';
import Vuetify, { VLayout } from 'vuetify/lib';
// globally register v-layout.
// now you don't need to import it in every component that uses it
Vue.use(Vuetify, { components: { VLayout } });
Normal Mode
If you import vuetify directly, it'll automatically load all its components for you and is ready to use without further configuration:
// not a-la-carte, will load all vuetify components
import Vue from "vue";
import Vuetify from "vuetify"; // **not** /lib
Vue.use(Vuetify);
const vuetify = new Vuetify({ /* ... */});
new Vue({vuetify}).$mount('#root');
I'm trying to use i18n outside a component I've found this solution https://github.com/dkfbasel/vuex-i18n/issues/16 telling to use Vue.i18n.translate('str'), but when I call this occurs an error Cannot read property 'translate' of undefined.
I'm using the following configuration
main.js
import i18n from './i18n/i18n';
new Vue({
router,
store,
i18n: i18n,
render: h => h(App)
}).$mount('#app')
i18n.js
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import i18nData from './i18nData'
Vue.use(VueI18n);
export default new VueI18n({
locale: 'en',
messages: i18nData,
});
i18nData.js
export default {
en: {
//my messages
}
}
Then I trying to use this
import Vue from 'vue';
Vue.i18n.translate('someMessage');
Can anyone help me?
To use i18n with Vue 3's composition API, but outside a component's setup(), you can access its translation API (such as the t function) on its global property.
E. g. in a file with unit-testable composition functions:
// i18n/index.js
import { createI18n } from 'vue-i18n'
import en from './en.json'
...
export default createI18n({
datetimeFormats: {en: {...}},
locale: 'en',
messages: { en }
})
// features/utils.js
//import { useI18n } from 'vue-i18n'
//const { t } = useI18n() // Uncaught SyntaxError: Must be called at the top of a `setup` function
import i18n from '../i18n'
const { t } = i18n.global
You should import i18n instead of Vue
import i18n from './i18n'
i18n.tc('someMessage')
You can use VueI18n outside components by importing i18n then, use "t" from i18n.global.
"t" doesn't need "$" and you can change Locale with i18n.global.locale.
import i18n from '../i18n';
const { t } = i18n.global;
i18n.global.locale = 'en-US'; // Change "Locale"
const data = {
name: t('name'), // "t" doesn't need "$"
description: t('description'), // "t" doesn't need "$"
};
I managed to make it work this way:
import router from '../router';
Translate a text:
let translatedMessage = router.app.$t('someMessage');
Get the current language:
let language = router.app.$i18n.locale;
I am new to Quasar framework. Could someone explains how load quasar-components in Globally use. (every where in my application)
My main.js is like:
import Vue from 'vue'
import Quasar from 'quasar'
import router from './router'
require(`quasar/dist/quasar.${__THEME}.css`)
Vue.config.productionTip = false
Vue.use(Quasar) // Install Quasar Framework
if (__THEME === 'mat') {
require('quasar-extras/roboto-font')
}
import 'quasar-extras/material-icons'
// import 'quasar-extras/ionicons'
// import 'quasar-extras/fontawesome'
// import 'quasar-extras/animate'
Quasar.start(() => {
/* eslint-disable no-new */
new Vue({
el: '#q-app',
router,
render: h => h(require('./App').default)
})
})
Unknown custom element: <q-btn> - did you register the component correctly?
For recursive components, make sure to provide the "name" option.
found in
---> <App> at src\App.vue
<Root>
Whenever you're using any Quasar elements (eg. q-btn, q-select), you need to import and export it in your .vue file.
Example, for a <q-btn> to display, you might use
<q-btn > Confirm </q-btn>
But to display that, you need to include following into your .vue file. Like:
import {
QSelect,
QBtn
} from 'quasar'
export {
QSelect,
QBtn
} from 'quasar'
Like this, you will be registering all your components.
In my projects I import and use with components like this
import Quasar, { QBtn, QSelect } from 'quasar-framewok';
Vue.use(Quasar, {
components: { QBtn, QSelect }
});
Only for test case import all
import Quasar, * as All from 'quasar';
Vue.use(Quasar, {
components: All,
directives: All
});
See Quasar docs