[Vuejs]-How do I update translated text when changing a language in a Vue.js app with i18n and Pinia?

2👍

You are not setting the i18n locale when you try to switch the language in your setNewLanguage function. You only update localStorage, but localStorage is not reactive.

You should import i18n in your Pinia store:

import { i18n } from './utils/i18n.js';

And set the global locale in your setNewLanguage function:

i18n.locale = ‘es’;

See i18n docs: https://vue-i18n.intlify.dev/guide/essentials/scope.html#locale-changing

👤Gabe

1👍

Saving the current locale in the Pinia store is not required to change the language. I18n and Quasar itself store necessary data.

However, locale storage comes in handy after reloading the page. You will be able to restore the last state at app startup.

Quasar uses standard names for locales of its internal components and system (en-GB instead of en). For example, q-table is expected to show No result according to the current language. I strongly recommend you use names instead of short ones to preserve the harmony.

Implementation

First rename src/locales/en.json to src/locales/en-GB.json, and also, src/locales/zh.json to src/locales/zh-CN.json.

Changing the locale will be easy if you use the names. To exercise, your code can be something like this:

<template>
  <q-btn color="secondary" :label="$t('changeLanguage')">
    <q-menu auto-close>
      <q-list style="min-width: 100px">
        <q-item v-for="(language, index) in languages" @click="changeLanguage(index)" clickable>
          <q-item-section>{{ language }}</q-item-section>
        </q-item>
      </q-list>
    </q-menu>
  </q-btn>
</template>

<script setup>
// Importar internos de vue
import { ref } from 'vue';
import { useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';

const $q = useQuasar();
const i18n = useI18n({useScope: 'global'});

import deQ from 'quasar/lang/de';
import enQ from 'quasar/lang/en-GB';
import esQ from 'quasar/lang/es';
import jaQ from 'quasar/lang/ja';
import ptQ from 'quasar/lang/pt';
import ruQ from 'quasar/lang/ru';
import zhQ from 'quasar/lang/zh-CN';

const langPacks = {
  de: deQ,
  'en-GB': enQ,
  es: esQ,
  ja: jaQ,
  pt: ptQ,
  ru: ruQ,
  'zh-CN': zhQ,
};

// Constantes y variables del componente
const languages = ref({
  'de': '🇩🇪 Deutsch',
  'en-GB': '🇬🇧 English',
  'es': '🇪🇸 Español',
  'ja': '🇯🇵 日本語',
  'pt': '🇵🇹 Português',
  'ru': '🇷🇺 Русский',
  'zh-CN': '🇨🇳 中文',
});


// Funciones y métodos
function changeLanguage(newLanguage) {
  i18n.locale.value = newLanguage;
  $q.lang.set(langPacks[newLanguage]);
  localStorage.setItem('language', newLanguage);
}
</script>

Note 1:

In this case, there is no need for the Pinia store anymore. You can remove it safely. If you need to detect the current locale, you can use $q.lang.isoName.

Using composition

Add a new composition file to manage the state and provides the necessary actions to change and restore locales.

// src/composable/use-locale-switcher.js

import { ref } from 'vue';
import { useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';

import deQ from 'quasar/lang/de';
import enQ from 'quasar/lang/en-GB';
import esQ from 'quasar/lang/es';
import jaQ from 'quasar/lang/ja';
import ptQ from 'quasar/lang/pt';
import ruQ from 'quasar/lang/ru';
import zhQ from 'quasar/lang/zh-CN';

const langPacks = {
  de: deQ,
  'en-GB': enQ,
  es: esQ,
  ja: jaQ,
  pt: ptQ,
  ru: ruQ,
  'zh-CN': zhQ,
};

export function useLocaleSwitcher() {
  const locale = ref('es');

  const $q = useQuasar();
  const i18n = useI18n({useScope: 'global'});

  function setLocale(lang) {
    locale.value = lang;
    i18n.locale.value = lang;
    $q.lang.set(langPacks[lang]);
    localStorage.setItem('language', lang);
  }

  function loadLastState(name) {
    const prevState = localStorage.getItem('language');
    setLocale(prevState || 'es');
  }

  return {
    locale,
    setLocale,
    loadLastState,
  };
}

Your lang switcher will be:

// src/components/ChangeLanguage
<template>
  <q-btn color="secondary" :label="$t('changeLanguage')">
    <q-menu auto-close>
      <q-list style="min-width: 100px">
        <q-item v-for="(language, index) in languages" @click="changeLanguage(index)" clickable>
          <q-item-section>{{ language }}</q-item-section>
        </q-item>
      </q-list>
    </q-menu>
  </q-btn>
</template>

<script setup>
// Importar internos de vue
import { ref } from 'vue';
import { useLocaleSwitcher } from '../composable/use-locale-switcher.js';

const localeSwitcher = useLocaleSwitcher();

// Constantes y variables del componente
const languages = ref({
  'de': '🇩🇪 Deutsch',
  'en-GB': '🇬🇧 English',
  'es': '🇪🇸 Español',
  'ja': '🇯🇵 日本語',
  'pt': '🇵🇹 Português',
  'ru': '🇷🇺 Русский',
  'zh-CN': '🇨🇳 中文',
});


// Funciones y métodos
function changeLanguage(newLanguage) {
  localeSwitcher.setLocale(newLanguage);
}
</script>

And tune the app main file to restore state:

// src/App.vue
<template>
  <router-view/>
</template>

<script setup>
import { useLocaleSwitcher } from './composable/use-locale-switcher.js';

const localeSwitcher = useLocaleSwitcher();
localeSwitcher.loadLastState();
</script>

Further:

For more information please visit the documentation.

👤Raeisi

Leave a comment