How to localize Nuxt v3 projects using Localazy

Vue 3 became the new default recommended version for new projects in February. With this new era, loads of frameworks, plugins, and libraries have also started focusing on the new Vue. Nuxt is no exception, and the team is nearing the stable release, which is planned for this summer.

Read more articles about Nuxt.js

Naturally, such a large transition requires a lot of development time and dedication. This is especially true for Nuxt, the largest and most popular framework built on Vue. As the previous version 2, Nuxt is an open-source hybrid Vue framework that eases the development of web applications with extra emphasis on performance, SEO optimizations, and ease & speed of development.

https://v3.nuxtjs.org/

At Localazy, we've been using Nuxt since the beginning, and we are excited to try the new version for our next projects too. And naturally, the implementation of i18n support is the crucial aspect we will be focusing on.

๐Ÿฅณ Getting started

Let's begin by creating a new Nuxt project. The new version of Nuxt also comes with a new CLI tool, which makes the process seamless. Run the following commands to create a new project and install the dependencies:

npx nuxi init localazy-nuxt3
cd localazy-nuxt3
npm i

Note that at the time of writing this article the Nuxt v3 has not released a stable version yet. It's possible that the API might change in the future, although it's unlikely given how close we are to the release day. This example runs on Nuxt version 3.0.0-rc.6 and and @intlify/nuxt3 version 0.2.3.

Prepare i18n module

Next, let's add support for the localization of your project. In this example, we're going to use @intlify/nuxt3, which is built on vue-i18n-next. Currently, this is the most stable i18n plugin for Nuxt that supports content localization.

To install it to our project, run npm install --save-dev @intlify/nuxt3 and then include it modules options in your nuxt.config.[ts|js]

// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'
export default defineNuxtConfig({
  // ...
  modules: ['@intlify/nuxt3']
  // ...
})

Note that it does not support route localization and SEO i18n enhancement like @nuxtjs/i18n did with Nuxt v2. As the authors from intlify state themselves, one of the purposes of the @intilify/nuxt3 module is "...finding issues on the vue-i18n-next so that @nuxtjs/i18n can support Nuxt3."

Nonetheless, adding support for route localization can be implemented manually, and it's also the approach we've decided to take at Localazy. Let us know in the comments if you would like us to elaborate on how we've done it. ๐Ÿ™‹โ€โ™‚๏ธ

Going multilingual

At this point, we can start our application by running npm run dev. No error should pop out, and you should be welcomed by the default welcome screen.

Default Welcome screen in English

This component is called NuxtWelcome, and it is used in app.vue. When you inspect this component in node_modules , you'll find out that it accepts several props which can modify most of the textual content inside. Let's make use of it and translate it ๐Ÿค—

First of all, create a new lang folder in the root folder of your project. Then create an en.json file inside and paste in the following.

{
  "title": "Welcome to Nuxt 3!",
  "readDocs": "We highly recommend you take a look at the Nuxt documentation, whether you are new or have previous experience with the framework.",
  "followTwitter": "Follow the Nuxt Twitter account to get latest news about releases, new modules, tutorials and tips.",
  "starGitHub": "Nuxt is open source and the code is available on GitHub, feel free to star it, participate in discussions or dive into the source."
}

This is the default English content on the welcome screen, which we will translate momentarily. Lastly, configure the lang directory to be the i18n source for the @intlify/nuxt3 in your nuxt.config.[js|ts]. Additionally, we'll change the locale to es so that it will set the language to Spanish by default.

import { defineNuxtConfig } from 'nuxt'
export default defineNuxtConfig({
  // ...
  modules: ['@intlify/nuxt3'],
  intlify: {
      localeDir: 'lang',
      vueI18n: {
        locale: 'es'
      }
  }
  // ...
})

We don't have the Spanish translations yet, and that's where Localazy comes in.

๐Ÿšฉ Connecting to Localazy

First of all, set up a new account on Localazy and create your new project. Using English as the source language is recommended, but you can choose any other. Turn on the Use community translations (ShareTM) option if you want to get translation suggestions from our shared translation memory.

ShareTM is a highly accurate shared translation memory that can help you accurately translate a significant portion of your project. Thanks to it, most of the new projects have as much as 50% of their strings automatically available as suggestions for translation into 80+ languages.

Proceed to create the project. Afterward, select Nuxt.js on the integration screen. We'll use the powerful CLI tool to manage the upload and download of texts.

Installation is available for Linux, macOS, and Windows. Note the read and write keys in step 2 - we'll need them shortly.

Localazy Quick Start - Nuxt.js

As suggested, create a localazy.json file in the root folder of your project. Copy the recommended configuration and change the translations folder to lang folder in both the upload and download sections.

{
 
    "writeKey": "<your-write-key>",
    "readKey": "<your-read-key>",
    
    "upload": {  
      "type": "json",
      "files": "lang/en.json"         
    },
    
    "download": {
      "files": "lang/${lang}.json"
    }
    
  }

Now you are ready to upload the content in the English file. All you need to do is to call localazy upload.

Translating strings

Now go to Localazy and add the Spanish language ๐Ÿ™‚

Localazy Languages List with source language only

Then click on the translate button to start translating. Let's just use the suggested machine translations, which is an amazing feature for multilingual prototyping.

Localazy Languages List with Spanish addedTranslating using machine engine suggestions

For your real project, you can choose from multiple approaches to translate your project with Localazy:

  1. ๐Ÿ’ช๐Ÿป Translate on your own or invite contributors - You can start translating on your own and use our built-in suggestion system.
  2. ๐Ÿฆพ Translate everything in bulk via machine translation - With the Localazy Autopilot plan, you can instantly translate all strings by running a machine translation over the content. This is great for the first iteration and localization testing of your Nuxt project.
  3. ๐Ÿšฉ Fully automate the translation process with the Continuous Localization services - You can order translations from our vetted translators and get your project translated by professionals automatically. The service is also proactive, so you don't have to micromanage translators.

Using translations in Nuxt

Come back to your application and run localazy download. You should see a newly created es.json file in the lang folder.

By using vue-i18n's $t the function, we'll resolve the key in the currently selected language, which we've defined to be Spanish in the nuxt.config.[js|ts]. To test it, change the app.vue content to the following.

<template>
  <div>
    <NuxtWelcome
    :title="$t('title')"
    :readDocs="$t('readDocs')"
    :followTwitter="$t('followTwitter')"
    :starGitHub="$t('starGitHub')"
     />
  </div>
</template>

Refresh your page and voila! The textual content, which is modifiable through NuxtWelcome's props, has been translated to Spanish ๐Ÿ˜

Translated Welcome screen to Spanish

โœ”๏ธ Conclusion

That's it! Now you're all set to serve your visitors content in their language!

Read more about what Localazy can do for you:

As said earlier, the Localazy website is powered by Nuxt. On top of that, we are proud sponsors of Nuxt.js and are delighted to give our fellow Nuxt lovers a gift.

Use the coupon "lovenuxt" during your Localazy plan checkout and get a 25% discount on your purchase.

Discount applies to Professional, Autopilot, and Agency plans. Enjoy!


This is a companion discussion topic for the original entry at https://localazy.com/blog/how-to-localize-nuxt-v3-using-localazy

Could you please tell about route localization for nuxt 3?

Maybe, @dan could help?

Since we have all the pages dynamic for the moment, we handle only the definition of multilingual routes for dynamic content and zero static pages. However, including a finite set of static pages shouldnโ€™t be too difficult.

Our approach is to divide each section of the site into modules. Each module contains its own services, components, locales, services etc. And each module also defines available dynamic pages and provides a sitemap definition.
Each such module also provides defineNuxtModule to extend Nuxt. This is an example of our languages module for Localazy Hub.

import { resolve } from 'path';
import { defineNuxtModule, addServerHandler, extendPages } from '@nuxt/kit';
import { LanguagesPagesExtender } from './services/languages-pages-extender';

export const sitemapRoute = '/sitemap-languages.xml';

export default defineNuxtModule({
  setup () {
    addServerHandler({
      route: sitemapRoute,
      lazy: true,
      handler: resolve(__dirname, './server/sitemap-languages.server.ts')
    });

    extendPages(async (pages) => {
      (await LanguagesPagesExtender.generatePages()).forEach((page) => {
        pages.push(page);
      });
    });
  }
});

As you can see, itโ€™s quite small and only two things are really happening - we define a server handler for a multilingual sitemap (which is just one section of the sitemap index) and we extend available pages via a generator.

The generator itself has two responsibilities.

  1. Fetch the data (that will differ in your case)
  2. Parse the data so it returns an array of route objects:
import { NuxtPage } from '@nuxt/schema';

...

const pages: NuxtPage[] = [];

... 
pages.push({
  name: `${slug}__${locale}`,
  path: `/${locale}/${slug}/:slug`,
  file: resolve(dirName, pathToPage)
});

In other words, we fetch the data for all locales, each entry as a unique slug which we use to define a name for the route and to define the path. Only :slug remains as a parameter in order for each logic handling component to use the parameter to fetch detailed API response from the server.

With such a service in place, itโ€™s pretty straightforward to define the sitemap server handler too. We use the sitemap npm package for that and again - fetch data, parse them for the sitemap package and serve.