Step-by-step: How to Create a Vue Multi-Language App with Vue-i18n
Tags: javascript, webdev, tutorial, vue
Published: 2022-02-09 18:19:09

Discover how to add translations to your Vue 3 application using “vue-i18n-next”. From nothing to a multi language app.

---

Our previous guide introduced you to [internationalizing a Next.js application with next-translate](https://medium.com/flycode/step-by-step-how-to-internationalize-your-nextjs-app-with-next-translate-3c8b13b87fc4) as an i18n library. This time, we will focus on doing it with Vue 3.

This step-by-step guide will teach you:
- How to initialize your Vue 3 application with “vue-i18n-next” (the i18n library that we will use)
- How to create translations and start localizing your website
- How to use the main translation feature

Ready to create a website in different languages? 🇺🇸🇫🇷

## Why do we choose Vue i18n next?

You probably heard of many libraries to translate your Vue application (“vue-i18next”, “vue-simple-i18n”, etc.).

In this guide, we will use the Vue i18n next library because it would benefit the most readers since it’s the most used one (+650k downloads per week).

Most GitHub repositories that you will find online are using it. So, right after this guide, you will understand the basics and deep dive further into all these online resources.

Don’t worry, we will probably certainly write about other libraries in the future. If you don’t want to miss other content, I highly recommend following [FlyCode on Twitter](https://twitter.com/FlyCode_Inc).

## 1. Create a new Vue 3 application

>  **Note:** You can skip to the next step if you already have an existing application.

Once you’re ready, you can open your terminal and move it into your project folder. The first thing you need to do is initialize a Vue 3 application.

You can enter the `vue create [project-name]` command to create a new project using the Vue CLI.

>  **Note:** If you don’t have the Vue CLI yet, you can install it using `npm install -g @vue/cli`.

In our case, we will name the project: “vue-3-i18n-example-with-vue-i18n-next” (`vue create vue-3-i18n-example-with-vue-i18n-next`).

Once you hit “Enter”, the Vue CLI will prompt you to select a preset for your new project. Select the “Default (Vue 3)” preset.

When your project is ready, move into it.

Your folder tree should look like below:

```shell
    .
    ├── README.md
    ├── babel.config.js
    ├── package-lock.json
    ├── package.json
    ├── public
    │   ├── favicon.ico
    │   └── index.html
    └── src
        ├── App.vue
        ├── assets
        │   └── logo.png
        ├── components
        │   └── HelloWorld.vue
        └── main.js

    4 directories, 10 files
```

## 2. Install vue-i18n-next in your Vue 3 project

The following step of this tutorial is to install the Vue i18n library that we will use.
Come back to your terminal and enter the command below:

```shell
$ vue add i18n
```

After the package installation, the CLI will prompt you with some questions to configure your Vue 3 project.

**Question 1: “The locale of project localization.”**

It’s the default language of your website. In this guide, it will be English.
You can press enter to keep the default value (en).

**Question 2: “The fallback locale of project localization.”**

It’s the locale you want to redirect your user if he tries to access a non-existing language on your website. Usually, we set the same fallback locale as the default locale.
You can do the same and keep the default parameter (ENTER ).

**Question 3: “The directory where store localization messages of project. It’s stored under `src` directory.”**

This configuration asks you how you want to name your translation folder (folder containing all the translations of your website).

In this guide, we will keep the default name “locales”. But, if you want, feel free to change it to anything else “translations”, “languages”, etc.

Again, to keep the default setting, you can press `ENTER`.

**Question 4: “Enable legacy API (compatible vue-i18n@v8.x) mode ?”**

By default, the answer is `N`. I recommend you to keep it because it’s one of the significant features of Vue 3.

>  **Note:** `legacy: false` to allow Vue I18n to switch the API mode from [Legacy API](https://vue-i18n.intlify.dev/api/legacy.html) mode to [Composition API mode](https://v3.vuejs.org/guide/composition-api-introduction.html).

After that, your project is ready to handle the first translations! 👏

If you look at your project tree, it should look like this:

```shell
    .
    ├── README.md
    ├── babel.config.js
    ├── package-lock.json
    ├── package.json
    ├── public
    │   ├── favicon.ico
    │   └── index.html
    ├── src
    │   ├── App.vue
    │   ├── assets
    │   │   └── logo.png
    │   ├── components
    │   │   ├── HelloI18n.vue
    │   │   └── HelloWorld.vue
    │   ├── i18n.js
    │   ├── locales
    │   │   └── en.json
    │   └── main.js
    └── vue.config.js

    5 directories, 14 files
```

Ask you can see, there are a lot of updates in your code and some new files! Let me introduce them to you.

- `vue.config.js` (at the folder root): a configuration file with all the i18n settings. You will see most of your CLI answers here.

- `.env` (at the folder root): an environment file with `VUE_APP_I18N_LOCALE` and `VUE_APP_I18N_FALLBACK_LOCALE` variables.

- `i18n.js` (in the `src/` folder): the i18n initialization by the createI18n function. There is a loadLocaleMessages function that loads your translation files.

- `en.json` (in the `locales/` folder): your English translation file. It will contain all your project translations.

- `HelloI18n.vue` (in the `src/components/` folder): a Vue demo component for the vue-i18n-next library (in the next section, we will launch it to see if everything is working).

## 3. Test the i18n configuration on our Vue 3 project

Before going further, it’s essential to test if everything is working correctly with the generated Vue i18next configuration.

To do so, we will use the `HelloI18n.vue` demo component. You will need to open your App.vue file and update the `<script>` and `<template>` parts to replace the current HelloWord component.

Your code will end up looking like this:

```vue
<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <HelloI18n />
</template>

<script>
import HelloI18n from "./components/HelloI18n.vue";

export default {
  name: "App",
  components: {
    HelloI18n
  }
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
```

Then, if you run your Vue application by typing npm run serve , you’ll have the following output:

![vue-i18n-next example](https://cdn-images-1.medium.com/max/6912/1*_Pc7RnSaweiWzhyG4UO20w.png)

If you see this page without any errors in your server console, it means that everything is appropriately configurated!

Before going further and creating our first global translations in Vue, let’s review the `HelloI18n.vue` code.

The example from the vue-i18n-next library is different from what we will use in this step-by-step guide. But, it’s interesting to explain it, so you will be able to deep dive into the [i18n single file components](https://kazupon.github.io/vue-i18n/guide/sfc.html) later on your side.

Indeed, the code below uses the local `t` function (translation function). As you can see in the setup function, the vue-i18n library is configured to use only the current file translations.

Below the file component, you can see some `<i18n>` tags with JSON code. This JSON contains the “Hello i18n in SFC!” text displayed when you launched the project using npm run serve.

```vue
<template>
  <p>{{ t("hello") }}</p>
</template>

<script>
import { defineComponent } from "vue";
import { useI18n } from "vue-i18n";

export default defineComponent({
  name: "HelloI18n",
  setup() {
    const { t } = useI18n({
      inheritLocale: true,
      useScope: "local"
    });

    // Something todo ..

    return { t };
  }
});
</script>

<i18n>
    {
      "en": {
        "hello": "Hello i18n in SFC!"
      },
    }
</i18n>
```

We will not discover this library feature in detail because it’s a particularity of the library and not using the global i18n translations. But, feel free to read more on the documentation if you want to create single components with proper translations.

## 4. Update the translations files

Before starting to update our project code, here are a few points to know:

* all your translation files are in the folder configured at the third question in the vue-i18n CLI (by default `locales/`)

* this folder contains one JSON file per locale (example: `locales/en.json` for the English language)

* each JSON follows the key/value schema (example: “message” is the translation key and “hello i18n !!” is the translation)

```jsin
{
  "message": "hello i18n !!"
}
```

You got it! If you want to add/edit/remove a translation, you should do it in this file.

If you want to have two languages on your website, you should do it in the two corresponding files (example: `locales/en.json` and `locales/fr.json`).

In our case, we will need to create another file inside the locales/ folder. This file will be for the French language (`fr.json` file).

Your project tree should look like below.

```shell
    .
    ├── README.md
    ├── babel.config.js
    ├── package-lock.json
    ├── package.json
    ├── public
    │   ├── favicon.ico
    │   └── index.html
    ├── src
    │   ├── App.vue
    │   ├── assets
    │   │   └── logo.png
    │   ├── components
    │   │   ├── HelloI18n.vue
    │   │   └── HelloWorld.vue
    │   ├── i18n.js
    │   ├── locales
    │   │   ├── en.json
    │   │   └── fr.json
    │   └── main.js
    └── vue.config.js

    5 directories, 15 files
```

Once you have done that, we will update the `locales/en.json` file with the following content:

```json
{
  "title": "Vue 3 i18n",
  "description": "A Vue i18n next example using vue-i18n-next"
}
```

And update the `locales/fr.json` file with the same content, but translated:

```json
{
  "title": "Vue 3 i18n",
  "description": "Un exemple Vue i18n next avec vue-i18n-next"
}
```

As you can see, we created two translations:
- one with `title` as name (key)
- the other one with `description` as a name (key)

Everything is ready on the translation side. Now let’s dive into the code part! 💻

## 5. Refactor the HelloI18n component to use the locales’ folder translations

Let’s refactor the `HelloI18n.js` file to a much simpler code that will use the global translation files.

First, we need to open the `i18n.js` file and update the `createI18n` function. You will need to add the `globalInjection` parameter and set it to `true`.

It will allow you to use the i18n object from everywhere using the $ character.

```vue
export default createI18n({
  legacy: false,
  globalInjection: true,
  locale: process.env.VUE_APP_I18N_LOCALE || "en",
  fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || "en",
  messages: loadLocaleMessages(),
});
```

To use a translation, you will be able to use the `$t` function from i18n:

```vue
<template>
  <h1>{{ $t('title') }}</h1>
  <p>{{ $t('description') }}</p>
</template>
```

Let’s come back to the `HelloI18n.js` file. We will simplify it by using an empty component and calling the `$t` function with our translation key (as above).

```vue
<template>
  <h1>{{ $t("title") }}</h1>
  <p>{{ $t("description") }}</p>
</template>

<script>
export default {
  name: "HelloI18n"
};
</script>
```

If you launch the project, you should have the below output.

![Vue 3 internationalization example](https://cdn-images-1.medium.com/max/6912/1*dkrxvmOhQlWQaw8z-qiEBw.png)

We’re good; our `HelloI18n` component uses the English translations in the `locales/en.json` file.

But… I believe you’re wondering how to change the language from English to French. We will do it by creating a Vue multi language switcher component!

## 6. Create a Vue multi language switcher component

The final step of this step-by-step guide helps you switch from one language to the other and display the appropriate translation.

Based on the locale changing documentation of vue-i18n, we can do it by creating a `<select>` HTML element that modifies the `$i18n.locale` variable (i18n instance current language).

You can do it by creating a new `LocaleSwitcher.vue` file in the `components/` folder.

Then, add the following code that creates a basic select with our two locales as a choice.

```vue
<template>
  <select v-model="$i18n.locale">
    <option v-for="(locale, i) in locales" :key="`locale-${i}`" :value="locale">
      {{ locale }}
    </option>
  </select>
</template>

<script>
export default {
  name: "LocaleSwitcher",
  data() {
    return { locales: ["fr", "en"] };
  }
};
</script>
```

The last step is to add the `LocaleSwitcher` to our `HelloI18n` component.

```vue
<template>
  <h1>{{ $t("title") }}</h1>
  <p>{{ $t("description") }}</p>
  <LocaleSwitcher />
</template>

<script>
import LocaleSwitcher from "./LocaleSwitcher.vue";

export default {
 name: "HelloI18n",
 components: { LocaleSwitcher }
};
</script>
```

Now, you can restart your project and play with the select! Here is the output for the French language:

![Vue multi language switcher component example](https://cdn-images-1.medium.com/max/6912/1*VfOkYOMhuVIFPO8pkf2UaA.png)

Boom… 💥 You just finalized your first internationalized website in Vue 3!

## Bonus: Manage your translations outside of your code with FlyCode 🚀

As you can imagine, updating the translations inside your project can become tricky for some reasons:
- if you start to have big translation files
- if you have a lot of supported languages
- if your product team is managing them and asking for a lot of changes

Let me show you one Git-based Product Editor created for this purpose. It will gather all your translations and allow you to manage them outside of your code editor. As an example, a product manager can modify them directly by himself.

Once he finishes updating all translations, he saves, and FlyCode creates a pull request on your GitHub repository. You can validate the PR and release your changes in just one click. ✅

{% youtube FqbDOe_VP7Y %}

Convinced? 😉 Here are a few articles that you can read and share with your team in addition to the [Flycode website](https://www.flycode.com/):

- [How Product Managers can work like software engineers? 👩‍💻](https://medium.com/flycode/how-product-managers-can-work-work-like-software-engineers-3dc34429c1e9)

- [How to edit your product like a <developer> 🤘](https://medium.com/flycode/how-to-edit-your-product-like-a-developer-13d6da375e58)

## Code is available on GitHub

If you want to retrieve the complete code and execute it, everything is available on the [FlyCode GitHub](https://github.com/flycode-org).

**GitHub => [Vue 3 i18n Example with Vue-i18n-next](https://github.com/flycode-org/vue-3-i18n-example-with-vue-i18n-next)**

I hope you liked this step-by-step guide! Follow [FlyCode on Twitter](https://twitter.com/flycodehq) to be notified when new content is available!