Search code examples
vue.jsinternationalizationvue-i18n

Vue i18n locale change not reflecting immediately in all components


I am working on a web application using the **Vue **and I am using vueI18n for internationalization. I have encountered an issue where the locale change is not immediately reflected in all components.

Here are the relevant details:

Application Details:

  • Framework: Vue
  • Vue version specified in package.json: ^3.2.13
  • Important packages to note: vueI18n

Problem Details: I am using vueI18n in two components (MyHeader.vue and HomeView.vue). Here are the relevant code snippets:

MyHeader.vue:

<div class="my-header">
    <ul>
      <router-link to="/">
        <li
          @mousedown="
            home.click = true;
            select('home');
          "
          @mouseup="home.click = false"
          class="home"
          :class="{ click: home.click, selected: home.selected }"
        >
          {{ $t("nav.home") }}
        </li>
      </router-link>
  ...
</div>

HomeView.vue:

<div class="grid">
      <img src="../assets/placeholder.jpg" :alt="$t('home.imgAlt')" />

      <div class="profile">
        <h2>{{ $t("home.profileH2") }}</h2>

        <p>{{ $t("home.profileP1") }}</p>

        <p>{{ $t("home.profileP2") }}</p>
      </div>
  ...
</div>

In HomeView.vue, I have a button that changes the value of this.$i18n.locale when clicked:

<button><img @click="changeLocale()" :src="require(`../assets/${locale}.png`)"></button>

And the script for the button:

changeLocale() {
      if (this.locale === "ES") {
        this.locale = "EN";
        this.$i18n.locale = "es";
      } else {
        this.locale = "ES";
        this.$root.$i18n.locale = "en";
      }
}

This is the i18n configuration in main.js:

const app = createApp(App);

const i18n = createI18n({
  locale: "en",
  messages: {
    en: require("./locales/en.json"),
    es: require("./locales/es.json"),
  },
});

app
  .component("myHeader", myHeader)
  .use(router)
  .use(i18n)
  .mount("#app");

The problem occurs when I click the button to change the locale. The locale changes, and therefore the language in HomeView.vue changes according to what is specified in the JSON files for the locales. However, in the MyHeader.vue component, the language of the links does not change until I click on each of them.

I tried changing the root locale through this.$root.$i18n.locale but it didn't work. I don't want to use a way to communicate the components, like Vuex, because as I understand i18n, I shouldn't have to. VueI18n should do it for me, right?

Thank you in advance!


Solution

  • So, while making a small reproducible code example I changed the method used to update the value of this.$i18n.locale to a more compact version and it worked. I still don't know why it worked, but it did.

    Previous method:

    methods: {
        changeLocale() {
          if (this.locale === "ES") {
            this.locale = "EN";
            this.$i18n.locale = "es";
          } else {
            this.locale = "ES";
            this.$root.$i18n.locale = "en";
          }
        }
      },
    

    Updated method:

    methods: {
        changeLocale() {
          this.$i18n.locale = this.$i18n.locale === "en" ? "es" : "en";
    
          if (this.$i18n.locale == "en")
            this.locale = "ES";
          else
            this.locale = "EN";
        }
      },