A self-hosted Flask API for multilingual neural machine translation with Meta's M2M100 model and CTranslate2. It exposes single and batch translation, validates M2M100 language codes, loads the model lazily, and includes Docker, CI and model-free contract tests.
The service is a cleaned, reusable version of translation components built for multilingual media workflows. It contains no company database schema, credentials, model weights or proprietary text.
- Direct translation between 100 languages without an English pivot
- CTranslate2 inference for lower memory use and faster CPU/GPU serving
- Single and batch JSON APIs
- Thread-safe tokenizer/model access
- Lazy loading and a lightweight health endpoint
- Environment-controlled device, compute type, beam size and request limits
- Compatibility routes for the original service contract
- Unit tests with an injected fake backend; CI downloads no model
client
-> Flask validation and request limits
-> M2M100 tokenizer
-> CTranslate2 model
-> decoded translations + elapsed time
Python 3.10+ is recommended.
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
ct2-transformers-converter \
--model facebook/m2m100_418M \
--output_dir models/m2m100_418M \
--quantization int8The converted model directory is deliberately ignored by Git. Review the upstream model licence before redistribution.
export M2M_MODEL_PATH=models/m2m100_418M
export M2M_TOKENIZER=facebook/m2m100_418M
gunicorn -c gunicorn.conf.py "app:app"PowerShell:
$env:M2M_MODEL_PATH = "models/m2m100_418M"
python app.pycurl http://localhost:5000/translate \
-H "Content-Type: application/json" \
-d '{"text":"Hello, how are you?","source_language":"en","target_language":"ja"}'{
"source_language": "en",
"target_language": "ja",
"translation": "こんにちは、お元気ですか?",
"elapsed_seconds": 0.123
}curl http://localhost:5000/translate/batch \
-H "Content-Type: application/json" \
-d '{"texts":["Good morning","Thank you"],"source_language":"en","target_language":"zh"}'Legacy POST /m2m_translate and POST /m2m_translate_youtube requests using question, from_code and to_code remain supported.
| Variable | Default | Purpose |
|---|---|---|
M2M_MODEL_PATH |
models/m2m100_418M |
Converted CTranslate2 model directory |
M2M_TOKENIZER |
facebook/m2m100_418M |
Hugging Face tokenizer ID or local path |
M2M_DEVICE |
cpu |
cpu, cuda or auto supported by CTranslate2 |
M2M_COMPUTE_TYPE |
int8 |
CTranslate2 compute type |
M2M_BEAM_SIZE |
4 |
Beam-search width |
MAX_TEXT_CHARS |
10000 |
Maximum characters per text |
MAX_BATCH_SIZE |
32 |
Maximum texts per batch |
PORT |
5000 |
Development server port |
python -m pip install -r requirements-dev.txt
ruff check .
pytest -qdocker build -t m2m100-service .
docker run --rm -p 5000:5000 \
-e M2M_MODEL_PATH=/models/m2m100_418M \
-v /absolute/path/to/models:/models:ro \
m2m100-service- Place authentication, TLS and rate limiting at an API gateway before Internet exposure.
- Size worker count against model memory; multiple Gunicorn workers load multiple model copies.
- Log language pair, latency and input length rather than raw private text.
- Evaluate translation quality on domain-specific held-out data before release.
- Add a durable queue when large subtitle or document batches must survive worker restarts.
Application code is MIT licensed. M2M100 model artefacts retain their upstream licence. M2M100 and Meta names belong to their respective owners; this independent project is not affiliated with or endorsed by Meta.