🎉 v1.0

Get started

  • Welcome
  • Documentation
  • Pricing
    Soon

Tools

  • I18n MCP
  • CLI
  • CI/CD Integrations
  • Compiler
    Alpha
  • Connect Your Engine

Resources

  • Languages
  • LLM Models
  • Guides

Company

  • Enterprise
  • CareersHiring!
Dashboard

Lingo.dev Compiler

  • How it works
  • Setup

Framework Integration

  • Next.js
  • Vite + React

Configuration

  • Configuration Reference
  • Translation Providers
  • Build Modes

Features

  • Manual Overrides
  • Custom Locale Resolvers
  • Automatic Pluralization
  • Locale Switching

Development

  • Development Tools
  • Project Structure

Guides

  • Best Practices
  • Migration Guide
  • Troubleshooting

Next.js Integration

Max PrilutskiyMax Prilutskiy·Updated 5 days ago·3 min read

Alpha

The Lingo.dev Compiler is in alpha. It is unstable, not recommended for production use, and APIs may change between releases.

The Lingo.dev Compiler integrates with Next.js App Router through a withLingo() config wrapper that transforms your build pipeline to produce per-locale bundles. It supports React Server Components, Webpack, and Turbopack with no changes to your component code.

Prerequisites#

Requirements

  • Next.js 14+ with App Router
  • Node.js 18+
  • @lingo.dev/compiler installed

Install#

bash
pnpm install @lingo.dev/compiler

Configure next.config.ts#

Wrap your Next.js config with withLingo. The config function must be async - this is required because withLingo performs asynchronous initialization during the build.

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

Async config required

The config must be exported as an async function, not as a plain object. If you export a plain object, the compiler cannot initialize and the build will fail. See Troubleshooting for details.

Add LingoProvider#

Wrap your root layout with LingoProvider to enable locale context throughout the component tree:

tsx
// 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 handles locale resolution, persistence, and dictionary loading. It works with both Server Components and Client Components.

Server Components and Client Components#

The compiler handles both component types transparently:

Component typeHow translations work
React Server ComponentsTranslations resolved at request time on the server. No client-side JS overhead.
Client Components ("use client")Translations bundled into the client chunk. useLingoContext() available for locale switching.
Shared componentsWork in both contexts. The compiler detects the rendering environment automatically.
tsx
// app/page.tsx - Server Component (default)
export default function Home() {
  return <h1>Welcome to our app</h1>;
  // Renders translated text with zero client JS
}
tsx
// app/components/greeting.tsx - Client Component
"use client";

export function Greeting() {
  return <p>Hello, world</p>;
  // Translations included in client bundle
}

Bundler support#

The withLingo() wrapper works with both bundlers supported by Next.js:

BundlerSupportNotes
WebpackFullDefault bundler. No additional configuration needed.
TurbopackFullEnable with next dev --turbopack. The compiler detects Turbopack automatically.

sourceRoot configuration#

The sourceRoot option tells the compiler which directory contains your translatable components. For Next.js App Router projects, this is typically ./app:

ts
{
  sourceRoot: "./app",
}

If you have components outside ./app (such as a shared components/ directory), set sourceRoot to the common parent:

ts
{
  sourceRoot: ".",
}

A broader sourceRoot means more files are scanned. For large projects, keep it as narrow as possible to reduce build times. Alternatively, use useDirective: true and add 'use i18n' only to files that need translation. See Project Structure for details.

Next Steps#

Setup
Full setup walkthrough with authentication
Configuration Reference
All configuration options
Locale Switching
Add a language switcher to your app
Build Modes
Dev, CI, and production workflows

Was this page helpful?