cl10n — continuous localization for Markdown
Keep translated mirrors of a Markdown corpus up to date, one changed paragraph at a time, without ever paying to translate the same text twice.
cl10n parses each document into an AST, Merkle-hashes it, and diffs two
revisions structurally. What comes out is not "this file changed" but a
per-paragraph verdict: reuse, revise, translate, retire. Only the units that
actually need an LLM become jobs; everything else is served from a committed
translation memory. Rendering then splices translations back into the source
tree, so headings, list nesting, table shape and code fences come from the
original and cannot be corrupted by a translation.
md/**.md ──► AST + Merkle hash ──► diff vs. last localized revision
│
REUSE / RECHECK ──────┤ (no API call)
TRANSLATE / REVISE ───┴──► queue ──► provider ──► memory
│
locales/<lang>/** ◄── splice ┘
Install
pip install markdown-localization[groq] # or markdown-localization[nvidia], markdown-localization[mistral]
pip install markdown-localization[all-providers] # all three connectors
The distribution is named markdown-localization; the package you import and
the command you run are both cl10n.
Python 3.11+. Providers are pluggable: groq is the default, NVIDIA NIM and
Mistral ship alongside it, and adding another is one TOML entry plus one
module — cl10n/PROVIDERS.md.
Quickstart
Point it at a corpus under md/, and pick your target languages:
export GROQ_API_KEY=...
cl10n plan --langs he,ru # diff the corpus → a queue of jobs
cl10n run l10n/queue/queue.json -c 8 # execute the queue
cl10n render --langs he,ru # memory → locales/he/**, locales/ru/**
cl10n status --langs he,ru # coverage per language
The same four commands serve a first-time translation and a daily update — there is no bootstrap mode. First-time translation is an incremental update whose previous revision happens to be empty.
Kill a run at any point and re-run it. The resume state is the translation
memory, not the queue: plan re-derives what is missing, so finished work is
never re-billed and interrupted work is never lost.
What you get for free
- Nothing is translated twice. Units are content-addressed, so the same paragraph in two files costs one translation, and a killed run resumes for the price of what it had not reached.
- Placeholders survive. Inline code, link targets and image sources are extracted per unit and checked against every response; a translation that loses one never enters the memory. The check runs again at render time, because the memory is a committed, hand-editable file.
- Structure cannot drift. Every render re-parses its own output and refuses to write a file whose block structure moved.
- Fallbacks are visible. A unit with no usable translation renders as English and is counted, never shipped silently.
- The parser is pinned, and drift is detected. Every hash is taken over
one exact parsing configuration;
python -m cl10n.compat_checkis the gate for moving a pin, and CI runs it weekly against the newest releases as an early warning.
Documentation
cl10n/USERGUIDE.md |
every flag of every subcommand, real output explained, worked flows, cookbook, troubleshooting |
cl10n/PROVIDERS.md |
teaching the pipeline a new LLM API |
cl10n/INTEGRATION.md |
adding cl10n to an existing repository, and the CI workflow that runs it |
AGENTS.md |
the repository itself: layout, tests, release process |
.claude/rules/ |
the design specs — why each component is shaped the way it is |
License
MIT — see LICENSE.
Metadata
Release files for markdown-localization 0.1.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| markdown_localization-0.1.5.tar.gz | 121.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| markdown_localization-0.1.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 264.7 kB
Release files / markdown_localization-0.1.5.tar.gz
| Download URL | markdown_localization-0.1.5.tar.gz |
|---|---|
| Size | 121.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7f64df05724d061b9136dd0f00967e69c42efcbbca0d02f14081c7a9c1b46e3f
|
|
BLAKE2b-256 checksum How to use checksums |
884212d34431de423e7d67ddefab094aca301b6b08de3620847ef6a57ccd6647
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.
Transparency logRelease files / markdown_localization-0.1.5-py3-none-any.whl
| Download URL | markdown_localization-0.1.5-py3-none-any.whl |
|---|---|
| Size | 143.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5fff043d2613e2a0781a6ed73a34e8f72c37fd9ff36718cd7763b122064c911c
|
|
BLAKE2b-256 checksum How to use checksums |
6fbc4222a418013e7cf8aebef10e670c5b8f547cb40fd19ac59f522f0307b995
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.
Transparency log