12 KiB
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 debaseNavItemsfrontend/src/app/dashboard/services/page.tsx— deplacer vers/admin/ou garder uniquement accessible via URL directe pour les utilisateurs avancesfrontend/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 deconstants.ts) - La page
/dashboard/servicespeut 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
Tabsde 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.languageounavigator.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 :
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 |
Украiнська | P2 |
da |
Dansk | P3 |
fi |
Suomi | P3 |
no |
Norsk | P3 |
zh |
中文 | P1 |
ja |
日本語 | P1 |
ko |
한국어 | P1 |
fa |
فارسی | P1 |
Architecture i18n :
- 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.
- Charger les messages dynamiquement (lazy loading) pour ne pas penaliser le bundle
- Le type
Localedoit etre genere dynamiquement ou etendu
Fichiers concernes :
frontend/src/lib/i18n.tsx— refonte du systemefrontend/src/messages/*.json— un fichier par languefrontend/src/app/dashboard/profile/page.tsx—UI_LANGUAGESa etendre
Contrainte RTL : Le persan (fa) est une langue droite-gauche (RTL). L'application doit :
- Ajouter
dir="rtl"sur<html>quand la locale estfaouar - 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.tsxaffiche tous les providers disponiblesTranslationModeToggle.tsxpropose un toggle Classic/LLMuseTranslationConfig.tsexige un provider selectionne pour valider la config (isConfigValidligne 184-188)- Les providers LLM sont deja bloques pour les non-Pro
Nouveau comportement propose :
Pour les utilisateurs Free / Starter :
- Le
ProviderSelectoret leTranslationModeTogglesont 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)
- Remplacer les noms techniques par des labels utilisateur :
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 simplifiefrontend/src/app/dashboard/translate/useTranslationConfig.ts— auto-selection du provider pour les utilisateurs basiquesfrontend/src/app/dashboard/translate/page.tsx— adapter le layout selon le tier
Logique d'auto-selection (dans useTranslationConfig.ts) :
// 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 :
// 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) :
// 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)
- Retirer « Services » de la sidebar et de la page Settings
- Ajouter
fa(persan) dansapi.ts - Auto-selection du provider pour les utilisateurs Free/Starter
- Detection automatique de la langue du navigateur
Phase 2 — Refonte Profil (impact eleve, complexite moyenne)
- Refactorer la page Profil en 3 onglets
- Deplacer ThemeToggle dans l'onglet Preferences
- i18n-ifier tous les textes hardcodes du profil
Phase 3 — Extension i18n (impact eleve, complexite elevee)
- Refondre le systeme i18n en fichiers separes
- Ajouter les langues P1 (de, es, it, pt, nl, ru, zh, ja, ko, fa)
- Support RTL pour
faetar - 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