@weglot/translate-react

Translate your
React, Next.js or Vite app

No t() wrappers, no JSON files. Add a build plugin and a Weglot API key: the text in your JSX is translated when your app builds, and your team edits translations in Weglot without touching code.

Get your API key

// what your users see

The JSX you wrote, in every language

Write the text once. Weglot translates it at build time.

enSave changessource
deÄnderungen speichern
frEnregistrer
ja変更を保存
arحفظ التغييراتRTL

Same button, five languages. Widths measured live.

app/settings/page.tsx
export default function Settings() {
  return (
    <button>Save changes</button>
  );
}

// no key, no t(), no en.json

No keys, no t(). Write the text in JSX, that is it.

0t() calls to add
0translation files to maintain
1npm install
2code edits: plugin and provider

// how it works

Four steps. Your components stay as they are.

Source and target languages come from your Weglot project, not from your code. The plugin reads the text in your JSX at build time and fetches its translations.

  1. Install the package and add your API key

    Create a Weglot 2.0 project, then copy its API key from the project settings. It starts with pk_. Keep .env out of version control.

    terminal · .env
    $ npm install @weglot/translate-react
    
    # .env
    WEGLOT_API_KEY=pk_your_weglot_api_key
  2. Add the plugin

    Wrap your Next.js config with withWeglot. Point sourceRoot to the folder that holds your pages and components.

    next.config.ts
    import type { NextConfig } from "next";
    import { withWeglot } from "@weglot/translate-react/next";
    
    const nextConfig: NextConfig = {};
    
    export default async function (): Promise<NextConfig> {
      return await withWeglot(nextConfig, { sourceRoot: "./app" });
    }
  3. Add the provider

    Wrap your root layout with WeglotProvider from the Next.js entry point, so that changing language refreshes your server components.

    app/layout.tsx
    import { WeglotProvider } from "@weglot/translate-react/react/next";
    
    export default function RootLayout({ children }: { children: React.ReactNode }) {
      return (
        <html lang="en">
          <body>
            <WeglotProvider>{children}</WeglotProvider>
          </body>
        </html>
      );
    }
  4. Build, and ship in every language of your project

    Each build fetches missing translations from Weglot and writes public/translations/<locale>.json. Ignore that folder. Add a language switcher with LocaleSwitcher or useWeglotContext.

    .gitignore
    public/translations/

// under the hood

What happens when you build

  1. 01Reads your JSX
  2. 02Sends new text
  3. 03Weglot translates
  4. 04Writes one file per language

// every language of your project

One build, every language you add

Pick languages in Weglot. The next build ships them.

SourceEnglishen
FrançaisFrench
DeutschGerman
EspañolSpanish
PortuguêsPortuguese
日本語Japanese
中文Chinese
한국어Korean
हिन्दीHindi
РусскийRussian
العربيةArabic · RTL
עבריתHebrew · RTL
+110 languagesSee the full list →

Add a language in Weglot, then build. Translation files deploy with your app.

// built for coding agents

Your agent sets it up

No strings to rewrite, so the change is small and easy to review.

Any coding agent. Paste one prompt in the agent you already use.

react/getting-started.md
react/dynamic-content.md
react/use-cases.md
developers.weglot.com/llms.txt

Docs agents can read. An llms.txt index and Markdown for every page.

✓Installs the packagepackage.json
✓Adds the pluginnext.config.ts
✓Adds the providerlayout.tsx
✓Ignores generated files.gitignore
?Asks for your API key.env

A diff you can review. No strings rewritten.

Paste in Claude Code

      

Copy the prompt. Same steps as the getting-started guide.

// what gets translated

The plugin knows text from code

app/pricing/page.tsx
export default function Pricing() {
  return (
    <section className="pricing">
      <h2>Choose your plan</h2>
      <input placeholder="Email address" />
      <a href="/signup">{"Start free trial"}</a>
      <span translate="no">Weglot</span>
    </section>
  );
}

Text is translated. JSX text, literals, constants, alt, title, placeholder, aria-label.

classNamehref="/signup"onClickhttps://…useStatekey={id}

Code is left alone. Class names, URLs, logic.

translate="no"

Your call. Keep any element as is, or use data-weglot-skip.

// for your team

Edit and review without touching code

my-next-app › German2 to review
SourceGermanStatus
Save changesÄnderungen speichernReviewed
Start your free trialKostenlos testenEditing
Cancel anytime.Jederzeit kündbar.To review
Choose your planWählen Sie Ihren TarifTo review

Review in Weglot. Product, marketing and translators edit the wording.

Edit saved · Kostenlos testen
No code change

No pull request to fix a word.

Track what is reviewed. See progress for each language.

// fit

When to use Weglot, and when not to

The package is in preview. Here is where it fits today.

Next.js App Router

Supported

Next.js 15 or 16.0.4+, React 19.

Vite

Supported

React 19, Node 20.9+. Webpack works too.

React Server Components

Supported

Changing language refreshes your server components.

CMS and API content

Supported

With tDynamic in Next.js server components.

Non-developers editing

Supported

Review and edit in the Weglot dashboard.

One URL per language

Not yet

The language is stored in a cookie today. Need indexed URLs per language now: use next-intl or Paraglide JS.

Translations as repo files

Translate Action

Weglot translates your JSON locale files in GitHub Actions and opens a pull request. See the docs →

React 18, Pages Router

Not supported

Also Next.js 14 or older.

CMS or website builder

Not this package

Your site isn't built in React: use Weglot's CMS integrations.

// compare

Why not a classic i18n library?

i18n libraries ask you to replace every string with a key and keep one file per language. Weglot reads the strings you already wrote. Here is how the options compare.

FAQ

Does it handle SEO: one URL per language and hreflang?

Not today. The visitor's language is stored in a cookie and every language is served on the same URLs, so search engines index the source language only.

You can translate page titles and descriptions with tDynamicAll in generateMetadata. If you need indexed URLs per language now, use a library with locale routing, such as next-intl or Paraglide JS.

How do I translate dynamic content from a CMS, an API or users?

The plugin only translates text written in your code. For content your code never sees, call tDynamic, tDynamicAll or tDynamicHtml from @weglot/translate-react/dynamic in Next.js server components.

If the API takes longer than 500 ms, or a text is requested for the first time, they return the source text. The translation is ready on a later request. If you cache data yourself, make the cache depend on the visitor's language.

Next.js or Vite: what changes?

Next.js uses withWeglot from @weglot/translate-react/next and WeglotProvider from @weglot/translate-react/react/next. Vite uses weglotPlugin from @weglot/translate-react/vite and WeglotProvider from @weglot/translate-react/react. Webpack uses weglotPlugin from @weglot/translate-react/webpack.

The dynamic content functions only run in Next.js server components.

Does it work with React Server Components?

Yes, with the Next.js App Router. Import WeglotProvider from @weglot/translate-react/react/next so that changing language refreshes your server components. tDynamic, tDynamicAll and tDynamicHtml run server-side, in server components.

What happens when I build?

The plugin finds the text in the JSX under sourceRoot and asks the Weglot API for the translations it lacks. Weglot generates them with an LLM, and the build waits up to translationTimeout (300 seconds by default). It then writes public/translations/<locale>.json.

If translation fails, the build fails and keeps what it received in the local cache: build again to continue. With buildMode: "cache-only", the build makes no network calls.

Where are the translations stored?

In your Weglot project, where you review and edit them. Each build also keeps the translations it received in <sourceRoot>/weglot/cache/<locale>.json. Commit that folder to build without calling the API, or ignore it. public/translations/ is generated and goes in .gitignore.

What gets translated, and how do I exclude something?

Text in JSX, string literals inside JSX expressions, strings read from constants, and attributes such as title, alt, placeholder and aria-label. Code, URLs, class names and strings outside JSX are left alone. Add translate="no" or data-weglot-skip to keep an element in the original language. Declare your own text props with translatableAttributes.

Make your React app multilingual without rewriting it

Install the package, add your API key, build.

terminal
$ npm install @weglot/translate-react
Get your API key