Opus-MT for phones β€” sixteen directions, INT8 ONNX

Sixteen Opus-MT translation directions prepared to run offline on a phone: three quantized ONNX graphs and one binary tokenizer per direction.

Nothing here is a new model. These are conversions of Helsinki-NLP Opus-MT models, published so that a mobile app can download a language pair once instead of shipping a converter, and so the conversion is reproducible by anyone.

Directions

ru-uk Β· uk-ru ru-en Β· en-ru uk-en Β· en-uk
de-en Β· en-de fr-en Β· en-fr it-en Β· en-it
ru-fr Β· fr-ru uk-fr Β· fr-uk

Directions, not languages: Opus-MT translates one way with one model, so ru-uk and uk-ru are two different sets of files. Ukrainian is covered by direct pairs with Russian rather than through English β€” on that pair the quality cost of two passes is particularly audible. French with Russian and Ukrainian is direct for the same reason.

Sizes run from 209 MB (ru-uk) to 264 MB (it-en). The spread comes from vocabulary, not architecture: every direction has six layers and d_model 512, but the shared vocabulary of it-en is 80 379 against 58 101 for de-en, and the difference lands in the embedding matrix.

Files in each directory

opus-mt-<pair>/
  encoder_model.onnx              INT8
  decoder_model.onnx              INT8
  decoder_with_past_model.onnx    INT8
  tokenizer.bin                   binary, see below
  manifest.json                   sizes, SHA-256, architecture, source model

Why three graphs and not one

decoder_model_merged does not quantize: the whole body of the graph hides inside a single If node, and the ONNX Runtime quantizer does not descend into subgraphs.

Dropping decoder_model and keeping only the cached decoder does not work either. It accepts an empty cache and returns logits of the right shape β€” but past_key_values.N.encoder.* holds projected encoder states, not history, and they are the decoder's only link to the input text. On an empty cache the model produces fluent, entirely invented translations.

Why the tokenizer is a binary file

Marian models have no tokenizer.json, and source.spm is a SentencePiece protobuf whose nmt_nfkc normalizer is a compiled 237 KB binary trie. Parsing that format on the device is a separate project with a high cost of error.

The conversion enumerates the normalizer's behaviour over code points once β€” about 4 800 rules β€” and stores it as a plain table alongside the pieces and the vocabulary. Every direction was verified piece-for-piece against the reference AutoTokenizer on a 15-sentence corpus in the source language of that direction.

Using them

The reference consumer is a Kotlin runtime (tokenizer, beam search, three ONNX sessions) built for My Chat and shared with a keyboard over an IPC contract; measured on a Galaxy Z Fold 6: median 109 ms per sentence, worst case 191 ms, after a one-off 587 ms to open a pair.

Any decoder works, with one requirement that is easy to miss:

The padding token must be forbidden during generation. Marian uses it as the decoder start token, and generation_config.json sets bad_words_ids: [[pad]]. en-uk selects it at the very first step: without the ban, generation repeats padding to the length limit and returns an empty string on a perfectly healthy model. Eleven of the twelve directions behave without the ban, which is exactly what makes the omission hard to notice.

Greedy decoding of the quantized graphs matches the fp32 reference sentence for sentence on five of the twelve directions and differs by a word or two on the rest β€” ordinary quantization drift, visible mostly in numerals and greetings. Beam search narrows it further.

Licence and attribution

The original models are Β© Helsinki-NLP, released under CC BY 4.0, and this derivative keeps that licence. If you use these files, credit the Helsinki-NLP Opus-MT project β€” the translation quality is theirs; only the packaging is ours.

  • Models: https://huggingface.co/Helsinki-NLP
  • Opus-MT / Tatoeba Challenge: Tiedemann, J. (2020), The Tatoeba Translation Challenge β€” Realistic Data Sets for Low Resource and Multilingual MT.

Reproducing

python3 tools/opus-mt/convert.py en uk --out dist/opus-mt
python3 tools/opus-mt/verify.py dist/opus-mt/en-uk

verify.py checks two things and refuses to skip either: that our tokenizer agrees with the reference piece for piece, and that the assembled graphs actually translate a sentence. The second check exists because the first one passed on en-uk while it was returning nothing at all.

Direct directions (October 2026)

100 more directions, so that German, Italian, Portuguese, Polish and the other EU languages translate to and from Russian and Ukrainian directly instead of through English. Each source model is pinned to the Hugging Face commit shown below, so a rebuild produces the same bytes. All of them were checked the same way as the original sixteen: tokenizer piece-for-piece against AutoTokenizer on a 15-sentence corpus in the source language, plus one end-to-end translation.

Quantization was checked against fp32, not assumed. Every direction was translated over its whole corpus by the INT8 graphs and by the fp32 reference, comparing numbers, repetition loops and exact matches. Symmetric int8 weights broke some models (en-hu looped, others turned 23 into 203); asymmetric uint8 weights of the same size fixed most of them. Each direction ships the better of the two β€” see the Weights column. Four directions (ru-fi, ru-lt, uk-sl, uk-sv) were left out: their source models mistranslate numbers and names even in fp32, so translation goes through English.

Multilingual Tatoeba models (tc-big-*-zle, zlw-zle, en-zls, …) need a target-language token as the first input token. It is stored in tokenizer.bin format version 2: the same layout plus one int32 after decoderStart β€” the token id that goes first. Version 1 files (all directions without a token) are unchanged. Directions of one multilingual model share byte-identical ONNX graphs.

tc-big directions are larger (β‰ˆ 560 MB) and, measured on a Galaxy A16 (4 GB), still faster than two passes through English: median 880 ms vs 1232 ms per sentence for de-ru, with β‰ˆ 150 MB more memory.

Licenses and attribution. Source models by Helsinki-NLP (JΓΆrg Tiedemann et al., OPUS-MT / Tatoeba-Challenge), released under CC BY 4.0 or Apache-2.0 as listed per direction. These files are format conversions (ONNX export, INT8 quantization, binary tokenizer) and keep the license of their source model.

Direction Source model Revision License Target token Weights Size
de-ru Helsinki-NLP/opus-mt-tc-big-de-zle d4db2a2cba cc-by-4.0 >>rus<< uint8 558 MB
de-uk Helsinki-NLP/opus-mt-de-uk a8ddab4329 apache-2.0 β€” uint8 220 MB
it-ru Helsinki-NLP/opus-mt-tc-big-it-zle 18be58942a cc-by-4.0 >>rus<< uint8 557 MB
it-uk Helsinki-NLP/opus-mt-it-uk 267bdf64e2 apache-2.0 β€” uint8 220 MB
ru-de Helsinki-NLP/opus-mt-tc-big-zle-de b2e247f0c4 cc-by-4.0 β€” int8 558 MB
ru-it Helsinki-NLP/opus-mt-tc-big-zle-it 30d97bab19 cc-by-4.0 β€” uint8 557 MB
uk-de Helsinki-NLP/opus-mt-uk-de f72b164a36 apache-2.0 β€” int8 220 MB
uk-it Helsinki-NLP/opus-mt-uk-it a6a4230c29 apache-2.0 β€” uint8 220 MB
de-fr Helsinki-NLP/opus-mt-de-fr 2b4fe242d2 apache-2.0 β€” int8 216 MB
de-it Helsinki-NLP/opus-mt-de-it 9038fd00f2 apache-2.0 β€” int8 213 MB
fr-de Helsinki-NLP/opus-mt-fr-de db80d26106 apache-2.0 β€” int8 216 MB
fr-it Helsinki-NLP/opus-tatoeba-fr-it 43a567d0bc apache-2.0 β€” int8 204 MB
it-de Helsinki-NLP/opus-mt-it-de 11728e1aaf apache-2.0 β€” uint8 213 MB
it-fr Helsinki-NLP/opus-mt-it-fr f28e1c68d3 apache-2.0 β€” uint8 212 MB
en-es Helsinki-NLP/opus-mt-en-es 5bc4493d46 apache-2.0 β€” uint8 226 MB
en-pl Helsinki-NLP/opus-mt-en-zlw 92ffd5aa93 apache-2.0 >>pol<< uint8 209 MB
en-pt Helsinki-NLP/opus-mt-tc-big-en-pt 9f2863d807 cc-by-4.0 >>por<< uint8 526 MB
es-en Helsinki-NLP/opus-mt-es-en c96e2c5399 apache-2.0 β€” uint8 226 MB
es-ru Helsinki-NLP/opus-mt-es-ru e49a0dcda4 apache-2.0 β€” uint8 222 MB
es-uk Helsinki-NLP/opus-mt-es-uk bbfb340b17 apache-2.0 β€” uint8 220 MB
pl-en Helsinki-NLP/opus-mt-pl-en 7f2bb874fd apache-2.0 β€” uint8 222 MB
pl-ru Helsinki-NLP/opus-mt-tc-big-zlw-zle a20a48b682 cc-by-4.0 >>rus<< uint8 560 MB
pl-uk Helsinki-NLP/opus-mt-pl-uk 35d5358648 apache-2.0 β€” uint8 220 MB
pt-en Helsinki-NLP/opus-mt-roa-en c26705dd23 apache-2.0 β€” uint8 226 MB
pt-ru Helsinki-NLP/opus-mt-tc-big-pt-zle 238244a142 cc-by-4.0 >>rus<< uint8 559 MB
pt-uk Helsinki-NLP/opus-mt-pt-uk b60b9e9c20 apache-2.0 β€” uint8 219 MB
ru-es Helsinki-NLP/opus-mt-ru-es f7fd0cd65f apache-2.0 β€” int8 222 MB
ru-pl Helsinki-NLP/opus-mt-tc-big-zle-zlw e14020b995 cc-by-4.0 >>pol<< uint8 560 MB
ru-pt Helsinki-NLP/opus-mt-tc-big-zle-pt 19ae5bd058 cc-by-4.0 >>por<< uint8 559 MB
uk-es Helsinki-NLP/opus-mt-uk-es b3b59a5c0f apache-2.0 β€” int8 219 MB
uk-pl Helsinki-NLP/opus-mt-uk-pl accfb29ee5 apache-2.0 β€” uint8 220 MB
uk-pt Helsinki-NLP/opus-mt-uk-pt f4fcafd143 apache-2.0 β€” int8 219 MB
bg-en Helsinki-NLP/opus-mt-bg-en 8a944b4e89 apache-2.0 β€” uint8 218 MB
bg-ru Helsinki-NLP/opus-mt-bg-ru 65b4db257a apache-2.0 β€” uint8 207 MB
bg-uk Helsinki-NLP/opus-mt-bg-uk bdd400e38f apache-2.0 β€” uint8 214 MB
cs-en Helsinki-NLP/opus-mt-cs-en 577d2053d2 apache-2.0 β€” uint8 220 MB
cs-ru Helsinki-NLP/opus-mt-tc-big-zlw-zle a20a48b682 cc-by-4.0 >>rus<< int8 560 MB
cs-uk Helsinki-NLP/opus-mt-cs-uk a0fed2bc39 apache-2.0 β€” int8 221 MB
da-en Helsinki-NLP/opus-mt-da-en 0960cff506 apache-2.0 β€” uint8 211 MB
da-ru Helsinki-NLP/opus-mt-da-ru f175c34aab apache-2.0 β€” int8 221 MB
el-en Helsinki-NLP/opus-mt-tc-big-el-en a691085627 cc-by-4.0 β€” uint8 546 MB
en-bg Helsinki-NLP/opus-mt-en-bg d7d00466d7 apache-2.0 >>bul<< uint8 218 MB
en-cs Helsinki-NLP/opus-mt-en-cs 2820c6a540 apache-2.0 β€” uint8 220 MB
en-da Helsinki-NLP/opus-mt-en-da 55d88cdf73 apache-2.0 β€” uint8 211 MB
en-el Helsinki-NLP/opus-mt-en-el 1653673990 apache-2.0 β€” uint8 226 MB
en-et Helsinki-NLP/opus-mt-en-et 624b0dc8ad apache-2.0 β€” uint8 211 MB
en-fi Helsinki-NLP/opus-mt-en-fi 2f68f12519 apache-2.0 β€” uint8 226 MB
en-ga Helsinki-NLP/opus-mt-en-ga 10337fc4a7 apache-2.0 β€” uint8 205 MB
en-hr Helsinki-NLP/opus-mt-en-zls f127a88f95 apache-2.0 >>hrv<< int8 208 MB
en-hu Helsinki-NLP/opus-mt-en-hu f2ee4d3f21 apache-2.0 β€” uint8 220 MB
en-lt Helsinki-NLP/opus-mt-tc-big-en-lt 2e08d64d80 cc-by-4.0 β€” uint8 545 MB
en-lv Helsinki-NLP/opus-mt-tc-big-en-lv ab7643b9b0 cc-by-4.0 >>lav<< uint8 543 MB
en-mt Helsinki-NLP/opus-mt-en-mt c0ce1eed30 apache-2.0 β€” uint8 204 MB
en-nl Helsinki-NLP/opus-mt-en-nl 8aad73b34f apache-2.0 β€” int8 231 MB
en-ro Helsinki-NLP/opus-mt-en-ro 96e8fea9e4 apache-2.0 β€” int8 212 MB
en-sk Helsinki-NLP/opus-mt-en-sk 04d19ccd45 apache-2.0 β€” uint8 214 MB
en-sl Helsinki-NLP/opus-mt-en-zls f127a88f95 apache-2.0 >>slv<< int8 208 MB
en-sv Helsinki-NLP/opus-mt-en-sv cec444c9ac apache-2.0 β€” uint8 205 MB
et-en Helsinki-NLP/opus-mt-et-en 8affd1fe86 apache-2.0 β€” uint8 211 MB
et-ru Helsinki-NLP/opus-mt-et-ru 856b8a4f29 apache-2.0 β€” uint8 221 MB
fi-en Helsinki-NLP/opus-mt-fi-en c4d8fff0f8 apache-2.0 β€” uint8 213 MB
fi-ru Helsinki-NLP/opus-mt-fi-ru a54f0b1fd0 apache-2.0 β€” uint8 221 MB
fi-uk Helsinki-NLP/opus-mt-fi-uk 282494b0f5 apache-2.0 β€” int8 220 MB
ga-en Helsinki-NLP/opus-mt-ga-en 277e70d7e2 apache-2.0 β€” uint8 205 MB
hr-en Helsinki-NLP/opus-mt-sla-en 90572be08b apache-2.0 β€” uint8 211 MB
hu-en Helsinki-NLP/opus-mt-hu-en cdf0ec884d apache-2.0 β€” uint8 220 MB
hu-uk Helsinki-NLP/opus-mt-hu-uk 0119c93b84 apache-2.0 β€” uint8 221 MB
lt-en Helsinki-NLP/opus-mt-tc-big-lt-en 19488d4ca3 cc-by-4.0 β€” uint8 545 MB
lt-ru Helsinki-NLP/opus-mt-lt-ru 174c2eb5a7 apache-2.0 β€” int8 221 MB
lv-en Helsinki-NLP/opus-mt-lv-en 580a8981c4 apache-2.0 β€” int8 208 MB
lv-ru Helsinki-NLP/opus-mt-lv-ru 700df1d717 apache-2.0 β€” uint8 221 MB
mt-en Helsinki-NLP/opus-mt-mt-en cb8bd173e2 apache-2.0 β€” uint8 204 MB
nl-en Helsinki-NLP/opus-mt-nl-en 48af999f2c apache-2.0 β€” uint8 231 MB
nl-uk Helsinki-NLP/opus-mt-nl-uk 1742f20a59 apache-2.0 β€” uint8 220 MB
ro-en Helsinki-NLP/opus-mt-roa-en c26705dd23 apache-2.0 β€” uint8 226 MB
ro-uk Helsinki-NLP/opus-mt-tc-base-ro-uk 9c5015a0da cc-by-4.0 β€” uint8 215 MB
ru-bg Helsinki-NLP/opus-mt-ru-bg 3c890c5082 apache-2.0 >>bul<< uint8 207 MB
ru-cs Helsinki-NLP/opus-mt-tc-big-zle-zlw e14020b995 cc-by-4.0 >>ces<< uint8 560 MB
ru-da Helsinki-NLP/opus-mt-ru-da 74f44f5b0e apache-2.0 β€” uint8 221 MB
ru-et Helsinki-NLP/opus-mt-ru-et 182a132893 apache-2.0 β€” uint8 221 MB
ru-lv Helsinki-NLP/opus-mt-ru-lv 4a27faad08 apache-2.0 β€” uint8 221 MB
ru-sk Helsinki-NLP/opus-mt-tc-big-zle-zlw e14020b995 cc-by-4.0 >>slk<< uint8 560 MB
ru-sl Helsinki-NLP/opus-mt-ru-sl c63e1a2871 apache-2.0 β€” uint8 222 MB
ru-sv Helsinki-NLP/opus-mt-ru-sv 8e629b2a57 apache-2.0 β€” int8 221 MB
sk-en Helsinki-NLP/opus-mt-sk-en dd1de0d53e apache-2.0 β€” uint8 214 MB
sk-ru Helsinki-NLP/opus-mt-tc-big-zlw-zle a20a48b682 cc-by-4.0 >>rus<< uint8 560 MB
sk-uk Helsinki-NLP/opus-mt-tc-big-zlw-zle a20a48b682 cc-by-4.0 >>ukr<< int8 560 MB
sl-en Helsinki-NLP/opus-mt-sla-en 90572be08b apache-2.0 β€” int8 211 MB
sl-ru Helsinki-NLP/opus-mt-sl-ru 64dbe987d2 apache-2.0 β€” uint8 221 MB
sl-uk Helsinki-NLP/opus-mt-sl-uk 85eab654bd apache-2.0 β€” uint8 221 MB
sv-en Helsinki-NLP/opus-mt-sv-en 202cf62400 apache-2.0 β€” uint8 205 MB
sv-ru Helsinki-NLP/opus-mt-sv-ru 60f8c287a1 apache-2.0 β€” uint8 219 MB
sv-uk Helsinki-NLP/opus-mt-sv-uk 98be9a979a apache-2.0 β€” int8 218 MB
uk-bg Helsinki-NLP/opus-mt-uk-bg 1b1eec8127 apache-2.0 β€” int8 214 MB
uk-cs Helsinki-NLP/opus-mt-uk-cs 658abd2632 apache-2.0 β€” uint8 221 MB
uk-fi Helsinki-NLP/opus-mt-uk-fi 82dd04cc5b apache-2.0 β€” uint8 220 MB
uk-hu Helsinki-NLP/opus-mt-uk-hu 58ce74387a apache-2.0 β€” uint8 221 MB
uk-nl Helsinki-NLP/opus-mt-uk-nl e2924abff4 apache-2.0 β€” int8 220 MB
uk-ro Helsinki-NLP/opus-mt-tc-base-uk-ro 80e56360cf cc-by-4.0 >>ron<< uint8 215 MB
uk-sk Helsinki-NLP/opus-mt-tc-big-zle-zlw e14020b995 cc-by-4.0 >>slk<< uint8 560 MB
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Model tree for AndrPixel/opus-mt-mobile-onnx

Quantized
(9)
this model