Search code examples
vue.jsvuejs2internationalizationvue-i18n

Vue I18n deletes component content when changing locale


I'm integrating Vue I18n into my app. I have a list rendered from a Vuex store and below I have some translatable content with a locale switcher (no page reload). When I switch the language, the strings are translated but the content before disappears.

I'm using single file components with the integration recommended by Vue-I18n

Vue.use(VueI18n)
const messages = {
  en: {
    message: {
      hello: 'hello world'
    }
  },
  ja: {
    message: {
      hello: 'こんにちは、世界'
    }
  }
}
const i18n = new VueI18n({
  locale: 'en',
  messages,
})
const app = new Vue({
  router,
  store,
  i18n,
  components: {
     ...
  }
}).$mount('#app')

This is part of my template

<h3>My products</h3>
  <div class="grid-x grid-x-margin margin-top" v-for="prod in products" :key="prod.id">
    <router-link class="hollow button" to="/search">{{ prod.name }} </router-link>
  </div>
   <p>{{ $t("message.hello") }}</p>
   <select v-model="$i18n.locale">
     <option v-for="(lang, i) in ['ja', 'en']" :key="i" :value="lang">{{ lang }}</option>
   </select>
</div>

the products object comes from Vuex store like so

computed: {
  products () {
    return this.$store.state.products.values()
  }
}

I expected the locale switch to dynamically update the string and not affect the above list. The product names don't need to be translated after all. The list of products is initially rendered correctly, when I change locale (no page reload) it disappears. I still see the component in the Vue developer tools, so it's there but the content is gone.


Solution

  • I suspect it has to do with how Vue detects changes to objects, but all I had to do was a small modification in the computed method, instead of returning values just return the Map object and let the v-for call values

    computed: {
      products () {
        return this.$store.state.products
      }
    }
    
    <div v-for="prod in products.values()" :key="prod.id">