Agentic localization: how this blog stays multilingual without a translation team
Every post on this journal can ship in English, Chinese, and Japanese. The translators are LLM agents; the editors are pull requests. Here's the pipeline.
You are reading a post that knows how to translate itself. Every article in this journal is a typed TypeScript module with an English source and optional locale variants — and the locale variants are produced by an LLM agent on a schedule, reviewed by a human, and merged like any other code change. This post (fittingly) ships with a Chinese translation produced by exactly that pipeline.
The content model: locales as fields, not forks
Each post exports one object with a translations map: en is required, zh and ja are optional. Title, description, and body travel together per locale, so a translation can never drift structurally from its source — the type checker won't allow it. The post's date, tags, and artwork are shared across locales, so there is exactly one source of truth for everything that isn't language.
The pipeline: diff, translate, review
Three steps, all boring on purpose:
- Detect staleness. A scheduled job lists posts where the English source changed after a locale variant last did (git history makes this a one-liner), plus posts missing a target locale entirely.
- Translate with full context. The agent reads the entire post — not strings in isolation — and writes the locale variant in place. It carries a style brief per language: simplified Chinese with mainland product vocabulary, Japanese in です/ます form, keep code identifiers and product names untranslated.
- Gate on review. The agent opens a pull request. A human (or a second reviewer agent with veto power) reads the diff. Nothing reaches production without a merge.
Because translations are code, every guarantee we rely on for code applies to them: CI type-checks the structure, the build fails on a missing field, and git revert un-ships a bad translation in seconds.
Why not machine-translate at the edge?
Runtime translation APIs are tempting — no files, no PRs. But they translate sentences, not arguments. An LLM agent that reads the whole article preserves the metaphors, the section structure, and the terminology of earlier posts. It can also decline: when a pun doesn't survive the trip, the agent rewrites the sentence rather than embarrassing us literally. And because the output is frozen in git, readers in every language see reviewed prose, not a dice roll per page load.
The same trick works on a CMS
If your content lives in Payload or another headless CMS instead of git, the shape survives: an afterChange hook detects source-locale edits, queues a translation task, and the agent writes target locales back as drafts via the API for editorial approval. The principle is identical — agents propose, humans approve, every change is a reviewable diff. We wrote up the full CMS-vs-git evaluation in a separate post if you're choosing a stack.