Guía de migración

Migra del antiguo compilador (lingo.dev/compiler) al nuevo @lingo.dev/compiler.

¿Por qué migrar?

El nuevo compilador ofrece:

  • Mejor DX — Automático por defecto (no requiere 'use i18n')
  • Mejor rendimiento — Compilaciones más rápidas, mejor HMR
  • Modos de compilación — Separación de preocupaciones dev/CI/prod
  • Anulaciones manuales — Atributo data-lingo-override
  • Resolvedores de locale personalizados — Detección de locale flexible
  • Herramientas de desarrollo — Pseudotraductor, widget de desarrollo (próximamente)
  • Arquitectura más limpia — Mejor separación de responsabilidades

Cambios incompatibles

1. Nombre del paquete

Antiguo:

npm install lingo.dev

Nuevo:

npm install @lingo.dev/compiler

2. Rutas de importación

Antiguo:

import lingoCompiler from "lingo.dev/compiler";
import { LingoProvider } from "lingo.dev/react/rsc";

Nuevo:

import { withLingo } from "@lingo.dev/compiler/next";
import { LingoProvider } from "@lingo.dev/compiler/react";

3. API de configuración

Next.js

Antiguo:

// next.config.js
import lingoCompiler from "lingo.dev/compiler";

export default lingoCompiler.next({
  sourceLocale: "en",
  targetLocales: ["es", "de"],
  models: "lingo.dev",
})(nextConfig);

Nuevo:

// next.config.ts
import { withLingo } from "@lingo.dev/compiler/next";

export default async function (): Promise<NextConfig> {
  return await withLingo(nextConfig, {
    sourceRoot: "./app", // New: specify source directory
    sourceLocale: "en",
    targetLocales: ["es", "de"],
    models: "lingo.dev",
  });
}

Cambios:

  • La configuración debe ser una función asíncrona
  • Nueva opción sourceRoot
  • Wrapper withLingo en lugar de lingoCompiler.next

Vite

Antiguo:

import lingoCompiler from "lingo.dev/compiler";

export default defineConfig(() =>
  lingoCompiler.vite({
    sourceRoot: "src",
    targetLocales: ["es", "de"],
    models: "lingo.dev",
  })(viteConfig)
);

Nuevo:

import { lingoCompilerPlugin } from "@lingo.dev/compiler/vite";

export default defineConfig({
  plugins: [
    lingoCompilerPlugin({
      sourceRoot: "src",
      sourceLocale: "en", // New: required
      targetLocales: ["es", "de"],
      models: "lingo.dev",
    }),
    react(),
  ],
});

Cambios:

  • Basado en plugins en lugar de wrapper de configuración
  • sourceLocale ahora es obligatorio
  • Colocar antes del plugin react()

4. Configuración del proveedor

Antiguo:

import { LingoProvider, loadDictionary } from "lingo.dev/react/rsc";

export default function Layout({ children }) {
  return (
    <LingoProvider loadDictionary={(locale) => loadDictionary(locale)}>
      {children}
    </LingoProvider>
  );
}

Nuevo:

import { LingoProvider } from "@lingo.dev/compiler/react";

export default function Layout({ children }) {
  return (
    <LingoProvider>
      {children}
    </LingoProvider>
  );
}

Cambios:

  • Sin prop loadDictionary—se gestiona internamente
  • API más simple

5. Estructura de archivos

Antiguo:

lingo/
├── dictionary.js
├── meta.json
└── [locale]/
    └── *.json

Nuevo:

.lingo/
└── metadata.json

Cambios:

  • Directorio renombrado (.lingo vs lingo)
  • Un único archivo de metadatos en lugar de múltiples archivos
  • Estructura JSON diferente

6. Directiva "use i18n"

Antiguo: Obligatoria por defecto. Añadir a cada archivo que quieras traducir:

'use i18n';

export function Component() { ... }

Nuevo: Opcional. Por defecto, todos los archivos se traducen automáticamente. Para activar el modo opt-in:

{
  useDirective: true, // Enable opt-in behavior
}

Luego añadir la directiva:

'use i18n';

export function Component() { ... }

Pasos de migración

Paso 1: Actualizar el paquete

# Uninstall old package
npm uninstall lingo.dev

# Install new package
npm install @lingo.dev/compiler

Paso 2: actualizar configuración

Next.js

Antes:

// next.config.js
import lingoCompiler from "lingo.dev/compiler";

export default lingoCompiler.next({
  sourceLocale: "en",
  targetLocales: ["es", "de"],
  models: "lingo.dev",
})(nextConfig);

Después:

// next.config.ts
import type { NextConfig } from "next";
import { withLingo } from "@lingo.dev/compiler/next";

const nextConfig: NextConfig = {};

export default async function (): Promise<NextConfig> {
  return await withLingo(nextConfig, {
    sourceRoot: "./app",
    sourceLocale: "en",
    targetLocales: ["es", "de"],
    models: "lingo.dev",
    dev: {
      usePseudotranslator: true, // Recommended for development
    },
  });
}

Vite

Antes:

import lingoCompiler from "lingo.dev/compiler";

export default defineConfig(() =>
  lingoCompiler.vite({
    sourceRoot: "src",
    targetLocales: ["es", "de"],
    models: "lingo.dev",
  })(viteConfig)
);

Después:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { lingoCompilerPlugin } from "@lingo.dev/compiler/vite";

export default defineConfig({
  plugins: [
    lingoCompilerPlugin({
      sourceRoot: "src",
      sourceLocale: "en",
      targetLocales: ["es", "de"],
      models: "lingo.dev",
      dev: {
        usePseudotranslator: true,
      },
    }),
    react(),
  ],
});

Paso 3: actualizar proveedor

Antes:

import { LingoProvider, loadDictionary } from "lingo.dev/react/rsc";

export default function Layout({ children }) {
  return (
    <LingoProvider loadDictionary={(locale) => loadDictionary(locale)}>
      {children}
    </LingoProvider>
  );
}

Después:

import { LingoProvider } from "@lingo.dev/compiler/react";

export default function Layout({ children }) {
  return (
    <LingoProvider>
      {children}
    </LingoProvider>
  );
}

Paso 4: limpiar archivos antiguos

# Backup old translations (optional)
mv lingo lingo.backup

# Remove old directory
rm -rf lingo

# New directory will be created automatically
# on first build

Paso 5: probar con Pseudotranslator

npm run dev

Con usePseudotranslator: true, verás traducciones falsas instantáneas. Verifica:

  • Todo el texto esperado está traducido
  • No hay errores de compilación
  • El diseño maneja longitudes de texto variables

Paso 6: generar traducciones reales

Actualiza la configuración para desactivar el pseudotranslator:

{
  dev: {
    usePseudotranslator: false,
  }
}

Reinicia el servidor de desarrollo. El compilador generará traducciones reales para cualquier texto nuevo o modificado.

Paso 7: Confirmar nuevas traducciones

git add .lingo/
git commit -m "chore: migrate to @lingo.dev/compiler"
git push

Mapeo de funcionalidades

Funcionalidades antiguas → Nuevos equivalentes

Función antiguaEquivalente nuevoNotas
dictionary.js.lingo/metadata.jsonFormato diferente
meta.json.lingo/metadata.jsonFusionado en un solo archivo
"use i18n" (obligatorio)"use i18n" (opcional)Ahora es opcional, no obligatorio
Prompts personalizadosOpción de configuración promptMisma funcionalidad
Editar traduccionesdata-lingo-overrideSobrescrituras basadas en atributos
Omitir traduccionesdata-lingo-override + vacíoO usar useDirective
Sobrescribir traduccionesdata-lingo-overrideBasado en atributos
Cambiar idiomasuseLingoContext()Devuelve { locale, setLocale }
Proveedores LLMConfiguración modelsMismos proveedores compatibles

Nuevas funcionalidades (no disponibles en el compilador antiguo)

  • Modos de compilacióntranslate vs cache-only
  • Pseudotraductor — Traducciones falsas instantáneas
  • Widget de desarrollo — Edición en el navegador (próximamente)
  • Resolvedores de locale personalizados — Detección flexible de locale
  • Pluralización automática — Soporte para ICU MessageFormat
  • Servidor de traducción — Traducciones bajo demanda en desarrollo

Traducir traducciones existentes

El nuevo compilador utiliza un formato de archivo diferente. Las traducciones existentes no se migran automáticamente.

Opciones:

Opción 1: Regenerar todas las traducciones

Permitir que el compilador genere traducciones nuevas:

  1. Eliminar el directorio antiguo lingo/
  2. Ejecutar el nuevo compilador
  3. Generar traducciones usando IA

Ventajas: Comienzo limpio, modelos de IA más recientes Desventajas: Costos de API, posible pérdida de matices

Opción 2: Script de migración manual

Crear un script para convertir el formato antiguo al nuevo:

// migrate-translations.ts
import * as fs from "fs";

const oldDir = "./lingo";
const newFile = "./.lingo/metadata.json";

// Read old translations
const oldTranslations = {}; // Parse old files

// Convert to new format
const newMetadata = {
  version: "1",
  sourceLocale: "en",
  targetLocales: ["es", "de"],
  translations: {}, // Convert old translations
};

// Write new metadata
fs.writeFileSync(newFile, JSON.stringify(newMetadata, null, 2));

Esto requiere trabajo manual y es específico del formato.

Opción 3: Enfoque híbrido

  1. Generar nuevas traducciones para la mayoría del texto
  2. Usar data-lingo-override para traducciones críticas que necesiten redacción exacta

Problemas comunes

"Cannot find module '@lingo.dev/compiler'" Ejecutar npm install @lingo.dev/compiler

"Config must be async function" (Next.js) Envolver tu configuración en async function:

export default async function () {
  return await withLingo(...);
}

"sourceLocale is required" Añadir sourceLocale: "en" a tu configuración.

Las traducciones no se muestran Verificar:

  1. LingoProvider está en el layout raíz
  2. .lingo/metadata.json existe
  3. No hay errores en la consola

Preguntas frecuentes

¿Puedo ejecutar ambos compiladores simultáneamente? No. Desinstalar el compilador antiguo antes de instalar el nuevo.

¿Pierdo mis traducciones? No si las migras manualmente. De lo contrario, regenerar usando IA (cuesta créditos de API).

¿Qué pasa si mi framework aún no es compatible? El nuevo compilador actualmente soporta Next.js y Vite. Otros frameworks próximamente. Continuar usando el compilador antiguo o contribuir con soporte para tu framework.

¿Cuánto tiempo tarda la migración?

  • Proyecto simple: 15-30 minutos
  • Proyecto complejo: 1-2 horas
  • La mayor parte del tiempo es probar y verificar las traducciones

¿Debo migrar ahora o esperar? Migrar cuando:

  • Necesites nuevas funcionalidades (modos de compilación, sobrescrituras, resolvers personalizados)
  • Estés iniciando un nuevo proyecto
  • Quieras mejor experiencia de desarrollo

Esperar si:

  • Tu proyecto funciona bien con el compilador antiguo
  • Necesitas frameworks aún no soportados por el nuevo compilador

Próximos pasos