Local, by default
Ship NLLB-200 (600M / 1.3B / 3.3B) right next to your binary. Everything runs on-device — no API keys, no rate limits, no data leaving your machine.
ct2rs · CTranslate2 · cpu · cudaZellig is a tiny Rust CLI that speaks 200 languages — on-device with NLLB, through a cloud translation service, or via your favourite LLM. Strings, files, whole directories. It preserves your formatting and stays out of the way.
cargo install zellig
docker run --rm ghcr.io/kodaskills/zellig
One small binary that pulls together the three jobs you used to glue together with shell scripts: machine translation, LLMs, and file-format-aware batch processing.
Ship NLLB-200 (600M / 1.3B / 3.3B) right next to your binary. Everything runs on-device — no API keys, no rate limits, no data leaving your machine.
ct2rs · CTranslate2 · cpu · cudaPlug Zellig into Anthropic, OpenAI, Gemini, xAI, DeepSeek, Groq, Ollama, or any OpenAI-compatible endpoint. Bring your own prompt; cache by default.
openai · anthropic · ollama · …DeepL, Google, Yandex, Azure, LibreTranslate, Bergamot, Baidu, Youdao, QQ, Lingva — picked at runtime per file, per language, or per glossary.
drop-in · auth via env · rate-awareWalks directories, filters by extension, and keeps your structure intact. PO comments, XLIFF metadata, JSON keys, TOML tables, YAML anchors, Markdown blocks.
po · xliff · json · toml · yaml · mdComments, plurals, msgctxt, fuzzy flags — preserved. Never overwrites an existing msgstr unless you ask.
Trans-unit attributes, inline tags, and state machinery survive the round trip.
Nested keys, ICU plurals, interpolation tokens like {{name}} stay verbatim.
Tables, arrays of tables, inline strings — translated values keep their key paths and order.
Anchors, aliases, and i18n.yml conventions are honoured; flow style preserved.
Code fences, links, and front-matter are left alone. Prose gets translated. JSX nodes opt-in.
Switch backends per command, per directory, or per language pair. Zellig caches every translation by content hash, so re-runs are free and deterministic.
Run on your laptop or a CI box. No network, no keys, no cost.
Any chat-completions endpoint. Prompts and glossaries are first-class.
Classic MT services for production-grade quality and speed.
Use Zellig as a one-shot command in your build pipeline, or drop into an interactive TUI when you're translating by feel.
Compose Zellig with the rest of Unix. Flags for everything, exit codes you can trust, scriptable output.
$ zellig translate "Where is the library?" --target fr
Où est la bibliothèque ?
$ zellig translate --dir docs/ --target ja --mode ollama
✓ 14 files translated → docs/ja/
$ zellig translate --dir ./locales \
--target es --target de --target it \
--mode deepl
✓ 126 files · 18,402 segments · 12.4s
A small TUI with multi-language targeting and file loading. Built with ratatui; keyboard navigation, live preview, and syntax-coloured output.
$ zellig tui ◆ zellig Translate ──────────────────────────────────────────────────────── Models │ Languages │ Config │ Translate │ File │ Detect ──────────────────────────────────────────────────────── ╭─ Source ↔ ─────────────────╮╭─ Target ───────────────╮ │ English ││ French │ ╰────────────────────────────╯╰────────────────────────╯ ╭─ Text ───────────────────────────────────────────────╮ │ The early bird catches the worm. │ ╰──────────────────────────────────────────────────────╯ ╭─ Translation ────────────────────────────────────────╮ │ Le lève-tôt attrape le ver. │ ╰──────────────────────────────────────────────────────╯ ──────────────────────────────────────────────────────── Type [Tab]=lang [Enter]=translate [Esc]=menu
:commandsFrom Asturian to Zulu — pivot through English when needed.
A 50-word string, NLLB-200 600M, cold cache.
Single static binary, no Python, no node_modules.
Tokio async fan-out across target languages and batches; backend-aware rate limits.
Directory walker, 10 translation services, 20+ AI/LLM backends, interactive TUI, content-hash caching, and 6 file formats.
First-class glossary files, do-not-translate rules, and streaming output for long documents.
In-editor preview, side-by-side diff, and one-click backend switching.
Run Zellig as a lightweight HTTP service for batch APIs and CI fan-out.
Frozen CLI, semver guarantees, long-term support for the v1 plugin ABI.
Zellig is MIT-licensed and developed in the open at github.com/kodaskills/zellig.
Issues, pull requests, and backend plugins all welcome.
Yes. Zellig runs NLLB-200 (600M, 1.3B, 3.3B) on-device via ct2rs / CTranslate2. After the first zellig models --download JustFrederik/nllb-200-distilled-600M-ct2-int8, everything happens on your machine — no network calls, no telemetry. For GPU acceleration, build with --features cuda and set device = "cuda" in [local] — the same binary runs on CPU-only machines too. Output quality can be tuned with repetition_penalty and no_repeat_ngram_size in your config.
By default, Zellig is conservative. Existing msgstrs, populated XLIFF targets, and already-localized JSON keys are skipped.
Yes — implement the Translator trait in Rust (around 60 lines) and wire it into your config. The plugin interface is stable and well-documented.
Zellig is at 0.1.x — early but functional. The CLI surface and file-format adapters are working; LLM prompts and the plugin ABI may still shift before 1.0. Pin your version in CI.
Those are excellent and Zellig stands on their shoulders. The differences: a single static binary, first-class LLM and local-model backends, content-hash caching, and an interactive REPL. Pick whichever fits your team.
Yes — an official image (including the local NLLB-200 backend) is published to GHCR after every release:
docker run --rm ghcr.io/kodaskills/zellig translate "Hello" --target fr
To translate a local directory, mount it as a volume:
docker run --rm -v "$(pwd):/data" ghcr.io/kodaskills/zellig translate --dir /data/locales --target es
A docker-compose.yml is included in the repo with a dev profile (cargo-watch hot-reload) and a prod profile for one-off runs. See the repository for details.
Glossary support is planned for v0.2. Today, JSON and YAML formats preserve interpolation tokens like {{name}} verbatim.