3 page links in the nav should be displayed in 3 languages by user choice. In the initial page load it works fine. Then click one language change link then again it works fine. But when I click a language change link another time only the last link's language changes when all of them should change language. What is causing this problem and how to fix it?
app.vue:
<template>
<nav class="navbar">
<NuxtLink class="pagelink" :key="page.slug" v-for="page in strings.pages" :href="'/' + page.slug">{{ page.name[lang] }}</NuxtLink>
<Languages />
</nav>
</template>
<script>
import Languages from "./components/languages.vue"
import languages from "../services/languages"
export default {
name: "Navbar",
data() {
return {
open: false,
strings: {
pages: [
{
slug: 'home',
name: { az: "Əsas", ru: "Главная", en: "Home" }
},
{
slug: 'about',
name: { az: "Haqqımızda", ru: "О нас", en: "About" }
},
{
slug: 'contact',
name: { az: "Əlaqə", ru: "Связаться", en: "Contact Us" }
}
]
}
}
},
computed: {
lang() {
return languages(this)
}
}
}
</script>
<style>
* {
margin: 10px;
}
</style>
languages.vue:
<template>
<div class="languages">
<NuxtLink :to="route.path + '?hl=az'">AZ</NuxtLink>
<NuxtLink :to="route.path + '?hl=ru'">RU</NuxtLink>
<NuxtLink :to="route.path + '?hl=en'">EN</NuxtLink>
</div>
</template>
<script>
export default {
name: "Languages",
setup() {
const route = useRoute()
return {
route
}
}
}
</script>
<style scoped>
div,
div a {
height: 40px;
display: inline-block;
}
img {
height: 60%;
display: inline-flex;
margin: 8px;
}
</style>
languages.js:
function languages(page) {
let langCookie = useCookie("language")
let language = langCookie.value
if (page.$route.query.hl) {
language = page.$route.query.hl
langCookie.value = language
}
return language || 'az';
}
export default languages
The primary issue I see with your code is that you are altering the cookie in the languages
function, called by your lang
computed.
A computed should never create side effects, see Vue docs for reference.
You should split your logic and only return the current language or a fallback value in the computed.
setup() {
let langCookie = useCookie('language');
return {
langCookie
}
},
computed: {
lang() {
return this.langCookie || 'az';
}
}
The code to persist the new language in the cookie should be extracted and called only when necessary. You could for example call it when the user click on a language link in the language selector or add an immediate watcher on the language value present in the URL using.
<template>
<div class="languages">
<!-- You don’t need to pass the current URL again here, you can alter the query only, as an object, vue-router will take care of computing the URL -->
<NuxtLink :to="{ query: { hl: 'az' } }">AZ</NuxtLink>
<NuxtLink :to="{ query: { hl: 'ru' } }">RU</NuxtLink>
<NuxtLink :to="{ query: { hl: 'en' } }">EN</NuxtLink>
</div>
</template>
<script>
import { watch } from 'vue';
import { useRoute } from 'vue-router';
import { useCookie } from '?';
export default {
name: 'Languages',
setup() {
const route = useRoute();
const langCookie = useCookie('language');
watch(
// Whenever the route query language change
() => route.query.hl,
// Save the new value in the cookie
(newLang) => {
langCookie.value = newLang;
},
{
// Do this logic immediately, in case the page is loaded
// with `hl` already set and different from the current cookie value
immediate: true
}
);
}
}
</script>