Categories
Vue

vue-i18n — Directive and HTML

Spread the love

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at how to create multilingual Vue apps with vue-i18n.

Custom Directive Localization

We can use the v-t directive for getting translations.

For instance, we can write:

main.js

import Vue from "vue";
import App from "./App.vue";
import VueI18n from "vue-i18n";

Vue.use(VueI18n);
Vue.config.productionTip = false;

const messages = {
  en: {
    hello: "hi"
  },
  fr: {
    hello: "bonjour"
  }
};

const i18n = new VueI18n({
  messages,
  locale: "fr"
});

new Vue({
  i18n,
  render: h => h(App)
}).$mount("#app");

App.vue

<template>
  <div id="app">
    <p v-t="'hello'"></p>
  </div>
</template>

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

We just put the v-t directive in our template and we get the translation.

So bonjour is displayed on the screen.

We can also write:

main.js

import Vue from "vue";
import App from "./App.vue";
import VueI18n from "vue-i18n";

Vue.use(VueI18n);
Vue.config.productionTip = false;

const messages = {
  en: {
    hello: "hi {name}"
  },
  fr: {
    hello: "bonjour {name}"
  }
};

const i18n = new VueI18n({
  messages,
  locale: "fr"
});

new Vue({
  i18n,
  render: h => h(App)
}).$mount("#app");

App.vue

<template>
  <div id="app">
    <p v-t="{ path: 'hello', args: { name: nickName } }"></p>
  </div>
</template>

<script>
export default {
  name: "App",
  computed: {
    nickName() {
      return "foo";
    }
  }
};
</script>

to interpolate translation.

The path has the path to the message, args has dynamic arguments.

Now we get bonjour foo displayed on the screen.

Use with Transitions

We can use the v-t directive with transitions.

For instance, we can write:

main.js

import Vue from "vue";
import App from "./App.vue";
import VueI18n from "vue-i18n";

Vue.use(VueI18n);
Vue.config.productionTip = false;

const messages = {
  en: {
    hello: "hi"
  },
  fr: {
    hello: "bonjour"
  }
};

const i18n = new VueI18n({
  messages,
  locale: "fr"
});

new Vue({
  i18n,
  render: h => h(App)
}).$mount("#app");

App.vue

<template>
  <div id="app">
    <button @click="toggle = !toggle">Toggle</button>
    <transition name="fade">
      <p v-t="'hello'" v-if="toggle"></p>
    </transition>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      toggle: true
    };
  }
};
</script>

<style>
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s;
}
.fade-enter,
.fade-leave-to {
  opacity: 0;
}
</style>

Then we get a transition effect thanks to the transition component.

$t vs v-t

$t is more flexible in that it can be used in component code and template.

However, it’s run every time a re-render occurs, which means it’s slower.

v-t has better performance than $t because of caching.

It’s also can be used for pre-translation with vue-i18n-extensions .

However, it isn’t as flexible as $t and it’s complex.

Component Interpolation

To add translations with HTML, we may want to put them ibn between our tags:

main.js

import Vue from "vue";
import App from "./App.vue";
import VueI18n from "vue-i18n";

Vue.use(VueI18n);
Vue.config.productionTip = false;

const messages = {
  en: {
    hello: "hi",
    world: "world"
  },
  fr: {
    hello: "bonjour",
    world: "monde"
  }
};

const i18n = new VueI18n({
  messages,
  locale: "fr"
});

new Vue({
  i18n,
  render: h => h(App)
}).$mount("#app");

App.vue

<template>
  <div id="app">
    <p>
      {{ $t('hello') }}
      <b>{{ $t('world') }}</b>
    </p>
  </div>
</template>

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

However, this is too inflexible.

We can use the i18n component to avoid this.

For instance, we can write:

main.js

import Vue from "vue";
import App from "./App.vue";
import VueI18n from "vue-i18n";

Vue.use(VueI18n);
Vue.config.productionTip = false;

const messages = {
  en: {
    hello: "hi {0}",
    world: "world"
  },
  fr: {
    hello: "bonjour {0}",
    world: "monde"
  }
};

const i18n = new VueI18n({
  messages,
  locale: "fr"
});

new Vue({
  i18n,
  render: h => h(App)
}).$mount("#app");

App.vue

<template>
  <div id="app">
    <i18n path="hello" tag="p" for="world">
      <b>{{ $t('world') }}</b>
    </i18n>
  </div>
</template>

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

We have the {0} placeholder to interpolate what we have inside i18n into the tags.

Then we see the 2nd word in bold.

Conclusion

We can put HTML formatted text in the i18n component.

Also, we can use the v-t directive as an alternative to $t .

It’s faster and works with transitions.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *