I'm using Nuxt.js and I have two plugins installed.
I need access to the VueI18n instance from lang.js in validate.js
Does someone know how to do this?
lang.js
Vue.use(VueI18n)
export default ({ app }) => {
app.i18n = new VueI18n({
locale: 'en',
messages
})
}
validate.js
Vue.use(VeeValidate, {
i18nRootKey: 'validations',
i18n, // access the VueI18n instance from plugin above
dictionary: {
en: validationMessages
}
})
export default ({ app }) => {
// This way I could get the instance but how to add it to the plugin?
console.log(app.i18n)
}
Just move your vue.use inside export default
export default ({ app }) => {
Vue.use(VeeValidate, {
i18nRootKey: 'validations',
i18n: app.i18n, // access the VueI18n instance from plugin above
dictionary: {
en: validationMessages
}
})
}
Related
It seems that Vue Meta has been upgraded to handle Vue.js 3 with a new npm package called vue-3-meta
Before Vue.js 3, it was easy to use vue-meta by adding it to the Vue instance:
import Vue from 'vue'
import VueMeta from 'vue-meta'
Vue.use(VueMeta, {
// optional pluginOptions
refreshOnceOnNavigation: true
})
However in Vue.js 3, there is no Vue instance; and instead you create the app by running createApp like such:
const app = createApp(App);
const router = createVueRouter();
app.use(router);
// need to make app use Vue-Meta here
I cannot find any documentation for vue-3-meta. import VueMeta from 'vue-meta' no longer works.
How do I import the vue-3-meta plugin properly and use it with app like in prior versions?
Disclaimer: vue-meta v3 is still in alpha!
This was the minimal implementation I needed to get started:
Update vue-meta to v3 (in package.json)
- "vue-meta": "^2.4.0",
+ "vue-meta": "^3.0.0-alpha.7",
...or with yarn:
yarn add vue-meta#alpha
Add metaManager to Vue app
import { createMetaManager } from 'vue-meta'
const app = createApp(App)
.use(router)
.use(store)
.use(createMetaManager()) // add this line
await router.isReady()
app.mount('#app')
Add <metainfo> to App.vue <template> (this is also where I set a "title template")
<template>
<metainfo>
<template v-slot:title="{ content }">{{ content ? `${content} | SITE_NAME` : `SITE_NAME` }}</template>
</metainfo>
<header />
<router-view />
<footer />
</template>
Set default meta in App.vue <script>
Vue 3 vanilla:
import { useMeta } from 'vue-meta'
export default {
setup () {
useMeta({
title: '',
htmlAttrs: { lang: 'en', amp: true }
})
}
}
or with vue-class-component:
import { setup, Vue } from 'vue-class-component'
import { useMeta } from 'vue-meta'
export default class App extends Vue {
meta = setup(() => useMeta({
title: '',
htmlAttrs: { lang: 'en', amp: true }
})
}
Override meta in each component
Vue 3 vanilla:
import { useMeta } from 'vue-meta'
export default {
setup () {
useMeta({ title: 'Some Page' })
}
}
or with vue-class-component:
import { computed } from '#vue/runtime-core'
import { setup, Vue } from 'vue-class-component'
import { useMeta } from 'vue-meta'
export default class SomePage extends Vue {
meta = setup(() => useMeta(
computed(() => ({ title: this.something?.field ?? 'Default' })))
)
}
See also:
"Quick Usage" (vue-meta next branch)
Vue Router Example (vue-meta next branch)
In addition to the previous answers, I also needed to add a transpileDependency in my vue.config.js, as I was using vue-cli:
module.exports = {
transpileDependencies: ['vue-meta']
}
Else, I would get the error:
error in ./node_modules/vue-meta/dist/vue-meta.esm-browser.min.js
Module parse failed: Unexpected token (8:7170)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
Thanks to this thread for pointing me to this: https://stackoverflow.com/a/65844988/3433137
metaManager is a MetaManager instance created from createMetaManager() of vue-meta.
Based on the Vue 3 + Vue Router example for vue-meta, here's an example usage:
import { createApp } from 'vue'
import { createMetaManager, defaultConfig, resolveOption, useMeta } from 'vue-meta'
const decisionMaker5000000 = resolveOption((prevValue, context) => {
const { uid = 0 } = context.vm || {}
if (!prevValue || prevValue < uid) {
return uid
}
})
const metaManager = createMetaManager({
...defaultConfig,
esi: {
group: true,
namespaced: true,
attributes: ['src', 'test', 'text']
}
}, decisionMaker5000000)
useMeta(
{
og: {
something: 'test'
}
},
metaManager
)
createApp(App).use(metaManager).mount('#app')
I try to make news web apps to use newsapi.org.
I wanted to hide my api_key so I decided to use env property in Nuxt.Js.
But now I got 401 status code from server.
first of all, I made the .env file in project file and I put my API_KEY.
and then I installed 'dotenv' use 'yarn add dotenv' command in VSCode terminal.
and I add nuxt.config.ts file. I have used TypeScript in my project so all file depend on TypeScript.
require('dotenv').config()
const { API_KEY } = process.env
export default {
~~~~~~~~~~
env: {
API_KEY,
},
}
and I used Vuex to get news information.
so I made code like following.
~/store/getNews.ts
import { MutationTree, ActionTree, GetterTree } from "vuex";
import axios from "axios";
const url = 'http://newsapi.org/v2/top-headlines';
interface RootState { }
export interface NewsArticles {
source?: {}
author?: string
title?: string
description?: string
url?: any
urlToImage?: any
publishedAt?: string
content?: string
}
interface State {
newArticle: NewsArticles
}
export const state = () => ({
newsArticle: []
})
export const getters: GetterTree<State, RootState> = {
newsArticle: (state: State) => state.newArticle
}
export const mutations: MutationTree<State> = {
setNewsArticle: (state: State, newsArticle: NewsArticles) => {
state.newArticle = newsArticle
}
}
export const actions: ActionTree<State, RootState> = {
getNewsArticle: async ({ commit },{params}) => {
try{
const data = await axios.get(url,{params})
commit('setNewsArticle', data.data.articles)
}catch(error){
commit('setNewsArticle',[])
}
}
}
export default { state, getters, mutations, actions }
and finally, I made vue file to show the news information like following.
<template>
<div>
<p>this is NewsApi test pages!!</p>
<ul v-for="(item, index) in items" :key="index">
<li>{{ item.title }}</li>
</ul>
</div>
</template>
<script lang="ts">
import { Component, namespace, Vue } from 'nuxt-property-decorator'
import { NewsArticles } from '~/store/getNews'
const getNews = namespace('getNews')
#Component({})
export default class extends Vue {
#getNews.Action getNewsArticle!: Function
#getNews.Getter newsArticle!: NewsArticles
items: any = []
async mounted() {
await this.getNewsArticle({
params: { country: 'jp', category: 'business', apiKey: process.env.API_KEY },
})
this.items = this.newsArticle
}
}
</script>
I ran my app but I got 401 status code and I checked the console error like following.
{status: "error", code: "apiKeyInvalid",…}
code: "apiKeyInvalid"
message: "Your API key is invalid or incorrect. Check your key, or go to https://newsapi.org to create a free API key."
status: "error"
I don't know why that error occurred.
I checked apikey correctly setting to confirm consle.log.
in index.vue
<script lang='ts'>
~~~~
export default class extend Vue{
mounted(){
console.log(process.env.API_KEY)
}
}
</script>
You don't need to call require('dotenv').config(), as Nuxt automatically invokes it.
Also, for the env vars to be available in the production build, their names must be prefixed with NUXT_ENV_ (i.e., NUXT_ENV_API_KEY). Note this allows you to keep the key from being checked into source (assuming your .env file is also kept out of source control), but your API key can still be observed in the Network tab in DevTools.
In project some common function are in separate .ts files.
How can I use i18 in that cases:
// for i18n
import Vue from 'vue'
declare module 'vue/types/vue' {
interface VueConstructor {
$t: any
}
}
declare module 'vue/types/options' {
interface ComponentOptions<V extends Vue> {
t?: any
}
}
(()=>{
const test = Vue.$t('auth.title');
console.log( test )
})()
Return an error:
Property '$t' does not exist on type 'VueConstructor<Vue>"
How can I fix it?
we can achieve the same like below
Step 1: create a separate index.ts file inside a i18n folder (you can do it your own way - root level or any where in your app)
i18n/index.ts
import Vue from 'vue';
import VueI18n from 'vue-i18n';
// register i18n module
Vue.use(VueI18n);
const i18n = new VueI18n({
locale: 'nb-NO', //if you need get the browser language use following "window.navigator.language"
fallbackLocale: 'en',
messages: {en, no},
silentTranslationWarn: true
})
const translate = (key: string) => {
if (!key) {
return '';
}
return i18n.t(key);
};
export { i18n, translate}; //export above method
Step 2: make sure to use(import) above in main.ts
main.ts
import { i18n } from '#/i18n';
new Vue({ i18n, render: h => h(app) }).$mount('#app')
after above configuration we should be able to use translation in any place that we want in our application
Step 3: How to use it in .ts and .vue files
// first import it into the file
import { translate, i18n } from '#/i18n';
//this is how we can use translation inside a html if we need
<template>
<h1>{{'sample text' | translate}}</h1>
</template>
//this is how we can use translation inside a .ts or .vue files
<script lang='ts'>
//normal scenario
testFunc(){
let test = `${translate('sample text')}`;
console.log(test );
}
//in your case it should be like below
(()=>{
const test = `${translate('auth.title')}`;
console.log( test )
})()
</script>
I hope that this will help you to resolve your issue.
I'm working on an app I'm migrate to VueJS so some parts are using old jQuery code.
So I'm trying to append an VueJS component using jQuery, so I made
import copyToClipboard from '../components/_base/VCopyToClipboard';
const CopyToClipboard = Vue.extend(copyToClipboard);
$(event.currentTarget).find('.dns-challenge-row').each((index, element) => {
const component = new CopyToClipboard({
propsData: {
targetId: $(element).find('code').attr('id'),
},
}).$mount();
$(element).append(component.$el);
});
Everything is working BUT when I go on the page where this component is appended, i18n return an error
Cannot translate the value of keypath 'tooltip.default'. Use the value of keypath as default.
FYI my translation messages are directly defined inside my SFC using the i18n keyword
i18n: {
messages: {
en: {
tooltip: {
default: 'Copy content',
success: 'Copied',
},
},
fr: {
tooltip: {
default: 'Copier le contenu',
success: 'Copié',
},
},
},
},
and I use then directly inside the SFC using this.$t('tooltip.default')
My i18n is import like the docs say but is loaded after the vue.js I use to create my component.
import {
Vue,
} from './vue';
import VueI18n from 'vue-i18n';
import en from '../../translations/en';
import fr from '../../translations/fr';
Vue.use(VueI18n);
export default new VueI18n({
locale: document.getElementsByTagName('html')[0].getAttribute('lang'),
messages: {
en,
fr,
},
});
The vue.js file is the the file where I put all my Vue.use() definitions, my routern, other stuff and is used to create the Vue instance inside another file
vueSetup(new Vue({
el: '#app',
components: {
...
},
i18n: i18n,
router: router,
store: store,
}));
Do you have an idea to solve this?
I tried to load i18n before the vue component without success and I saw a lot of GitHub issues with this error but not like my case.
Just import and add i18n instance to the new component instance
const CopyToClipboard = Vue.extend(copyToClipboard);
$(event.currentTarget).find('.dns-challenge-row').each((index, element) => {
const component = new CopyToClipboard({
i18n: i18n,
propsData: {
targetId: $(element).find('code').attr('id'),
},
}).$mount();
$(element).append(component.$el);
});
I was using vuetify and wanted to change theme from vuex store using $vuetify instance but i got this error Cannot set property 'theme' of undefined"
here is my code
export default {
getters: {},
mutations: {
toggleDarkTheme(state) {
this.$vuetify.theme.primary = "#424242";
}
}
};
For Vuetify 2.0 you can try following method. (After following Vuetify 2.0 Upgrade guide for themes)
import Vuetify from './plugins/vuetify'
export default {
getters: {},
mutations: {
toggleDarkTheme(state) {
Vuetify.framework.theme.themes.light.primary = "#424242";
}
}
$vuetify is an instance property hence you can access any vue
instance property using
Vue.prototype.$prop
For your case
import Vue from 'vue';
export default {
getters: {},
mutations: {
toggleDarkTheme(state) {
Vue.prototype.$vuetify.theme.primary = "#424242";
}
}
};
This one worked for me
...
toggleDarkTheme(state) {
window.$nuxt.$root.$vuetify.theme.dark = true
}
For Nuxt.js projects with Vuetify set as a buildModule, you can access $vuetify from the $nuxt property in the Vue instance:
import Vue from 'vue';
export actions = {
yourAction() {
Vue.prototype.$nuxt.$vuetify.theme.dark = true;
}
}