Testing Vue Translations

The Vue-i18n documentation does a good job of explaining the usage for this library, but the documents lack much information about testing localization of Vue apps. This guide will explain how I have added Jest unit tests to my Vue-i18n implementation.

Why Use Vue-i18n

Vue-i18n provides an easy way to integrate translation, pluralization, dateTime, and number formatting based on a users locale. This library is integrated with Vue.js and is by far the most maintained and popular Vue.js localization library.

Other nice aspects of Vue-i18n include having a fallback locale in case a translation is not available in a particular language, and falling back to the value of the key if no translation if found in either the selected or fallback locale.

There are no other Vue-specific libraries which are as active and well maintained.

An alternative might be to use a i18n library that does not automatically integrate with Vue, but this would be reinventing much of what Vue-i18n already does.

Testing Vue-i18n

Writing tests is always a good idea. Adding unit tests to an application which uses Vue-i18n is not difficult. Here are some test examples that could help you make sure that translation and localization is working for your Vue application.

import VueI18n from 'vue-i18n'
import Vue from 'vue'
import { shallowMount, createLocalVue } from '@vue/test-utils';

const TranslatedComponent = Vue.component('translated', {
  template: '<div>{{ $t("translated") }}</div>'
});

const UntranslatedComponent = Vue.component('untranslated', {
  template: '<div>{{ $t("untranslated") }}</div>'
});

  describe('translation', () => {
    function initWrapper(component) {
      const localVue = createLocalVue()
      localVue.use(VueI18n)
      const messages = {
        en: {
          'translated': 'hi buddy'
        },
        zh: {
          'translated': '你好世界'
        }
      }
      const i18n = new VueI18n({
        locale: 'en',
        fallbackLocale: 'en',
        messages
      })
      return shallowMount(component, {
        i18n,
        localVue
      })
    }

    test('translates component to English', () => {
      let wrapper = initWrapper(TranslatedComponent);
      expect(wrapper.element).toMatchSnapshot();
    });

    test('translates component to Chinese', () => {
      let wrapper = initWrapper(TranslatedComponent);
      wrapper.vm.$i18n.locale = 'zh'
      expect(wrapper.element).toMatchSnapshot();
    });

    test('falls back to English if language dictionary is not found', () => {
      let wrapper = initWrapper(TranslatedComponent);
      wrapper.vm.$i18n.locale = 'xx'
      expect(wrapper.element).toMatchSnapshot();
    });

    test('falls back to key value if key not found', () => {
      let wrapper = initWrapper(UntranslatedComponent);
      expect(wrapper.element).toMatchSnapshot();
    });
  });

Here we ensure that we can translate into English, change the locale to Chinese and translate into Chinese, and then we make sure that if an unknown locale is provided, the text is simply the key of the translated phrase. In the above example, the last snapshot will look something like <div>untranslated</div>

Vue-i18n allows you to manage translations in a few different ways. One way is to use tags inside a component. Another in to have single json files with a language's translations. One test you may want to write is to ensure that every language has the same keys. This will help ensure that no language is missing a translation, and that if the key of one language is updated, all other language keys are also updated.

If you are using tags, you can add this as part of that component's unit test. If you have a single json file for each language, you can just loop through the language files and compare them to the base language.

Say your translation key/values look like this:

{
    "dog": "dog",
    "cat": "cat",
    "boy": "boy"
}

And

{
    "dog": "狗",
    "cat": "猫"
}

Clearly the Chinese language is missing the boy key/value translation. So what you will want to do is loop through the object properties of the English file, and make sure that each of those is found in the Chinese object. If one is missing, you test should fail, and you should report what is missing.

These are two of the most common ways of testing to make sure that your translation implementation is actually working. Translating Vue files is pretty easy, and so is adding good tests.