Setting Up i18n for Localization in Vue.js

Written on: December, 2024

5 min read

Localization and internationalization are essential for creating multilingual websites. They help you reach a broader audience by providing content in different languages. In this blog post, I'll show you how to set up i18n in a Vue.js project using the Vue I18n library. By following these steps, you can easily localize your Vue.js applications and provide a better user experience for international users.

Steps

  1. Setting up Vue.js Project
  2. First, ensure you have a Vue.js project set up. If not, I recommend using my Vue.js starter template to quickly scaffold a new project. You can find the template on GitHub at the following link:

    https://github.com/Aldikrasniqi/vue-starter.git
  3. Installing Vue I18n
  4. Next, install the Vue I18n library in your project. Run the following command in your terminal to add Vue I18n as a dependency:

    https://vue-i18n.intlify.dev/guide/installation.html
    1npm install vue-i18n
  5. Setting Up i18n
  6. In the src/i18n.ts file, create a function called messages that dynamically loads language JSON files from the src/locales folder. After that, create an i18n instance which accepts the legacy option (a boolean that indicates whether to use legacy API or composition API), a locale option (the default language of the application), a fallbackLocale option (the fallback language if the translation is not found in the current language), and a messages option (the language files loaded in the messages function).

    1import { createI18n } from 'vue-i18n'
    2
    3const messages = Object.fromEntries(
    4  Object.entries(import.meta.glob('./locales/*.json', { eager: true })).map(([key, value]) => {
    5    const locale = key.match(/\.\/locales\/(.*)\.json$/)?.[1]
    6    return [locale, (value as any).default]
    7  })
    8)
    9
    10export const i18n = createI18n({
    11  legacy: false, // Use Composition API
    12  locale: 'en', // Default locale
    13  fallbackLocale: 'en', // Fallback locale
    14  messages
    15})
    16
  7. Integrating i18n with Vue
  8. In the src/main.ts file, the i18n instance is registered with the Vue application:

    1import { createPinia } from 'pinia'
    2import { i18n } from './i18n'
    3import { createApp } from 'vue'
    4import App from './App.vue'
    5import lang from './plugins/lang'
    6import router from './router'
    7import './assets/index.css'
    8
    9const app = createApp(App)
    10
    11app.use(createPinia())
    12app.use(router)
    13app.use(i18n)
    14app.use(lang)
    15app.mount('#app')
    16
  9. Creating Language Files
  10. Create language files for each supported language in the src/locales folder. Each language file should contain key-value pairs of translation strings.

    1{
    2  "home": "This is the home page",
    3  "about": "This is the about page"
    4}
    5
  11. Configuring i18n as a global plugin
  12. In the src/plugins folder, create a file named lang.ts to configure i18n as a global plugin. This file exports a function that installs the i18n instance on the Vue app.

    1// src/plugins/lang.ts
    2import { i18n } from '@/i18n'
    3
    4export default {
    5  install: (app: any) => {
    6    app.config.globalProperties.$t = i18n.global.t
    7    app.config.globalProperties.$locale = i18n.global.locale
    8
    9    const savedLocale = localStorage.getItem('locale') || 'en'
    10    i18n.global.locale.value = savedLocale
    11  }
    12}
  13. Using i18n in Vue Components
  14. You can now use i18n in your Vue components to display localized text. Use the $t method to access translation strings based on their keys.

    Using i18n in Vue Components
  15. Switching Between Languages
  16. To switch between languages, create a language switcher component that changes the locale of the i18n instance. This component can be placed in the header or footer of your application.

    1<script lang="ts" setup>
    2import { useGlobalI18n } from '@/composables/useGlobalI18n'
    3import { languages } from '@/utils/general'
    4import { ref } from 'vue'
    5
    6const { locale } = useGlobalI18n()
    7const dropdownVisible = ref(false)
    8const currentLocale = ref(locale.value)
    9
    10function changeLanguage(lang: string) {
    11  locale.value = lang
    12  currentLocale.value = lang
    13  dropdownVisible.value = false
    14}
    15
    16function toggleDropdown() {
    17  dropdownVisible.value = !dropdownVisible.value
    18}
    19</script>
    20
    21<template>
    22  <div class="relative">
    23    <button
    24      class=""
    25      @click="toggleDropdown"
    26    >
    27      <span>{{ languages.find(lang => lang.code === locale)?.label }}</span>
    28      <svg
    29        xmlns="http://www.w3.org/2000/svg"
    30        class="w-5 h-5 ml-2"
    31        fill="none"
    32        viewBox="0 0 24 24"
    33        stroke="currentColor"
    34        stroke-width="2"
    35      >
    36        <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" />
    37      </svg>
    38    </button>
    39    <div
    40      v-show="dropdownVisible"
    41      class="absolute right-0 mt-2 w-36 bg-white border border-gray-200 rounded-lg shadow-lg dark:bg-gray-800 dark:border-gray-700"
    42    >
    43      <ul>
    44        <li
    45          v-for="language in languages"
    46          :key="language.code"
    47          @click="changeLanguage(language.code)"
    48          class="px-4 py-2 text-sm text-gray-600 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700 cursor-pointer"
    49        >
    50          {{ language.label }}
    51        </li>
    52      </ul>
    53    </div>
    54  </div>
    55</template>
  17. Unit Testing Components
  18. For testing, I use the Vitest library, a simple and lightweight testing library for Vue.js applications. It provides a clean and easy-to-use API for writing unit tests for Vue components. If you don't have it installed, you can install it with the following command: npm install @vitest/vue. First, create a test file for the component you want to test. In the following code, I've imported the AboutView component, mocked some language data, and created an instance of i18n with the locale set to 'en' and mocked languages.

    1import { describe, it, expect } from 'vitest'
    2import { mount } from '@vue/test-utils'
    3import { createI18n } from 'vue-i18n'
    4import AboutView from '@/views/AboutView.vue'
    5
    6// Mock translations
    7const messages = {
    8  en: { about: 'About Us' },
    9  sv: { about: 'Om Oss' }
    10}
    11
    12const i18n = createI18n({
    13  locale: 'en',
    14  messages
    15})
  19. Test Suite
  20. I've created a test suite with the describe function and a test case with the it function. In the test case, I've mounted the AboutView component with the i18n instance and checked if the component renders the translated text correctly. Finally, I've run the test suite with the test function.

    1describe('About Component', () => {
    2  it('renders translated text', () => {
    3    const wrapper = mount(AboutView, {
    4      global: {
    5        plugins: [i18n]
    6      }
    7    })
    8
    9    expect(wrapper.text()).toContain('About Us')
    10  })
    11
    12  it('updates text when locale changes', async () => {
    13    const wrapper = mount(AboutView, {
    14      global: {
    15        plugins: [i18n]
    16      }
    17    })
    18
    19    expect(wrapper.text()).toContain('About Us')
    20
    21    i18n.global.locale = 'sv'
    22    await wrapper.vm.$nextTick()
    23
    24    // Verify the updated text
    25    expect(wrapper.text()).toContain('Om Oss')
    26  })
    27})
    28

Conclusion

Setting up i18n in a Vue.js project is straightforward with the Vue I18n library. By following the steps outlined above, you can easily localize your Vue.js applications and provide a better user experience for international users. If you have any questions or feedback, feel free to leave a comment. Thank you for reading!
Back to Blogs
Aldi Krasniqi