How to add Internationalization to a Vue Application
Adding internationalization capabilities to a Vue application allows it to support multiple languages and reach global audiences. In this comprehensive guide, we will walk through the step-by-step process to add i18n to a Vue app.
Overview
Here are the key things we will cover:
- Setting up a Vue project with Vue CLI
- Installing and configuring the vue-i18n plugin
- Organizing translation messages into locales
- Using localization methods in components
- Adding a locale switcher dropdown
- Managing fallback languages
- Optimizing performance with async messages
- Testing translations with Jest
- Deploying the localized app
By the end, you’ll have a solid understanding of how to internationalize a Vue app to support multiple languages.
Prerequisites
To follow along, you’ll need:
- Node.js installed on your machine
- Basic understanding of Vue, JavaScript and web development
- A code editor like Visual Studio Code
Setting up the Vue Project
We‘ll use Vue CLI to quickly scaffold a new project. Make sure you have it installed globally:
npm install -g @vue/cli
Then generate the project:
vue create my-app
This will prompt you to pick a preset. Go with the default (babel, eslint) option.
Once it finishes installing, cd into the project folder:
cd my-app
And run the dev server:
npm run serve
You should now have a basic Vue app running at http://localhost:8080.
Installing and Configuring vue-i18n
For translations, we‘ll use the vue-i18n plugin.
Install it:
npm install vue-i18n
Then create a plugin file src/plugins/i18n.js and initialize the i18n plugin:
import Vue from ‘vue‘
import VueI18n from ‘vue-i18n‘
Vue.use(VueI18n)
export default new VueI18n({
locale: ‘en‘,
messages: {}
})
This sets English as the default locale and contains the locales messages (which we‘ll add later).
Now import and apply this plugin in src/main.js:
import i18n from ‘./plugins/i18n‘
new Vue({
i18n,
render: h => h(App)
}).$mount(‘#app‘)
Our i18n plugin is now all set up!
Organizing Translation Messages
The messages object will contain all the translation strings for each supported locale.
Let‘s organize the messages into separate locale files:
src/locales/
en.json
es.json
So the English strings go into en.json:
{
"welcome": "Welcome to Our App"
}
And the same key for Spanish in es.json:
{
"welcome": "Bienvenidos a nuestra aplicación"
}
Now import these into src/plugins/i18n.js and merge them into the messages object:
import en from ‘../locales/en.json‘
import es from ‘../locales/es.json‘
export default new VueI18n({
locale: ‘en‘,
messages: {
en: {
...en
},
es: {
...es
}
}
})
This loads the locale messages and makes them available to components via the $t() method.
Using Localization in Components
In any component, you can now translate a string like:
<template>
</template>
It will lookup the welcome key from the current locale and display the translated string.
You can also bind translations:
<button>{{ $t("save") }}</button>
And render strings with placeholders:
{{ $t("hello_name", { name: "John" }) }}
This allows translating the whole app‘s text into different languages!
Adding a Locale Switcher
To let users change languages, we need to add a locale switcher.
Start by adding a data property with the supported locales:
data() {
return {
locales: [
{ name: ‘English‘, locale: ‘en‘ },
{ name: ‘Español‘, locale: ‘es‘ }
]
}
}
Then loop over these to output a dropdown in the template:
<select v-model="$i18n.locale">
<option
v-for="(locale, index) in locales"
:key="index"
:value="locale.locale"
>
{{ locale.name }}
</option>
</select>
This binds the selection to VueI18n‘s internal locale property. So when changed, it will switch the active translation messages used in the app!
Managing Fallback Languages
It‘s also good practice to specify a fallback locale in case a translation key is missing from the active language:
export default new VueI18n({
locale: ‘en‘,
fallbackLocale: ‘en‘,
messages: {
// ...
}
})
Now if a translation key doesn‘t exist for Spanish, it will lookup and show the key from English instead of the missing key.
Optimizing Performance
To avoid bloating bundle size with all translations, we can lazy-load messages as needed:
First, install the @intlify/vue-i18n-loader:
npm install --save-dev @intlify/vue-i18n-loader
Then chain it to the Vue loader in vue.config.js:
module.exports = {
chainWebpack: config => {
config.module
.rule(‘vue‘)
.use(‘i18n‘)
.loader(‘@intlify/vue-i18n-loader‘)
}
}
Now translations will be asynchronously loaded on demand instead of all being bundled. This improves load performance!
Testing Translations
Vue apps usually use Jest for testing. We can also test translations by mocking $t() in our tests:
import { shallowMount } from ‘@vue/test-utils‘
describe(‘Translation‘, () => {
test(‘welcome text‘, () => {
const wrapper = shallowMount(Component, {
mocks: {
$t: key => {
// mock translation method
switch(key) {
case ‘welcome‘: return ‘Translated welcome text‘
}
}
}
})
expect(wrapper.text()).toContain(‘Translated welcome text‘)
})
})
This lets you verify translated text and locales without needing the actual plugin.
Deployment
When building for production, the translations can be compiled into the app:
// vue.config.js
module.exports = {
pluginOptions: {
i18n: {
locale: ‘en‘,
fallbackLocale: ‘en‘,
localeDir: ‘locales‘,
enableInSFC: false
}
}
}
Configure your server and you’re ready to deploy your Vue app globally!
Summary
Adding internationalization to a Vue app takes only a few steps:
- Install vue-i18n
- Import and apply the plugin
- Externalize translations into locale files
- Load messages into the plugin
- Use
$t()in templates for translating text - Enable switching locales
- Set fallback languages
- Lazy load messages
- Test translations
- Compile and deploy globally
Following this guide, you should now have a good grasp of how to translate a Vue app into multiple languages.
The key is leveraging vue-i18n to manage translations centrally. This keeps international text organized cleanly in one place.
The possibilities also open up to localize dates, numbers, plurals and more according to locale needs.
So try adding i18n to your next Vue project! Let me know if you have any other questions.