Major changes across backend, frontend, infrastructure: - Provider system with model selection (Google, DeepL, OpenAI, Ollama, Google Cloud) - Admin panel: user management, pricing, settings - Glossary system with CSV import/export - Subscription and tier quota management - Security hardening (rate limiting, API key auth, path traversal fixes) - Docker compose for dev, prod, and IONOS deployment - Alembic migrations for new tables - Frontend: dashboard, pricing page, landing page, i18n (en/fr) - Test suite and verification scripts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
9.5 KiB
Story 4.8: Page Translation - Progress & Download
Status: done
Story
En tant qu'utilisateur, Je veux voir la progression de la traduction en temps réel et télécharger le fichier traduit, de sorte que je sache quand mon fichier est prêt et puisse l'utiliser.
Acceptance Criteria
- Submit Translation: Au clic sur "Translate", POST vers
/api/v1/translateavecfile,source_lang,target_lang,mode,provider(si LLM) - Job ID Storage: Stocker le
job_idretourné (202 response:{data: {id, status: "processing"}, meta: {...}}) - Progress Polling: Poll
GET /api/v1/translations/{job_id}toutes les 2 secondes pendantstatus === "processing" - Progress Display: Afficher progress bar (0-100%),
current_step, et temps restant estimé (meta.estimated_remaining_seconds) - Status Transitions:
processing→completed(succès) oufailed(erreur) - Error Display: Si
failed, affichererror_messagedu backend avec toast notification - Download Button: Quand
completed, afficher bouton "Download" qui GET/api/v1/download/{job_id} - Download Filename: Header
Content-Dispositionfourni par backend →{original_name}_translated.{ext} - Success Toast: Afficher confirmation après téléchargement réussi
- State Reset: Option "New Translation" pour réinitialiser et uploader un nouveau fichier
- Merge Directive: UI Progress depuis
frontend/src/components/file-uploader.tsx(lignes 592-609) - Colocation: Composants/hooks/types dans
frontend/src/app/dashboard/translate/
Tasks / Subtasks
-
Task 1: Étendre types.ts (AC: #1, #2)
- 1.1 Ajouter
TranslationJob,TranslationStatus,TranslationProgress - 1.2 Ajouter
UseTranslationSubmitReturninterface
- 1.1 Ajouter
-
Task 2: Créer useTranslationSubmit.ts hook (AC: #1, #2, #3, #4, #5)
- 2.1 State:
jobId,status,progress,currentStep,error,estimatedRemaining - 2.2
submitTranslation(file, config): POST/api/v1/translate→ return job_id - 2.3
pollProgress(): setInterval 2s → GET/api/v1/translations/{job_id} - 2.4 Cleanup interval on unmount ou quand status !== "processing"
- 2.5 Return:
{ submitTranslation, jobId, status, progress, currentStep, error, estimatedRemaining, reset }
- 2.1 State:
-
Task 3: Créer TranslationProgress.tsx (AC: #4, #6)
- 3.1 Props:
progress,currentStep,estimatedRemaining,error - 3.2 Progress bar avec pourcentage (shadcn/ui Progress)
- 3.3 Afficher
current_steptextuel (ex: "Translating slide 5/10") - 3.4 Afficher temps restant formaté (ex: "2 min remaining")
- 3.5 Error state: message rouge si
status === "failed" - 3.6 Copier styles depuis
file-uploader.tsx(lignes 592-609)
- 3.1 Props:
-
Task 4: Créer TranslationComplete.tsx (AC: #7, #8, #9)
- 4.1 Props:
jobId,fileName,onNewTranslation - 4.2 Download button: GET
/api/v1/download/{job_id}→ trigger browser download - 4.3 Success toast après download
- 4.4 "New Translation" button → callback
onNewTranslation - 4.5 Checkmark icon + message "Translation Complete!"
- 4.6 Copier styles depuis
file-uploader.tsx(lignes 627-649)
- 4.1 Props:
-
Task 5: Modifier page.tsx pour intégrer le flow complet (AC: #1, #10)
- 5.1 State flow: Upload → Config → Submit → Progress → Complete
- 5.2 Intégrer
useTranslationSubmithook - 5.3 Conditionnel: afficher Progress si
status === "processing" - 5.4 Conditionnel: afficher Complete si
status === "completed" - 5.5 Conditionnel: afficher Error si
status === "failed" - 5.6
handleTranslate→submitTranslation(file, config.getConfig()) - 5.7
handleNewTranslation→ reset all states
-
Task 6: Vérifier le build et tester (AC: Tous)
- 6.1
npm run build→ 0 erreurs TypeScript - 6.2 Tester submit translation → job_id retourné
- 6.3 Tester polling progress → progress bar updates
- 6.4 Tester download → fichier téléchargé
- 6.5 Tester error handling → message affiché
- 6.6 Tester new translation → reset complet
- 6.1
Dev Notes
🏗️ Stack Technique
| Technologie | Version |
|---|---|
| Next.js | 16.0.6 (App Router) |
| React | 19.2.0 |
| TanStack Query | v5.90.21 (optionnel - polling manuel OK) |
| Tailwind CSS | configuré |
| Lucide React | disponible |
| shadcn/ui | Progress, Button, Card, Toast |
📁 Structure Cible (Colocation Pattern)
frontend/src/app/dashboard/translate/
├── page.tsx # Existant — à modifier
├── types.ts # Existant — à étendre
├── useFileUpload.ts # Existant — pas de modif
├── FileDropZone.tsx # Existant — pas de modif
├── FilePreview.tsx # Existant — pas de modif
├── useTranslationConfig.ts # Existant — pas de modif
├── LanguageSelector.tsx # Existant — pas de modif
├── TranslationModeToggle.tsx # Existant — pas de modif
├── ProviderSelector.tsx # Existant — pas de modif
├── useTranslationSubmit.ts # 🆕 Hook submit + polling
├── TranslationProgress.tsx # 🆕 Progress bar + status
└── TranslationComplete.tsx # 🆕 Download + success
⚠️ Règle absolue (architecture.md):
🚨 FICHIERS SPÉCIAUX: page.tsx, layout.tsx → TOUJOURS minuscules
🚨 COLOCATION: Components/hooks/types dans le dossier de leur page
🔗 API Endpoints Backend (Déjà implémentés)
| Endpoint | Méthode | Request | Response |
|---|---|---|---|
/api/v1/translate |
POST | FormData: file, source_lang, target_lang, mode, provider | 202: {data: {id, status: "processing"}, meta: {rate_limit_remaining}} |
/api/v1/translations/{job_id} |
GET | — | {data: {id, status, progress_percent, current_step, ...}, meta: {estimated_remaining_seconds}} |
/api/v1/download/{job_id} |
GET | — | Binary file + Content-Disposition header |
References
- [Source: _bmad-output/planning-artifacts/epics.md#Story-4.8] — Story requirements
- [Source: _bmad-output/planning-artifacts/architecture.md#Frontend-Architecture] — TanStack Query + colocation
- [Source: _bmad-output/planning-artifacts/architecture.md#API-Response-Formats] — Format réponse API
- [Source: routes/translate_routes.py#L1064-1151] — GET /api/v1/translations/{job_id} endpoint
- [Source: routes/translate_routes.py#L1188-1317] — GET /api/v1/download/{job_id} endpoint
- [Source: frontend/src/components/file-uploader.tsx#L592-649] — UI Progress + Download patterns
- [Source: _bmad-output/implementation-artifacts/4-7-page-translation-configuration.md] — Context config, types existants
Dev Agent Record
Agent Model Used
Claude Sonnet 4 (claude-sonnet-4@20250514)
Debug Log References
N/A
Completion Notes List
- ✅ Étendu types.ts avec TranslationStatus, TranslationJob, TranslationSubmitResponse, TranslationStatusResponse, UseTranslationSubmitReturn
- ✅ Créé useTranslationSubmit.ts hook avec submitTranslation, pollProgress (2s interval), cleanup on unmount, reset
- ✅ Créé TranslationProgress.tsx avec progress bar (shadcn/ui Progress), current_step display, temps restant formaté, error state
- ✅ Créé TranslationComplete.tsx avec download button (GET /api/v1/download), success toast, "New Translation" button
- ✅ Modifié page.tsx pour intégrer le flow complet: Upload → Config → Submit → Progress → Complete/Failed
- ✅ Build Next.js réussi (0 erreurs TypeScript)
File List
Fichiers créés:
- frontend/src/app/dashboard/translate/useTranslationSubmit.ts
- frontend/src/app/dashboard/translate/TranslationProgress.tsx
- frontend/src/app/dashboard/translate/TranslationComplete.tsx
Fichiers modifiés:
- frontend/src/app/dashboard/translate/types.ts
- frontend/src/app/dashboard/translate/page.tsx
- _bmad-output/implementation-artifacts/sprint-status.yaml (in-progress → review)
Senior Developer Review (AI)
Reviewer: Code Review Agent
Date: 2026-02-23
Outcome: Changes Requested → Fixed → Approved
Issues Found: 9 (3 High, 4 Medium, 2 Low)
Critical Issues Fixed
- AC #6 Not Fully Implemented (HIGH) - Error toast notification added in page.tsx useEffect
- Silent Polling Failures (HIGH) - Polling failures now tracked and surfaced to user after 3 consecutive failures
- Race Condition (HIGH) - Added
isPollingRefto prevent overlapping poll requests
Medium Issues Fixed
- Memory Leak (MEDIUM) - Blob URL now properly managed with useRef and cleanup on unmount
- No Upload Progress (MEDIUM) - Submit button now shows "Uploading..." with spinner during file upload
- No Retry Tracking (MEDIUM) - Added
pollingFailuresstate andMAX_POLLING_FAILURESconstant - Accessibility (MEDIUM) - Added ARIA attributes to Progress component and error alerts
Code Quality Improvements Applied
- Added
isPollingandpollingFailuresto hook return type - Enhanced error messages for network failures
- Added visual indicator when connection is lost during translation
- Proper cleanup of intervals and blob URLs on component unmount
Change Log
- 2026-02-23: Story created - ready for development
- 2026-02-23: Implementation complete - all 6 tasks completed, build successful, ready for review
- 2026-02-23: Code review complete - 9 issues identified and fixed, all HIGH/MEDIUM issues resolved