Why does the language load only after reloading the page? i18n - javascript

When you first start the application, the application language should be installed on the system. But this only works when the page is reload. How to make the language load the first time?
<template>
...
<f7-menu-dropdown-item href="#" #click="setLocale('en')">
<f7-menu-dropdown-item href="#" #click="setLocale('ru')">
...
</template>
export default {
methods: {
setLocale(locale){
import(`../langs/${locale}.json`).then((msgs) => {
this.$i18n.setLocaleMessage(locale, msgs)
this.$i18n.locale = locale
localStorage.setItem('language', locale);
})
},
//Before creating, I check if there is any value in localStore and if not, then I install the system language.
beforeCreate(){
if(localStorage.getItem('language') === null){
let lng = window.navigator.systemLanguage || window.navigator.language;
lng = lng.substr(0, 2).toLowerCase();
localStorage.setItem('language', lng);
}
}
}
}
}
i18n
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import en from '../langs/en.json'
import ru from '../langs/ru.json'
Vue.use(VueI18n)
export const i18n = new VueI18n({
locale: window.localStorage.getItem("language"),
fallbackLocale: 'en',
messages:{
en,
ru
}
})

Related

I can't set i18n.locale in the javascript part of an inertiajs app

I want to use vue-i18n (version 9.1) in an interiajs app (laravel9 + vue3).
Since I need to do several things when switching languages, I need to outsource setting the i18n locale in the javascript part.
Unfortunately, this does not work:
I have already tried using $i18n.locale or this.$i18n.locale, without success (Error-message: this.$i18n / $i18n is not defined).
I am missing a hint how to set $i18n.locale in the javascript.
Here is my code:
app.js setup of i18n
require('./bootstrap');
import { createApp, h } from 'vue';
import { createI18n } from 'vue-i18n'
import { createInertiaApp } from '#inertiajs/inertia-vue3';
import { InertiaProgress } from '#inertiajs/progress';
const appName = window.document.getElementsByTagName('title')[0]?.innerText || 'Laravel';
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => require(`./Pages/${name}.vue`),
setup({ el, app, props, plugin }) {
const i18n = createI18n({
locale: "de",
// locale: props.initialPage.props.locale, // user locale by props
fallbackLocale: "en", // set fallback locale
messages: loadLocaleMessages(),
});
return createApp({ render: () => h(app, props) })
.use(plugin)
.use(i18n)
.mixin({ methods: { route } })
.mount(el);
},
});
Authenticated.vue switch locale
<script setup>
import {ref, onMounted} from 'vue';
import BreezeDropdown from '#/Components/Dropdown.vue';
import BreezeNavLink from '#/Components/NavLink.vue';
import BreezeResponsiveNavLink from '#/Components/ResponsiveNavLink.vue';
import ProjectVersion from '#/Components/ProjectVersion.vue';
import {Link} from '#inertiajs/inertia-vue3';
import { usePage } from '#inertiajs/inertia-vue3';
import { computed } from 'vue';
function switchLanguage(key){
console.log('switchLanguage to ' + key);
this.$i18n.locale = key; // not working
}
</script>
<template>
<div v-if="$i18n.locale == 'en'">
<a #click.prevent="switchLanguage('de')" href="#">
Deutsch
</a>
</div>
<div v-if="$i18n.locale == 'de'">
<a #click.prevent="switchLanguage('en')" href="#">
English
</a>
</div>
</template>
I am happy about every hint.
In fact, this would not work in the way you're using it, since it's not a reference to the component instance inside that function. The composition API docs for i18n even says that we need "to replace access to this"
I haven't tried it, but I believe this would look something like this:
<script setup>
import { useI18n } from 'vue-i18n'
const { t, locale } = useI18n({
locale: 'en',
messages: {
en: {
// ...
},
de: {
// ...
}
}
})
const switchLanguage = (key) => {
locale.value = key
}
</script>

React.js i18n dynamically change language

I am using "i18n" for multilingual support in my "React.js" project. I have a "Switch" button in "Navbar" component. and when that button is clicked I add current language information to "lcoalstore". And when I check in browser, language option works dynamically in "localstore". My problem is I want to change app language every time user changes language. But that doesn't happen.
Here is my i18n code:
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import messages_az from "./translations/az.json";
import messages_en from "./translations/en.json";
// the translations
// (tip move them in a JSON file and import them)
const resources = {
en: {
translation: messages_en,
},
az: {
translation: messages_az,
},
};
i18n
.use(initReactI18next) // passes i18n down to react-i18next
.init({
resources,
lng: localStorage.getItem("lang"),
detection: {
order: ["localStorage", "lang"],
lookupQuerystring: "lang",
lookupLocalStorage: "lang",
caches: ["localStorage"],
},
keySeparator: false, // we do not use keys in form messages.welcome
fallbackLng: "az", // use az if detected lng is not available
interpolation: {
escapeValue: false, // react already safes from xss
},
});
export default i18n;
I fixed That!
Here is my swtich button :
<Menu.Item key="lang" className=" navMenuItem">
<Switch
onChange={langSwitch}
className="langSwitch"
checkedChildren="En"
unCheckedChildren="Az"
defaultChecked
/>
</Menu.Item>
So, i Added this code to my langSwitch() function :
function langSwitch(checked) {
console.log(`switch to ${checked}`);
if (checked) {
i18n.changeLanguage("en");
} else {
i18n.changeLanguage("az");
}
}

characters wont display correct with Quasar Framework together with i18n

Im using i18n together with Quasar Framework. It works great but I have some problems with some special characters in certain languages when grabbing text from my own definations.
I got this in i18n.js in my boot:
import Vue from "vue";
import VueI18n from "vue-i18n";
import messages from "src/i18n";
Vue.use(VueI18n);
const i18n = new VueI18n({
locale: "en-us",
fallbackLocale: "en-us",
messages,
});
export default ({ app }) => {
// Set i18n instance on app
app.i18n = i18n;
};
// if you need to import it from
// other files, then:
export { i18n };
and use it in template like this:
<template>
...
<div>{{ $t('hello') }}</div>
...
and in my bootfile
boot: ["i18n"],
framework: {
iconSet: "material-icons", // Quasar icon set
lang: "en-us", // Quasar language pack
Here is the setup in my language component:
export default {
data() {
return {
toggleSMenu: false,
myData: ["one", "two"],
lang: this.$i18n.locale,
langOptions: [
{ value: "en-us", label: "EN" },
{ value: "nl", label: "NL" }
]
};
},
When I change to Dutch (NL) some caracters wont display correctly. How can I add support for dutch letters?

Vue i18n translation for single file components

I'm using laravel and currently trying to do multilanguage pages,
So i've found this pretty neat plugin called VueI18N for translations and got it working (somehow) by installing it via npm and then putting the following code in my app.js
//app.js
window.Vue = require('vue');
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
//tons of more components here
Vue.component('vue-test', require('./components/VueTestFileForLocalization.vue').default);
const messages = {
en: {
message: {
hello: 'Hello, {name}!'
}
},
de: {
message: {
hello: 'Guten Tag, {name}!'
}
}
};
const i18n = new VueI18n({
locale: 'de',
messages
});
const app = new Vue({
el: '#vue-app',
i18n
});
Then in my vue-test i tried outputting this successfully:
<template>
<div>{{ $t('message.hello', { name: 'John' }) }}</div>
</template>
<script>
export default {
data() {
return {};
},
created() {
this.$i18n.locale = 'en';
}
};
</script>
and by changing the locale i can also display the other language. Great.
Now I think with so many components, I might have a problem defining all the localization inside app.js , and its not beautiful either. So I tried looking up This link here to the docs for single file components but unsuccessfully, unfortunately.
I copy-pasted the code, (vue-i18n-loader should also be installed by laravel by default) and modified the webpack file. The error I get seems pretty common after research but I cannot seem to fix it.
Value of key 'hello' is not a string!
Cannot translate the value of keypath 'hello'. Use the value of keypath as default
It does simply output whatever the key is i specify in message.
Does any of you out there have an idea, what I might have done wrong or forgot to setup?
Any hints would be appreciated very very much.
Thank you for your time
Best regards,
Desory
While not a direct answer to your question I recently found another approach to the same problem that is less effort when it comes to maintaining translations.
I put all my translations in JSON files so I can share the same translations between Laravel backend and Vue front end.
I did this based on this:
https://www.codeandweb.com/babeledit/tutorials/how-to-translate-your-vue-app-with-vue-i18n
So as per: https://laravel.com/docs/7.x/localization#using-translation-strings-as-keys
Create resources/lang/en.json etc. with contents:
{
"my_message": "This is my message in english",
...
}
I'd create resources/js/i18n.js containing:
import Vue from "vue";
import VueI18n from "vue-i18n";
Vue.use(VueI18n);
function loadLocaleMessages() {
const locales = require.context(
"../lang",
true,
/[A-Za-z0-9-_,\s]+\.json$/i
);
const messages = {};
locales.keys().forEach(key => {
const matched = key.match(/([A-Za-z0-9-_]+)\./i);
if (matched && matched.length > 1) {
const locale = matched[1];
messages[locale] = locales(key);
}
});
return messages;
}
export default new VueI18n({
locale: process.env.VUE_APP_I18N_LOCALE || "en",
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || "en",
messages: loadLocaleMessages()
});
and in app.js import that as follows:
//Localise
import i18n from "./i18n";
Vue.use(i18n);
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
const app = new Vue({
i18n,
el: "#app"
});
You can then use the same translations in your blade templates with the __ helper and in Vue with $t(...)
Try the changes below for app.js and your code should work fine:
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import App from './components/VueTestFileForLocalization.vue';
Vue.use(VueI18n);
const messages = {
en: {
message: {
hello: 'Hello, {name}!'
}
},
de: {
message: {
hello: 'Guten Tag, {name}!'
}
}
};
const i18n = new VueI18n({
locale: 'de',
messages
});
new Vue({
i18n,
render: h => h(App)
}).$mount('#vue-app');
I had the same problem, i solved it by restarting the server.
Run npm run serve again.
Hope it helps someone in the future..

How to transfer value from Vuex Store to i18n.js?

I am trying to make the language that I chose was saved when the program was restarted.
How to save the value of locale:'' in i18n when switching languages?
I want to transfer this value from VUEX Store to i18n, but I don’t know how to do it right.
The default local: 'en'.
When the language is changed, the value in locale is overwritten and stored in localStorage, and when the program is restarted, the value at the created () stage is taken from localStorage.
Maybe at least an example exists where a similar function is implemented?
<template>
...
<f7-menu-dropdown-item href="#" #click="setLocale('en')">
<f7-menu-dropdown-item href="#" #click="setLocale('ru')">
...
</template>
export default {
methods: {
setLocale(locale){
import(`../langs/${locale}.json`).then((msgs) => {
this.$i18n.setLocaleMessage(locale, msgs)
this.$i18n.locale = locale
localStorage.setItem('language', locale);
})
},
created(){
if(localStorage.getItem('language') !== null){
localStorage.setItem('language', navigator.language || navigator.userLanguage);
}
}
}
}
i18n.js
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import en from '../langs/en.json'
import ru from '../langs/ru.json'
Vue.use(VueI18n)
export const i18n = new VueI18n({
locale: window.localStorage.getItem("language"),
fallbackLocale: 'ru',
messages:{
en,
ru
}
})

Categories

Resources