Advanced i18n in Nuxt using Interpolations

Debbie O'Brien

Debbie O'Brien

Aug 17, 2020
4 min read
Share on Twitter or LinkedIn

In NuxtJS on our home page we have a title which has the letters JS as a green color, a different color to the rest of the text. Obviously this is done by adding a span with a color of light-green. This span is then added to all the other languages we have. We then import this using v-html. So far so good. It works. Why change this?

title: 'The Intuitive <span class="text-nuxt-lightgreen">Vue</span> Framework',
<p v-html="$t('title')"></p>

So recently we added eslint to our main website. Obviously this didn't pass the rule where v-html is considered a bad practice. But with eslint we can just turn off the rule. Problem solved. OK but what happens if we need to change the light-green to a dark-green. Well we need to change it in the i18n file of each language. Tedious? Well we could just do a find and replace. Problem solved.

So basically it means people can translate our text and change the text and color to anything they like. But surely they wouldn't do that. But that's not the point. Should we really have this in our translations? Is it really necessary? Isn't there a better way?

That's where i18n interpolation comes into practice. With i18n, instead of using v-html we can instead use interpolation. How?

i18n gives us an <i18n> component that we can use on any of our pages or inside our components. In this component we can set up the tag to be any html element we want such as h2, div, a or whatever we want to use for that particular text.

<i18n tag="h1"></i18n>  

We then allocate it to our translation. If for example in our en-EN.js file we have homepage.title:

module.exports = {
  homepage: {
    title:
      'The Intuitive <span class="text-nuxt-lightgreen">Vue</span> Framework'
  }
}

Then this is what we will use as the path in our <i18n> component.

<i18n
    tag="h1"
    path="homepage.title"
>
</i18n>          

We can also add classes to our component just like any other component

<i18n
    tag="h1"
    path="homepage.welcome.title"
    class="title"
>
</i18n>

We can now use slots inside our component to render what we want, which in our case is our span class. We give the slot a name so we can then refer to it in our translation file. And then we add our span.

<i18n
    tag="h1"
    path="homepage.welcome.title"
    class="title"
>
	 <template v-slot:frameworkType>
      <span class="text-nuxt-lightgreen">
          Vue
      </span>
   </template>
</i18n>  

Now in our translation file we can add the name of our slot enclosed in curly brackets where we want the actual span to appear.

module.exports = {
  homepage: {
    title: 'The Intuitive {frameworkType} Framework'
  }
}

This will now give us the translated text with a placeholder for our span class. And in our fr-FR.js file we can add the French translation where our placeholder will go at the end of the sentence instead of after the word Intuitive like in English.

module.exports = {
  homepage: {
    title: 'Le Framework Intuitif basé sur {frameworkType}'
  }
}

Now if we want to modify our span to be a different colour or add more styling we only have to do it in one place, and our translators only have to worry about translating the texts without having to deal with unnecessary html.

It is also possible to add more than one slot to your <i18n> component. For example, for styling purposes, you might want to add a break in the sentence. Just make sure you give them unique names and then you can use the placeholders in your translation files.

<i18n
    tag="h1"
    path="homepage.welcome.title"
    class="title"
>
	<template v-slot:br>
	    <br />
	</template>
	 <template v-slot:frameworkType>
      <span class="text-nuxt-lightgreen">
          Vue
      </span>
   </template>
</i18n> 
title: 'The Intuitive {br} {frameworkType} Framework',
title: 'Le Framework Intuitif {br} basé sur {frameworkType}',

As you an see it is much better to use i18n interpolation rather than v-html in your code as it allows you to keep your styling and html separate from your translations. This not only makes it easier for translators but it also makes it much easier to modify as the html code is not repeated throughout the translation files.

If you have never worked with i18n then check out these links to help you get started:

Don't miss out anything about Vue, your favourite framework.

Subscribe to receive all the articles we publish in a concise format, perfect for busy devs.

Related Articles

How to create a Geolocated Currency with MaxMind in Vue.js

Learn in this tutorial how to use content that depends on the language and location of the user and apply true i18n in Vue.js

Samuel Snopko

Samuel Snopko

Apr 22, 2019

How to use script setup in Nuxt 2

If you love Vue script setup and want to use it in your current Nuxt 2 project, the Nuxt team has made it possible to start using it today!

Paul Melero

Paul Melero

Feb 14, 2022

How to use the new Fetch in Nuxt.js

The Nuxt team is on fire, releasing new stuff every week! In this tip Samuel shows you a feature that might've gone unnoticed... till now.

Samuel Snopko

Samuel Snopko

Sep 7, 2020

Sponsors

VueDose is proudly supported by its sponsors. If you enjoy it, consider supporting it to ensure the project maintainability.

Silver
Learning Partner