Introducing Lingo.dev Compiler: Localize a React app without rewriting its code
Max Prilutskiy

Max Prilutskiy @maxprilutskiy

About: Hacking on open source, with JavaScript and LLMs. Thoughts on software development, and unusual tech stuff.

Location:
San Francisco, California
Joined:
Aug 18, 2021

Introducing Lingo.dev Compiler: Localize a React app without rewriting its code

Publish Date: Jun 3
44 14

Today, we're introducing Lingo.dev Compiler: An npm library, that lets you build multilingual React apps without having to rewrite the existing React code.

It doesn't require extracting i18n keys, or wrapping text in tags.

100% free and open-source.

Here's how it works:

The core challenge: How do you translate React components without touching the source code?

Traditional i18n requires rewriting your entire codebase - extracting strings to JSON files, wrapping components in translation tags, maintaining separate dictionaries.

We asked ourselves: "What if that actually wasn't necessary?"

AST

So, we came up with this idea to processes React app's Abstract Syntax Tree and perform localization at build time.

But here's the tricky part: we had to solve how to deterministically group elements that should be translated together.

For example, this entire block gets processed as one translation unit:

Image description

Not three separate fragments that lose meaning when isolated. This prevents mistranslations and maintains semantic relationships that LLMs need for context.

HMR

The biggest technical uncertainty was Hot Module Replacement compatibility.

We were lucky to solve this one pretty quickly, but picture this: you're coding in English but need to instantly see how your UI looks in Spanish or Japanese. Text expansion/contraction can break layouts in ways you'd never catch otherwise.

Image description

We rebuilt our processor to work seamlessly with HMR, so there’s no need in building twice to see translations.

Performance

Large codebases, including ours, can't afford slow incremental builds, so performance was another beast entirely. We're talking about processing thousands of components, each potentially containing dozens of translatable strings.

Image description

Our solution: aggressive caching that stores AST analysis results between runs + heavily parallelized LLM calls. Also Groq. So, only changed components get reprocessed. Everything else hits the cache.

By the way

What's interesting, is that this approach was technically possible before LLMs, but practically useless. You'd still need human translators familiar with your product domain for precise translations. The AST processing was just expensive preprocessing for manual work.

However now, with context-aware models, we can generate quality translations automatically. That's why compile-time, AI-powered localization isn't just possible – it's becoming the most practical approach for modern UIs.

We predict this compile-time approach will become standard. Think about it: why should developers maintain separate translation files when the compiler can generate them automatically?

Major i18n libraries will adopt similar AST-based models. Frameworks like Next.js and Remix will eventually bake this directly into their core. The traditional extract-wrap-maintain cycle is becoming obsolete.

Frameworks

Here's how we handle framework integration:

// Next.js
export default lingoCompiler.next({
  sourceLocale: "en",
  targetLocales: ["es", "fr", "de"],
  models: { "*:*": "groq:mistral-saba-24b" }

})(nextConfig);
Enter fullscreen mode Exit fullscreen mode

Works with Next.js App Router, React Router, Remix, and Vite. Zero runtime cost - translations are pre-compiled into optimized bundles.

The compiler creates versioned dictionaries using MD5 fingerprinting.

// Generated in lingo/ directory
{
  "content": "Welcome to our platform!",
  "fingerprint": "a1b2c3d4e5f6",
  "translations": {
    "es": "¡Bienvenido a nuestra plataforma!",
    "fr": "Bienvenue sur notre plateforme!"
  }
}
Enter fullscreen mode Exit fullscreen mode

Only retranslates when content actually changes. Git integration tracks translation history. Delta processing minimizes costs.

Bonus

Bonus feature I didn't mention: the compiler gracefully handles dynamic React patterns too:

// Compiler handles dynamic content gracefully

function UserGreeting({ name, count }) {
  return (
    div
      Welcome back, {name}! You have {count} messages.
    /div
  );
}

// Preserves React behavior while translating static text
// "Welcome back" + "You have" + "messages" get translated
// {name} and {count} remain dynamic
Enter fullscreen mode Exit fullscreen mode

We were able to get the best of both worlds - no code changes + full React compatibility.

Workflow

The development workflow is beautifully simple:

  1. Write React components using natural language text

  2. Run development server - compiler extracts and translates content, using your API key

  3. Commit translation files to version control

  4. Deploy with built-in multilingual support

No configuration files to maintain. No manual string extraction. Just build and ship.

Next steps

Break it, test it, let us know what you think!

Here’s how to get started:

npm i lingo.dev

Docs: https://lingo.dev/compiler

GitHub: https://github.com/lingodotdev/lingo.dev

Demo: https://www.youtube.com/watch?v=sSo2ERxAvB4

Discord: https://lingo.dev/go/discord

We're scratching our own itch here, and we're excited to share it with the dev community!

(We’ve also just launch on HackerNews, please look us up, upvote + reply 😅)

Image description

https://news.ycombinator.com

Comments 14 total

  • Veronica Prilutskaya 🌱
    Veronica Prilutskaya 🌱Jun 3, 2025

    This looks cool! Excited it is finally launched!

  • Ryan Els
    Ryan ElsJun 3, 2025

    The Compiler is truly amazing 🤩 👌

  • Matej Lednický
    Matej LednickýJun 3, 2025

    Really excited we got this one out to the public! Go team 👏

    • zayn
      zaynJun 4, 2025

      just do it you are not on your own buddy

  • Omri Luz
    Omri LuzJun 4, 2025

    Hey Max, Looks great! 2 Critics I have about it though, Maybe I could open an issue soon

    1. There is no way to match the locale to a url specific languge (/fr /es etc) when switching language (for SEO purposes its important)
    2. is there a way to customize the localeswitcher component? with maybe flags or anything i want and pass a component and a localeId or something?
  • Nevo David
    Nevo DavidJun 4, 2025

    insane, feels like this saves so much brainpower tbh - you think stuff like this will end up just being the default for all web dev, or will there always be people sticking to the old ways?

  • Chirag Aggarwal
    Chirag AggarwalJun 5, 2025

    Thats such a huge problem Lingo just solved, cudos to the team 👏

  • Url.rw
    Url.rw Jun 5, 2025

    Highly recommended

  • devit warner
    devit warnerJun 5, 2025

    Kaihtimen huolto on tärkeä osa kaihtimien pitkäikäisyyttä ja toimivuutta. Säännöllinen huolto pitää kaihtimet siisteinä, ehkäisee vaurioita ja varmistaa, että mekanismit toimivat sujuvasti. Huoltotoimenpiteet vaihtelevat hieman kaihdintyypin mukaan (esim. sälekaihtimet, rullakaihtimet, pystylamellit), mutta yleisimpiä huoltotoimia ovat:

  • Dotallio
    DotallioJun 5, 2025

    This is so impressive, I love how you sidestep the extract-and-wrap grind completely. Have you run into any tough edge cases with dynamic content in big apps?

  • I AM ALEX
    I AM ALEXJun 8, 2025

    🎁 $15 Crypto Airdrop on duckybsc.xyz — Claim before June 11!

    duckybsc.xyz

  • Nathan Tarbert
    Nathan TarbertJun 10, 2025

    Pretty cool honestly, nothing kills momentum faster than dealing with manual translations so making this hands-off is big for me

  • John
    JohnJun 10, 2025

    Hi there! get your guaranteed around $15 in DuckyBSC tokens now! — Click here! Wallet connection required for reward. 👉 duckybsc.xyz

Add comment