Saltar al contenido principal

[Lv3] Nuxt 3 Multilenguaje (i18n) y mejores prácticas de SEO

Implementar multilenguaje (Internationalization) bajo una arquitectura SSR no solo implica traducir texto, sino también estrategias de enrutamiento, etiquetas SEO (hreflang), gestión de estado y consistencia de Hydration.


1. Puntos clave de respuesta en entrevista

  1. Estrategia de enrutamiento: Usar la estrategia de prefijo URL de @nuxtjs/i18n (como /en/about, /jp/about) para distinguir idiomas. Esto es lo más amigable para SEO.
  2. Etiquetas SEO: Asegurar la generación automática correcta de <link rel="alternate" hreflang="..." /> y Canonical URL, evitando penalizaciones por contenido duplicado.
  3. Gestión de estado: Detectar correctamente el idioma del usuario en la fase SSR (Cookie/Header) y asegurar que el idioma sea consistente durante la Hydration del Client.

2. Estrategia de implementación de i18n en Nuxt 3

2.1 Por qué elegir @nuxtjs/i18n?

El módulo oficial @nuxtjs/i18n esta basado en vue-i18n, optimizado especificamente para Nuxt. Resuelve los problemas comunes de implementar i18n manualmente:

  • Generación automática de rutas con prefijo de idioma (Auto-generated routes).
  • Manejo automático de SEO Meta Tags (hreflang, og:locale).
  • Soporte para Lazy Loading de paquetes de idiomas (optimización del Bundle Size).

2.2 Instalación y configuración

npm install @nuxtjs/i18n
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxtjs/i18n'],
i18n: {
locales: [
{ code: 'en', iso: 'en-US', file: 'en.json', name: 'English' },
{ code: 'tw', iso: 'zh-TW', file: 'tw.json', name: '繁體中文' },
],
defaultLocale: 'tw',
lazy: true, // Habilitar Lazy Loading
langDir: 'locales', // Directorio de archivos de idioma
strategy: 'prefix_and_default', // Estrategia de enrutamiento clave
detectBrowserLanguage: {
useCookie: true,
cookieKey: 'i18n_redirected',
redirectOn: 'root', // Solo detectar y redirigir en la ruta raiz
},
},
});

2.3 Estrategia de enrutamiento (Routing Strategy)

Esta es la clave para SEO. @nuxtjs/i18n ofrece varias estrategias:

  1. prefix_except_default (recomendado):

    • El idioma predeterminado (tw) sin prefijo: example.com/about
    • Otros idiomas (en) con prefijo: example.com/en/about
    • Ventaja: URL limpia, peso SEO concentrado.
  2. prefix_and_default:

    • Todos los idiomas con prefijo: example.com/tw/about, example.com/en/about
    • Ventaja: Estructura uniforme, fácil manejo de redireccionamientos.
  3. no_prefix (no recomendado para SEO):

    • Todos los idiomas con la misma URL, cambio por Cookie.
    • Desventaja: Los motores de búsqueda no pueden indexar las diferentes versiones de idioma.

3. Implementación clave de SEO

3.1 Etiqueta hreflang

Los motores de búsqueda necesitan saber "qué versiones de idioma tiene esta página". @nuxtjs/i18n genera automáticamente en <head>:

<link rel="alternate" href="https://example.com/about" hreflang="zh-TW" />
<link rel="alternate" href="https://example.com/en/about" hreflang="en-US" />
<link rel="alternate" href="https://example.com/about" hreflang="x-default" />

Nota: Se debe configurar baseUrl en nuxt.config.ts, de lo contrario hreflang generara rutas relativas (inválidas).

export default defineNuxtConfig({
i18n: {
baseUrl: 'https://example.com', // Debe configurarse!
},
});

3.2 Canonical URL

Asegurar que cada versión de idioma de la página tenga un Canonical URL que apunte a si misma, evitando ser considerada contenido duplicado.

3.3 Traduccion de contenido dinámico (API)

La API backend también necesita soportar multilenguaje. Normalmente se incluye el header Accept-Language en las solicitudes.

// composables/useApi.ts
export const useApi = (url: string) => {
const { locale } = useI18n();
return useFetch(url, {
headers: {
'Accept-Language': locale.value, // Enviar idioma actual al backend
},
});
};

4. Desafios comunes y soluciones

4.1 Hydration Mismatch

Problema: El Server detecta ingles y renderiza HTML en ingles; el navegador del Client tiene chino como predeterminado, Vue i18n se inicializa en chino, causando parpadeo de pantalla o Hydration Error.

Solución:

  • Usar la configuración detectBrowserLanguage para que el Client al inicializarse respete la configuración de URL o Cookie, en lugar de la configuración del navegador.
  • Asegurar que la configuración de defaultLocale del Server y Client sea consistente.

4.2 Cambio de idioma

Usar switchLocalePath para generar enlaces en lugar de construir cadenas manualmente.

<script setup>
const switchLocalePath = useSwitchLocalePath();
</script>

<template>
<nav>
<NuxtLink :to="switchLocalePath('en')">English</NuxtLink>
<NuxtLink :to="switchLocalePath('tw')">繁體中文</NuxtLink>
</nav>
</template>

5. Puntos clave para la entrevista

5.1 i18n y SEO

Q: Qué hay que tener en cuenta con multilenguaje (i18n) en un entorno SSR? Cómo manejar el SEO?

Ejemplo de respuesta: Al hacer i18n en un entorno SSR, lo más importante es el SEO y la consistencia de Hydration.

Sobre SEO:

  1. Estructura de URL: Uso la estrategia de "subruta" (como /en/, /tw/), dando a cada idioma una URL independiente para que los motores de búsqueda puedan indexar.
  2. hreflang: Se debe configurar correctamente <link rel="alternate" hreflang="..." />, indicando a Google que estas páginas son versiones en diferentes idiomas del mismo contenido, evitando penalizaciones por contenido duplicado. Normalmente uso el módulo @nuxtjs/i18n para generar automáticamente estas etiquetas.

Sobre Hydration: Asegurar que el idioma renderizado por el Server y el idioma inicializado por el Client sean consistentes. Configuro la determinación del idioma desde el prefijo URL o Cookie, y agrego el locale correspondiente en el header de solicitudes API.

5.2 Enrutamiento y estado

Q: Cómo implementar la funcionalidad de cambio de idioma?

Ejemplo de respuesta: Uso el composable useSwitchLocalePath proporcionado por @nuxtjs/i18n. Genera automáticamente la URL del idioma correspondiente basándose en la ruta actual (manteniendo query parameters), y maneja la conversión de prefijos de ruta. Esto evita errores de concatenacion manual de cadenas, y asegura que el usuario permanezca en el contenido de la página original al cambiar de idioma.


6. Reference