How to Translate a Vue.js / Nuxt Website into Multiple Languages (2026 Guide)

July 2, 2026LingoJs Blog
How to Translate a Vue.js / Nuxt Website into Multiple Languages (2026 Guide)

Vue.js and Nuxt power millions of websites and web applications worldwide. But when it comes to adding multilingual support, the Vue ecosystem has historically been more fragmented than React's — leaving developers to piece together solutions from multiple libraries and manual configuration.

In 2026, you have three solid paths: vue-i18n (the official Vue internationalization library), @nuxtjs/i18n (the Nuxt module that wraps vue-i18n with routing and SEO), and LingoJS (the one-script approach that works with any Vue or Nuxt project without touching your codebase).

This guide walks through all three approaches — with real code examples, setup times, and a clear framework for choosing the right one.


Why Vue.js Multilingual Matters in 2026

Vue.js is the second most popular frontend framework globally, and Nuxt is the most popular Vue meta-framework. Companies like Nintendo, GitLab, Adobe, and BMW use Vue in production. If your Vue app only speaks one language, you are invisible to a significant portion of your potential audience.

The numbers are clear: 75% of users prefer buying from websites in their native language, and localized pages consistently rank higher in regional search engines. For Nuxt sites — which rely on SSR and static generation for SEO — translating your content unlocks organic traffic in every market you target.


Approach 1: vue-i18n — The Official Library

vue-i18n is the standard internationalization library for Vue.js, maintained by the Vue core team. It integrates with Vue 3's Composition API and provides reactive translation, pluralization, date formatting, and locale switching.

Setup

npm install vue-i18n@10
// i18n.ts
import {createI18n} from 'vue-i18n';
import en from './locales/en.json';
import fr from './locales/fr.json';
 
const i18n = createI18n({
  legacy: false,
  locale: 'en',
  fallbackLocale: 'en',
  messages: {en, fr}
});
 
export default i18n;
// main.ts
import {createApp} from 'vue';
import App from './App.vue';
import i18n from './i18n';
 
const app = createApp(App);
app.use(i18n);
app.mount('#app');

In your components, you use the $t() function:

<template>
  <h1>{{ $t('hero.title') }}</h1>
  <p>{{ $t('hero.subtitle') }}</p>
</template>

What works well

vue-i18n is fast, well-documented, and tightly integrated with Vue's reactivity system. Lazy-loading locale files is supported out of the box. The Composition API support (useI18n()) is clean and idiomatic.

What gets complicated

Every string you want translated must be wrapped in $t() or t() in your templates. That means touching every component that renders user-facing text. Translation files are JSON that you maintain manually. Adding a new language means copying the entire English JSON file and translating every entry. For a mid-sized Vue app with 500+ translatable strings across 20 components, this represents days of initial setup and ongoing maintenance.

SEO is manual too — you need to configure hreflang tags, localized metadata, and a multilingual sitemap yourself or through a Nuxt module.


Approach 2: @nuxtjs/i18n — The Nuxt Module

If you are using Nuxt 3, the @nuxtjs/i18n module wraps vue-i18n and adds automatic route generation, locale detection, SEO tags, and URL strategies. It is the most complete i18n solution for Nuxt projects.

Setup

npx nuxi module add i18n
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxtjs/i18n'],
  i18n: {
    locales: ['en', 'fr', 'de', 'es', 'it'],
    defaultLocale: 'en',
    strategy: 'prefix',
    vueI18n: './i18n.config.ts'
  }
});
// i18n.config.ts
export default defineI18nConfig(() => ({
  legacy: false,
  locale: 'en',
  messages: {
    en: { welcome: 'Welcome' },
    fr: { welcome: 'Bienvenue' },
    de: { welcome: 'Willkommen' }
  }
}));

The module generates per-locale routes automatically (/fr/about, /de/about), injects hreflang tags, and provides composables like useLocalePath() and useSwitchLocalePath() for building language switchers.

What works well

Route generation and hreflang automation save hours of manual configuration. The strategy option supports prefix (/fr/about), prefix except default (/about + /fr/about), and no prefix modes. SEO metadata per locale is handled through useSeoMeta() in combination with the i18n module.

What still requires work

You still write every translation manually in JSON files. The module handles the routing layer but does not translate your content — it only serves the right file for each locale. For a Nuxt site with a blog, documentation, or user-generated content, the translation file maintenance burden grows linearly with every page you add.

Performance-wise, each locale adds to your bundle if you inline messages. Lazy-loading helps, but the initial locale file needs to be available for server-side rendering.


Approach 3: LingoJS — One Script, Zero Code Changes

LingoJS works with any Vue or Nuxt project without any codebase changes. You add one script tag to your HTML template (or use the Nuxt useHead composable for the script), and LingoJS automatically detects, translates, and serves your content in every language you enable.

Setup for Vue

<!-- index.html -->
<script
  src="https://cdn.jsdelivr.net/gh/Flowcodelab/LingoJs@main/lingo-snippet.obf.js"
  data-api-key="YOUR_API_KEY"
  async
></script>

Setup for Nuxt

<!-- app.vue -->
<script setup>
useHead({
  script: [{
    src: 'https://cdn.jsdelivr.net/gh/Flowcodelab/LingoJs@main/lingo-snippet.obf.js',
    async: true,
    'data-api-key': 'YOUR_API_KEY'
  }]
});
</script>

That is it. LingoJS handles everything automatically:

  • Detects all text in your Vue components — including dynamically rendered content, v-if blocks, and slots
  • Translates using contextual AI that understands your UI structure
  • Serves translations from a global CDN at ~26ms average
  • Manages hreflang tags, localized metadata, and schema.org in every language
  • Provides a customizable language switcher widget
  • Caches translations at the edge for repeat visitors

You never modify a single $t() call or maintain a translation JSON file.


Comparison: Vue-i18n vs Nuxt-i18n vs LingoJS

vue-i18n@nuxtjs/i18nLingoJS
Setup time1-3 hours30-60 min2 min
Code changes requiredEvery componentEvery componentNone
Translation methodManual JSONManual JSONAI (auto)
New languageCopy + translate all keysCopy + translate all keysClick "Add"
Hreflang/SEOManualAutomatic (routing)Automatic (full)
Dynamic contentManual $t() wrappingManual $t() wrappingAuto-detected
Bundle impact~12KB + locale files~15KB + locale files0KB (external CDN)
CostFree (MIT)Free (MIT)From €19/mo

Performance: What Impact Does Translation Have?

vue-i18n loaded with a single locale adds approximately 12KB to your Vue bundle. Each additional locale loaded eagerly adds the size of its JSON message file. For a Nuxt site using SSR, the server must load and process these files on every request.

LingoJS loads asynchronously from jsDelivr's global CDN. The script does not block rendering, and translation payloads are cached at the edge. The result: your Vue app's Core Web Vitals are unaffected. The average translation delivery time is 26ms, which is imperceptible to users.


SEO for Vue/Nuxt Multilingual Sites

Nuxt's SSR and static generation already give you a strong SEO foundation. But adding languages multiplies the complexity:

  • Hreflang tags must be present on every page variant, reciprocal, and point to the correct locale URL
  • Canonical URLs must reference the correct language version
  • Meta tags (title, description, og:title, og:description) must be translated per locale
  • Structured data (schema.org) should be localized
  • Multilingual sitemaps help Google discover every language version

@nuxtjs/i18n handles hreflang generation automatically when using the prefix strategy. vue-i18n alone does none of this — you build it yourself. LingoJS handles all of it automatically, including translated metadata and schema.org, without any configuration.


When to Use Each Approach

Use vue-i18n if: You are building a pure Vue SPA (no Nuxt), need per-string control over translations, have a limited number of strings to translate, or already have an internal translation team producing JSON files.

Use @nuxtjs/i18n if: You are on Nuxt 3, want automatic route generation and SEO basics handled, and are comfortable maintaining translation files. This is the best library approach for Nuxt projects.

Use LingoJS if: You want your Vue or Nuxt site to be multilingual today without modifying components, managing translation files, or configuring SEO. You value engineering speed, have a content-heavy site, or are a small team that cannot dedicate resources to i18n maintenance.


How to Get Started

If you want to evaluate the zero-code approach first, install LingoJS on your Vue or Nuxt project in two minutes:

  1. Create a free account at lingojs.com
  2. Get your API key from the dashboard
  3. Add the script tag to your HTML template or app.vue
  4. Choose your target languages in the dashboard
  5. Deploy — your site is now multilingual

No code changes, no JSON files, no i18n configuration. Your Vue components stay exactly as they are. LingoJS handles detection, translation, caching, and SEO.

Start your free 30-day trial →

Translate your website in 10 minutes. From €19/mo.

Try free for 30 days →
Open new horizons

Upgrade your business with new targets

We help you to reach new markets and customers by providing a seamless translation experience.