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)
9.5 KiB
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 --noEmitlanding 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,06–0,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é (
.pdfdansSUPPORTED_EXTENSIONS, modelayout/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/availableles 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
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.pg_dump -U wordly wordly: les défauts du compose sonttranslate/translate_db.- « L'API sur :8000 » : le compose publie 8001:8000 → c'est
:8001côté hôte. 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, seulgoogle_cloudest rétrogradé pour les non-Pro. Un Free peut envoyerprovider=openaiouopenrouter_premiumet consommer les moteurs vendus 49 €/mois. La grille existe pourtant dansPLANS[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.