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)
104 lines
9.5 KiB
Markdown
104 lines
9.5 KiB
Markdown
# 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,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é** (`.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.
|