Руководство по миграции
Переходите со старого компилятора (lingo.dev/compiler) на новый @lingo.dev/compiler.
Зачем переходить?
Новый компилятор предлагает:
- Лучший DX — Всё автоматом по умолчанию (без
'use i18n') - Лучшая производительность — Быстрее сборка, круче HMR
- Режимы сборки — Разделение dev/CI/prod
- Ручные override'ы — Атрибут
data-lingo-override - Кастомные locale-резолверы — Гибкое определение локали
- Dev-инструменты — Псевдопереводчик, dev-виджет (скоро)
- Чище архитектура — Логичное разделение ответственности
Важные изменения
1. Имя пакета
Было:
npm install lingo.dev
Стало:
npm install @lingo.dev/compiler
2. Пути импорта
Было:
import lingoCompiler from "lingo.dev/compiler";
import { LingoProvider } from "lingo.dev/react/rsc";
Стало:
import { withLingo } from "@lingo.dev/compiler/next";
import { LingoProvider } from "@lingo.dev/compiler/react";
3. API конфигурации
Next.js
Было:
// next.config.js
import lingoCompiler from "lingo.dev/compiler";
export default lingoCompiler.next({
sourceLocale: "en",
targetLocales: ["es", "de"],
models: "lingo.dev",
})(nextConfig);
Стало:
// 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",
});
}
Что поменялось:
- Конфиг теперь должен быть async-функцией
- Новый параметр
sourceRoot - Обёртка
withLingoвместоlingoCompiler.next
Vite
Было:
import lingoCompiler from "lingo.dev/compiler";
export default defineConfig(() =>
lingoCompiler.vite({
sourceRoot: "src",
targetLocales: ["es", "de"],
models: "lingo.dev",
})(viteConfig)
);
Новое:
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(),
],
});
Изменения:
- Теперь используется плагин вместо обёртки конфига
- Теперь обязательно указывать
sourceLocale - Разместите перед плагином
react()
4. Настройка провайдера
Старое:
import { LingoProvider, loadDictionary } from "lingo.dev/react/rsc";
export default function Layout({ children }) {
return (
<LingoProvider loadDictionary={(locale) => loadDictionary(locale)}>
{children}
</LingoProvider>
);
}
Новое:
import { LingoProvider } from "@lingo.dev/compiler/react";
export default function Layout({ children }) {
return (
<LingoProvider>
{children}
</LingoProvider>
);
}
Изменения:
- Нет пропса
loadDictionary— теперь всё внутри - Более простой API
5. Структура файлов
Старое:
lingo/
├── dictionary.js
├── meta.json
└── [locale]/
└── *.json
Новое:
.lingo/
└── metadata.json
Изменения:
- Папка переименована (
.lingoпротивlingo) - Один файл метаданных вместо нескольких
- Другая структура JSON
6. Директива "use i18n"
Старое: Требуется по умолчанию. Добавляйте во все файлы, которые хотите перевести:
'use i18n';
export function Component() { ... }
Новое: Необязательно. По умолчанию все файлы переводятся автоматически. Чтобы включить вручную:
{
useDirective: true, // Enable opt-in behavior
}
Потом добавьте директиву:
'use i18n';
export function Component() { ... }
Шаги миграции
Шаг 1: Обновите пакет
# Uninstall old package
npm uninstall lingo.dev
# Install new package
npm install @lingo.dev/compiler
Шаг 2: Обновите конфигурацию
Next.js
До:
// next.config.js
import lingoCompiler from "lingo.dev/compiler";
export default lingoCompiler.next({
sourceLocale: "en",
targetLocales: ["es", "de"],
models: "lingo.dev",
})(nextConfig);
После:
// 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
До:
import lingoCompiler from "lingo.dev/compiler";
export default defineConfig(() =>
lingoCompiler.vite({
sourceRoot: "src",
targetLocales: ["es", "de"],
models: "lingo.dev",
})(viteConfig)
);
После:
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(),
],
});
Шаг 3: Обновите провайдер
До:
import { LingoProvider, loadDictionary } from "lingo.dev/react/rsc";
export default function Layout({ children }) {
return (
<LingoProvider loadDictionary={(locale) => loadDictionary(locale)}>
{children}
</LingoProvider>
);
}
После:
import { LingoProvider } from "@lingo.dev/compiler/react";
export default function Layout({ children }) {
return (
<LingoProvider>
{children}
</LingoProvider>
);
}
Шаг 4: Удалите старые файлы
# Backup old translations (optional)
mv lingo lingo.backup
# Remove old directory
rm -rf lingo
# New directory will be created automatically
# on first build
Шаг 5: Проверьте с помощью псевдопереводчика
npm run dev
С usePseudotranslator: true вы сразу увидите фейковые переводы. Проверьте:
- Весь нужный текст переведён
- Нет ошибок компиляции
- Верстка справляется с разной длиной текста
Шаг 6: Сгенерируйте реальные переводы
Обновите конфиг, чтобы отключить псевдопереводчик:
{
dev: {
usePseudotranslator: false,
}
}
Перезапустите dev-сервер. Компилятор сгенерирует реальные переводы для любого нового или изменённого текста.
Шаг 7: Зафиксируйте новые переводы
git add .lingo/
git commit -m "chore: migrate to @lingo.dev/compiler"
git push
Сопоставление функций
Старые функции → Новые эквиваленты
| Старая функция | Новый эквивалент | Примечания |
|---|---|---|
dictionary.js | .lingo/metadata.json | Другой формат |
meta.json | .lingo/metadata.json | Объединено в один файл |
| "use i18n" (обязательно) | "use i18n" (необязательно) | Теперь по желанию, не обязательно |
| Custom prompts | prompt config option | Та же функциональность |
| Редактирование переводов | data-lingo-override | Переопределения на основе атрибутов |
| Пропуск переводов | data-lingo-override + пусто | Или используйте useDirective |
| Переопределение переводов | data-lingo-override | На основе атрибутов |
| Переключение локалей | useLingoContext() | Возвращает { locale, setLocale } |
| LLM-провайдеры | models config | Поддерживаются те же провайдеры |
Новые функции (не было в старом компиляторе)
- Режимы сборки —
translatevscache-only - Псевдопереводчик — Мгновенные фейковые переводы
- Виджет для разработки — Редактирование прямо в браузере (скоро)
- Пользовательские резолверы локалей — Гибкое определение локали
- Автоматическое склонение по числу — Поддержка ICU MessageFormat
- Сервер переводов — Переводы по запросу в режиме разработки
Перевод существующих переводов
Новый компилятор использует другой формат файлов. Существующие переводы не мигрируются автоматически.
Варианты:
Вариант 1: Перегенерировать все переводы
Пусть компилятор создаст новые переводы с нуля:
- Удалите старую директорию
lingo/ - Запустите новый компилятор
- Сгенерируйте переводы с помощью AI
Плюсы: Чистый старт, свежие AI-модели Минусы: Стоимость API, возможна потеря нюансов
Вариант 2: ручной скрипт миграции
Напишите скрипт для конвертации старого формата в новый:
// 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));
Это ручная работа и зависит от формата.
Вариант 3: гибридный подход
- Сгенерируйте новые переводы для большинства текстов
- Используйте
data-lingo-overrideдля важных переводов, где нужна точная формулировка
Частые проблемы
"Cannot find module '@lingo.dev/compiler'"
Выполните npm install @lingo.dev/compiler
"Config must be async function" (Next.js)
Обёрните ваш config в async function:
export default async function () {
return await withLingo(...);
}
"sourceLocale is required"
Добавьте sourceLocale: "en" в ваш config.
Переводы не отображаются Проверьте:
LingoProviderнаходится в корневом layout.lingo/metadata.jsonсуществует- Нет ошибок в консоли
FAQ
Можно ли запускать оба компилятора одновременно? Нет. Удалите старый компилятор перед установкой нового.
Я потеряю свои переводы? Нет, если перенесёте их вручную. Иначе — пересоздайте с помощью AI (тратятся API кредиты).
Что если мой фреймворк ещё не поддерживается? Новый компилятор сейчас поддерживает только Next.js и Vite. Другие фреймворки появятся позже. Пока используйте старый компилятор или добавьте поддержку самостоятельно.
Сколько времени занимает миграция?
- Простой проект: 15–30 минут
- Сложный проект: 1–2 часа
- Больше всего времени уходит на тестирование и проверку переводов
Стоит ли мигрировать сейчас или подождать? Мигрируйте, если:
- Нужны новые фичи (build-режимы, overrides, кастомные резолверы)
- Начинаете новый проект
- Хотите лучший DX
Подождите, если:
- Ваш проект отлично работает со старым компилятором
- Вам нужны фреймворки, которые пока не поддерживаются новым компилятором
Что дальше
- Быстрый старт — настройте новый компилятор
- Справочник по конфигурации — изучите все опции
- Лучшие практики — рекомендуемые рабочие процессы
- Устранение неполадок — частые проблемы