Интеграция Vite + React

@lingo.dev/compiler интегрируется с Vite через плагин, который работает как с SPA, так и с SSR.

Установка

1. Установите пакет

pnpm install @lingo.dev/compiler

2. Настройте Vite

Добавьте lingoCompilerPlugin в конфиг Vite:

// vite.config.ts
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", "fr"],
      models: "lingo.dev",
      dev: {
        usePseudotranslator: true,
      },
    }),
    react(),
  ],
});

Порядок плагинов: Поместите lingoCompilerPlugin перед плагином react(). Это нужно, чтобы компилятор преобразовал ваш JSX до обработки React.

3. Добавьте Provider

Обверните приложение в LingoProvider в точке входа:

// src/main.tsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { LingoProvider } from "@lingo.dev/compiler/react";
import App from "./App";
import "./index.css";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <LingoProvider>
      <App />
    </LingoProvider>
  </StrictMode>
);

Важно: Разместите LingoProvider как можно выше в дереве компонентов. Если используете TanStack Router или React Router, разместите LingoProvider выше провайдера роутера.

Настройка SPA

Для одностраничных приложений достаточно описанной выше настройки. Локаль управляется на клиенте.

Переключатель языка

"use client";

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

export function LanguageSwitcher() {
  const { locale, setLocale } = useLingoContext();

  return (
    <div>
      <label>Language:</label>
      <select value={locale} onChange={(e) => setLocale(e.target.value)}>
        <option value="en">English</option>
        <option value="es">Español</option>
        <option value="de">Deutsch</option>
        <option value="fr">Français</option>
      </select>
    </div>
  );
}

Настройка SSR (React Router, Remix, TanStack Start)

Для SSR-фреймворков может понадобиться обработка определения локали на сервере.

Кастомное определение локали

Создайте .lingo/locale-resolver.server.ts для серверной логики:

// .lingo/locale-resolver.server.ts
export async function getServerLocale(): Promise<string> {
  // Access request context (framework-specific)
  // Example: parse cookies, headers, or database
  return "en"; // Return detected locale
}

И .lingo/locale-resolver.client.ts для клиентской части:

// .lingo/locale-resolver.client.ts
export function getClientLocale(): string {
  return localStorage.getItem("locale") || "en";
}

export function persistLocale(locale: string): void {
  localStorage.setItem("locale", locale);
}

Смотрите Custom Locale Resolvers для примеров под разные фреймворки.

Интеграция с TanStack Router

Для TanStack Router разместите LingoProvider выше RouterProvider:

// src/main.tsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { RouterProvider, createRouter } from "@tanstack/react-router";
import { LingoProvider } from "@lingo.dev/compiler/react";
import { routeTree } from "./routeTree.gen";

const router = createRouter({ routeTree });

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <LingoProvider>
      <RouterProvider router={router} />
    </LingoProvider>
  </StrictMode>
);

Это гарантирует доступность переводов во всех ваших компонентах с маршрутизацией и не нарушает контекст при разделении кода.

Интеграция с React Router

Для React Router v6/v7:

// src/main.tsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import { LingoProvider } from "@lingo.dev/compiler/react";
import App from "./App";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <LingoProvider>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </LingoProvider>
  </StrictMode>
);

HMR и разработка

Компилятор полностью поддерживает Hot Module Replacement (HMR) в Vite. Когда вы обновляете переводимый текст:

  1. Компилятор обнаруживает изменения
  2. Сервер переводов генерирует новые переводы (или псевдопереводы)
  3. HMR обновляет ваш компонент без полной перезагрузки
  4. Состояние компонента сохраняется

Fast Refresh работает как обычно — компилятор не мешает HMR в Vite.

Конфигурация сборки

Сборка для разработки

{
  dev: {
    usePseudotranslator: true, // Fast fake translations
  }
}

Запустите npm run dev, чтобы сразу видеть результат с псевдопереводами.

Сборка для продакшена

{
  buildMode: "cache-only", // Use pre-generated translations
}

Запустите npm run build. Переводы берутся из .lingo/metadata.json — никакие API-запросы не нужны.

Рекомендуется: генерируйте настоящие переводы в CI перед продакшен-сборкой. Подробнее см. Режимы сборки.

Разделение кода

Компилятор поддерживает разделение кода в Vite. Каждый лениво загружаемый чанк содержит только нужные ему переводы.

// Lazy-loaded route
const Dashboard = lazy(() => import("./pages/Dashboard"));

// Dashboard component's translations are bundled with the Dashboard chunk

Переводы автоматически tree-shaken — в каждый чанк попадают только используемые переводы.

TypeScript

Компилятор полностью типизирован:

import type { LingoConfig } from "@lingo.dev/compiler";

const config: LingoConfig = {
  sourceRoot: "src",
  sourceLocale: "en",
  targetLocales: ["es", "de"],
  models: "lingo.dev",
};

Переменные окружения

Используйте систему переменных окружения Vite для API-ключей:

# .env
VITE_LINGO_API_KEY=your_key_here

Доступ в конфиге:

{
  models: "lingo.dev",
  // API key is automatically read from LINGODOTDEV_API_KEY env variable
}

Никогда не коммитьте API-ключи. Добавьте .env в .gitignore.

Частые проблемы

"Не удаётся найти модуль '@lingo.dev/compiler/react'" Убедитесь, что пакет установлен: pnpm install @lingo.dev/compiler

HMR ломается после добавления LingoProvider Проверьте, что lingoCompilerPlugin стоит перед плагином react() в конфиге Vite.

Переводы не отображаются в проде Проверьте buildMode: "cache-only" и что в .lingo/metadata.json есть переводы для всех локалей.

Контекст ломается при code splitting Убедитесь, что LingoProvider размещён выше вашего router provider (TanStack Router, React Router и т.д.). Иначе маршруты с code-splitting могут потерять контекст.

Порт 60000 уже занят Сервер переводов автоматически ищет свободные порты (60000-60099). Если все заняты, настройте вручную:

{
  dev: {
    translationServerStartPort: 61000, // Use different port range
  }
}

Дальше