1
0 Comments

Translate a static site into 40 languages without breaking Core Web Vitals

I work at ConveyThis, which sells managed website translation. This is the pipeline we built to localize our own marketing site into 55 languages, extracted and open-sourced under AGPL. Saying that up front because it is relevant to how you read the rest.

The thing that cost us the most was a metric that lied. Our coverage number read 100% - every extracted segment translated - while thousands of strings on the site were still in English. Coverage measures translated-of-extracted, so it is structurally blind to extraction bugs, and one bug that skipped any block containing an <svg> had quietly dropped every icon-and-label pair we had. The tool now ships a gate that compares rendered output against the source instead, because the ratio you naturally reach for cannot see this class of failure at all.

The technical core is that translations are spliced into already-built HTML by byte offset and the document is never re-serialised from a DOM. Inlined critical CSS, the LCP element, asset hashes and the width/height attributes that hold CLS all survive untouched - which is why the locale pages match the source on Core Web Vitals rather than approximately resembling it. The alternative, re-running a framework build per locale, puts every page back through the critical-CSS step, and that tooling drops an unpredictable slice of each page's classes.

It is not tied to a model, either. Claude by default, Gemini, anything OpenAI-compatible — which means Ollama and LM Studio, so you can run the whole thing locally with no key and nothing leaving the machine. That matters more than it sounds: a lot of the content people want translated is not content they want to send anywhere.

What it does not do: anything hydrated (islands re-render over your translations), anything that is not HTML, and anything where content changes faster than you build. The scripts detect and say so rather than failing quietly. If your site is in that category our paid product is a better fit, and the README says that too - I would rather not have people spend a weekend finding out.

on August 26, 2026