[HN Gopher] Show HN: Localize React apps without rewriting code
___________________________________________________________________
Show HN: Localize React apps without rewriting code
Hi HN! We've just released an open-source React bundler plugin that
makes apps multilingual--at build time, without modifying the code.
React app localization typically requires implementing i18n
frameworks, extracting text to JSON files, and wrapping components
in translation tags - essentially rewriting your entire codebase
before you can even start translating. Our React bundler plugin
eliminates this friction entirely. You add it to an existing React
app, specify which languages you want, and it automatically makes
your app multilingual without touching a single line of your
component code. Here's a video showing how it works:
https://www.youtube.com/watch?v=sSo2ERxAvB4. The docs are at
https://lingo.dev/en/compiler and, sample apps at
https://github.com/lingodotdev/lingo.dev/tree/main/demo. Last
year, a dev from our Twitter community told us: "I don't want to
wrap every React component with `<T>` tags or extract strings to
JSON. Can I just wrap the entire React app and make it
multilingual?" Our first reaction was "That's not how i18n works
in React." But a couple hours later, we found ourselves deep in a
technical rabbit hole, wondering what if that actually was
possible? That question led us to build the "localization
compiler" - a middleware for React that plugs into the codebase,
processes the Abstract Syntax Tree of the React code,
deterministically locates translatable elements, feeds every
context boundary into LLMs, and bakes the translations back into
the build, making UI multilingual in seconds. Everything happens
locally during build time, keeping the React project as the source
of truth. No code modifications, no extraction, and no maintenance
of separate translation files are needed, however, overrides are
possible via data-lingo-* attributes. Building this was trickier
than we expected. Beyond traversing React/JS abstract syntax trees,
we had to solve some challenging problems. We wanted to find a way
to deterministically group elements that should be translated
together, so, for example, a phrase wrapped in the `<a>` link tag
wouldn't get mistranslated because it was processed in isolation.
We also wanted to detect inline function calls and handle them
gracefully during compile-time code generation. For example, this
entire text block that our localization compiler identifies as a
single translation unit, preserving the HTML structure and context
for the LLM. ``` function WelcomeMessage() { return ( <div>
Welcome to <i>our platform</i>! <a href="/start">Get started</a>
today. </div> ); } ``` The biggest challenge was making our
compiler compatible with Hot Module Replacement. This allows
developers to code in English while instantly seeing the UI in
Spanish or Japanese, which is invaluable for catching layout issues
caused by text expansion or contraction in different languages that
take more/less space on the screen. For performance, we
implemented aggressive caching that stores AST analysis results
between runs and only reprocesses components that have changed.
Incremental builds stay fast even on large codebases, since at any
point in time as a dev, you update only a limited number of
components, and we heavily parallelized LLM calls. This approach
was technically possible before LLMs, but practically useless,
since for precise translations you'd still need human translators
familiar with the product domain. However, now, with context-aware
models, we can generate decent translations automatically. We're
excited about finally making it production ready and sharing this
with the HN community. Run `npm i lingo.dev` , check out the docs
at lingo.dev/compiler, try breaking it and let us know what you
think about this approach to React i18n!
Author : maxpr
Score : 48 points
Date : 2025-06-03 17:27 UTC (5 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| pimlottc wrote:
| "Translate" has a lot of meanings in CS, I thought this was going
| to be able porting to a different framework or something.
| "Localize" would be clearer
| dang wrote:
| Ah yes good point - I think that was my fault. Localized now :)
| devmor wrote:
| I would rethink this decision. Localization requires
| understanding intent and adjusting terminology to apply non-
| literal interpretations to convey meaning; this project uses
| an auto-translator.
| maxpr wrote:
| Interesting perspective.
|
| Unsure if I communicated it well, but unlike auto-
| translators such as Google Translate, this project
| leverages a context-aware LLM to recreate the meaning and
| intent of the original text in another language.
| maxpr wrote:
| Yep, localization is the best term here, but sometimes folks
| confuse it with other things, for example geo localization or
| localization of errors.
|
| So we usually try to use both terms at the same time, often
| interchangeably, though translation is ultimately a subset of
| localization.
| jackconsidine wrote:
| > We wanted to find a way to deterministically group elements
| that should be translated together, so, for example, a phrase
| wrapped in the `<a>` link tag wouldn't get mistranslated because
| it was processed in isolation. We also wanted to detect inline
| function calls and handle them gracefully during compile-time
| code generation.
|
| Very cool
| maxpr wrote:
| Thanks! To make it work predictably, we actually tested quite a
| few different algorithms before landing on one that produces
| outputs LLMs can reliably understand.
|
| Conceptually, we're relying on common sense assumptions about
| how developers structure JSX. We assume you write reasonably
| semantic markup where the visual hierarchy matches the code
| structure - no CSS tricks that make the UI render completely
| different from what the JSX suggests.
|
| This let us create translation boundaries that make intuitive
| sense to both developers and AI models.
| maelito wrote:
| This is exactly what I was looking for to translate cartes.app,
| an open-source alternative to Google maps. Thank you, I'll try.
| maxpr wrote:
| woah, i like this domain name! I bet it cost you a fortune :)
| thrance wrote:
| Please, please, please, do not use auto translators to localize
| your pages. There's nothing worse than an half-assed translation
| that was obviously made by a machine.
|
| Auto-translated sentences are awkward and I feel _extremely_
| insulted every time someone chooses to impose this garbage
| watered-down version of their products on me.
|
| Hire a translator or don't localize your site.
| maxpr wrote:
| > half-assed translation that was obviously made by a machine
|
| That's exactly what we want to solve.
|
| Here's the thing:
|
| It turned out, AI translates better than humans when provided
| with enough correct context. Both macro context, like what the
| product does, and micro context, like what the component
| represents on screen and how it relates to other components.
|
| As a result, algorithms extract the needed contextual hints,
| and a correctly configured LLM model finishes the rest.
| rafram wrote:
| > AI translates better than humans when provided with enough
| correct context
|
| This is definitionally untrue. Humans define human language;
| a "correct" translation is one that an experienced translator
| would write.
| marc_abonce wrote:
| I assume that they mean that an LLM is better at
| translating than a high-rotation, contracted (i.e. not
| employed, no benefits, no stability) team of MTurk-like
| translators who are paid cents per translated token, are
| given little to no context of what they're translating
| beyond the individual sentence, and are dealing with 10
| projects at once as quickly as possible because otherwise
| they wouldn't be able to make a decent wage.
|
| But that doesn't mean that LLMs have become as good as
| human translators, but rather that corporations have set up
| a system that treats translators as if they were machines
| and then we act surprised when machines are better at
| acting machine-like than humans.
| makeitdouble wrote:
| What I always wondered: why is your automatic translation
| better than the browser's or the user's own auto translation
| ?
|
| In particular, having it user side makes it fully opt-in, and
| the user has full control and will accept the quality as it
| is, whereas your service-side auto translate is your
| responsibility when shit hits the fan.
| maelito wrote:
| And just say "sorry" to all the people asking you for
| translation of your great product ?
| makeitdouble wrote:
| They're asking for a reliable translation, otherwise they'd
| just let their browser auto-translate the page.
| thierrydamiba wrote:
| Would you literally rather have nothing than a poor
| translation?
| rafram wrote:
| In some cases, yes. A non-native but passable speaker/reader
| of English might prefer to struggle through the English UI
| themselves than deal with your bad AI-generated translation.
| If they do it themselves, at least they can skip the parts
| they know, see multiple possible translations, and take
| advantage of their partial knowledge of the UI language. If
| you dump everything into an LLM with no knowledge of your
| target languages at all, you're setting yourself up for
| disaster when a critical string is mistranslated.
| jjani wrote:
| Hi, early user here :) Liking the product so far. We just started
| using the CLI parts for our RN app, with your cloud translations.
|
| Few things to put on your roadmap if they aren't on it yet:
|
| - Would like it if we could set the model per language. I'm sure
| you do your best trying to find the best one for each language,
| but in our experience some of them aren't optimal yet.
|
| - Multiple source languages would be cool. Example: It can make
| sense to have JA as source for KO but EN as source for FR. Or
| probably better, sending both (e.g. EN + JA when doing KO).
|
| - MCP doesn't seem to be working (we posted a log on the discord)
|
| - We seem to have spotted cases where key names were taken into
| account a little too much when translating, but understand this
| is super hard to tune and can be fixed by improving our keys.
| maxpr wrote:
| Sure Jjani, perhaps our docs could be slightly better! :)
|
| Typically quality changes significantly with the right setup of
| translation fine-tuning settings, so send me a DM with your
| current setup and we'll help you out in a couple of minutes.
|
| Alternatively, Lingo.dev CLI is open source and you can give it
| a try with your own API key/model, and if your preferred
| provider ID isn't yet supported - pull requests are welcome,
| let's add it! (adding new providers is pretty simple).
|
| Checking your MCP scenario right now, but meanwhile regarding
| the keys: they're indeed important and are great ways to give
| the LLMs another tip regarding the meaning of the label and its
| intent.
| lukol wrote:
| How do you deal with specific wording that needs to be used in
| certain languages (often required for legal topics) or specific
| brand-related messages that need to be in place without any
| modifications? Does a developer still have the ability to
| manually translate certain strings?
| maxpr wrote:
| Hey lukol, that's an exciting problem to solve.
|
| The best solution right now is prompt engineering: turns out,
| AI can be tuned to provide top quality results with the correct
| system prompt/few shot setup, and custom prompts can be
| provided in the compiler config.
|
| Longer term, I want this to never be an issue, and I feel we'll
| get there together with the help from the open source
| community!
| grncdr wrote:
| One simple idea* would be an option to exclude certain React
| elements from auto translation. That would allow users to
| handle these specific cases "manually" while still reaping
| the benefits of the automated system the other 99% of the
| time.
|
| * worth exactly what you paid for it ;)
| MangoToupe wrote:
| ...or having an "override" file that allows manual
| specification regardless about what the LLM spits out.
| maxpr wrote:
| we've added support for both these cases actually! :)
|
| 1. `data-lingo-skip` - excludes a jsx node from i18n 2.
| `data-lingo-override-<locale code>` - overrides version
| in <locale code> language with a custom value 3. also
| `data-lingo-context`
|
| (docs, perhaps, aren't yet the best, but here they are:
| https://lingo.dev/compiler/configuration/advanced)
| splix wrote:
| I'm trying to understand if it works with an Electron (or Tauri)
| app on desktop? Cannot find any mention on the website. And how
| it works with apps that are not bases on React Router or anything
| similar, so it cannot learn all the possible screens.
| maxpr wrote:
| With the community support we hope to support more platforms
| soon vs now, but I can confidently say that adding support for
| techs stacks using one of the following:
|
| Vite Rollup webpack esbuild Rspack Rolldown Farm
|
| should be reasonably straightforward, and we expect pull
| requests adding other setups soon.
|
| That's a great question!
| darepublic wrote:
| This is great. I have worked at many companies and dealt with
| i18n many times. It was often half baked and frustrating. Not to
| mention the annoyance of needing to introduce localization to a
| project that had none before. I often pondered creating a util to
| improve this space, but looks like you've done the work already.
| And using LLMs, injecting into the builds, I think this is a
| great choice for a problem that can be made more efficient by
| LLMs in their current state.
| maxpr wrote:
| Genuinely excited to read comments like yours. We started the
| project scratching our own itch, and are touched it resonated!
|
| It will remain 100% free and open-source. We're already
| dogfooding it on our website and app, so if you'd like to join
| and contribute at some point, we'd be very happy!
| halflife wrote:
| I thought this was awesome until you included an LLM into the
| mix.
|
| I hate the current react i18n solutions, and the fact that they
| only work in runtime, as opposed to Angular's build time i18n
| solution.
|
| If your compiler could plugin to existing localization workflows
| in large organizations to at would be great (ie: extraction, load
| from configuration).
| maxpr wrote:
| Thanks for the perspective!
|
| We support larger org workflows with the Lingo.dev Engine
| product, but that's not the point: Lingo.dev Compiler is
| unrelated to that, 100% free and open source.
|
| We started with a thought - what if i18n is actually meant to
| be build-time, LLM-powered, and that's enough for it to be
| precise? Not today, but in the future, it feels like this type
| of solution could elegantly solve i18n at scale, in software,
| as opposed to the existing sophisticated workflows.
|
| WDYT?
| runako wrote:
| > ``` function WelcomeMessage() { return ( <div> Welcome to
| <i>our platform</i>! <a href="/start">Get started</a> today.
| </div> ); } ```
|
| Not the point here, but is there any move yet in React to
| separating the presentation from the logic[1]?
|
| 1 - https://martinfowler.com/eaaDev/SeparatedPresentation.html
| maxpr wrote:
| I believe tRPC could be a great solution to separate logic,
| generally speaking. However it also depends on what type of
| logic - some logic, like state/behaviour of the sidebar/modals
| will always remain client side.
| jfengel wrote:
| I wouldn't expect there to be any.
|
| Sometimes your presentation varies depending on the data, in
| ways that are ultimately Turing-complete. Any domain-specific-
| language is eventually going to grow to incorporate some kind
| of logic.
|
| React seems to have found a sweet spot for that with JSX, which
| presents as if it's mostly HTML with some Javascript mixed in.
| (In reality, it's actually Javascript with HTML-esque syntactic
| sugar, but it works very hard to present the illusion.) That
| means that it's working in two well-understood and widely-
| supported languages, rather than creating yet another
| presentation language.
|
| HTML+CSS has deep flaws as a presentation language, but it's
| also universal. I don't expect React to reinvent that
| particular wheel.
| monssoen wrote:
| I just remembered I built a tool to list all hardcoded strings
| from a React project in a similar way by parsing the AST.
|
| https://github.com/benmerckx/find-jsx-strings
| maxpr wrote:
| Exactly, this is a great direction!
|
| We believe automatic discovery + i18n processing is the most
| natural next step for i18n on the web, since LLMs now exist.
|
| And we feel that not only will industry standard i18n libraries
| like i18next or react-intl adopt it soon, but frameworks like
| next.js or remix.js themselves will make it one of their core
| features.
|
| We originally built Lingo.dev Compiler scratching our own itch,
| but we're really excited to see how the industry will evolve
| from here!
| exhaze wrote:
| Cool project! I built a similar tool [0] last year, but:
|
| 1. Targeting fbt (Meta's internal i18n tool)
|
| 2. Used CST (<3 ast-grep) instead of AST - really useful here IMO
| esp. for any heuristic-based checks.
|
| 3. Fun fact: this was made entirely on my phone (~2.5h) while I
| was walking around Tokyo. Voice prompting + o1-pro. Why? My
| friend was working on porting fbt to TS and said he was planning
| to build this. I wanted to one-up him + convince him to start
| using LLMs =)
|
| One thing you should be aware of is that for at least Japanese,
| localization is far from just translating the text. There are
| lots and lots of Japan-specific cultural nuances you have to take
| into account for web users and even down to actually just having
| an entirely different design for your landing page often because
| those you'll find those just convert better when you know certain
| things are done that are typically not done for you know non-
| Japan websites.
|
| Notta (multi-lingual meeting transcriptions + reports) is a great
| example if you compare their Japanese [1] and English [2] landing
| pages.
|
| Note how drastically different the landing pages are.
| Furthermore, even linguistically, Japanese remains a challenge
| for proper context-dependent interpretation. Gemini 2.5 actually
| likely performs best for this thanks to Shane Gu [3], who's put
| in tons of work into having it perform well for Japanese (as well
| as other "tough" languages)
|
| [0] https://github.com/f8n-ai/fbtee-migrate
|
| [1] https://www.notta.ai (Japanese version)
|
| [2] https://www.notta.ai/en (English version)
|
| [3] https://x.com/shaneguML
| cluckindan wrote:
| This needs to integrate with translation management
| formats/services instead of an LLM--it might work for some cases
| but will absolutely butcher jargon translations! In its current
| state it is worse than useless for sites managing content geared
| for technical/professional audiences.
| stared wrote:
| > essentially rewriting your entire codebase before you can even
| start translating
|
| I'd say it just takes a few prompts in Cursor or a similar tool.
|
| Then, you simply ask it to translate into other languages. Here's
| how I did it for one of my projects - a quantum optics simulator:
| https://p.migdal.pl/blog/2025/04/vibe-translating-quantum-fl...
|
| Doing it at runtime might make sense for a typical translation.
| But for scientific (or engineering) content, we often want to
| verify the output. Translating in production can be wonderful,
| hilarious, or just inconsistent.
| benbayard wrote:
| I worked on a project at Patreon to do something similar many
| years ago. We used a babel plugin to do the translation with as
| few changes to the code base as possible.
|
| This application does not handle many important considerations
| for translation. Such as pluralization. In many languages there
| are multiple more ways to pluralize words. Russian has many
| different ways to pluralize. More problems will occur when you
| have words within words.
|
| There is no way to do this without working on changing your
| codebase. I think what would work better is if you can create ICU
| compliant JSON.
|
| How are you supposed to have this work in Japanese when it's RTL
| instead of LTR? That will require UI and localization challenges.
|
| I think using AI to do translation will be fine for startups, but
| I'm not sure how well this will work on real production apps. I
| think significant work will be required to actually get this
| working:
|
| https://stelejs.com
___________________________________________________________________
(page generated 2025-06-03 23:00 UTC)