No description
  • Python 36.7%
  • JavaScript 26.9%
  • CSS 20.5%
  • HTML 11%
  • Dockerfile 4.9%
Find a file
2026-04-30 15:23:24 +02:00
backend first commit 2026-04-30 15:23:24 +02:00
frontend first commit 2026-04-30 15:23:24 +02:00
docker-compose.yml first commit 2026-04-30 15:23:24 +02:00
README.md first commit 2026-04-30 15:23:24 +02:00

Traducteur Local — Suite de traduction auto-hébergée

Traduction automatique privée, basée sur MarianMT (Helsinki-NLP).
Zéro donnée envoyée à l'extérieur. Zéro dépendance cloud. Tourne sur votre machine.


Démarrage en 3 commandes

git clone https://github.com/vous/translation-suite.git
cd translation-suite
mkdir -p models && sudo chown 1001:1001 models   # évite une PermissionError au premier téléchargement
docker compose up -d

L'interface est disponible sur http://localhost:3000

Premier lancement : le premier appel de traduction télécharge le modèle MarianMT correspondant (~300 Mo par paire de langues). Les suivants utilisent le cache local. Vous verrez un indicateur de chargement pendant ce téléchargement initial.


Prérequis

Outil Version minimale
Docker 24.x
Docker Compose v2.x (docker compose, pas docker-compose)
RAM disponible 1 Go (standard) · 512 Mo (minimal, MAX_LOADED_MODELS=1)
Espace disque 300 Mo par paire de langues téléchargée

Architecture

translation-suite/
├── backend/                  # Moteur de traduction (FastAPI + MarianMT)
│   ├── main.py               # Point d'entrée, logging, middleware
│   ├── translator.py         # Logique MarianMT, pivot EN, cache LRU
│   ├── routes.py             # Endpoints /translate /languages /health
│   ├── requirements.txt      # Dépendances Python (versions figées)
│   └── Dockerfile            # Multi-stage, CPU only, non-root
├── frontend/                 # Interface web statique
│   ├── index.html            # Structure HTML, zéro CDN
│   ├── style.css             # Thème clair/sombre, responsive
│   ├── app.js                # Logique UI, appels API, historique
│   ├── config.js             # URL backend configurable
│   ├── nginx.conf            # Proxy /api/, headers sécurité, logs privacy
│   └── Dockerfile            # nginx:alpine, ~8 Mo
├── models/                   # Modèles téléchargés (volume persistant, gitignore)
├── docker-compose.yml
└── .env.example

Flux d'une traduction :

Navigateur → Nginx :3000 → /api/translate → Backend :8000 → MarianMT (CPU) → Réponse

Le backend n'est jamais exposé directement à l'extérieur en production.


Configuration

Copiez .env.example en .env et ajustez :

cp .env.example .env
Variable Défaut Description
MAX_LOADED_MODELS 3 Modèles simultanés en RAM (~300 Mo chacun)
WARMUP_PAIR (vide) Pré-charger un modèle au démarrage (ex: fr-en)
LOG_LEVEL INFO DEBUG · INFO · WARNING · ERROR
TRANSFORMERS_OFFLINE 0 1 = bloque tout téléchargement (mode air-gap)
CORS_ORIGINS * Restreindre en production : http://localhost:3000
FRONTEND_PORT 3000 Port exposé pour l'interface

Ajuster la consommation mémoire

Profil MAX_LOADED_MODELS RAM utilisée Cas d'usage
Minimal 1 ~400 Mo Raspberry Pi, NAS
Standard 3 ~1 Go VPS 2 Go
Large 6 ~2 Go VPS 4 Go ou machine locale

Modifiez dans docker-compose.yml ou .env, puis :

docker compose up -d --force-recreate backend

Gestion des modèles de traduction

Comment les modèles sont chargés

Les modèles Helsinki-NLP/opus-mt sont téléchargés automatiquement au premier appel pour chaque paire de langues demandée, puis conservés dans ./models/ pour tous les appels suivants.

./models/
├── opus-mt-fr-en/     # Français → Anglais
├── opus-mt-en-de/     # Anglais → Allemand
└── opus-mt-fr-de/     # Français → Allemand (si disponible)

Logique de pivot automatique

Si aucun modèle direct fr → de n'existe, le backend traduit automatiquement via l'anglais : fr → en → de. La réponse inclut "pivot_used": true pour vous en informer. Ce mécanisme est transparent pour l'utilisateur.

Pré-télécharger des modèles manuellement

Pour éviter la latence du premier appel (utile avant une démo ou en mode offline) :

# Exemple : pré-télécharger français ↔ anglais
docker compose run --rm backend python -c "
from translator import translate
translate('test', 'fr', 'en')
translate('test', 'en', 'fr')
print('Modèles téléchargés.')
"

Supprimer un modèle

rm -rf ./models/opus-mt-fr-en/

Il sera retéléchargé au prochain appel si TRANSFORMERS_OFFLINE=0.

Mode air-gap (zéro réseau)

Pré-téléchargez tous les modèles nécessaires, puis :

# Dans .env
TRANSFORMERS_OFFLINE=1

Le backend refusera tout téléchargement réseau. Toute paire de langues absente retournera une erreur 404 claire.


Compatibilité DeepLX

Ce backend est compatible avec le format de requête/réponse DeepLX, ce qui permet de l'utiliser avec des extensions navigateur comme DeepL for Chrome ou tout outil attendant une API DeepL auto-hébergée.

Configuration d'une extension compatible DeepLX

Dans les paramètres de votre extension, renseignez :

URL de l'API : http://localhost:3000/api/translate
               (ou http://votre-serveur:3000/api/translate)
Clé API      : (laisser vide ou mettre n'importe quelle valeur)

Exemple d'appel direct

curl -s -X POST http://localhost:3000/api/translate \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Bonjour le monde",
    "source_lang": "fr",
    "target_lang": "en"
  }' | jq .

Réponse :

{
  "code": 200,
  "data": "Hello world",
  "source_lang": "fr",
  "target_lang": "en",
  "alternatives": [],
  "pivot_used": false,
  "elapsed_ms": 412
}

Endpoints disponibles

Méthode Endpoint Description
POST /api/translate Traduit un texte (compatible DeepLX)
GET /api/languages Liste les langues disponibles
GET /api/health Statut du service (healthcheck)
GET /api/docs Documentation Swagger interactive

Déploiement sur VPS

Exposer via un reverse proxy (recommandé)

Exemple avec Nginx sur l'hôte (sans SSL géré par ce projet) :

server {
    listen 443 ssl;
    server_name translate.mondomaine.fr;

    ssl_certificate     /etc/letsencrypt/live/translate.mondomaine.fr/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/translate.mondomaine.fr/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_read_timeout 180s;
    }
}

En production, commentez le ports du backend dans docker-compose.yml pour qu'il ne soit accessible que via le réseau interne Docker.

Commandes utiles

# Voir les logs en temps réel
docker compose logs -f

# Logs backend uniquement (sans le contenu traduit)
docker compose logs -f backend

# Statut des conteneurs
docker compose ps

# Redémarrer uniquement le backend (ex: après changement de config)
docker compose restart backend

# Mettre à jour (rebuild des images)
docker compose up -d --build

# Arrêter sans supprimer les volumes
docker compose stop

# Arrêter et supprimer les conteneurs (les modèles dans ./models/ sont conservés)
docker compose down

Engagement Zéro Donnée Externe

Ce projet est conçu par construction pour ne jamais transmettre vos textes à l'extérieur :

  • Traduction locale — Les modèles MarianMT tournent entièrement sur votre machine. Aucune requête de traduction ne quitte votre serveur.
  • Logs sans contenu — Les logs du backend enregistrent uniquement les codes de langue, les temps de réponse et les erreurs techniques. Le texte traduit n'y figure jamais.
  • Historique navigateur — L'historique des traductions est stocké dans le localStorage de votre navigateur. Il n'est jamais envoyé au serveur, même local.
  • Zéro CDN — Le frontend ne charge aucune ressource externe (pas de Google Fonts, pas de bibliothèque JS depuis un CDN). Tout est servi localement.
  • Télémétrie désactivéeHF_HUB_DISABLE_TELEMETRY=1 est positionné par défaut : HuggingFace ne reçoit aucune statistique d'utilisation.
  • Téléchargement unique — Les modèles sont téléchargés une seule fois depuis HuggingFace lors du premier appel, puis conservés localement. Les appels suivants sont 100% offline.

Licence

Ce projet est distribué sous licence GNU Affero General Public License v3.0 (AGPLv3).

Cela signifie que toute modification de ce code, y compris si vous l'utilisez pour fournir un service en ligne, doit être publiée sous la même licence. Voir le fichier LICENSE pour le texte complet.