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"]
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 | |
|---|---|---|---|
| mdxlate-1.1.5.tar.gz | 17.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mdxlate-1.1.5-py3-none-any.whl | Python 3 | none | any | Details |
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
|