translation · text · WASM · ~105 MB / pair
The M2M100 demo covers 100 languages with one 470 MB model. MarianMT (Helsinki-NLP's OPUS-MT) takes the opposite bet: a separate, tiny bilingual model per pair. Each is ~105 MB and quick to load — you only download the direction you need. Pick a pair, type, and watch it stream, all on-device.
| Model | Xenova/opus-mt-en-de · en-fr · en-es |
|---|---|
| Task / pipeline | translation (sequence-to-sequence) |
| Architecture | MarianMT — a compact Transformer encoder-decoder; one model per language pair (no language codes) |
| Pairs shipped | English → German, French, Spanish (each a distinct model) |
| Quantization | q8 (8-bit) ONNX |
| Backend | WebAssembly (runs anywhere; no WebGPU needed) |
| Download | ~105 MB per pair (~49 MB encoder + ~57 MB decoder), cached after first load |
| License | CC-BY-4.0 (Helsinki-NLP OPUS-MT) |
| Web APIs | WebAssembly, Web Workers — all Baseline widely available |
Pick a language pair and translate. The default English → German model loads automatically; choosing another pair downloads that small model on demand. Greedy decoding streams the output live.
A translator encodes the source, then decodes the target one token at a time. Marian's whole design choice is size: because each model only knows one pair, it can be small (~105 MB) and load fast — versus M2M100's 470 MB for all-of-them-at-once. Here are the exact token counts and the real decode speed; translate the same sentence on both pages to feel the trade.
When you know the exact directions your app needs, per-pair models are the efficient choice: ship only those pairs, load them fast, and keep the footprint small — all on-device, no server, no per-call fees.
Translate a phrase and switch pairs to feel how each small model loads and runs.
Localise a batch of UI strings into a target language in one fast pass.
Round-trip a sentence out and back with two Marian models and measure the drift.
Sentiment-check an English reply with DistilBERT, then localise it with Marian.
Each pair is its own model; the pipeline call needs no language codes:
import { pipeline } from "@huggingface/transformers";
const translate = await pipeline(
"translation",
"Xenova/opus-mt-en-de",
); // downloads + caches ~105 MB once — this pair only
const out = await translate("Hello, how are you?");
// → [{ translation_text: "Hallo, wie geht es dir?" }]
There's no src_lang/tgt_lang — the direction is baked into the model. To add a
pair, load its repo (opus-mt-en-fr, opus-mt-en-es, …). This page streams tokens
via a TextStreamer inside a Web Worker so the UI stays responsive.