Table of Contents
URL: https://www.progressiverobot.com/vuejs-i18n-formatting-fallbacks/
Today we'll be covering how a number of formatting options available with the <^>vue-i18n<^> plugin for internationalization (i18n). We'll also be covering how to handle fallbacks when no string is available for a locale. We'll be using the <^>vue-i18n<^> plugin written by Kazuya Kawaguchi, and this article is building up from this previous one, which introduces using <^>vue-i18n<^> for internationalization (i18n) in Vue.js apps.
<^>vue-i18n<^> provides a number of ways to format your app strings. We can even define a custom formatter if you don't like the default style. We can also provide fallbacks that are useful when we're missing strings for a given locale.
App Setup
We'll start by assuming you've already created a simple <^>Vue<^> app. Now we'll add the <^>vue-i18n<^> plugin using your preferred method:
# Yarn
$ yarn add vue-i18n
# npm
$ npm install vue-i18n
# Vue CLI 3.x+
$ vue add i18n
We'll continue where we left off in the last post. I'll skip the code for the <SelectLocale /> component in that post since it won't be changing, but feel free to include it if you're following along from last time 🐊!
[label main.js]
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import App from './App.vue';
Vue.use(VueI18n);
const messages = {
en: {
message: {
hello: 'Hello, {name}!'
}
},
de: {
message: {
hello: 'Guten Tag, {name}!'
}
}
};
const i18n = new VueI18n({
locale: 'en',
messages
});
new Vue({
render: h => h(App),
i18n
}).$mount('#app');
[label App.vue]
<template>
<div id="app">
<HelloGator />
</div>
</template>
<script>
import HelloGator from './components/HelloGator.vue';
export default {
name: 'App',
components: {
HelloGator
}
}
</script>
[label components/HelloGator.vue]
<template>
<div>{{ $t('message.hello', { name: 'Gator' }) }}</div>
</template>
<script>
export default { name: 'Gator' }
</script>
Formatting Features
We've already covered the basic formatting that <^>vue-i18n<^> uses with the code above. The plugin offers a couple of other formatting-related features such as lists, HTML, and custom formatters.
Lists
The <^>vue-i18n<^> plugin also provides a way to format using lists of variables. We'll pass an array of strings as the second parameter of $t which are accessible in our app strings through their index:
[label main.js]
const messages = {
en: {
message: {
hello: 'Hello, {name}!',
<^>counting: 'One: {0}, Two: {1}, Three: {2}'<^>
}
},
de: {
message: {
hello: 'Guten Tag, {name}!',
<^>counting: 'Eins: {0}, Zwei: {1}, Drei: {2}'<^>
}
}
};
Now let's add our message.counting string to HelloGator.vue:
[label Template: components/HelloGator.vue]
<div>
{{ $t('message.hello', { name: 'Gator' }) }}
<br />
{{ $t('message.counting', ['🐊', '🤖', '👽']) }}
</div>
HTML
The <^>vue-i18n<^> plugin also lets us use HTML directly in our app strings. Any standard HTML will be rendered in the browser.
We'll add the message.welcome app string below, wrapped with a <strong> tag:
[label main.js]
const messages = {
en: {
message: {
hello: 'Hello, {name}!',
counting: 'One: {0}, Two: {1}, Three: {2}',
welcome: '<strong>Welcome!</strong>'
}
},
de: {
message: {
hello: 'Guten Tag, {name}!',
counting: 'Eins: {0}, Zwei: {1}, Drei: {2}',
welcome: '<strong>Wilkommen!</strong>'
}
}
};
Now let's add our HTML app string to HelloGator.vue:
[label Template: components/HelloGator.vue]
<div>
{{ $t('message.hello', { name: 'Gator' }) }}
<br />
{{ $t('message.counting', ['🐊', '🤖', '👽']) }}
<br />
{{ $t('message.welcome') }}
</div>
You should now see a bold <^>Welcome!<^> or <^>Wilkommen!<^> depending on the locale.
Ruby on Rails
There's also out-of-the-box support for Ruby on Rails style i18n, if that's your preference:
const messages = {
en: {
message: {
hello: 'Hello, %{name}!',
...
}
},
...
}
Custom
You probably won't need this feature, but the <^>vue-i18n<^> plugin also allows you to define your own custom formatter. We won't cover this in detail here but it mostly involves writing a function that would take the place of the $t translation function made available by the plugin. Make sure to check the Custom Formatting Docs if you'd like to learn more.
Fallbacks
The <^>vue-i18n<^> plugin allows us to easily fallback on another locale's app strings if the current locale is missing any.
Let's add another app string called message.description which will only be available in English. We'll also specify the fallbackLanguage so the plugin uses the English app strings if they're missing from another locale:
[label main.js]
const messages = {
en: {
message: {
hello: 'Hello, {name}!',
<^>description: 'This sentence is in English!'<^>
}
},
de: {
message: {
hello: 'Guten Tag, {name}!'
}
}
};
const i18n = new VueI18n({
locale: 'en',
<^>fallbackLocale: 'en',<^>
messages
});
Now let's add our English-only message to HelloGator.vue:
[label Template: components/HelloGator.vue]
<div>
{{ $t('message.hello', { name: 'Gator' }) }}
<br />
{{ $t('message.description') }}
</div>
You'll notice that when switching the locale to de we'll see the first message in German with the second message in English. This is super useful if you'd like to begin adding support for a new locale but don't have all the app strings defined yet.
Wrapping Up
With all of the formatting options offered by <^>vue-i18n<^>, it's rare you'll have to implement custom formatting logic yourself. There's enough out-of-the-box support to cover most formatting use cases related to internationalizing your app. As always, make sure to check out the docs! 🤓