How to Globalize Your Vue.js App with i18n: A Step-by-Step Guide
Table of contents
- Introduction: The Power of i18n Across Frameworks
- The Core of i18n: Key-Value Pairs and Language Switching
- Setting Up Vue i18n in Your Project
- Step 1: Installing Dependencies
- Step 2 : Plugin Registration
- Step 3: Configuring Vite
- Step 4: Setting Up Environment Variables
- Step 5: Creating Locale JSON Files
- Step 6: Initializing i18n
- Step 7: Creating a Translation Utility
- Step 8: Using i18n in Your Components
- Managing Translations with BabelEdit
- Alternatives
- TLDR:
- Resources and further reading
Introduction: The Power of i18n Across Frameworks
Internationalization (i18n) is a crucial aspect of modern web development, allowing applications to adapt to various languages and regions seamlessly. The key aspects of i18n include :
Locale detection: Identifying the user's locale (language and region) to tailor the application's content accordingly.
Text translation: Managing translations for all text elements in the application, including user interface elements, messages, and labels.
Formatting: Displaying numbers, dates, times, and currencies in a format appropriate for the user's locale.
The importance of i18n with local languages cannot be overstated. It allows your application to:
Reach a broader audience
Improve user experience for non-native speakers
Comply with local regulations and cultural norms
Increase user engagement and retention
While i18n can be implemented in various frameworks like React, Angular, or vanilla JavaScript, today we'll dive deep into vue-i18n, a plugin specifically focusing on Vue 3 with the Composition API and <script setup>
method, an area where comprehensive tutorials are surprisingly scarce online.
The Core of i18n: Key-Value Pairs and Language Switching
At its heart, i18n in Vue.js revolves around two main concepts:
Key-Value Pairs: We define translation strings as key-value pairs, where the key remains constant across languages, and the value changes based on the selected locale.
Language Switching: We implement a mechanism to change the active locale, causing our application to re-render with the new language.
Let's see how this looks in practice:
// en.json
{
"greeting": "Hello, world!"
}
// hi.json
{
"greeting": "नमस्ते, दुनिया!"
}
In this example, we have translations for English and Hindi. The key greeting
remains the same, but the value changes for each language.
Setting Up Vue i18n in Your Project
Step 1: Installing Dependencies
First, we need to install the necessary packages:
npm install vue-i18n@9 @intlify/unplugin-vue-i18n
Vue I18n is the core library for internationalization in Vue.js applications. The @intlify/unplugin-vue-i18n
is a Vite plugin that helps with the automatic importing of locale messages.
Step 2 : Plugin Registration
Now, let's configure Vue i18n in our project:
// main.ts
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
import i18n from "./i18n";
const app = createApp(App);
app.use(createPinia()).use(i18n).mount("#app");
Step 3: Configuring Vite
Next, we configure Vite to work with our i18n setup:
import VueI18nPlugin from "@intlify/unplugin-vue-i18n/vite";
import path from "path";
export default defineConfig({
// ... other configurations
plugins: [
// ... other plugins
VueI18nPlugin({
runtimeOnly: false,
include: path.resolve(__dirname, "src/i18n/locales/**"),
}),
],
// ... other configurations
});
This configuration tells Vite to use the Vue I18n plugin and where to find our locale files. The runtimeOnly: false
option allows us to use the full version of Vue I18n, which includes the compiler. This is necessary if we want to use custom formatting or pluralization rules.
Step 4: Setting Up Environment Variables
Create a .env
file in your project root:
VITE_DEFAULT_LOCALE=en
VITE_FALLBACK_LOCALE=en
VITE_SUPPORTED_LOCALES=en,hindi,kannada,telugu,marathi,punjabi,tamil,malyalam,gujrati,bengali,odia,urdu
These variables define our default locale, fallback locale, and all supported locales. Using environment variables allows us to easily change these settings without modifying our code.
Step 5: Creating Locale JSON Files
For each supported language, create a JSON file in the src/i18n/locales/
directory. For example, en.json
for English:
{
"my_profile": {
"first_name": "First Name",
"last_name": "Last Name",
"mobile_number": "Mobile Number",
"email": "Email",
"change_language": "Change Language",
"alert": "Language changed successfully!"
},
"locale": {
"en": "English",
"hindi": "Hindi",
"kannada": "Kannada"
// ... other languages
}
}
To effectively manage translations in your Vue.js application, create separate .json
files for each supported language or locale. Each file should be structured as an object, where nested objects may represent each page within your app. Inside these nested objects, define key-value pairs for each translatable text. The nested structure allows for better organization and maintainability of translations. For higher accuracy, consider using professional third-party translators instead of relying on automated tools like Google Translate or AI.
Step 6: Initializing i18n
Create an index.ts
file in your src/i18n/
directory:
import { createI18n } from "vue-i18n";
import en from "./locales/en.json";
export default createI18n({
locale: import.meta.env.VITE_DEFAULT_LOCALE,
fallbackLocale: import.meta.env.VITE_FALLBACK_LOCALE,
legacy: false,
globalInjection: true,
messages: { en },
});
This sets up our i18n instance with the default locale and fallback locale from our environment variables. The legacy: false
the option enables the Composition API style, and globalInjection: true
allows us to use the $t
function in our templates.
Step 7: Creating a Translation Utility
Create a translate.ts
file in your src/i18n/
directory:
import i18n from "@/i18n";
import { nextTick } from "vue";
const Trans = {
get defaultLocale() {
return import.meta.env.VITE_DEFAULT_LOCALE;
},
get supportedLocales() {
return import.meta.env.VITE_SUPPORTED_LOCALES.split(",");
},
set currentLocale(newLocale: string) {
i18n.global.locale.value = newLocale;
},
getUserLocale() {
const locale = window.navigator.language || Trans.defaultLocale;
return {
locale: locale,
localeNoRegion: locale.split("-")[0],
};
},
getPersistedLocale() {
const persistedLocale = localStorage.getItem("user-locale");
if (Trans.isLocaleSupported(persistedLocale)) {
return persistedLocale;
} else {
return null;
}
},
guessDefaultLocale() {
const userPersistedLocale = Trans.getPersistedLocale();
if (userPersistedLocale) {
return userPersistedLocale;
}
const userPreferredLocale = Trans.getUserLocale();
if (Trans.isLocaleSupported(userPreferredLocale.locale)) {
return userPreferredLocale.locale;
}
if (Trans.isLocaleSupported(userPreferredLocale.localeNoRegion)) {
return userPreferredLocale.localeNoRegion;
}
return Trans.defaultLocale;
},
isLocaleSupported(locale: string | null) {
return Trans.supportedLocales.includes(locale);
},
async switchLanguage(newLocale: string) {
await Trans.loadLocaleMessages(newLocale);
Trans.currentLocale = newLocale;
document.querySelector("html")!.setAttribute("lang", newLocale);
localStorage.setItem("user-locale", newLocale);
},
async loadLocaleMessages(locale: string) {
if (!i18n.global.availableLocales.includes(locale)) {
const messages = await import(`@/i18n/locales/${locale}.json`);
i18n.global.setLocaleMessage(locale, messages.default);
}
return nextTick();
},
};
export default Trans;
This utility provides methods for switching languages, loading locale messages, and other helpful functions. It includes logic for guessing the user's preferred locale based on their browser settings and previously selected language.
Step 8: Using i18n in Your Components
Now, let's see how to use i18n in a Vue component. Here's an example from the Profile.vue
component:
<script setup lang="ts">
import { useI18n } from "vue-i18n";
import Tr from "@/i18n/translation";
const { t, locale } = useI18n({ useScope: "global" });
const supportedLocales = Tr.supportedLocales;
const switchLanguage = async (event: Event) => {
alert(t("my_profile.alert"));
const newLocale = (event.target as HTMLOptionElement).value;
await Tr.switchLanguage(newLocale);
};
</script>
<template>
<div class="form-control w-full">
<label class="text-xs font-semibold text-gray-500">
{{ $t("my_profile.first_name") }}
<input
v-model="userStore.userProfile.first_name"
type="text"
:placeholder="userStore.userProfile.first_name"
class="input text-sm font-normal"
disabled
/>
</label>
</div>
<div class="flex flex-col w-full">
<span class="text-xs font-semibold text-gray-500">{{
$t("my_profile.change_language")
}}</span>
<select
@change="switchLanguage"
class="input rounded-md border focus:ring focus:ring-opacity-50 text-sm"
>
<option
v-for="sLocale in supportedLocales"
:key="`locale-${sLocale}`"
:value="sLocale"
:selected="locale === sLocale"
>
{{ t(`locale.${sLocale}`) }}
</option>
</select>
</div>
</template>
In this component, we're using the $t
function in the template to translate our keys, and the t
function in the script for the same purpose. We've also created a custom dropdown to switch between languages.
This setup provides a flexible and maintainable internationalization system that can grow with your application. It allows for easy addition of new languages and provides a smooth user experience for switching between languages.
In this example, we're using the useI18n
composable to access translation functions and the current locale. We also implement a language switcher that allows users to change the application's language dynamically.
Managing Translations with BabelEdit
While we've covered the basics of implementing i18n in your Vue 3 app, managing translations across multiple languages can become challenging as your app grows. This is where tools like BabelEdit can be incredibly helpful.
BabelEdit is a powerful translation editor for web apps that supports Vue I18n out of the box. It provides a user-friendly interface for managing your translation files, making it easier to keep your translations organized and up-to-date.
Some key features of BabelEdit include:
Visual editing of JSON and YAML translation files
Side-by-side comparison of translations
Auto-translation suggestions
Search and filter functionality
Export to various formats
Refer to the BabelEdit documentation to learn how to use it.
Alternatives
While Vue I18n is a popular choice for internationalization in Vue applications, there are other alternatives you might consider for other frameworks:
Globalize: A JavaScript library for internationalization and localization
FormatJS: A modular collection of JavaScript libraries for internationalization
Google Translate: While not a full i18n solution, it can be used for quick, automated translations
Each of these libraries has its own strengths and might be more suitable depending on your specific project requirements.
Remember, the key to successful internationalization is planning for it from the start of your project. It's much easier to build with i18n in mind than to retrofit it into an existing application.
TLDR:
In this article, we've explored how to implement i18n in a Vue.js application using Vue 3's Composition API with script setup. We've covered:
The basic setup of vue-i18n
Using translations in both templates and the Composition API's script setup
Managing translation files with BabelEdit
Suggesting alternatives to i18n
Resources and further reading
For more in-depth information on Vue i18n and advanced use cases like Datetime, currencies, pluralisation, number localization, interpolation and its integration with Vue Router for multiple locales, check out the official Vue i18n documentation or this Lokalise blog post.
Subscribe to my newsletter
Read articles from Sahil Ahmed directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Sahil Ahmed
Sahil Ahmed
I'm Sahil Ahmed, an experienced software engineer who wants to be a digital polymath. My journey in software development is driven by a curiosity to create efficient, user-centric solutions for real-world problems across web and mobile platforms while writing clean code. I also love to read classic literature and play football.