mdxlate
Translate Markdown docs into multiple languages using LLMs.
Batteries included: prompt template, CLI, OpenAI/OpenRouter provider switch, and a simple change-detection cache.
📚 Documentation
- Getting Started – Installation and quick start
- CLI Reference – Complete command-line guide
- Programmatic Usage – Python API and examples
- Caching System – How the cache works
- Custom Prompt – Customize translations
- Error Handling – Failure recovery
- Development Guide – Contributing
- FAQ – Troubleshooting
Install
pip install -e .
Quick start
- Initialize the editable prompt (creates
~/.mdxlate/translation_instruction.txt):
mdx init
- Run translations:
export OPENAI_API_KEY=sk-... # or use OPEN_ROUTER_API_KEY when provider=openrouter
mdx run docs_src out --languages de fr --model gpt-4o-mini
Result: translated files under out/<lang>/..., preserving the original folder structure.
A cache file .mdxlate.hashes.json is written in docs_src.
CLI
mdx run [OPTIONS] DOCS_SRC OUT_DIR
Options
--base-language TEXT– Base language (default:en)--languages TEXT...– Target languages, space-separated (default:de)--model TEXT– Model name (default:gpt-4o-mini)--provider [openai|openrouter]– Backend provider (default:openai)--api-key TEXT– API key (overrides env)--api-env-key TEXT– Env var to read (default:OPENAI_API_KEY)--base-url TEXT– Custom base URL (e.g., OpenRouter)--prompt-path PATH– Use a custom prompt file instead of the default--force– Force re-translation, bypassing cache--cache-dir PATH– Directory for cache file (defaults to source directory)
Examples
OpenAI (env var):
export OPENAI_API_KEY=sk-...
mdx run docs_src out --languages de fr --model gpt-4o-mini
OpenRouter:
export OPEN_ROUTER_API_KEY=or-...
mdx run docs_src out --languages de --provider openrouter --model google/gemini-2.5-pro
Custom prompt:
mdx run docs_src out --languages de --prompt-path ./my_prompt.txt
Custom cache directory (for read-only CI/CD):
mdx run docs_src out --languages de --cache-dir /tmp
Error Handling
If any file fails to translate (e.g., due to API errors, rate limits, or network issues), mdxlate will:
- Continue processing other files instead of crashing
- Save the cache for successful translations
- Generate a failure report at
.mdxlate.failures.jsonwith details about what failed
Example failure report:
{
"failures": [
{
"file": "docs/advanced.md",
"error": "Rate limit exceeded",
"error_type": "RateLimitError"
}
]
}
After fixing the issue (e.g., waiting for rate limits to reset), re-run the translation. Only failed files will be retried thanks to the cache.
Behavior
- Prompt: default lives at
~/.mdxlate/translation_instruction.txt(created bymdx init). You can edit it freely or pass--prompt-path. - Cache: re-translation is skipped if file bytes + prompt content + model + language are unchanged. By default, cache is written to source directory as
.mdxlate.hashes.json. Use--cache-dirfor read-only environments. - Structure: each language gets its own mirror tree under
OUT_DIR/<lang>/.
Programmatic use
from pathlib import Path
from mdxlate.start_translation import start_translation
start_translation(
docs_src=Path("docs_src"),
out_dir=Path("out"),
base_language="en",
languages=["de", "fr"],
model="gpt-4o-mini",
provider="openai", # or "openrouter"
api_key=None, # pass explicitly or rely on env
base_url=None,
prompt_path=None,
cache_dir=None, # optional: specify custom cache directory
)
Integrations
- Jekyll – Complete guide for translating Jekyll sites with frontmatter preservation
Files of interest
mdxlate/cli.py– Typer CLI (mdx init,mdx run)mdxlate/client.py–make_client()factory (OpenAI/OpenRouter)mdxlate/translator.py– translation, hashing, and I/Omdxlate/translation_instruction.txt– default prompt template
Development
Setup
pip install -e .
pip install ruff mypy pytest
Code Quality
This project uses Ruff for linting and formatting, and Mypy for type checking:
# Lint code
ruff check src tests
# Auto-fix linting issues
ruff check --fix src tests
# Format code
ruff format src tests
# Type check
mypy src --ignore-missing-imports
# Run tests
pytest tests/
CI/CD
The .github/workflows/quality.yml workflow runs automatically on every push and PR:
- ✅ Ruff linting
- ✅ Ruff formatting check
- ✅ Mypy type checking
License
MIT
Layout
repo/
pyproject.toml
README.md
src/
mdxlate/
__init__.py
cli.py
client.py
translator.py
start_translation.py
translation_instruction.txt
tests/ # optional
main.py # optional local test runner
---
# pyproject.toml
```toml
[build-system]
requires = ["setuptools>=69", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "mdxlate"
version = "0.1.0"
description = "Translate Markdown docs into multiple languages using LLMs."
readme = "README.md"
requires-python = ">=3.10"
license = { text = "MIT" }
authors = [{ name = "Tobias Bück" }]
dependencies = [
"typer>=0.12",
"openai>=1.40",
"tenacity>=8.2",
]
[project.scripts]
mdx = "mdxlate.cli:app"
[tool.setuptools]
package-dir = {"" = "src"}
[tool.setuptools.packages.find]
where = ["src"]
include = ["mdxlate*"]
[tool.setuptools.package-data]
mdxlate = ["translation_instruction.txt"]
[tool.pytest.ini_options]
addopts = "-q"
testpaths = ["tests"]
Metadata
Release files for mdxlate 1.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 | Provenance | Actions |
|---|---|---|---|---|
| mdxlate-1.1.5.tar.gz | 17.9 kB | Without provenance | Details for mdxlate-1.1.5.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| mdxlate-1.1.5-py3-none-any.whl | Python 3 | none | any | Details for mdxlate-1.1.5-py3-none-any.whl |
Total release size: 29.9 kB
Release files / mdxlate-1.1.5.tar.gz
| Download URL | mdxlate-1.1.5.tar.gz |
|---|---|
| Size | 17.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0584a1591b44e814e570de2bf8604fa12ce9818d2dce291c34ca1c264a03a220
|
|
BLAKE2b-256 checksum How to use checksums |
f55dbf167ce428f0d9455fc30fddd46b881b59fc9dc1dbc6c0185bff7646509c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.22
|
Release files / mdxlate-1.1.5-py3-none-any.whl
| Download URL | mdxlate-1.1.5-py3-none-any.whl |
|---|---|
| Size | 12.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
46396d6fd259230cd669ec6708250209f123b2e8cf4d465063c6f33b795cee6f
|
|
BLAKE2b-256 checksum How to use checksums |
83f7dc57fa8d7d7837f22888980fe344359f48c0486621393852154bf5f0f532
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.22
|
Security for mdxlate 1.1.5
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A 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.