A computed
property will do what you're looking for, since they only trigger a re-run when their dependencies change. Since this.$t('LOCALE.STRING')
doesn't change unless your locale changes, you're guaranteed only a single run, after which the value will be cached by Vue for subsequent renders.
<template>
...
<input
...
:placeholder="translatedPlaceholder"
>
...
</template>
<script>
...
computed: {
translatedPlaceholder() {
return $t('translation.string');
},
},
...
</script>
The awesome part about this solution is that if the locale does change, then Vue will indeed refresh the computed property, updating it to the correct value.
I've put together an interactive snippet to help demonstrate this syntax, if you're looking for a more extensive example.
The snippet includes a simple localized greeting followed by a random number in a <p>
tag, with two buttons. The localized string in the text is pulled from a computed property.
The first button will generate a new number, causing the <p>
to re-render in the DOM.
The second button will switch the locale, causing Vue-i18n to refresh the localized string.
Whenever the computed localization property is re-executed, it will log to console.
I also set the script up to log to console whenever Vue updates the DOM too.
const messages = {
en: {
"greeting": 'Hello!',
},
es: {
"greeting": '¡Hola!',
},
};
new Vue({
i18n: new VueI18n({
locale: 'en',
messages,
}),
data() {
return {
num: 1,
}
},
computed: {
localizedGreeting() {
console.log('Computed executed');
return this.$t('greeting');
},
},
methods: {
swapLocale() {
this.$i18n.locale = (this.$i18n.locale == 'en' ? 'es' : 'en');
},
randomNum() {
this.num = Math.floor(Math.random() * 10000);
},
},
updated() {
console.log('DOM updated');
},
}).$mount('#app')
.as-console-wrapper {
max-height: 120px !important;
}
<script src="https://unpkg.com/vue@2/dist/vue.min.js"></script>
<script src="https://unpkg.com/vue-i18n@8"></script>
<div id="app">
<p>{{ `${localizedGreeting} #${num}` }}</p>
<button @click="randomNum()">Re-render Greeting</button>
<button @click="swapLocale">Swap Greeting Locale</button>
</div>
As you can see, re-rendering doesn't cause the computed property to re-execute, but swapping the locale does, which is exactly what we're looking for here.
As a final note– while there is technically a performance hit in your original code, since you're re-executing $t()
calls, it's worth bearing in mind that the actual performance hit is probably tiny. Don't trade simplicity for performance gains unless it really makes sense.
Remember, premature optimization is the root of all evil!