Quick Start

Add multilingual support to your React app in under 5 minutes.

Prerequisites

  • Node.js 18+
  • React application using Next.js (App Router) or Vite

Installation

pnpm install @lingo.dev/compiler

Configuration

Next.js

Make your config async and wrap it with withLingo:

// 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"],
    models: "lingo.dev",
    dev: {
      usePseudotranslator: true, // Fake translations for development
    },
  });
}

Vite

Add the Lingo plugin to your Vite config:

// vite.config.ts
import { defineConfig } from "vite";
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,
      },
    }),
    // ...other plugins
  ],
});

Setup Provider

Next.js

Wrap your app with LingoProvider in your root 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>
  );
}

Vite

Wrap your app with LingoProvider in your entry point:

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

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

Authentication

The compiler uses Lingo.dev Engine by default for translations.

Sign up at lingo.dev and authenticate:

npx lingo.dev@latest login

This saves your API key locally. The free Hobby tier is sufficient for most projects.

Having authentication issues? If your browser is blocking the auth flow, manually add your API key to .env:

LINGODOTDEV_API_KEY=your_key_here

Find your API key in the Lingo.dev project settings.

Option 2: Direct LLM Provider

Alternatively, use any supported LLM provider directly. Update your config:

{
  models: {
    "*:*": "groq:llama-3.3-70b-versatile",
    // or "google:gemini-2.0-flash"
    // or "openai:gpt-4o"
    // or "anthropic:claude-3-5-sonnet"
  }
}

Add the corresponding API key to .env:

GROQ_API_KEY=your_key
# or GOOGLE_API_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY

See Translation Providers for all supported providers.

Run Development Server

Start your dev server:

npm run dev

The compiler will:

  1. Scan your JSX for translatable text
  2. Generate pseudotranslations (fake translations to visualize what gets translated)
  3. Inject them into your components
  4. Store metadata in .lingo/metadata.json

Why pseudotranslations? They're instant (no API calls), show exactly what gets translated, and help test your UI with varying text lengths—all without spending API credits.

Test Translation

Add a simple component:

export function Welcome() {
  return (
    <div>
      <h1>Welcome to our app</h1>
      <p>This text will be translated automatically</p>
    </div>
  );
}

No code changes needed—text is automatically extracted and translated.

Add Language Switcher (Optional)

Let users change languages:

"use client"; // For Next.js

import { useLocale, setLocale } from "@lingo.dev/compiler/react";

export function LanguageSwitcher() {
  const locale = useLocale();

  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>
      <option value="fr">Français</option>
    </select>
  );
}

Generate Real Translations

When ready for real translations, update your config:

{
  dev: {
    usePseudotranslator: false, // Disable fake translations
  }
}

Restart your dev server. The compiler will now generate real AI translations for any new or changed text.

Cost-conscious? Pseudotranslations are free and instant. Only disable them when you need to review actual translation quality.

Common Questions

Do I need to mark every translatable string? No. The compiler automatically detects JSX text. To opt-in instead, set useDirective: true and add 'use i18n' at the top of files you want to translate.

What about dynamic content or props? The compiler handles string attributes like alt, aria-label, and placeholder automatically. For dynamic text, use template syntax: <p>Hello {name}</p> works as expected.

Can I customize specific translations? Yes. Use the data-lingo-override attribute:

<h1 data-lingo-override={{ es: "Bienvenido", de: "Willkommen" }}>
  Welcome
</h1>

How do I commit translations? Commit the .lingo/ directory to version control. It contains metadata and cached translations—safe to commit and should be versioned alongside your code.

Next Steps