fix: integrate deepseek, resolve silent google api errors, fix google cloud keys
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2s

This commit is contained in:
2026-05-17 17:11:06 +02:00
parent 669cf7fde8
commit b50419e2ec
2062 changed files with 272359 additions and 523 deletions

View File

@@ -0,0 +1,92 @@
---
title: 'Reconstruire le parcours utilisateur glossaire'
type: 'refactor'
created: '2026-05-16'
status: 'draft'
context: []
---
<frozen-after-approval reason="human-owned intent — do not modify unless human renegotiates">
## Intent
**Problem:** L'utilisateur Pro voit DEUX liens "Glossaires" dans la sidebar à cause d'un doublon dans constants.ts (`baseNavItems` contient un item glossary + `proNavItem` est aussi un item glossary → `getNavItems(isPro=true)` retourne les deux). Le GlossarySelector sur la page de traduction est un petit dropdown caché, visible uniquement pour les Pro, sans label ni indication de son rôle. L'utilisateur ne comprend pas le cheminement: créer un glossaire → le sélectionner → traduire.
**Approach:** Corriger le doublon de navigation, rendre le GlossarySelector visible et explicatif pour TOUS les utilisateurs (les Free voient un badge "Pro"), supprimer la page Context obsolète, et ajouter un lien clair entre la page Glossaires et la page Traduction.
## Boundaries & Constraints
**Always:**
- Un seul lien "Glossaires" dans la sidebar, jamais deux
- Le GlossarySelector doit être visible sur la page de traduction pour TOUS les utilisateurs connectés
- Les utilisateurs Free doivent voir le sélecteur grisé avec un badge "Pro" (pas caché)
- Le system prompt reste sur la page Glossaires (déjà fusionné)
- Backend inchangé — seul le frontend est touché
**Ask First:** Aucune décision ambiguë — tout est clair.
**Never:**
- Ne pas toucher aux routes API ou au backend
- Ne pas recréer une page Context séparée
- Ne pas supprimer les presets professionnels (HVAC, IT, etc.)
## I/O & Edge-Case Matrix
| Scenario | Input / State | Expected Output / Behavior | Error Handling |
|----------|--------------|---------------------------|----------------|
| Utilisateur Pro voit la sidebar | isPro=true, page quelconque | Un seul lien "Glossaires" dans le menu | N/A |
| Utilisateur Free voit la sidebar | isPro=false | Aucun lien Glossaires (proOnly=true) | N/A |
| Utilisateur Free sur page traduction | isPro=false, mode LLM | GlossarySelector visible mais grisé, badge "Pro", clic → tooltip "Upgrade required" | N/A |
| Utilisateur Pro sur page traduction | isPro=true | GlossarySelector fonctionnel, dropdown avec ses glossaries | Toast si fetch échoue |
| Utilisateur avec 0 glossaries | glossaries=[] | Sélecteur affiche "Aucun glossaire — Créez-en un" avec lien vers /dashboard/glossaries | N/A |
| Utilisateur accède /dashboard/context par URL | N'importe quel état | Redirige vers /dashboard/glossaries | N/A |
</frozen-after-approval>
## Code Map
- `frontend/src/app/dashboard/constants.ts` -- Navigation: contient le doublon glossary (baseNavItems + proNavItem)
- `frontend/src/app/dashboard/translate/page.tsx` -- Page traduction: emplacement du GlossarySelector, conditions de visibilité
- `frontend/src/app/dashboard/translate/GlossarySelector.tsx` -- Composant dropdown de sélection de glossaire
- `frontend/src/app/dashboard/translate/useTranslationConfig.ts` -- Hook qui gère glossaryId
- `frontend/src/app/dashboard/context/page.tsx` -- Page obsolète à supprimer/remplacer par redirect
- `frontend/src/app/dashboard/glossaries/page.tsx` -- Page Glossaries fusionnée (OK, pas toucher)
## Tasks & Acceptance
**Execution:**
- [ ] `frontend/src/app/dashboard/constants.ts` -- Supprimer `proNavItem` et la fonction `getNavItems`, remettre les items proOnly dans `baseNavItems` avec le flag proOnly. Garder exactement 4 items: Translate, Profile, Glossaries (proOnly), API Keys (proOnly). -- Un seul lien glossary dans la sidebar, jamais de doublon.
- [ ] `frontend/src/app/dashboard/translate/GlossarySelector.tsx` -- Refactoriser: toujours rendre le composant visible (même pour Free). Si l'utilisateur n'est pas Pro: afficher le dropdown grisé avec badge "Pro" et tooltip "Upgrade required". Si l'utilisateur est Pro mais n'a pas de glossaries: afficher un message "Aucun glossaire" avec un lien cliquable vers /dashboard/glossaries. Ajouter le composant `useUser` ou recevoir `isPro` en prop. -- Tous les utilisateurs voient le sélecteur, les Free comprennent que c'est Pro.
- [ ] `frontend/src/app/dashboard/translate/page.tsx` -- Retirer la condition `config.isPro &&` autour du GlossarySelector. Placer le GlossarySelector à un endroit visible dans le panneau de config (entre ProviderSelector et le bouton Traduire). S'assurer que `isPro` est passé en prop au GlossarySelector. -- Le sélecteur est visible pour tous, pas caché derrière une condition.
- [ ] `frontend/src/app/dashboard/context/page.tsx` -- Remplacer tout le contenu par un redirect côté client vers `/dashboard/glossaries` (`useRouter` + `useEffect` ou `router.replace`). -- L'ancienne URL redirige proprement.
**Acceptance Criteria:**
- Given un utilisateur Pro connecté, when il regarde la sidebar, then il voit exactement UN lien "Glossaires"
- Given un utilisateur Free connecté, when il va sur la page de traduction, then il voit le GlossarySelector grisé avec un badge "Pro"
- Given un utilisateur Pro avec des glossaries, when il va sur la page de traduction, then il peut sélectionner un glossary dans le dropdown
- Given un utilisateur Pro sans glossary, when il va sur la page de traduction, then le sélecteur affiche "Aucun glossaire" avec un lien vers la page Glossaires
- Given n'importe quel utilisateur, when il accède /dashboard/context, then il est redirigé vers /dashboard/glossaries
## Spec Change Log
## Design Notes
**Parcours utilisateur attendu:**
1. L'utilisateur clique sur "Glossaires" dans la sidebar → arrive sur la page unifiée (system prompt + presets + CRUD glossaires)
2. L'utilisateur crée ou charge un glossaire (manuel, CSV, template)
3. L'utilisateur va sur "Traduire" → voit le sélecteur "Glossaire" en clair → sélectionne son glossaire → traduit
4. Le glossaire est appliqué automatiquement à la traduction
Le GlossarySelector doit recevoir `isPro` et `disabled` en props. Si `!isPro`, le composant se rend en mode "locked" (grisé + badge Pro). Si `isPro && glossaries.length === 0`, afficher un CTA vers la page glossaires.
## Verification
**Commands:**
- `cd frontend && npx next build --webpack` -- expected: build réussi sans erreurs TypeScript
**Manual checks:**
- Sidebar Pro: exactement un lien Glossaires
- Sidebar Free: aucun lien Glossaires
- Page traduction Free: GlossarySelector visible mais grisé avec badge Pro
- Page traduction Pro: GlossarySelector fonctionnel
- URL /dashboard/context: redirige vers /dashboard/glossaries

View File

@@ -0,0 +1,511 @@
# Cahier des Charges — Refonte Design & Positionnement IA
**Auteur** : Mary (Business Analyst), basé sur l'audit du 2026-05-08
**Projet** : Office Translator
**Objectif** : Transformer l'IA d'une feature cachée en différentiateur central, et corriger les problèmes UX prioritaires
---
## 1. Contexte et Enjeux
### 1.1 État des lieux
Office Translator dispose d'un moteur de traduction IA complet (DeepSeek V3, Claude 3.5 Haiku, glossaires métier, system prompts, vision sur images). Cependant, l'audit révèle que :
- L'IA est **invisible** pour les utilisateurs Free (provider selector masqué)
- La landing page **ne mentionne pas** la traduction IA comme différenciateur principal
- Les métriques de qualité sont **fictives** (confiance 96% hardcodée, segments 142 hardcodés)
- Plusieurs pages mélangent **texte hardcodé et clés i18n**, cassant l'internationalisation
- Aucune section **"Comment ça marche"**, aucune **preuve sociale**, aucun **playground de démo**
### 1.2 Objectifs mesurables
| KPI | Actuel (estimé) | Cible |
|-----|-----------------|-------|
| Taux de conversion Free → Pro | < 2% | 5-8% |
| Taux de rebond landing page | Inconnu | -30% |
| Feature discovery IA (Free users) | ~0% | 80% |
| Score de confiance utilisateur | Variable (métriques fausses) | Données réelles, toujours pertinentes |
---
## 2. Périmètre des Travaux
### Phase 1 — Correction UX / i18n (P0)
### Phase 2 — Positionnement IA sur la Landing (P1)
### Phase 3 — Freemium IA & Conversion (P1)
### Phase 4 — Enrichissement Landing & Social Proof (P2)
### Phase 5 — Nettoyage technique (P3)
---
## 3. Phase 1 — Correction UX / i18n (P0)
### 3.1 Internationalisation des pages
**Problème** : Les pages `translate/page.tsx`, `services/page.tsx`, et `features-section.tsx` contiennent du texte hardcodé (anglais et français) au lieu d'utiliser les clés i18n.
#### 3.1.1 Page de traduction (`translate/page.tsx`)
Textes à migrer vers i18n :
| Texte hardcodé | Clé i18n proposée | Fichier |
|---|---|---|
| "Source Document" | `dashboard.translate.sourceDocument` | translate/page.tsx |
| "Configuration" | `dashboard.translate.configuration` | translate/page.tsx |
| "Traduction en cours" | `dashboard.translate.translating` | translate/page.tsx |
| "Moniteur en direct" | `dashboard.translate.liveMonitor` | translate/page.tsx |
| "Résumé" | `dashboard.translate.summary` | translate/page.tsx |
| "Moteur" | `dashboard.translate.engine` | translate/page.tsx |
| "Confiance" | `dashboard.translate.confidence` | translate/page.tsx |
| "Annuler" | `dashboard.translate.cancel` | translate/page.tsx |
| "Segments" | `dashboard.translate.segments` | translate/page.tsx |
| "Caractères" | `dashboard.translate.characters` | translate/page.tsx |
| "Écoulé" | `dashboard.translate.elapsed` | translate/page.tsx |
| "Seg/min" | `dashboard.translate.segPerMin` | translate/page.tsx |
| "Haute qualité" | `dashboard.translate.highQuality` | translate/page.tsx |
| "Qualité" | `dashboard.translate.quality` | translate/page.tsx |
| "Traduction terminée" | `dashboard.translate.completed` | translate/page.tsx |
| "Remplacer" | `dashboard.translate.replace` | translate/page.tsx |
| "PDF Translation Mode" | `dashboard.translate.pdfMode.title` | translate/page.tsx |
| "Preserve Layout" | `dashboard.translate.pdfMode.preserveLayout` | translate/page.tsx |
| "Text Only" | `dashboard.translate.pdfMode.textOnly` | translate/page.tsx |
| Descriptions PDF mode (2 paragraphes) | `dashboard.translate.pdfMode.preserveLayoutDesc` / `textOnlyDesc` | translate/page.tsx |
| Labels du pipeline (Upload, Analyse, Traduction, Reconstruction, Finalisation) | `dashboard.translate.pipeline.upload` etc. | translate/page.tsx |
**Critères d'acceptation** :
- Toutes les 13 locales (`en`, `fr`, `es`, `de`, `pt`, `it`, `nl`, `ru`, `ja`, `ko`, `zh`, `ar`, `fa`) doivent avoir une traduction pour chaque clé
- Aucun texte visible en dur dans le code source
- Test visuel sur 3 locales minimum (en, fr, fa) pour vérifier l'affichage
#### 3.1.2 Page Services (`services/page.tsx`)
Textes à migrer :
| Texte hardcodé | Clé i18n proposée |
|---|---|
| "Translation Providers" | `dashboard.services.title` |
| "Providers are configured by the administrator..." | `dashboard.services.subtitle` |
| "Classic Translation" | `dashboard.services.classicTitle` |
| "LLM · Context-Aware (Pro)" | `dashboard.services.llmTitle` |
| "Available" | `dashboard.services.available` |
| "Provider configuration is admin-only" | `dashboard.services.adminOnly.title` |
| Description du panneau admin | `dashboard.services.adminOnly.description` |
| "Loading providers..." | `dashboard.services.loading` |
| "No providers are currently configured..." | `dashboard.services.none` |
| "Model:" | `dashboard.services.model` |
#### 3.1.3 Composant features (`features-section.tsx`)
Ce composant est un composant legacy non utilisé par la landing actuelle (`landing-page.tsx` a sa propre section features). Il doit être soit supprimé, soit intégré avec i18n complète. Voir Phase 5 — section 7.3.
### 3.2 Métriques dynamiques
**Problème** : Les statistiques affichées pendant et après la traduction sont hardcodées et fictives.
#### 3.2.1 Données fictives identifiées
Fichier `translate/page.tsx`, lignes 128-129 :
```typescript
const totalSegments = 142;
const totalChars = 12847;
```
Et le score de confiance est calculé avec une formule arbitraire :
```typescript
Math.min(96, Math.round(82 + submit.progress * 0.14))
```
#### 3.2.2 Solution — Données réelles depuis le backend
**Backend** : L'endpoint de progression (`/api/v1/translate/{session_id}/progress`) doit retourner :
```json
{
"progress": 65,
"current_step": "Translating segment 87/134",
"total_segments": 134,
"completed_segments": 87,
"total_chars": 12450,
"completed_chars": 8092,
"elapsed_seconds": 23,
"estimated_remaining_seconds": 12,
"segments_per_minute": 227,
"provider": "openrouter"
}
```
**Frontend** : Remplacer les constantes hardcodées par les valeurs retournées par l'API de progression. Si l'API ne retourne pas ces champs, les calculer côté frontend à partir des données disponibles, ou afficher "—" au lieu d'un chiffre inventé.
**Critères d'acceptation** :
- Le nombre de segments affiché correspond au nombre réel de segments dans le document
- Le score de confiance est soit basé sur des métriques réelles, soit retiré et remplacé par un indicateur qualitatif ("Standard" / "Haute précision" selon le provider)
- Aucun chiffre fictif visible par l'utilisateur
### 3.3 Suppression du score de confiance fictif
Si le calcul d'un vrai score de confiance est trop complexe pour cette phase, remplacer par un indicateur qualitatif du provider :
| Provider | Label affiché |
|---|---|
| Google / LibreTranslate | "Traduction standard" |
| DeepL | "Haute qualité" |
| DeepSeek / LLM Essential | "IA Contextuelle" |
| Claude / LLM Premium | "IA Expert — Haute précision" |
Ce label remplace le pourcentage fictif "96%" et est purement informatif, basé sur le type de provider sélectionné.
---
## 4. Phase 2 — Positionnement IA sur la Landing (P1)
### 4.1 Nouvelle section "AI Translation Engine"
**Emplacement** : Sur la landing page (`landing-page.tsx`), entre le Hero et la section "Why Us" existante.
#### 4.1.1 Structure de la section
```
┌──────────────────────────────────────────────────────────┐
│ Badge : 🧠 AI-Powered Translation Engine │
│ │
│ Titre : La traduction qui comprend votre métier │
│ Sous-titre : Nos modèles IA analysent le contexte, │
│ respectent votre terminologie et traduisent même │
│ le texte dans vos images. │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 📋 Contexte │ │ 📖 Glossaire│ │ 👁️ Vision │ │
│ │ │ │ │ │ │ │
│ │ Décrivez │ │ Définissez │ │ Le texte │ │
│ │ votre │ │ vos termes │ │ dans les │ │
│ │ domaine │ │ métier │ │ images est │ │
│ │ technique │ │ (CTA=AHU) │ │ traduit │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ ┌──── Comparaison visuelle ────────────────────────┐ │
│ │ Source (FR) : "La batterie de chauffe est │ │
│ │ raccordée sur la CTA" │ │
│ │ │ │
│ │ Google : "The heating battery is connected │ │
│ │ on the call to action" ❌ │ │
│ │ │ │
│ │ Notre IA : "The heating coil is connected │ │
│ │ to the AHU" ✅ │ │
│ └────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
```
#### 4.1.2 Clés i18n de la section
| Clé | FR | EN |
|---|---|---|
| `landing.ai.badge` | Moteur de Traduction IA | AI-Powered Translation Engine |
| `landing.ai.title` | La traduction qui comprend votre métier | Translation that understands your craft |
| `landing.ai.subtitle` | Nos modèles IA analysent le contexte, respectent votre terminologie et traduisent même le texte dans vos images. | Our AI models analyze context, respect your terminology, and even translate text inside images. |
| `landing.ai.context.title` | Contexte métier | Industry Context |
| `landing.ai.context.desc` | Décrivez votre domaine et obtenez des traductions adaptées, pas génériques. | Describe your field and get tailored translations, not generic ones. |
| `landing.ai.glossary.title` | Glossaires métier | Industry Glossaries |
| `landing.ai.glossary.desc` | Définissez vos termes techniques. CTA restera "Air Handling Unit", jamais "Call To Action". | Define your technical terms. CTA stays "Air Handling Unit", never "Call To Action". |
| `landing.ai.vision.title` | Vision sur images | Image Vision |
| `landing.ai.vision.desc` | Le texte incrusté dans vos images, diagrammes et graphiques est détecté et traduit. | Text embedded in images, diagrams and charts is detected and translated. |
| `landing.ai.comparison.source` | Source (FR) | Source (FR) |
| `landing.ai.comparison.google` | Google Translate | Google Translate |
| `landing.ai.comparison.ai` | Notre IA | Our AI |
#### 4.1.3 Critères d'acceptation
- La section est responsive (mobile : colonne unique, desktop : 3 colonnes pour les features)
- L'exemple de comparaison est statique mais réaliste (pas d'appel API)
- L'animation au scroll est fluide (fade-in des cartes)
- La section est entièrement i18n-ready (13 locales)
### 4.2 Section "Comment ça marche"
**Emplacement** : Après la section AI Engine, avant "Why Us".
#### 4.2.1 Structure
```
┌──────────────────────────────────────────────────────────┐
│ Comment ça marche ? │
│ │
│ ① Déposez ② Configurez ③ Téléchargez │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ Upload │ ──▶ │ Choix │ ──▶ │ Fichier│ │
│ │ fichier│ │ langue │ │ traduit│ │
│ └────────┘ │ + IA │ │ + même │ │
│ └────────┘ │ format │ │
│ └────────┘ │
│ │
│ DOCX, XLSX, PPTX, PDF — Votre format est préservé │
└──────────────────────────────────────────────────────────┘
```
#### 4.2.2 Clés i18n
| Clé | FR | EN |
|---|---|---|
| `landing.howItWorks.title` | Comment ça marche ? | How it works |
| `landing.howItWorks.subtitle` | Trois étapes. Zéro perte de format. | Three steps. Zero formatting loss. |
| `landing.howItWorks.step1.title` | Déposez votre fichier | Upload your file |
| `landing.howItWorks.step1.desc` | Glissez-déposez votre document Excel, Word, PowerPoint ou PDF. | Drag & drop your Excel, Word, PowerPoint or PDF document. |
| `landing.howItWorks.step2.title` | Choisissez la langue et le moteur | Pick language & engine |
| `landing.howItWorks.step2.desc` | Sélectionnez la langue cible et le moteur de traduction — classique ou IA contextuelle. | Select target language and engine — standard or context-aware AI. |
| `landing.howItWorks.step3.title` | Téléchargez le résultat | Download the result |
| `landing.howItWorks.step3.desc` | Récupérez votre document traduit avec un formatage identique à l'original. | Get your translated document with formatting identical to the original. |
### 4.3 Refonte de la section "Why Us" existante
La section actuelle ("Why Us") se concentre sur la préservation du format. Elle doit intégrer l'IA comme dimension :
Ajouter 2 cartes aux 6 existantes :
| Carte | Icône | Clé i18n |
|---|---|---|
| Traduction IA contextuelle | `Brain` | `landing.why.aiContext.title` / `landing.why.aiContext.desc` |
| Glossaires personnalisés | `BookOpen` | `landing.why.glossary.title` / `landing.why.glossary.desc` |
Passer de 6 à 8 cartes, disposées en 2 lignes de 4 sur desktop, 4+4 sur tablette, colonne sur mobile.
---
## 5. Phase 3 — Freemium IA & Conversion (P1)
### 5.1 Visibilité du Provider Selector pour tous les utilisateurs
**Problème actuel** : `translate/page.tsx` ligne 339 : `{config.isPro && (<ProviderSelector ... />)}` — le sélecteur est complètement masqué pour les utilisateurs Free.
**Solution** : Afficher le Provider Selector pour tous les utilisateurs avec les providers LLM en état "verrouillé" :
```
┌─ Provider ──────────────────────────────────┐
│ ○ Google Traduction — 130+ langues │
│ ○ DeepL — Haute qualité │
│ │
│ ── ✨ AI · Context-Aware ─── PRO ── │
│ │
│ 🔒 DeepSeek V3 — Contexte + Glossaire │
│ 🔒 Claude 3.5 Haiku — Haute précision │
│ │
│ → Débloquer l'IA — Essai gratuit │
└──────────────────────────────────────────────┘
```
**Critères d'acceptation** :
- Les providers "classic" sont utilisables par tous
- Les providers LLM sont visibles mais grisés avec une icône 🔒
- Un CTA "Débloquer l'IA" apparaît sous les providers verrouillés
- Le CTA mène vers la page pricing avec ancre sur le plan Pro
- L'utilisateur Free peut toujours traduire avec les providers classiques
### 5.2 Quota de traductions IA gratuites
**Règle** : Chaque utilisateur Free dispose de **5 crédits IA** par mois.
#### 5.2.1 Backend — Compteur de crédits
- Ajouter un champ `ai_credits_used` et `ai_credits_limit` dans la table utilisateur
- Free : `ai_credits_limit = 5` par mois (reset au 1er de chaque mois)
- Starter : `ai_credits_limit = 0` (pas d'IA)
- Pro : `ai_credits_limit = -1` (illimité)
- Business : `ai_credits_limit = -1` (illimité)
#### 5.2.2 Endpoint API
```
GET /api/v1/auth/me
```
Ajouter dans la réponse :
```json
{
"ai_credits_used": 2,
"ai_credits_limit": 5,
"ai_credits_remaining": 3
}
```
```
POST /api/v1/translate
```
Si l'utilisateur sélectionne un provider LLM et `ai_credits_remaining <= 0`, retourner :
```json
{
"error": "ai_credits_exhausted",
"message": "Vous avez utilisé vos 5 traductions IA gratuites ce mois-ci. Passez au plan Pro pour un accès illimité.",
"upgrade_url": "/pricing"
}
```
#### 5.2.3 Frontend — Affichage du compteur
Dans le Provider Selector, quand un utilisateur Free a des crédits IA restants :
```
✨ AI · Context-Aware — 3/5 essais gratuits ce mois-ci
```
Quand les crédits sont épuisés :
```
✨ AI · Context-Aware — Essais épuisés → Voir les plans
```
### 5.3 Page de démo interactive (Mini-Playground)
**Emplacement** : Landing page, optionnel, section dédiée après la comparaison IA.
#### 5.3.1 Fonctionnement
L'utilisateur saisit une phrase technique (ou choisit un exemple prédéfini) et voit en temps réel la différence entre Google Translate et l'IA avec glossaire.
**Exemples prédéfinis** :
- "La batterie de chauffe est raccordée sur la CTA n°3" (HVAC)
- "Le serveur proxy reverse les requêtes vers le load balancer" (IT)
- "Le tribunal d'instance a prononcé la résiliation du bail" (Legal)
**Backend** : Endpoint dédié sans authentification :
```
POST /api/v1/demo/translate
{
"text": "La batterie de chauffe est raccordée sur la CTA",
"source_lang": "fr",
"target_lang": "en"
}
```
Réponse :
```json
{
"google": "The heating battery is connected on the CTA",
"ai": "The heating coil is connected to the AHU",
"glossary_applied": ["batterie=coil", "CTA=AHU"]
}
```
**Rate limiting** : Maximum 10 requêtes par IP par heure pour éviter l'abus.
**Critères d'acceptation** :
- Fonctionne sans inscription
- Affiche les deux résultats côte à côte
- Surligne les termes où le glossaire a été appliqué
- 3 exemples prédéfinis cliquables
- Champ libre pour saisie personnalisée
- Responsive mobile (résultats empilés)
---
## 6. Phase 4 — Enrichissement Landing & Social Proof (P2)
### 6.1 Section Preuve Sociale
**Emplacement** : Après "How it works", avant le pricing.
#### 6.1.1 Éléments
- **Compteur animé** : "X documents traduits ce mois-ci" (données réelles depuis l'admin dashboard)
- **Logos clients** (si disponibles) ou "Utilisé par des équipes dans X pays"
- **3 témoignages** (citations fictives mais réalistes en attendant de vrais retours) :
| Personne | Contexte | Citation |
|---|---|---|
| Marie D., Responsable CVC | "Nos documents techniques HVAC étaient toujours mal traduits. Avec les glossaires, c'est comme avoir un traducteur spécialisé." |
| Thomas K., DSI | "L'API s'est intégrée en une heure. 200 documents par mois, zéro retouche de mise en page." |
| Sophie L., Cabinet juridique | "Les contrats multilingues nécessitaient 2h de reformatage. Maintenant, c'est immédiat." |
#### 6.1.2 Clés i18n
| Clé | FR |
|---|---|
| `landing.social.title` | Ils traduisent plus intelligemment |
| `landing.social.subtitle` | Des professionnels dans 12 pays font confiance à Office Translator |
| `landing.social.documentsCount` | documents traduits ce mois-ci |
### 6.2 FAQ sur la Landing
Ajouter une section FAQ directement sur la landing page (pas seulement sur /pricing). Questions prioritaires :
1. "Quelle est la différence entre traduction classique et IA ?"
2. "Mon format sera-t-il vraiment préservé ?"
3. "Mes documents sont-ils sécurisés ?"
4. "Puis-je utiliser mes propres termes techniques ?"
5. "Quels formats de fichier sont supportés ?"
---
## 7. Phase 5 — Nettoyage technique (P3)
### 7.1 Suppression des composants legacy
Les fichiers suivants semblent être d'anciennes versions de la landing page, redondants avec `landing-page.tsx` :
- `components/landing/hero-section.tsx` — supprimer (le hero est dans `landing-page.tsx`)
- `components/landing/features-section.tsx` — supprimer (la section features est dans `landing-page.tsx`)
**Action** : Vérifier qu'aucun import ne référence ces fichiers, puis supprimer.
### 7.2 Vérification des imports
Avant suppression, vérifier avec `grep` qu'aucun composant n'importe `HeroSection` ou `FeaturesSection`.
### 7.3 Audit des clés i18n orphelines
Après la Phase 1, certaines clés i18n pourraient ne plus être utilisées. Faire un passage pour identifier et nettoyer les clés mortes.
---
## 8. Matrice de Dépendances
```
Phase 1 (i18n + métriques)
├── Bloque rien, mais tout le reste bénéficie d'une base propre
Phase 2 (Landing IA)
├── Dépend de Phase 1 pour les clés i18n de la landing
Phase 3 (Freemium IA)
├── Dépend partiellement de Phase 2 (CTA "Débloquer l'IA" vers pricing)
├── Backend indépendant (compteur crédits)
├── Mini-playground peut être parallélisé
Phase 4 (Social proof)
├── Indépendant des autres phases
├── Peut être fait en parallèle
Phase 5 (Nettoyage)
└── Faire en dernier, une fois que tout est stable
```
## 9. Estimation d'Effort
| Phase | Effort frontend | Effort backend | Complexité |
|---|---|---|---|
| Phase 1 — i18n + métriques | 2-3 jours | 1 jour (endpoint progress enrichi) | Moyenne |
| Phase 2 — Landing IA | 2 jours | 0 | Faible |
| Phase 3 — Freemium IA | 1 jour | 2 jours (crédits + demo endpoint) | Moyenne |
| Phase 3 — Mini-playground | 1.5 jours | 0.5 jour | Moyenne |
| Phase 4 — Social proof | 1 jour | 0 | Faible |
| Phase 5 — Nettoyage | 0.5 jour | 0 | Faible |
| **Total** | **~8 jours** | **~3.5 jours** | |
## 10. Risques et Mitigations
| Risque | Probabilité | Impact | Mitigation |
|---|---|---|---|
| L'endpoint de progression ne retourne pas les segments | Moyenne | Faible | Afficher "—" au lieu de chiffres faux, et itérer côté backend |
| Les 5 crédits IA Free génèrent un trafic excessif sur les LLM | Faible | Moyenne | Rate limiting strict par IP +监控 des coûts LLM |
| Les témoignages fictifs posent un problème éthique | Faible | Moyenne | Les marquer comme "exemples illustratifs" ou les remplacer par des beta-testeurs réels |
| Traduction de 13 locales pour toutes les nouvelles clés | Élevée | Faible | Commencer par EN + FR, ajouter les autres locales progressivement |
---
## 11. Critères de Succès Globaux
Le cahier des charges sera considéré comme rempli quand :
1. ✅ Aucun texte hardcodé visible dans les pages translate, services, landing
2. ✅ Les métriques de traduction reflètent la réalité du document en cours
3. ✅ La landing page comporte une section IA Engine avec comparaison visuelle
4. ✅ La landing page comporte une section "Comment ça marche"
5. ✅ Le Provider Selector est visible pour les utilisateurs Free (avec LLM verrouillé)
6. ✅ Les utilisateurs Free disposent de 5 crédits IA mensuels
7. ✅ Le score de confiance fictif est remplacé par un indicateur qualitatif réel
8. ✅ Les composants legacy sont supprimés

View File

@@ -0,0 +1,267 @@
# Brief Marketing — Office Translator
**Auteur** : Mary (Business Analyst)
**Date** : 2026-05-08
**Statut** : Brouillon — à affiner avec Sepehr
---
## 1. Positionnement
### 1.1 Énoncé de positionnement
**Office Translator est le seul outil de traduction de documents qui combine préservation parfaite du formatage ET traduction IA contextuelle avec glossaires métier.**
Pas seulement un traducteur. Un traducteur qui **comprend votre domaine** et vous rend un document **prêt à l'emploi**.
### 1.2 Catégorie
Traduction de documents professionnels — niche entre :
- Les traducteurs génériques (Google Translate, DeepL) → bon marché mais pas de format
- Les agences de traduction → qualité mais cher et lent
- Les outils de localisation (Phrase, Crowdin) → complexes et B2B lourd
**Notre sweet spot** : Professionnels et PME qui veulent de la qualité IA + du format préservé, sans l'overhead d'une agence.
### 1.3 Taglines candidates
| # | FR | EN | Ton |
|---|---|---|---|
| 1 | Traduisez vos documents. Gardez votre mise en page. | Translate your docs. Keep your layout. | Direct |
| 2 | L'IA qui parle votre métier. | The AI that speaks your industry. | Différenciant |
| 3 | Zéro retouche post-traduction. | Zero post-translation rework. | Bénéfice concret |
| 4 | Vos documents, traduits par une IA qui comprend votre vocabulaire. | Your documents, translated by AI that knows your vocabulary. | Technique |
**Recommandation** : #2 comme tagline secondaire (différenciant IA), #3 comme promesse principale (bénéfice concret).
---
## 2. Segments Cibles
### 2.1 Segmentation primaire
| Segment | Taille estimée | Pain point | Willingness to pay |
|---|---|---|---|
| **Ingénieurs CVC / HVAC** | Moyenne | Documents techniques mal traduits, termes spécifiques ignorés | Élevée (19-49€/mois) |
| **Cabinets d'ingénierie multinationaux** | Grande | Contrats, rapports, spécifications en 3+ langues | Élevée (49€+ / mois) |
| **Départements IT / DSI** | Grande | Documentation technique, wikis, procédures | Moyenne (9-19€/mois) |
| **Cabinets juridiques internationaux** | Moyenne | Contrats multilingues, clauses précises | Élevée (19-49€/mois) |
| **Professionnels de santé / pharma** | Moyenne | Protocoles, notices, rapports cliniques | Élevée (19-49€/mois) |
| **Freelances traducteurs** | Grande | Gain de productivité sur le post-traduction | Faible (9€/mois) |
### 2.2 Persona prioritaire #1 — L'ingénieur technique
- **Qui** : Ahmed, 35 ans, ingénieur CVC dans un bureau d'études franco-anglophone
- **Où** : Paris, Lyon, Casablanca, Dubaï
- **Pain** : Reçoit des spécifications techniques en anglais, doit les partager en français. Google Translate traduit "batterie" par "battery" au lieu de "coil". Passe 2h à corriger la mise en page.
- **Solution** : Glossaire HVAC intégré + IA contextuelle + format préservé
- **Canal** : LinkedIn, forums techniques HVAC, Google "traduction document technique"
### 2.3 Persona prioritaire #2 — La PME internationale
- **Qui** : Sophie, 42 ans, directrice juridique dans une PME franco-allemande
- **Où** : France, Allemagne, Suisse
- **Pain** : Contrats en FR/DE/EN à maintenir. Chaque traduction = 3 jours avec agence externe à 0.12€/mot.
- **Solution** : Traduction instantanée avec glossaire juridique + API pour automatiser
- **Canal** : Google "traduction contrat juridique", LinkedIn B2B, partenaires chambers of commerce
---
## 3. Messages Clés
### 3.1 Hiérarchie des messages
```
NIVEAU 1 — Promesse principale
"Zéro retouche post-traduction"
→ Le format est identique. Vous téléchargez, vous envoyez.
NIVEAU 2 — Différenciateur IA
"L'IA qui comprend votre vocabulaire métier"
→ Glossaires personnalisés, contexte technique, vision sur images.
NIVEAU 3 — Preuves
- Comparaison avant/après (Google vs IA)
- Démonstration interactive sur la landing
- Témoignages clients
NIVEAU 4 — Confiance
- Fichiers supprimés après traitement
- Pas de bait-and-switch sur les prix
- Aperçu du document avant traduction
```
### 3.2 Messages par segment
| Segment | Accroche | Bénéfice secondaire |
|---|---|---|
| Ingénieurs CVC | "CTA, batterie, groupe froid — votre glossaire, votre traduction" | Format Excel préservé : cellules fusionnées, formules, couleurs |
| Juridique | "Contrats traduits en 30 secondes, pas 3 jours" | Clauses exactes, terminologie légale certifiée |
| IT | "Documentation technique traduite à la volée" | API REST pour intégration CI/CD, webhooks |
| Santé | "Protocoles cliniques multilingues sans erreur" | Glossaire médical intégré, conformité terminologique |
---
## 4. Canaux d'Acquisition
### 4.1 Canaux digitaux (court terme)
| Canal | Action | Budget estimé | ROI attendu |
|---|---|---|---|
| **SEO** | Pages dédiées "traduction [format] [langue]" | 0€ (temps) | Élevé, long terme |
| **Google Ads** | Campagnes "traduction document", "translate xlsx" | 200-500€/mois | Moyen, immédiat |
| **Product Hunt** | Lancement coordonné | 0€ | Fort en visibilité |
| **Reddit** | Posts sur r/translator, r/hvac, r/sysadmin | 0€ | Moyen |
| **LinkedIn** | Posts techniques + cas d'usage | 0€ (organique) | Moyen |
| **Alternatives.to** | Listing sur les sites de comparaison | 0€ | Moyen |
### 4.2 Contenu SEO — Pages à créer
Ces pages capturent l'intention de recherche "long tail" à forte conversion :
| URL cible | Titre SEO | Mot-clé principal |
|---|---|---|
| `/translate/xlsx-to-english` | Traduire un fichier Excel en anglais en gardant le format | traduire xlsx anglais |
| `/translate/docx-french-english` | Traduction Word français-anglais — format préservé | traduction word français anglais |
| `/translate/pptx-online` | Traduire PowerPoint en ligne gratuitement | traduire powerpoint en ligne |
| `/translate/hvac-documents` | Traduction de documents techniques CVC/HVAC | traduction documents techniques |
| `/translate/legal-documents` | Traduction de contrats et documents juridiques | traduction contrats juridiques |
| `/translate/pdf-online` | Traduire un PDF en ligne en gardant la mise en page | traduire pdf en ligne |
### 4.3 Partenariats (moyen terme)
| Partenaire | Type | Action |
|---|---|---|
| Chambers of commerce franco-étrangères | Visibilité | Offrir des essais Pro aux membres |
| Éditeurs de logiciels CVC (Danfoss, Carrier) | Intégration | Plugin/glossaire pré-intégré |
| Écoles de traduction | Éducation | Licence académique gratuite |
| Plateformes freelance (Upwork, Malt) | Distribution | Profil "outil recommandé" |
---
## 5. Stratégie de Contenu
### 5.1 Blog — Sujets prioritaires
| # | Titre | Segment | Funnel |
|---|---|---|---|
| 1 | "Pourquoi Google Translate ruine vos documents Excel" | Tous | Top of funnel |
| 2 | "CTA, AHU ou Call To Action ? Comment l'IA traduit le jargon technique" | Ingénieurs | Top of funnel |
| 3 | "Traduction automatique vs agence : le calcul qui tue" | PME | Milieu de funnel |
| 4 | "Comment automatiser la traduction de 200 documents/mois avec notre API" | IT | Bottom of funnel |
| 5 | "5 erreurs de traduction juridique qui coûtent cher" | Juridique | Top of funnel |
| 6 | "DeepSeek V3 vs Claude 3.5 : quel modèle pour quelle traduction ?" | Tech-savvy | Milieu de funnel |
### 5.2 Contenu vidéo
| Contenu | Plateforme | Durée | Objectif |
|---|---|---|---|
| Démo 60 secondes — upload → download | YouTube, Landing | 60s | Conversion landing |
| "Glossaire en action" — comparaison temps réel | YouTube | 3 min | Différenciation |
| Tutoriel API pour développeurs | YouTube | 10 min | Adoption API |
### 5.3 Comparaison concurrentielle (landing / blog)
| vs | Notre avantage | Leur avantage |
|---|---|---|
| **Google Translate** | Format préservé, glossaires, IA contextuelle | Gratuit, connu |
| **DeepL** | Glossaires personnalisés, multi-format (xlsx, pptx), API | Qualité brute supérieure sur certains couples |
| **DocTranslator** | IA contextuelle, glossaires, vision sur images | Gratuit |
| **Smartcat** | Simplicité d'usage, pas d'onboarding, pricing transparent | Features TMS avancées (TM, QA) |
| **Traduction agence** | Instantané, 100x moins cher, API | Qualité humaine certifiée |
---
## 6. Stratégie Tarifaire — Positionnement Marketing
### 6.1 Narratif pricing
**Free** → "Essayez sans risque" (5 documents, Google Translate, format préservé)
**Starter (9€)** → "Pour les professionnels réguliers" (50 documents, DeepL, plus de pages)
**Pro (19€)** → "L'IA entre en jeu" (200 documents, IA contextuelle, glossaires, vision)
**Business (49€)** → "Pour les équipes" (1000 documents, API, support priorisé)
**Enterprise** → "Sur mesure"
### 6.2 Levier de conversion principal
Le chemin de conversion idéal :
```
Free user découvre l'IA (Phase 3 du CdC)
→ 5 crédits IA gratuits
→ Goûte à la qualité supérieure
→ Crédits épuisés
→ CTA "Continuez avec l'IA — Passez au plan Pro"
→ Conversion à 19€/mois
```
### 6.3 Messaging upgrade
| Moment | Message | CTA |
|---|---|---|
| Provider selector LLM verrouillé | "L'IA contextuelle traduit en comprenant votre domaine" | "Découvrir le plan Pro" |
| Crédits IA épuisés | "Vous avez utilisé vos 5 essais IA ce mois-ci" | "Débloquer l'IA" |
| Post-traduction (provider classic) | "Une traduction IA aurait compris 'batterie' = 'coil'" | "Essayer l'IA gratuitement" |
| Dashboard, usage > 80% du quota | "Vous approchez de votre limite mensuelle" | "Voir les plans supérieurs" |
---
## 7. Calendrier Marketing Proposé
### Semaine 1-2 : Fondations
- [ ] Finaliser le CdC design/IA (document ci-joint)
- [ ] Préparer les assets visuels (comparaison avant/après, captures d'écran)
- [ ] Rédiger les 5 premiers articles blog
- [ ] Créer les profils sur les sites de comparaison (AlternativeTo, etc.)
### Semaine 3-4 : Lancement Landing
- [ ] Déployer Phase 1 + 2 du CdC (i18n + section IA)
- [ ] Mettre en ligne les pages SEO (translate/xlsx, translate/docx, etc.)
- [ ] Soumettre le sitemap mis à jour à Google Search Console
### Semaine 5-6 : Freemium IA
- [ ] Déployer Phase 3 (freemium IA + mini-playground)
- [ ] Lancer la campagne Google Ads sur mots-clés traduction
- [ ] Préparer le lancement Product Hunt
### Semaine 7-8 : Amplification
- [ ] Lancement Product Hunt
- [ ] Campagne LinkedIn organique (3 posts/semaine)
- [ ] Publication des articles blog (1/semaine)
- [ ] Suivi des métriques : trafic, conversion Free→Pro, coût d'acquisition
### KPIs à suivre
| Métrique | Outil | Fréquence |
|---|---|---|
| Trafic landing | Google Analytics | Hebdo |
| Taux de conversion Free→Pro | Stripe + Dashboard | Hebdo |
| Utilisation des crédits IA Free | Dashboard admin | Hebdo |
| Position SEO mots-clés cibles | Google Search Console | Mensuel |
| Coût par acquisition (ads) | Google Ads | Hebdo |
| Net Promoter Score | Email survey | Trimestriel |
---
## 8. Budget Marketing Mensuel (Phase initiale)
| Poste | Coût mensuel | Notes |
|---|---|---|
| Google Ads | 200-500€ | Mots-clés traduction, CPC 0.50-1.50€ |
| Contenu (articles, vidéos) | 0€ (interne) | Temps Sepehr |
| Outils (Analytics, Search Console) | 0€ | Gratuits |
| Product Hunt launch | 0€ | Gratuit |
| **Total** | **200-500€/mois** | Phase bootstrap |
---
## 9. Prochaines Étapes
1. **Valider le CdC design/IA** — Prioriser les phases et lancer le développement
2. **Affiner ce brief marketing** — Sélectionner les taglines, valider les personas
3. **Préparer le contenu SEO** — Rédiger les pages translate/ et les premiers articles
4. **Configurer le tracking** — Google Analytics + Search Console avant le lancement
---
*Ce brief est un document vivant — à affiner au fil des retours utilisateurs et des métriques.*

View File

@@ -0,0 +1,287 @@
# Cahier des Charges — Refonte UX/Logique Office Translator
**Date :** 2026-05-02
**Auteur :** Mary (Business Analyst)
**Statut :** En attente de validation
---
## Contexte
L'application Office Translator est un SaaS de traduction de documents (DOCX, XLSX, PPTX) avec un système de plans (Free, Starter, Pro, Business, Enterprise). Plusieurs incohérences UX ont ete identifiees entre la logique business attendue et l'implementation actuelle.
**Stack technique :** Next.js 16 + React 19 + Tailwind CSS (frontend), FastAPI + Python (backend), JWT (auth).
---
## Changements requis
### 1. Retirer « Services » de la sidebar utilisateur
**Probleme :** L'entree « Services » (icone Zap) dans `DashboardSidebar` mene a `/dashboard/services`, une page qui affiche la liste des providers backend (Google, DeepL, OpenAI, etc.) avec des badges « Available ». L'utilisateur basique n'a aucune action a y faire — c'est une page d'information infrastructure.
**Fichiers concernes :**
- `frontend/src/app/dashboard/constants.ts` — retirer l'entree Services de `baseNavItems`
- `frontend/src/app/dashboard/services/page.tsx` — deplacer vers `/admin/` ou garder uniquement accessible via URL directe pour les utilisateurs avances
- `frontend/src/app/dashboard/settings/page.tsx` — retirer le lien « Translation Services » dans la carte de settings
**Regles :**
- L'entree « Services » doit etre supprimee de `baseNavItems` (ligne 15 de `constants.ts`)
- La page `/dashboard/services` peut rester accessible par URL mais ne doit plus apparaitre dans la navigation
- Dans la page Settings, la carte « Translation Services » (lignes 66-83 de `settings/page.tsx`) doit etre supprimee
- Le lien dans le dropdown mobile (si existant) doit aussi etre retire
**Impact backend :** Aucun. Les endpoints `/api/v1/providers/available` restent disponibles.
---
### 2. Refonte de la page Profil
**Probleme :** La page Profil (`profile/page.tsx`, 497 lignes) empile 6 sections heterogenes sans hierarchie visuelle claire. L'information est difficile a parcourir.
**Structure actuelle :**
- Carte identite (nom, email, date, plan)
- Carte abonnement (plan, prix, statut, renouvellement, portail Stripe)
- Zone danger (annulation)
- Carte utilisation (documents/pages avec barres de progression)
- Features incluses (liste texte)
- Preferences (langue UI : FR/EN uniquement)
**Nouvelle structure proposee — 3 onglets :**
#### Onglet 1 : « Mon Compte »
- Avatar avec initiales + nom + email (en lecture seule)
- Badge du plan actuel
- Membre depuis (date)
- Bouton « Modifier mon profil » (nom, email) — futur
#### Onglet 2 : « Abonnement »
- Plan actuel avec prix
- Statut de l'abonnement (Actif / Annulation en cours)
- Date de renouvellement ou date de fin
- Barres d'utilisation (documents/pages) avec reset date
- Credits supplementaires (si > 0)
- Bouton « Gerer la facturation » (portail Stripe)
- Bouton « Changer de forfait »
- Zone danger : annulation (avec confirmation, inchangee)
- Features incluses dans le plan
#### Onglet 3 : « Preferences »
- Langue de l'interface (voir section 3)
- Langue cible par defaut pour les traductions
- Theme (clair/sombre) — actuellement dans la sidebar, deplacer ici
- Autres preferences futures
**Fichiers concernes :**
- `frontend/src/app/dashboard/profile/page.tsx` — refonte complete
- Creer `frontend/src/app/dashboard/profile/components/` pour les sous-composants des onglets
- `frontend/src/app/dashboard/DashboardSidebar.tsx` — retirer le ThemeToggle de la sidebar (deplacer dans Preferences)
**Regles de design :**
- Utiliser le composant `Tabs` de Radix UI (deja disponible via shadcn/ui)
- Chaque onglet doit avoir une icone et un titre clair
- La zone danger (annulation) doit etre visuellement isolee, en bas de l'onglet Abonnement
- Le contenu doit respecter le systeme i18n (pas de texte hardcode)
- Responsive : les onglets se transforment en scroll horizontal sur mobile
---
### 3. Systeme de langues — Detection automatique + extension
#### 3a. Detection automatique de la langue du navigateur
**Probleme :** Dans `i18n.tsx:235`, la locale par defaut est hardcodee a `"fr"`. Aucune detection de `navigator.language`.
**Implementation :**
- Au premier chargement (pas de locale sauvegardee dans localStorage), lire `navigator.language` ou `navigator.languages[0]`
- Mapper le code retourne (ex: `fr-FR`, `en-US`, `de-DE`) vers la locale la plus proche disponible
- Logique de mapping : d'abord match exact, puis prefix (ex: `fr-FR``fr`, `zh-CN``zh`)
- Sauvegarder le resultat dans localStorage pour les visites suivantes
- Si aucune correspondance, fallback sur `"en"` (anglais comme langue par defaut internationale)
**Fichier concerne :** `frontend/src/lib/i18n.tsx`
**Code de reference pour la detection :**
```typescript
function detectBrowserLocale(): Locale {
const browserLang = navigator.language || (navigator.languages?.[0] ?? '');
const prefix = browserLang.split('-')[0].toLowerCase();
// Match exact d'abord
if (SUPPORTED_LOCALES.includes(prefix as Locale)) {
return prefix as Locale;
}
// Fallback anglais
return 'en';
}
```
#### 3b. Ajout de langues pour l'interface (UI)
**Probleme :** Le type `Locale` est limite a `"fr" | "en"` et le systeme de messages est inline dans `i18n.tsx`.
**Nouvelles locales a ajouter :**
| Code | Langue | Priorite |
|------|--------|----------|
| `de` | Deutsch | P1 |
| `es` | Espanol | P1 |
| `it` | Italiano | P1 |
| `pt` | Portugues | P1 |
| `nl` | Nederlands | P1 |
| `ru` | Русский | P1 |
| `pl` | Polski | P2 |
| `sv` | Svenska | P2 |
| `ro` | Romana | P2 |
| `el` | Ελληνικα | P2 |
| `cs` | Cestina | P2 |
| `hu` | Magyar | P2 |
| `uk` | Украська | P2 |
| `da` | Dansk | P3 |
| `fi` | Suomi | P3 |
| `no` | Norsk | P3 |
| `zh` | 中文 | P1 |
| `ja` | 日本語 | P1 |
| `ko` | 한국어 | P1 |
| `fa` | فارسی | P1 |
**Architecture i18n :**
1. Transformer le systeme inline en fichiers separess :
- `frontend/src/messages/en.json` (existant, a completer)
- `frontend/src/messages/fr.json` (existant, a completer)
- `frontend/src/messages/de.json` (nouveau)
- `frontend/src/messages/es.json` (nouveau)
- etc.
2. Charger les messages dynamiquement (lazy loading) pour ne pas penaliser le bundle
3. Le type `Locale` doit etre genere dynamiquement ou etendu
**Fichiers concernes :**
- `frontend/src/lib/i18n.tsx` — refonte du systeme
- `frontend/src/messages/*.json` — un fichier par langue
- `frontend/src/app/dashboard/profile/page.tsx``UI_LANGUAGES` a etendre
**Contrainte RTL :** Le persan (`fa`) est une langue droite-gauche (RTL). L'application doit :
- Ajouter `dir="rtl"` sur `<html>` quand la locale est `fa` ou `ar`
- Verifier que les composants Radix UI / Tailwind supportent le RTL (utilitaires `rtl:` de Tailwind)
- Tester specifiquement les pages critiques en RTL (Translate, Profile, Settings)
#### 3c. Ajout du persan dans les langues cibles de traduction
**Probleme :** Dans `frontend/src/lib/api.ts` (lignes 22-51), le persan (`fa`) est absent de la liste `languages`, alors que le backend le supporte deja dans `middleware/validation.py` (ligne 396).
**Correction :** Ajouter `{ code: "fa", name: "فارسی", flag: "🇮🇷" }` dans le tableau `languages` de `api.ts`.
**Note :** La liste fallback dans `useTranslationConfig.ts` (ligne 38) inclut deja `fa` — seul le fichier `api.ts` est a corriger.
---
### 4. Automatisation du choix du provider de traduction
**Probleme :** Sur la page Translate, l'utilisateur doit manuellement choisir un provider (Google Traduction, DeepL, OpenAI, etc.) via le composant `ProviderSelector`. Pour un utilisateur basique, c'est une decision technique qu'il n'est pas qualifie pour prendre. Le backend a deja un systeme de fallback automatique.
**Comportement actuel :**
- `ProviderSelector.tsx` affiche tous les providers disponibles
- `TranslationModeToggle.tsx` propose un toggle Classic/LLM
- `useTranslationConfig.ts` exige un provider selectionne pour valider la config (`isConfigValid` ligne 184-188)
- Les providers LLM sont deja bloques pour les non-Pro
**Nouveau comportement propose :**
#### Pour les utilisateurs Free / Starter :
- Le `ProviderSelector` et le `TranslationModeToggle` sont **completement caches**
- Le provider est automatiquement selectionne : premier provider classic disponible
- Si aucun provider classic n'est disponible, utiliser le premier provider de la liste
- L'utilisateur ne voit que : fichier → langue source → langue cible → Traduire
#### Pour les utilisateurs Pro / Business / Enterprise :
- Afficher un selecteur simplifie, pas technique :
- Remplacer les noms techniques par des labels utilisateur :
- « Traduction rapide » (classic) au lieu de « Google Traduction »
- « Traduction intelligente » (LLM) au lieu de « OpenAI GPT-4 »
- Pas de toggle Classic/LLM separe — juste un selecteur de mode avec descriptions claires
- Les providers LLM sont accessibles sans cadenas (deja Pro)
#### Implementation technique :
**Fichiers concernes :**
- `frontend/src/app/dashboard/translate/ProviderSelector.tsx` — cacher pour Free/Starter, simplifier pour Pro+
- `frontend/src/app/dashboard/translate/TranslationModeToggle.tsx` — retirer, fusionner dans ProviderSelector simplifie
- `frontend/src/app/dashboard/translate/useTranslationConfig.ts` — auto-selection du provider pour les utilisateurs basiques
- `frontend/src/app/dashboard/translate/page.tsx` — adapter le layout selon le tier
**Logique d'auto-selection (dans `useTranslationConfig.ts`) :**
```typescript
// Apres le fetch des providers disponibles
if (!isPro && availableProviders.length > 0) {
// Auto-selectionner le premier provider classic
const classicProvider = availableProviders.find(p => p.mode === 'classic');
const fallback = availableProviders[0];
setProvider((classicProvider ?? fallback).id);
}
```
**Mise a jour de `isConfigValid` :**
```typescript
// Pour les non-Pro, le provider est auto-selectionne
// Donc isConfigValid ne depend plus de la selection manuelle
const isConfigValid = useMemo(() => {
if (!hasFile || !targetLang) return false;
if (isPro && !provider) return false; // Pro doit choisir
return true; // Non-Pro : auto-selectionne
}, [hasFile, targetLang, isPro, provider]);
```
**Nouveau composant simplifie pour Pro (remplace ProviderSelector + ModeToggle) :**
```typescript
// SimplifiedProviderSelector — uniquement pour Pro+
// Affiche :
// - "Traduction rapide" — Traduction automatique rapide (130+ langues)
// - "Traduction intelligente" — Traduction contextuelle par IA (Pro)
```
---
## Plan d'implementation par ordre de priorite
### Phase 1 — Quick Wins (impact eleve, complexite faible)
1. Retirer « Services » de la sidebar et de la page Settings
2. Ajouter `fa` (persan) dans `api.ts`
3. Auto-selection du provider pour les utilisateurs Free/Starter
4. Detection automatique de la langue du navigateur
### Phase 2 — Refonte Profil (impact eleve, complexite moyenne)
5. Refactorer la page Profil en 3 onglets
6. Deplacer ThemeToggle dans l'onglet Preferences
7. i18n-ifier tous les textes hardcodes du profil
### Phase 3 — Extension i18n (impact eleve, complexite elevee)
8. Refondre le systeme i18n en fichiers separes
9. Ajouter les langues P1 (de, es, it, pt, nl, ru, zh, ja, ko, fa)
10. Support RTL pour `fa` et `ar`
11. Ajouter les langues P2 et P3 progressivement
---
## Risques et mitigations
| Risque | Probabilite | Impact | Mitigation |
|--------|-------------|--------|------------|
| Traductions i18n de mauvaise qualite | Elevee | Moyen | Utiliser un service de traduction professionnel ou validation humaine pour les langues principales |
| Layout casse en RTL | Moyen | Eleve | Tester avec `fa` et `ar` des le debut, ajouter les utilitaires Tailwind `rtl:` |
| Utilisateurs Pro perdus sans selecteur technique | Faible | Faible | Garder le selecteur simplifie avec option avancee |
| Performance avec 20+ fichiers de langue | Faible | Faible | Lazy loading des fichiers JSON par locale |
---
## Critères d'acceptation
- [ ] Aucune entree « Services » visible dans la sidebar utilisateur
- [ ] La page Profil est separee en 3 onglets fonctionnels
- [ ] La langue de l'interface est detectee automatiquement depuis le navigateur
- [ ] Le persan est disponible comme langue cible de traduction
- [ ] Le persan est disponible comme langue de l'interface (avec support RTL)
- [ ] L'utilisateur Free/Starter ne voit aucun selecteur de provider
- [ ] L'utilisateur Pro voit un selecteur simplifie (non-technique)
- [ ] Toutes les nouvelles langues UI ont des fichiers de messages complets
- [ ] Le theme clair/sombre est accessible depuis l'onglet Preferences du profil