Files
office_translator/docs/marketing/PLAN-ALIGNEMENT-CODE.md
sepehr 526c87348f
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m20s
feat(translation): quality pipeline overhaul + new features (audit 2026-08-29)
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)
2026-08-29 18:38:09 +02:00

104 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Plan d'alignement Marketing ↔ Code — wordly.art
> Analyse effectuée le 2026-08-29, croisée ligne à ligne avec le code backend, la landing et les docs de lancement.
> Principe : **le lancement (Product Hunt / Show HN) attire des relecteurs techniques** — chaque promesse non tenue y sera testée publiquement. Ce plan sépare ce qu'il faut corriger **dans les textes** (rapide) de ce qu'il faut corriger **dans le code** (pour tenir les promesses).
>
> **Statut au 2026-08-29 : vagues A et B appliquées et testées (442 tests backend passent, `tsc --noEmit` landing OK). Restent les items P2 de la vague C.**
---
## 1. Ce qui est déjà conforme ✅
| Affirmation marketing | Vérification code | Statut |
|---|---|---|
| Prix 0/9/19/49 €, annuel 20 % (7,20/15,20/39,20) | `models/subscription.py:39-155` (86,40/182,40/470,40 €/an) | ✅ exact |
| Quotas 2/50/200/1 000 docs, pages 10/50/200/500, fichiers 5/10/25/50 Mo | idem | ✅ exact |
| API Business 10 000 appels/mois, 5 sièges | `api_calls_per_month: 10_000`, `team_seats: 5` | ✅ exact |
| Crédits 50/5 € · 100/9 € · 250/20 € · 500/35 € · 1 000/60 € (0,060,10 €) | `CREDIT_PACKAGES` (`models/subscription.py:316`) | ✅ exact |
| Landing : sections pricing/FAQ/preuve/waitlist + Vercel Analytics + waitlist endpoint + compteur | `app/page.tsx`, `components/*`, `routes/waitlist_routes.py` | ✅ en place |
| Événements analytics (`translation_started`, `pricing_cta_click`, `waitlist_joined`, `waitlist_error`) | présents dans les 3 composants | ✅ branchés |
| Footer sans « SOC 2 » | `app/page.tsx` — mention absente | ✅ corrigé |
| Blog Docker : « CORS `*` refuse de démarrer en prod » | `main.py:379-386` (`sys.exit`) | ✅ vrai |
| « DeepL moteur des plans payants » | Starter+ : `providers: ["google","deepl",…]` | ✅ exact |
| Blog 1 : « à partir de 0,06 €/page » | cohérent avec les crédits (1 page = 1 crédit de base) | ✅ |
---
## 2. Écarts détectés — promesses non tenues par le code
### E1. 🔴 « PDF is on the roadmap » (Show HN + Product Hunt) — FAUX, et ça cache une feature
- Show HN : *« (PDF is the obvious next one.) »* · Product Hunt : *« PDF is on the roadmap »*.
- **Réel : le PDF est déjà supporté** (`.pdf` dans `SUPPORTED_EXTENSIONS`, mode `layout`/`text_only`, pdf2docx fallback) **et depuis le 2026-08-29 les PDF scannés passent par OCR Mistral** (`services/mistral_ocr.py`) — ce que DeepL et Azure refusent.
- **C'est l'inverse : c'est un argument de vente majeur à ajouter.** Telle quelle, la phrase invite les relecteurs HN à trouver une fonctionnalité qui existe déjà dans le dashboard.
### E2. 🔴 « Files auto-deleted after 60 min » (landing, FAQ, Show HN, PH, Reddit, X, blogs 1/3) — inexact
- Réel (`config.py`) : uploads **30 min**, résultats **120 min**, TTL générique 60.
- Deux options : corriger le texte (« uploads deleted after 30 min, results within 2 h ») **ou** passer `OUTPUT_FILE_TTL_MINUTES` à 60. Recommandation : garder 120 min (l'utilisateur doit pouvoir re-télécharger) et corriger les textes.
### E3. 🔴 « Encrypted at rest » (FAQ §sécurité, X-thread, blog 3 §données) — non implémenté
- Aucun chiffrement des fichiers au repos dans le code (uploads/outputs en clair). TLS : dépend du reverse-proxy (vrai en prod nginx+HSTS).
- **À retirer des textes** tant que non implémenté (ou implémenter, cf. §3-C5).
### E4. 🟠 « 60+ langues » (landing stats, PH, X-thread) — l'app en expose 35
- Réel : `/api/v1/languages` = **35 langues** ; le sélecteur UI = 35. (Le validateur accepte ~100 codes, mais invisibles pour l'utilisateur.)
- Options : (a) corriger le chiffre en « 35 », (b) **exposer les ~60-100 langues déjà validées** côté API/UI — recommandé, c'est un travail faible et les LLM couvrent ces langues.
### E5. 🟠 « 7 moteurs » avec Minimax et DeepSeek cités (FAQ, Show HN) — incohérent avec les plans
- Réel (`models/subscription.py`) : Business = `google, google_cloud, deepl, openrouter, openrouter_premium, openai, zai`**ni Minimax ni DeepSeek direct** (DeepSeek n'est que le modèle IA « essentiel » interne).
- Harmoniser : retirer Minimax/DeepSeek des listes, **ou** les ajouter au plan Business (l'endpoint `/providers/available` les expose déjà à l'UI !).
### E6. 🟡 « 100 % formatting preserved » (landing, comparatif, x-thread) — survendu
- Cas limites réels : PDF scannés (sortie re-mise en page, pas d'« in place »), placeholders `[translation overflow]` sur débordements, texte dans images non traduit sans l'option vision.
- Recommandation : garder la promesse forte mais crédible (« formatting preserved — formulas, merges, styles ») + publier une page « limites connues ». Sur HN, un contre-exemple suffira à casser le « 100 % ».
### E7. 🟠 Blog Docker (auto-hébergement) : 4 erreurs factuelles
1. `GOOGLE_TRANSLATE_API_KEY=...` : **cette variable n'existe pas** — le moteur Google gratuit n'a pas de clé ; le moteur payant = `GOOGLE_CLOUD_API_KEY`. Remplacer par un exempilaire réel du `.env.example`.
2. `pg_dump -U wordly wordly` : les défauts du compose sont **`translate` / `translate_db`**.
3. « L'API sur :8000 » : le compose publie **8001:8000** → c'est `:8001` côté hôte.
4. `git clone https://gitea.parsanet.org/...` : repo privé → rendre public ou générer (`github.com/<org>/office-translator`).
### E8. 🟠 Le backend n'applique PAS la grille « moteurs par plan » (fuite de revenus)
- Dans `translate_document_v1`, seul `google_cloud` est rétrogradé pour les non-Pro. **Un Free peut envoyer `provider=openai` ou `openrouter_premium`** et consommer les moteurs vendus 49 €/mois. La grille existe pourtant dans `PLANS[plan]["providers"]`.
- Idem : **`translate_images` (vision) n'est pas gated**, alors que la FAQ dit « Pro and Business plans ».
---
## 3. Plan d'action
### Vague A — Avant lancement (textes, ~½ journée) — P0 ✅ APPLIQUÉE
| # | Action | Fichiers | Statut |
|---|---|---|---|
| A1 | Remplacer « PDF on the roadmap » par la feature : « PDF supported — incl. scanned PDFs via OCR » | `launch/show-hn.md`, `launch/product-hunt.md` | ✅ |
| A2 | Corriger la rétention : « uploads deleted after 30 min, results auto-deleted within 2 h » | landing `social-proof-section.tsx`, `faq-section.tsx`, `show-hn.md`, `product-hunt.md`, `reddit-posts.md`, `x-thread.md`, `blog/1`, `blog/3`, `MARKETING_PLAN.md` | ✅ |
| A3 | Supprimer « encrypted at rest » / « at rest » | `faq-section.tsx`, `x-thread.md`, `blog/3` | ✅ |
| A4 | Blog Docker : clé `GOOGLE_CLOUD_API_KEY`, `pg_dump` translate/translate_db, port hôte 8001, URL de dépôt générique, + mention MISTRAL_API_KEY | `blog/5-auto-heberger-traduction-docker.md` | ✅ |
| A5 | Ajouter PDF (+ OCR scannés) aux formats annoncés : hero, badges `.pdf`, drag & drop + `accept` PDF, FAQ formats | `hero-section.tsx`, `translation-card.tsx`, `faq-section.tsx` | ✅ |
### Vague B — Semaine 1 (code, ~2-3 j) — P1 ✅ APPLIQUÉE
| # | Action | Détail | Statut |
|---|---|---|---|
| B1 | **Gating moteurs par plan** : `translate_document_v1` rejette (403 `PRO_FEATURE_REQUIRED`) tout `provider` hors `PLANS[tier]["providers"]` ; helpers testés (`tests/test_plan_gating.py`) ; `/providers/available` filtré par plan (l'UI ne propose plus un moteur refusé) | ferme la fuite de revenus E8 | ✅ |
| B2 | Gater `translate_images` aux plans Pro+ | la FAQ redevient exacte | ✅ |
| B3 | Langues : `/api/v1/languages` expose désormais **107 langues nommées** (35 populaires d'abord, puis ordre alphabétique ; `LANGUAGE_NAMES` complété) → la promesse « 60+ » est tenue | E4 résolu par le code | ✅ |
| B4 | Moteurs harmonisés : Minimax/DeepSeek retirés des listes marketing (DeepSeek présenté « via OpenRouter ») ; cohérent avec le filtrage du catalogue | résout E5 | ✅ |
### Vague C — Avant le scale — P2
| # | Action | Détail |
|---|---|---|
| C1 | Remplacer « 100 % » par une promesse démontrable + page « limites connues » (PDF scannés re-mis en page, overflow, images) | E6 |
| C2 | Si l'argument « chiffré au repos » est voulu : chiffrer `uploads/`+`outputs/` (clé env `FILES_ENCRYPTION_KEY`, chiffrement AES au write/read) alors seulement réintroduire la mention | E3 |
| C3 | Mettre à jour `MARKETING_PLAN.md` : ajouter PDF + OCR scannés aux différenciateurs (vs DeepL/Azure qui refusent les scannés), mentionner webhooks & API keys | valorise l'existant |
| C4 | Décider TTL outputs : si la promesse « 60 min » est gardée, passer `OUTPUT_FILE_TTL_MINUTES=60` au lieu de changer 9 textes | alternative à A2 |
| C5 | NPS « enquête post-traduction » (source KPI dans MARKETING_PLAN §6) : non implémenté — retirer la ligne ou créer le mini-formulaire post-download | KPIs honnêtes |
### Decision needed (propriétaire) — ✅ TRANCHÉES LE 2026-08-29
- **Rétention** : textes corrigés (A2) — les TTL code restent 30 min / 120 min.
- **Langues** : 107 exposées via `/languages` (B3) — la promesse « 60+ » est tenue.
- **Minimax/DeepSeek** : retirés du discours commercial (DeepSeek mentionné « via OpenRouter ») ; plans inchangés.
---
## 4. Résumé
Le socle commercial du document marketing est **fiable** (prix, quotas, crédits, API, landing, waitlist, analytics : tout correspond au code). Les écarts se concentrent sur **6 chiffres/affirmations répétées** (60 min, 60+ langues, 7 moteurs, 100 %, chiffrement au repos, « PDF à venir ») et **2 trous d'application côté code** (gating moteurs et vision par plan). Les vagues A (textes) et B (code) suffisent pour un lancement PH/HN sans Vulnerabilité factuelle.