Tutorial

More i18n with Vue: Formatting and Fallbacks

Vue.js

While this tutorial has content that we believe is of great benefit to our community, we have not yet tested or edited it to ensure you have an error-free learning experience. It's on our list, and we're working on it! You can help us out by using the "report an issue" button at the bottom of the tutorial.

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 🐊!

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');
App.vue
<template>
  <div id="app">
    <HelloGator />
  </div>
</template>

<script>
import HelloGator from './components/HelloGator.vue';

export default {
  name: 'App',
  components: {
    HelloGator
  }
}
</script>
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:

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:

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:

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:

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:

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:

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! πŸ€“

Creative Commons License