🌐 English · العربية · Dansk · Deutsch · Español · Suomi · Français · हिन्दी · Magyar · Italiano · 日本語 · Nederlands · Norsk · Português · Română · Русский · Svenska · Türkçe · 中文
🗿 README Rosetta
README Rosetta translates your README (and your Sphinx docs) into dozens of languages with a local model via Ollama or with Claude. It parses your Markdown instead of trusting the model with it, so code blocks, tables, links and badges come through untouched, and it checks every translation before writing it.
pip install readme-rosetta
readme-rosetta --langs es fr ja
That writes README.es.md, README.fr.md and README.ja.md, and adds a language bar to the top of every file:
🌐 English · Español · Français · 日本語
✨ Why it works
- Only prose is translated. The document is parsed with a real Markdown parser. Headings, paragraphs, table cells and the text inside HTML blocks are translated; code, front matter, URLs, inline HTML and link targets never reach the model.
- Every translation is checked. A segment is rejected if a placeholder goes missing, if a single line turns into several, if the length is implausible, or if the text is in the wrong language or script (for example Thai showing up in an Arabic README). Rejected segments are retried with the reason fed back to the model.
- Failures are loud. If a segment still fails, it keeps its source text, the run lists it, and the command exits with a non-zero status so CI notices.
- Incremental by default. Translations are cached per segment in
.rosetta/cache.json. When you edit one paragraph, only that paragraph is sent to the model again, and unchanged text stays byte-for-byte identical, so diffs stay small. Commit the cache file. - Links keep working. In-page links such as
[Install](#install)are pointed at the translated headings, and the language bar only lists files that exist.
🚀 Usage
Backends
| Backend | Setup | Default model |
|---|---|---|
ollama (default) |
Install Ollama and keep it running. The model is pulled on first use. | qwen2.5:7b |
anthropic |
pip install "readme-rosetta[anthropic]" and set ANTHROPIC_API_KEY. |
claude-opus-5-5 |
Small models are fast but make more mistakes, especially in languages that do not use the Latin alphabet. If the run reports failures, use a larger model or the anthropic backend.
# Local, with a bigger model
readme-rosetta --langs ar hi ja --model qwen2.5:14b
# Claude, four languages at a time
readme-rosetta --backend anthropic --langs de es fr it ja ko pt-BR zh --jobs 4
Options
| Option | Description | Default |
|---|---|---|
path |
Source Markdown file, or a directory that contains README.md. |
README.md |
--langs |
Target language codes, such as es fr pt-BR. Run --list-languages to see all of them. |
from config |
--src-lang |
Source language code. | en |
--backend |
ollama or anthropic. |
ollama |
--model |
Model name for the backend. | see above |
--jobs, -j |
Number of languages to translate in parallel. | 1 |
--readme |
Main README to write, if it is not the source file. | source file |
--no-split |
Append every translation to the main README instead of writing README.<lang>.md files. |
off |
--base-url |
Prefix for language bar links, for places where relative links break (such as PyPI). | relative links |
--cache |
Cache file. | .rosetta/cache.json |
--no-cache |
Ignore the cache and don't write it. | off |
--allow-fallback |
Exit with status 0 even if some segments could not be translated. | off |
--dry-run |
Show how many segments each language needs, without calling the model or writing files. | off |
--verbose, -v |
Detailed logging. | off |
Configuration
Put your defaults in pyproject.toml, then run readme-rosetta with no arguments:
[tool.readme-rosetta]
langs = ["es", "fr", "ja", "pt-BR"]
backend = "ollama"
model = "qwen2.5:7b"
jobs = 2
# Never translated: product names, commands, brand terms
do-not-translate = ["README Rosetta", "Ollama"]
# Preferred translations for recurring terms, per language
[tool.readme-rosetta.glossary.es]
"pull request" = "solicitud de cambios"
"release" = "versión"
🤖 GitHub Action
Keep translations up to date automatically. On every push that changes the README, this workflow re-translates the changed paragraphs and opens a pull request:
name: Translate README
on:
push:
branches: [main]
paths: [README.md]
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: juleshenry/readme_rosetta@main
with:
langs: es fr ja
backend: anthropic
anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
Leave out backend to run Ollama on the runner instead. That needs no API key, but it is slow on a CPU runner.
📚 Sphinx Integration
With --sphinx, README Rosetta sets up Sphinx internationalization and translates the documentation:
- Sets up Sphinx: creates
docs/if it doesn't exist. - Configures i18n: adds
locale_dirsandgettext_compacttoconf.py. - Extracts strings: runs
gettextandsphinx-intlto create.pocatalogs. - Translates catalogs: translates new and fuzzy entries, keeping reStructuredText roles, literals, links and substitutions intact.
- Builds HTML: builds the site once per language.
readme-rosetta --sphinx --langs es ja
Entries that fail validation are left empty, so Sphinx falls back to the source text for them. To clear bad entries from older catalogs, run python3 scripts/cleanup_translations.py.
📖 GitBook
--gitbook writes a SUMMARY.md that links your README and every translation, for GitBook navigation.
readme-rosetta --gitbook --langs hi zh pt
🔄 Upgrading from 0.1.x
- The old "Documentation Support in Multiple Languages" table is removed automatically on the first run and replaced by the language bar.
- Old cache files are ignored. The first run translates everything again.
- The default Ollama model is now
qwen2.5:7b. To keep the old model, setmodel = "llama3.2". --rawhas been removed. Language bar links are relative unless you pass--base-url.
📜 License
This project is licensed under the MIT License. See LICENSE for details.
Metadata
Release files for readme-rosetta 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| readme_rosetta-0.2.0.tar.gz | 43.9 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| readme_rosetta-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 82.1 kB
Release files / readme_rosetta-0.2.0.tar.gz
| Download URL | readme_rosetta-0.2.0.tar.gz |
|---|---|
| Size | 43.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7a00e6b4c0c5e2e45f8843701fc069db0c93e405adae95fee385d90c89efb184
|
|
BLAKE2b-256 checksum How to use checksums |
e99efb567c1f10da80a45ef2872a6f3f78a925c083b1af96483d7f90df36f7d1
|
| 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 30, 2026.
Transparency logRelease files / readme_rosetta-0.2.0-py3-none-any.whl
| Download URL | readme_rosetta-0.2.0-py3-none-any.whl |
|---|---|
| Size | 38.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
34f92e054bf4c924409d71606caaf33c21a89400499cc1e33c0a5c7e6ab2514e
|
|
BLAKE2b-256 checksum How to use checksums |
2b37d5b7c9a590daa04d98afb420e8822fc27bdcbf58af902e8fcd048ea49d09
|
| 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 30, 2026.
Transparency logSecurity for readme-rosetta 0.2.0
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for readme_rosetta-0.2.0.tar.gz
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 30, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.