Vue3 + i18n (bonus i18n ally)
Tags: webdev, vue, i18n, vite
Published: 2022-11-17 18:52:52

How to configure i18n and vue3 so that at the end of the project the translation files are not 10000 lines long and incomprehensible.

The solution? i18n namespaced files and the i18n ally extension!

## 1. Create a brand new project

```
pnpm create vue@latest
```

```
✔ Project name: … vue3-i18n
✔ Add TypeScript? … Yes
✔ Add JSX Support? … No
✔ Add Vue Router for Single Page Application development? … No
✔ Add Pinia for state management? … No
✔ Add Vitest for Unit Testing? … No
✔ Add an End-to-End Testing Solution? › No
✔ Add ESLint for code quality? … No
✔ Add Prettier for code formatting? … No
```

```
pnpm install && pnpm run dev
```

You should now bet able to see a basic Vue3 project on **localhost:5173**

## 2. i18n

### Install i18n for Vue3

```
pnpm install vue-i18n@9
```

### Create some translation files

Here is my architecture. Follow it for this tutorial, you can change it later with some job.

![i18n files architecture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ciclisu4k3nz2j4c5ln.png)

locales/en/auth.json

```
{
  "SignIn": "Sign In",
  "SignUp": "Sign Up"
}
```

locales/en/commons.json

```
{
  "height": "Height",
  "weight": "Weight"
}
```

For the FR part, I let you translate by yourself!

### Init i18n configuration file

Inside locales folder create an **index.ts** file.

```
import { createI18n, type I18n, type Locale } from "vue-i18n";
import authEN from "./en/auth.json";
import authFR from "./fr/auth.json";
import commonsEN from "./en/commons.json";
import commonsFR from "./fr/commons.json";

let i18n: I18n;

const init = () => {
  i18n = createI18n({
    locale: "en",
    messages: {
      en: {
        auth: authEN,
        commons: commonsEN,
      },
      fr: {
        auth: authFR,
        commons: commonsFR,
      },
    },
  });
};

const setLocale = (locale: Locale): void => {
  i18n.global.locale = locale;
};

init();

export { i18n, setLocale };
```

### Add i18n to the Vue3 app

inside the **main.ts** import i18n as

```
import { i18n } from "./locales";
```

And the use this i18n

```
createApp(App).use(i18n).mount("#app");
```

## 3. Test our integration

Replace the content of App.vue with

```
<script setup lang="ts">
  import {setLocale} from "./locales"
  const changeLocale = () => {
    setLocale('fr')
  }
</script>

<template>
  <main>
    {{$t('auth.SignIn')}}
    {{$t('commons.height')}}
    <button @click=changeLocale>Change Locale</button>
  </main>
</template>
```
 
You should see: 

![integration testing](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5b3nf0sfae0g32x2c9sj.png)

And if you click on the button... TADA! Strings are no FR ones.

## 4. Bonus: i18n ally

Dealing with a large set of locales and translation can be such a pain in the a$$. 

This is where the [i18n ally extension](https://marketplace.visualstudio.com/items?itemName=Lokalise.i18n-ally) come to the rescue.

### i18n ally installation

You can add it to VSCode from the embeded marketplace or from [this link](https://marketplace.visualstudio.com/items?itemName=Lokalise.i18n-ally)

### i18n ally configuration

Open **User Settings Preferences (JSON)** from the quick access shortcut.

```
shift + cmd + p
```

And the add in the end of the JSON file these lines

```
  "i18n-ally.dirStructure": "auto",
  "i18n-ally.enabledFrameworks": ["vue"],
  "i18n-ally.enabledParsers": ["json", "yaml"],
  "i18n-ally.extract.autoDetect": true,
  "i18n-ally.namespace": true,
  "i18n-ally.pathMatcher": "{locale}/{namespaces}.json",
```

### i18n ally usage

When i18n ally is installed and configured in VSCode, you can open it from the sidebar button.

![i18n ally](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7v6lvyt7f00wgq1csspe.png)

I let you play with this useful extension, but with it you can auto translate your string, create keys and see you translation coverage. 

## Links

[vue3](https://vuejs.org/guide/introduction.html)
[vue-i18n-next](https://github.com/intlify/vue-i18n-next)
[i18n-ally](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7v6lvyt7f00wgq1csspe.png)

## Questions? 

If you have some questions or issues, please share it with me in a comment, I will take a look at it quickly :) 

Ciao