Интеграция с Next.js
@lingo.dev/compiler интегрируется с Next.js App Router через асинхронный конфигуратор, который поддерживает и Webpack, и Turbopack.
Установка
1. Установите пакет
pnpm install @lingo.dev/compiler
2. Настройте Next.js
Обновите ваш next.config.ts, чтобы использовать асинхронный обёртчик withLingo():
import type { NextConfig } from "next";
import { withLingo } from "@lingo.dev/compiler/next";
const nextConfig: NextConfig = {
// Your existing Next.js config
};
export default async function (): Promise<NextConfig> {
return await withLingo(nextConfig, {
sourceRoot: "./app",
sourceLocale: "en",
targetLocales: ["es", "de", "fr"],
models: "lingo.dev",
dev: {
usePseudotranslator: true,
},
});
}
Почему async? Обёртка лениво загружает плагины и динамически подбирает конфиг. Это ускоряет сборку и позволяет подключать плагины по необходимости.
3. Добавьте провайдер
Обверните приложение в LingoProvider в корневом layout:
// app/layout.tsx
import { LingoProvider } from "@lingo.dev/compiler/react";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<LingoProvider>
<html>
<body>{children}</body>
</html>
</LingoProvider>
);
}
Важно: Поместите LingoProvider внутрь <html>, оборачивая весь контент. Работает и с Server, и с Client Components.
React Server Components
Компилятор полностью поддерживает React Server Components (RSC). Серверные компоненты переводятся на этапе сборки, а переводы встраиваются в серверный вывод.
// app/page.tsx (Server Component)
export default function Page() {
return (
<div>
<h1>Welcome to our app</h1>
<p>This is a server component—translated at build time</p>
</div>
);
}
Для переведённого текста в Server Components не добавляется JS на клиенте.
Client Components
Для Client Components используйте директиву "use client":
"use client";
import { useLingoContext } from "@lingo.dev/compiler/react";
export function LanguageSwitcher() {
const { locale, setLocale } = useLingoContext();
return (
<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>
</select>
);
}
Client Components получают оптимизированные translation-бандлы. Включаются только переводы, используемые в этом компоненте.
Определение локали
По умолчанию локаль хранится в cookie (locale). Компилятор сам определяет и сохраняет локаль.
Кастомное определение локали на сервере
Для своей логики (база, заголовки, поддомен) создайте .lingo/locale-resolver.server.ts:
// .lingo/locale-resolver.server.ts
import { headers } from "next/headers";
export async function getServerLocale(): Promise<string> {
const headersList = await headers();
const acceptLanguage = headersList.get("accept-language");
// Parse accept-language header
const locale = acceptLanguage?.split(",")[0]?.split("-")[0] || "en";
return locale;
}
Эта функция вызывается на сервере для каждого запроса. Она должна возвращать код локали (например, "en", "es").
Кастомное сохранение локали на клиенте
Для своей логики на клиенте (localStorage, параметры URL) создайте .lingo/locale-resolver.client.ts:
// .lingo/locale-resolver.client.ts
export function getClientLocale(): string {
// Check URL parameter first
const params = new URLSearchParams(window.location.search);
const urlLocale = params.get("lang");
if (urlLocale) return urlLocale;
// Fall back to localStorage
return localStorage.getItem("locale") || "en";
}
export function persistLocale(locale: string): void {
localStorage.setItem("locale", locale);
// Optionally update URL
const url = new URL(window.location.href);
url.searchParams.set("lang", locale);
window.history.replaceState({}, "", url.toString());
}
Подробнее см. в разделе Custom Locale Resolvers.
Middleware для маршрутизации по локали
Если хотите маршрутизацию по локали (/en/about, /es/about), реализуйте middleware Next.js:
// middleware.ts
import { NextRequest, NextResponse } from "next/server";
const locales = ["en", "es", "de", "fr"];
const defaultLocale = "en";
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// Check if pathname already has a locale
const pathnameHasLocale = locales.some(
(locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
);
if (pathnameHasLocale) return;
// Get locale from cookie or accept-language header
const localeCookie = request.cookies.get("locale")?.value;
const acceptLanguage = request.headers.get("accept-language");
const locale =
localeCookie ||
acceptLanguage?.split(",")[0]?.split("-")[0] ||
defaultLocale;
// Redirect to localized pathname
request.nextUrl.pathname = `/${locale}${pathname}`;
return NextResponse.redirect(request.nextUrl);
}
export const config = {
matcher: ["/((?!api|_next|_vercel|.*\\..*).*)"],
};
Обновите свои маршруты, чтобы использовать динамический сегмент [locale]:
app/
[locale]/
page.tsx
about/
page.tsx
layout.tsx
Конфигурация сборки
Сборка для разработки
{
dev: {
usePseudotranslator: true, // Fast fake translations
}
}
Запустите npm run dev, чтобы стартовать dev-сервер с мгновенными псевдопереводами.
Сборка для продакшена
{
buildMode: "cache-only", // Use pre-generated translations
}
Запустите npm run build для сборки продакшена. API-ключи не нужны — переводы берутся из .lingo/metadata.json.
Лучше всего: генерируйте реальные переводы в CI перед продакшен-сборкой. См. Build Modes для рекомендуемого workflow.
Поддержка Turbopack
Компилятор работает и с Webpack, и с Turbopack (Next.js 15+).
Чтобы использовать Turbopack в разработке:
next dev --turbo
Компилятор сам определяет и настраивает нужный бандлер.
TypeScript
Компилятор полностью типизирован. Импортируйте типы из @lingo.dev/compiler:
import type { LingoConfig } from "@lingo.dev/compiler";
const config: LingoConfig = {
sourceRoot: "./app",
sourceLocale: "en",
targetLocales: ["es", "de"],
models: "lingo.dev",
};
Частые проблемы
"Cannot find module '@lingo.dev/compiler/react'"
Убедитесь, что вы установили пакет: pnpm install @lingo.dev/compiler
HMR не работает после добавления LingoProvider
Проверьте, что LingoProvider находится в корневом layout, а не во вложенном layout или странице.
Переводы не отображаются в production-сборке
Проверьте, что вы используете buildMode: "cache-only" и что в .lingo/metadata.json есть переводы для всех локалей.
"Отсутствуют переводы для локали X"
Запустите dev-сервер с usePseudotranslator: false, чтобы сгенерировать настоящие переводы, или выполните CI-сборку, чтобы заполнить .lingo/metadata.json.
Дальнейшие шаги
- Справочник по конфигурации — все параметры конфигурации
- Пользовательские резолверы локалей — настройка определения локали
- Ручные переопределения — переопределение отдельных переводов
- Лучшие практики — рекомендуемые подходы и рабочие процессы