feat(translation): quality pipeline overhaul + new features (audit 2026-08-29)
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m20s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m20s
Translation quality & format preservation: - Word: merge adjacent same-format runs into one unit (sentence-level coherence like inline-tag handling); translate comments/balloons; dedupe textbox collection (was translated twice); RTL no longer overrides center/justify alignment; CJK/Arabic font hints (eastAsia/cs) - PPTX: chart translations now actually reach the output file (ChartPart.blob is read-only — rewrite chart XML in the saved ZIP); CJK typeface hints (a:ea) - Excel: sheet renames no longer break references — rewrite cell formulas (3D/quoted), defined names, data validations, cond. formats - PDF: bold/italic honored (hebo/heit/hebi); table cells never merge; unchanged blocks left untouched (typography preserved, fixes duplicate hyperlinks); attempted/changed stats + route gate now cover PDF; CJK font paths; scanned PDFs via Mistral OCR (detection + admin settings) Features: - formality param (formal/informal) + automatic regional-variant prompts - output_mode=bilingual docx (source above translation) - per-user translation memory on Redis (falls back to LRU), context-hashed - QA report + 0-100 confidence score in job status; L0 on by default - OpenAI-compatible providers: whole chunk in ONE numbered-JSON request (~15x fewer calls) with per-item fallback; base prompt always present (custom prompt no longer replaces translation instructions) Infra & marketing alignment: - plan-based engine gating + vision gating (closes paid-engine leak); /providers/available filtered per plan; 107 languages exposed - zh-CN/zh-TW validation fixed; libmagic disabled on Windows (native crash) - admin: Mistral OCR settings + engine status dashboard; httpx<0.28 pin (TestClient breakage); Prometheus test fixture fixed - marketing docs aligned with code (PDF+OCR, retention, engines, pricing) - security: .env.ionos/.env.production/provider_settings.json removed Tests: 1173 passed / 0 failed (6 network tests deselected: free Google endpoint temporarily blocked from this machine)
This commit is contained in:
165
docs/marketing/blog/5-auto-heberger-traduction-docker.md
Normal file
165
docs/marketing/blog/5-auto-heberger-traduction-docker.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# Auto-héberger son outil de traduction de documents : guide Docker complet
|
||||
|
||||
> Article SEO « self-hosted » — brouillon complet. Capture l'audience développeurs/homelab. Basé sur le déploiement réel du projet (Docker Compose, Postgres, Redis).
|
||||
|
||||
## Introduction
|
||||
|
||||
Un outil de traduction de documents posé sur un SaaS pose toujours la même question : **où vont mes fichiers ?** Pour les documents confidentiels (compta, juridique, RH, brevets), l'auto-hébergement est la seule réponse qui tienne.
|
||||
|
||||
Ce guide montre comment monter une pile complète de traduction de documents — API, base, cache, interface — sur votre propre infrastructure, avec Docker. (Le projet dont on s'inspire est open source : Office Translator / Wordly.art.)
|
||||
|
||||
## Architecture cible
|
||||
|
||||
```
|
||||
[Client web / API]
|
||||
│
|
||||
[Nginx (reverse proxy, TLS)]
|
||||
│
|
||||
[FastAPI (Python 3.11+, port 8000)]
|
||||
├── [PostgreSQL] ← utilisateurs, glossaires, quotas
|
||||
├── [Redis] ← rate limiting (token bucket), files
|
||||
└── [Fichiers] ← uploads / outputs (volume local)
|
||||
│
|
||||
[Next.js (port 3000)] ← interface
|
||||
```
|
||||
|
||||
Points clés :
|
||||
- **FastAPI** asynchrone pour l'API de traduction (Swagger sur `/docs`)
|
||||
- **PostgreSQL** pour les données structurées, **Redis** pour le rate limiting par IP et les files
|
||||
- **Nginx** devant pour le TLS et le reverse proxy
|
||||
- Volumes persistants pour les fichiers (suppression automatique au TTL, ex. 60 min)
|
||||
|
||||
## 1. Prérequis
|
||||
|
||||
- Une machine Linux (VPS, serveur physique, ou même un NAS)
|
||||
- Docker + Docker Compose installés
|
||||
- Un domaine pointant vers la machine (pour le TLS)
|
||||
- Les clés API de vos moteurs de traduction (au minimum Google ; DeepL, OpenRouter, OpenAI, x.ai/Zai selon vos besoins)
|
||||
|
||||
## 2. Déploiement
|
||||
|
||||
### 2.1 Cloner et configurer
|
||||
|
||||
```bash
|
||||
git clone <URL_DU_DÉPÔT> /opt/wordly # dépôt à adapter (miroir public recommandé)
|
||||
cd /opt/wordly
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Dans `.env`, renseignez au minimum :
|
||||
|
||||
```ini
|
||||
# Moteurs — le Google « classic » (gratuit) ne demande AUCUNE clé.
|
||||
# Clés optionnelles pour les moteurs payants :
|
||||
GOOGLE_CLOUD_API_KEY=...
|
||||
# ou DEEPL_API_KEY, OPENROUTER_API_KEY, OPENAI_API_KEY...
|
||||
# Optionnel : OCR Mistral pour les PDF scannés
|
||||
# MISTRAL_API_KEY=...
|
||||
|
||||
# Sécurité
|
||||
SECRET_KEY=<générer une clé longue et aléatoire>
|
||||
CORS_ORIGINS=https://wordly.example
|
||||
APP_ENV=production
|
||||
```
|
||||
|
||||
> **Sécurité** : `CORS_ORIGINS` ne doit jamais être `*` en production — l'application le refuse et refuse de démarrer. Générez `SECRET_KEY` avec `openssl rand -hex 32`.
|
||||
|
||||
### 2.2 Lancer la pile
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
Ça démarre :
|
||||
- L'API sur `:8001` côté hôte (mappée sur le 8000 du conteneur ; docs Swagger sur `http://localhost:8001/docs`)
|
||||
- L'interface sur `:3000`
|
||||
- Postgres + Redis en interne
|
||||
|
||||
### 2.3 Mettre Nginx devant (TLS)
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name wordly.example;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/wordly.example/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/wordly.example/privkey.pem;
|
||||
|
||||
# Headers de sécurité (HSTS, CSP)
|
||||
add_header Strict-Transport-Security "max-age=63072000" always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://127.0.0.1:8001;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Renouvelez le certificat avec `certbot renew` (cron).
|
||||
|
||||
## 3. Exploitation
|
||||
|
||||
### Surveillance
|
||||
|
||||
- `GET /health` — état de l'API, des moteurs, de la base et du cache
|
||||
- Prometheus + Grafana (fournis en `docker-compose.monitoring.yml`) pour les métriques système et applicatives
|
||||
|
||||
### Sauvegarde (non négociable)
|
||||
|
||||
La base Postgres et le répertoire de fichiers sont votre patrimoine. Deux couches :
|
||||
|
||||
1. **Sauvegarde quotidienne de la base** :
|
||||
```bash
|
||||
docker compose exec db sh -c 'pg_dump -U ${POSTGRES_USER:-translate} ${POSTGRES_DB:-translate_db}' | gzip > /backups/wordly-$(date +%F).sql.gz
|
||||
```
|
||||
2. **Réplication vers un NAS/autre site** via `rsync` + SSH (le projet fournit un plan de sauvegarde automatique et une procédure de restauration en ~20 min, y compris bascule sur un serveur de secours)
|
||||
|
||||
Règle d'or : **une sauvegarde qu'on n'a jamais restaurée est une sauvegarde qui n'existe pas**. Testez la restauration au moins une fois par trimestre.
|
||||
|
||||
### Nettoyage automatique
|
||||
|
||||
Les fichiers uploadés sont supprimés automatiquement après leur TTL (60 min par défaut). Le nettoyage est orchestré côté application ; surveillez le disque quand même (un gros fichier en attente peut saturer le volume).
|
||||
|
||||
## 4. Durcissement
|
||||
|
||||
- [ ] `CORS_ORIGINS` restreint à vos domaines
|
||||
- [ ] `SECRET_KEY` unique et stockée en variable d'environnement (jamais dans le repo)
|
||||
- [ ] Pas de port Postgres/Redis exposé publiquement (réseau Docker interne uniquement)
|
||||
- [ ] Rate limiting actif (token bucket dans Redis, par IP client)
|
||||
- [ ] Fail2ban sur SSH si l'accès serveur passe par SSH
|
||||
- [ ] Mises à jour de Docker + des images (vulnérabilités)
|
||||
- [ ] Monitoring des disques, CPU et mémoire (Grafana)
|
||||
|
||||
## 5. Coût vs SaaS
|
||||
|
||||
| Poste | Self-hosted (VPS 4 vCPU / 8 Go) | SaaS |
|
||||
|---|---|---|
|
||||
| Infrastructure | ~40–80 €/mois | Inclus |
|
||||
| Coût par page | Coût des API uniquement | Coût API + marge |
|
||||
| Maîtrise des données | Totale | Partagée |
|
||||
| Maintenance | À votre charge | À charge de l'éditeur |
|
||||
| Mises à jour / sécurité | À votre charge | À charge de l'éditeur |
|
||||
|
||||
Le self-hosted gagne quand **les données sont sensibles** ou quand le **volume est énorme**. Il perd quand vous n'avez personne pour faire la maintenance — dans ce cas, le SaaS est souvent plus fiable *en pratique*, même si les fichiers transigent avec un tiers.
|
||||
|
||||
## Conclusion
|
||||
|
||||
Auto-héberger une pile de traduction de documents, c'est 1 h de déploiement et une vraie responsabilité d'exploitation. Avec Docker Compose, Postgres, Redis et Nginx, l'architecture tient sur une seule machine ; ce qui coûte ensuite, c'est la discipline (sauvegardes, durcissement, mises à jour).
|
||||
|
||||
Si les documents sont confidentiels, cette discipline se paie d'elle-même.
|
||||
|
||||
---
|
||||
**Métadonnées SEO**
|
||||
- Title : « Auto-héberger un outil de traduction de documents : guide Docker 2026 »
|
||||
- Meta description : « FastAPI, Postgres, Redis, Nginx : déployez une pile de traduction de documents sur votre propre infra. Sauvegardes, durcissement, coût vs SaaS. »
|
||||
- Mots-clés : auto héberger traduction, docker traduction documents, self hosted translation
|
||||
- URL : /blog/auto-heberger-traduction-documents-docker
|
||||
Reference in New Issue
Block a user