Skip to content

Translate Markdown with DeepL

Asterios Raptis edited this page Mar 24, 2026 · 5 revisions

📘 Translate Markdown with DeepL – translate_book_deepl.py

This script translates Markdown (.md) files using the DeepL Free API, overwrites the original files, and maintains a .skiplist to prevent duplicate work.


🚀 Features

  • ✅ Translate single Markdown files or entire directories

  • ✅ Overwrites original .md files

  • ✅ Automatically skips and logs empty files

  • .skiplist tracks already translated files

  • ✅ Supports dry-run mode (no writing)

  • ✅ Logs skipped files with reason to logs/skipped.log

  • ✅ Reads DeepL API key from .env file


📦 Setup

  1. Install dependencies (via Poetry):
poetry install
  1. Set your DeepL API key in .env:
DEEPL_AUTH_KEY=your_deepl_api_key_here
  1. Make sure this line is in .gitignore:
.skiplist
logs/
.env

🧑‍💻 CLI Usage

Translate a single file:

poetry run translate-book-deepl \
  --file manuscript/chapters/01-intro.md \
  --target-lang DE

Translate a full directory:

poetry run translate-book-deepl \
  --base-dir manuscript/chapters \
  --target-lang DE

Simulate translation (dry run):

poetry run translate-book-deepl \
  --file manuscript/chapters/01-intro.md \
  --target-lang DE \
  --dry-run

🌍 Translate from German to English

By default, the script assumes the source language is English.
To translate from German to English, add the --source-lang DE flag:

Translate a directory (DE → EN):

poetry run translate-book-deepl \
  --source-lang DE \
  --target-lang EN \
  --base-dir manuscript

Translate a single file (DE → EN):

poetry run translate-book-deepl \
  --source-lang DE \
  --target-lang EN \
  --file manuscript/chapters/01-intro.md

⚙️ Options

Argument Description Example
--file Translate a specific Markdown file --file path/to/file.md
--base-dir Translate all .md files recursively in folder --base-dir manuscript/
--target-lang Language code to translate into (required) --target-lang DE
--source-lang Language code to translate from (default: EN) --source-lang DE
--dry-run Skip writing and .skiplist update --dry-run

📁 Files & Logs

.skiplist

  • Tracks files already processed

  • Used to skip files in future runs

logs/skipped.log

  • Contains lines like:
skiplist: manuscript/chapters/01-intro.md
empty: manuscript/chapters/05-empty.md
not_found: manuscript/chapters/ghost.md

🧠 Best Practices

  • 🛡 Protect your .env — never commit it to Git

  • Commit translations after verification

  • 🧪 Use --dry-run before bulk operations


✅ Example .env File

DEEPL_AUTH_KEY=abc123-your-api-key

📜 License

MIT or same license as your project.
This script uses the DeepL Free API with a free limit of 500,000 characters/month.


🧠 Bonus: Other Free Translation Alternatives

If DeepL isn’t enough or you want fallback options, here are more tools:

1. LibreTranslate

  • 🔓 Open-source, REST API

  • Public instance: https://libretranslate.com

curl -X POST https://libretranslate.com/translate \
-H 'Content-Type: application/json' \
-d '{
  "q": "Hello!",
  "source": "en",
  "target": "fr",
  "format": "text"
}'

2. Argos Translate

  • 🔒 100% offline/local translation

  • Use in Python, no API key required

pip install argostranslate

3. MarianMT / OpenNMT (HuggingFace)

  • 🧪 Best for custom/local AI setups

  • Requires Python and GPU for best performance

  • Self-hosted or offline use


🏁 Conclusion

If you want to avoid the complexity and costs of Google Translate, the DeepL Free API is a fantastic choice—with generous limits, great quality, and ease of use. Combine it with LibreTranslate for fallback or Argos Translate for local, offline use.

✨ Ready to build? Start with DeepL, and scale up with open-source alternatives when needed.

Clone this wiki locally