Skip to content

Cómo Traducir una App Vue.js: Guía Completa

Aprende cómo localizar tu app Vue.js usando vue-i18n. Esta guía completa cubre traducción de cadenas, pluralización, formato de fechas y mejores prácticas para la traducción de apps Vue.js.

  • date icon

    18 de noviembre de 2025

  • 06 min de lectura
Cómo Traducir una App Vue.js: Guía Completa

Traducir tu app Vue.js es esencial para llegar a una audiencia global. vue-i18n es el plugin oficial de internacionalización para Vue.js, proporcionando una solución potente y flexible para gestionar traducciones. Esta guía te guiará a través del proceso de traducir una app Vue.js usando vue-i18n.

Entendiendo la Localización de Vue.js con vue-i18n

vue-i18n es la biblioteca estándar de internacionalización para Vue.js. Proporciona componentes Vue, directivas y una API de composición para manejar traducciones, pluralización y formateo de fechas, números y monedas.

Paso 1: Instalar Dependencias

Para Vue 3:

npm install vue-i18n@9

Para Vue 2:

npm install vue-i18n@8

O con yarn:

yarn add vue-i18n@9  # Vue 3
yarn add vue-i18n@8  # Vue 2

Paso 2: Crear Archivos de Traducción

Crea un directorio locales en tu carpeta src y agrega archivos de traducción para cada idioma:

src/locales/en.json (Inglés - por defecto):

{
  "app": {
    "welcome": "Welcome to our app!",
    "title": "My Vue.js App"
  },
  "button": {
    "submit": "Submit",
    "cancel": "Cancel",
    "delete": "Delete"
  },
  "error": {
    "network": "Network error. Please try again.",
    "notFound": "Page not found"
  },
  "items": {
    "count": "{count} items",
    "count_zero": "No items",
    "count_one": "{count} item",
    "count_other": "{count} items"
  },
  "user": {
    "greeting": "Hello, {name}! You have {count} messages.",
    "greeting_zero": "Hello, {name}! You have no messages.",
    "greeting_one": "Hello, {name}! You have {count} message.",
    "greeting_other": "Hello, {name}! You have {count} messages."
  }
}

src/locales/es.json (Español):

{
  "app": {
    "welcome": "¡Bienvenido a nuestra aplicación!",
    "title": "Mi Aplicación Vue.js"
  },
  "button": {
    "submit": "Enviar",
    "cancel": "Cancelar",
    "delete": "Eliminar"
  },
  "error": {
    "network": "Error de red. Por favor, inténtalo de nuevo.",
    "notFound": "Página no encontrada"
  },
  "items": {
    "count": "{count} elementos",
    "count_zero": "No hay elementos",
    "count_one": "{count} elemento",
    "count_other": "{count} elementos"
  },
  "user": {
    "greeting": "¡Hola, {name}! Tienes {count} mensajes.",
    "greeting_zero": "¡Hola, {name}! No tienes mensajes.",
    "greeting_one": "¡Hola, {name}! Tienes {count} mensaje.",
    "greeting_other": "¡Hola, {name}! Tienes {count} mensajes."
  }
}

src/locales/fr.json (Francés):

{
  "app": {
    "welcome": "Bienvenue dans notre application!",
    "title": "Mon Application Vue.js"
  },
  "button": {
    "submit": "Soumettre",
    "cancel": "Annuler",
    "delete": "Supprimer"
  },
  "error": {
    "network": "Erreur réseau. Veuillez réessayer.",
    "notFound": "Page non trouvée"
  },
  "items": {
    "count": "{count} éléments",
    "count_zero": "Aucun élément",
    "count_one": "{count} élément",
    "count_other": "{count} éléments"
  },
  "user": {
    "greeting": "Bonjour, {name}! Vous avez {count} messages.",
    "greeting_zero": "Bonjour, {name}! Vous n'avez aucun message.",
    "greeting_one": "Bonjour, {name}! Vous avez {count} message.",
    "greeting_other": "Bonjour, {name}! Vous avez {count} messages."
  }
}

Paso 3: Configurar vue-i18n (Vue 3)

Crea un archivo de configuración i18n:

src/i18n.js:

import { createI18n } from 'vue-i18n';
import en from './locales/en.json';
import es from './locales/es.json';
import fr from './locales/fr.json';

const messages = {
  en,
  es,
  fr
};

const i18n = createI18n({
  locale: 'en', // Locale por defecto
  fallbackLocale: 'en', // Locale de respaldo
  messages,
  legacy: false, // Usar modo Composition API
  globalInjection: true // Habilitar $t global
});

export default i18n;

O con TypeScript (src/i18n.ts):

import { createI18n } from 'vue-i18n';
import en from './locales/en.json';
import es from './locales/es.json';
import fr from './locales/fr.json';

const messages = {
  en,
  es,
  fr
} as const;

const i18n = createI18n({
  locale: 'en',
  fallbackLocale: 'en',
  messages,
  legacy: false,
  globalInjection: true
});

export default i18n;

Paso 4: Inicializar i18n en tu App (Vue 3)

src/main.js:

import { createApp } from 'vue';
import App from './App.vue';
import i18n from './i18n';

const app = createApp(App);
app.use(i18n);
app.mount('#app');

O con TypeScript (src/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');

Paso 5: Configurar vue-i18n (Vue 2)

Para Vue 2, la configuración es ligeramente diferente:

src/i18n.js:

import Vue from 'vue';
import VueI18n from 'vue-i18n';
import en from './locales/en.json';
import es from './locales/es.json';
import fr from './locales/fr.json';

Vue.use(VueI18n);

const messages = {
  en,
  es,
  fr
};

const i18n = new VueI18n({
  locale: 'en',
  fallbackLocale: 'en',
  messages
});

export default i18n;

src/main.js (Vue 2):

import Vue from 'vue';
import App from './App.vue';
import i18n from './i18n';

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

Paso 6: Usar Traducciones en Plantillas

Usa la función $t en plantillas:

Antes:

<template>
  <h1>Welcome to our app!</h1>
</template>

Después:

<template>
  <h1>{{ $t('app.welcome') }}</h1>
</template>

Paso 7: Usar Traducciones en Script (Composition API - Vue 3)

Usa el composable useI18n:

<template>
  <h1>{{ t('app.welcome') }}</h1>
</template>

<script setup>
import { useI18n } from 'vue-i18n';

const { t } = useI18n();
</script>

Paso 8: Usar Traducciones en Script (Options API)

<template>
  <h1>{{ welcomeMessage }}</h1>
</template>

<script>
export default {
  computed: {
    welcomeMessage() {
      return this.$t('app.welcome');
    }
  }
};
</script>

Paso 9: Interpolación de Cadenas con Variables

Pasa variables a las traducciones:

translation.json:

{
  "user": {
    "greeting": "Hello, {name}!"
  }
}

Componente:

<template>
  <p>{{ $t('user.greeting', { name: userName }) }}</p>
</template>

<script setup>
import { ref } from 'vue';

const userName = ref('John');
</script>

O con Composition API:

<template>
  <p>{{ t('user.greeting', { name: userName }) }}</p>
</template>

<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';

const { t } = useI18n();
const userName = ref('John');
</script>

Paso 10: Pluralización

vue-i18n soporta pluralización usando claves especiales:

translation.json:

{
  "items": {
    "count": "{count} items",
    "count_zero": "No items",
    "count_one": "{count} item",
    "count_other": "{count} items"
  }
}

Componente:

<template>
  <p>{{ $t('items.count', count, { count }) }}</p>
</template>

<script setup>
import { ref } from 'vue';

const count = ref(5);
</script>

O con Composition API:

<template>
  <p>{{ t('items.count', count, { count }) }}</p>
</template>

<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';

const { t } = useI18n();
const count = ref(5);
</script>

Paso 11: Formatear Fechas

Usa la función $d o el método d:

Plantilla:

<template>
  <p>{{ $d(date, 'long') }}</p>
</template>

<script setup>
import { ref } from 'vue';

const date = ref(new Date());
</script>

Composition API:

<template>
  <p>{{ d(date, 'long') }}</p>
</template>

<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';

const { d } = useI18n();
const date = ref(new Date());
</script>

Configurar formatos de fecha en i18n:

const i18n = createI18n({
  locale: 'en',
  messages,
  datetimeFormats: {
    en: {
      short: {
        year: 'numeric',
        month: 'short',
        day: 'numeric'
      },
      long: {
        year: 'numeric',
        month: 'long',
        day: 'numeric',
        weekday: 'long'
      }
    },
    es: {
      short: {
        year: 'numeric',
        month: 'short',
        day: 'numeric'
      },
      long: {
        year: 'numeric',
        month: 'long',
        day: 'numeric',
        weekday: 'long'
      }
    }
  }
});

Paso 12: Formatear Números

Usa la función $n o el método n:

Plantilla:

<template>
  <p>Número: {{ $n(number) }}</p>
  <p>Moneda: {{ $n(amount, 'currency') }}</p>
</template>

<script setup>
import { ref } from 'vue';

const number = ref(1234.56);
const amount = ref(1234.56);
</script>

Composition API:

<template>
  <p>Número: {{ n(number) }}</p>
  <p>Moneda: {{ n(amount, 'currency') }}</p>
</template>

<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';

const { n } = useI18n();
const number = ref(1234.56);
const amount = ref(1234.56);
</script>

Configurar formatos de número en i18n:

const i18n = createI18n({
  locale: 'en',
  messages,
  numberFormats: {
    en: {
      currency: {
        style: 'currency',
        currency: 'USD'
      }
    },
    es: {
      currency: {
        style: 'currency',
        currency: 'EUR'
      }
    }
  }
});

Paso 13: Cambiar Idioma Programáticamente

Permite a los usuarios cambiar idiomas:

Composition API:

<template>
  <div>
    <button @click="changeLanguage('en')">English</button>
    <button @click="changeLanguage('es')">Español</button>
    <button @click="changeLanguage('fr')">Français</button>
  </div>
</template>

<script setup>
import { useI18n } from 'vue-i18n';

const { locale } = useI18n();

const changeLanguage = (lang) => {
  locale.value = lang;
  localStorage.setItem('language', lang);
};
</script>

Options API:

<template>
  <div>
    <button @click="changeLanguage('en')">English</button>
    <button @click="changeLanguage('es')">Español</button>
    <button @click="changeLanguage('fr')">Français</button>
  </div>
</template>

<script>
export default {
  methods: {
    changeLanguage(lang) {
      this.$i18n.locale = lang;
      localStorage.setItem('language', lang);
    }
  }
};
</script>

Paso 14: Detección de Idioma y Persistencia

Carga la preferencia de idioma guardada al iniciar la app:

src/i18n.js:

import { createI18n } from 'vue-i18n';
import en from './locales/en.json';
import es from './locales/es.json';
import fr from './locales/fr.json';

const messages = {
  en,
  es,
  fr
};

// Obtener idioma guardado o detectar idioma del navegador
const getInitialLocale = () => {
  const saved = localStorage.getItem('language');
  if (saved && messages[saved]) return saved;
  
  const browserLang = navigator.language.split('-')[0];
  return messages[browserLang] ? browserLang : 'en';
};

const i18n = createI18n({
  locale: getInitialLocale(),
  fallbackLocale: 'en',
  messages,
  legacy: false,
  globalInjection: true
});

export default i18n;

Paso 15: Manejar Idiomas de Derecha a Izquierda (RTL)

Para idiomas RTL como árabe y hebreo:

<template>
  <div :dir="textDirection" :lang="currentLocale">
    <!-- Contenido de tu app -->
  </div>
</template>

<script setup>
import { computed, watch } from 'vue';
import { useI18n } from 'vue-i18n';

const { locale } = useI18n();

const currentLocale = computed(() => locale.value);
const isRTL = computed(() => ['ar', 'he', 'fa'].includes(locale.value));
const textDirection = computed(() => isRTL.value ? 'rtl' : 'ltr');

watch(locale, (newLocale) => {
  document.documentElement.dir = isRTL.value ? 'rtl' : 'ltr';
  document.documentElement.lang = newLocale;
}, { immediate: true });
</script>

Mejores Prácticas

1. Usar Claves de Traducción Descriptivas

Malo:

{
  "msg1": "Submit"
}

Bueno:

{
  "button": {
    "submit": "Submit"
  }
}

2. Organizar por Característica

{
  "auth": {
    "login": "Login",
    "logout": "Logout"
  },
  "dashboard": {
    "title": "Dashboard"
  }
}

3. Usar Namespaces

Para apps grandes, divide las traducciones en namespaces:

i18n.js:

import commonEN from './locales/en/common.json';
import authEN from './locales/en/auth.json';

const messages = {
  en: {
    common: commonEN,
    auth: authEN
  }
};

Uso:

<template>
  <p>{{ $t('auth.login') }}</p>
</template>

4. Proporcionar Fallbacks

const i18n = createI18n({
  fallbackLocale: 'en',
  missingWarn: false, // Deshabilitar advertencias en producción
  fallbackWarn: false
});

5. Usar Formateo de Texto Enriquecido

<template>
  <p v-html="$t('welcome', { link: '<a href="/about">here</a>' })"></p>
</template>

Nota: Ten cuidado con v-html por seguridad. Sanitiza la entrada del usuario.

6. Probar Longitudes de Cadenas

Algunos idiomas son más largos que otros. Diseña tu UI para acomodar:

  • Alemán y finlandés: 30-50% más largo que inglés
  • Idiomas asiáticos: Pueden necesitar más espacio vertical

Errores Comunes

1. Olvidar Instalar vue-i18n

Siempre instala la versión correcta:

npm install vue-i18n@9  # Vue 3
npm install vue-i18n@8  # Vue 2

2. No Usar Modo Composition API (Vue 3)

Para Vue 3, usa legacy: false:

const i18n = createI18n({
  legacy: false, // Importante para Vue 3
  // ...
});

3. Codificar Cadenas de Formato Directamente

Malo:

<p>${{ amount.toFixed(2) }}</p>

Bueno:

<p>{{ $n(amount, 'currency') }}</p>

4. No Manejar Traducciones Faltantes

Proporciona fallbacks y maneja claves faltantes con gracia.

Avanzado: Carga Perezosa de Traducciones

Carga traducciones bajo demanda:

const loadLocaleMessages = async (locale) => {
  const messages = await import(`./locales/${locale}.json`);
  i18n.global.setLocaleMessage(locale, messages.default);
  return messages.default;
};

// Uso
await loadLocaleMessages('es');
i18n.global.locale.value = 'es';

Avanzado: Soporte TypeScript

Para mejor soporte TypeScript:

src/types/vue-i18n.d.ts:

import { DefineLocaleMessage } from 'vue-i18n';

declare module 'vue-i18n' {
  export interface DefineLocaleMessage {
    app: {
      welcome: string;
      title: string;
    };
    button: {
      submit: string;
      cancel: string;
      delete: string;
    };
    // ... otros tipos de mensaje
  }
}

Avanzado: Usar con Vue Router

Integra con Vue Router para routing basado en locale:

import { createRouter, createWebHistory } from 'vue-router';
import { useI18n } from 'vue-i18n';

const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/:locale?',
      component: Layout,
      children: [
        {
          path: '',
          name: 'home',
          component: Home
        }
      ]
    }
  ]
});

router.beforeEach((to, from, next) => {
  const locale = to.params.locale || 'en';
  const { locale: i18nLocale } = useI18n();
  
  if (i18nLocale.value !== locale) {
    i18nLocale.value = locale;
  }
  
  next();
});

Avanzado: Usar con Pinia (Gestión de Estado)

Almacena locale en Pinia:

import { defineStore } from 'pinia';
import { useI18n } from 'vue-i18n';

export const useLocaleStore = defineStore('locale', {
  state: () => ({
    currentLocale: 'en'
  }),
  actions: {
    setLocale(locale) {
      this.currentLocale = locale;
      const { locale: i18nLocale } = useI18n();
      i18nLocale.value = locale;
      localStorage.setItem('language', locale);
    }
  }
});

Usar con Nuxt.js

Para aplicaciones Nuxt.js, vue-i18n está integrado:

nuxt.config.js:

export default {
  modules: ['@nuxtjs/i18n'],
  i18n: {
    locales: ['en', 'es', 'fr'],
    defaultLocale: 'en',
    vueI18n: {
      fallbackLocale: 'en',
      messages: {
        en: require('./locales/en.json'),
        es: require('./locales/es.json'),
        fr: require('./locales/fr.json')
      }
    }
  }
};

Conclusión

Localizar tu app Vue.js con vue-i18n es sencillo cuando sigues estos pasos:

  1. Instalar vue-i18n (versión 9 para Vue 3, versión 8 para Vue 2)
  2. Crear archivos JSON de traducción para cada idioma
  3. Configurar vue-i18n con tus mensajes
  4. Usar $t en plantillas o useI18n en Composition API
  5. Manejar pluralización con claves especiales
  6. Formatear fechas y números usando formateadores integrados
  7. Permitir a los usuarios cambiar idiomas
  8. Probar exhaustivamente en todos los idiomas soportados

Siguiendo estas prácticas, crearás una app que proporciona una experiencia nativa para usuarios en todo el mundo, expandiendo significativamente tu base de usuarios potencial.

Optimiza tu Flujo de Trabajo de Localización Vue.js

Gestionar traducciones para múltiples idiomas puede volverse complejo a medida que tu app crece. Considera usar una plataforma de gestión de traducciones para:

  • Colaborar con traductores
  • Mantener traducciones sincronizadas con tu código base
  • Automatizar el flujo de trabajo de traducción
  • Mantener consistencia en todos los idiomas
  • Generar archivos de traducción automáticamente

¿Listo para llevar tu app Vue.js a nivel global? Explora la plataforma de localización de AZbox y optimiza tu flujo de trabajo de traducción:

Ver Planes y Precios de AZbox

Blog

Últimas Publicaciones

Descubre nuestros últimos artículos y actualizaciones.

Servicios de localización de videojuegos: guía 2026 para llevar tu juego al mundo
date icon

21 de febrero de 2026

05 min de lectura

Servicios de localización de videojuegos: guía 2026 para llevar tu juego al mundo

Llevar tu juego a nivel global no es solo traducir texto: es hacer que los jugadores de cada mercado sientan que el jueg

Leer más
Software de localización de apps: guía 2026 para elegir y usar la herramienta adecuada
date icon

20 de febrero de 2026

05 min de lectura

Software de localización de apps: guía 2026 para elegir y usar la herramienta adecuada

Si estás llevando tu app más allá de un solo idioma, el software de localización de apps es la palanca que convierte

Leer más
Traducción para SaaS: Guía Completa para Localizar Tu Producto
date icon

15 de febrero de 2026

04 min de lectura

Traducción para SaaS: Guía Completa para Localizar Tu Producto

La traducción para SaaS ya no es opcional. Si quieres crecer más allá de tu mercado local, necesitas una estrategia

Leer más
Fondo de llamada a la acción

Comienza el Crecimiento Global Hoy

Sube tus archivos de idioma, recibe las traducciones y mantén cada idioma sincronizado mientras tu producto sigue cambiando.

Comenzar - Es Gratis