Files
office_translator/_bmad-output/implementation-artifacts/4-8-page-translation-progress-download.md
Sepehr Ramezani 26bd096a06 feat: production deployment - full update with providers, admin, glossaries, pricing, tests
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>
2026-04-25 15:01:47 +02:00

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

  1. Submit Translation: Au clic sur "Translate", POST vers /api/v1/translate avec file, source_lang, target_lang, mode, provider (si LLM)
  2. Job ID Storage: Stocker le job_id retourné (202 response: {data: {id, status: "processing"}, meta: {...}})
  3. Progress Polling: Poll GET /api/v1/translations/{job_id} toutes les 2 secondes pendant status === "processing"
  4. Progress Display: Afficher progress bar (0-100%), current_step, et temps restant estimé (meta.estimated_remaining_seconds)
  5. Status Transitions: processingcompleted (succès) ou failed (erreur)
  6. Error Display: Si failed, afficher error_message du backend avec toast notification
  7. Download Button: Quand completed, afficher bouton "Download" qui GET /api/v1/download/{job_id}
  8. Download Filename: Header Content-Disposition fourni par backend → {original_name}_translated.{ext}
  9. Success Toast: Afficher confirmation après téléchargement réussi
  10. State Reset: Option "New Translation" pour réinitialiser et uploader un nouveau fichier
  11. Merge Directive: UI Progress depuis frontend/src/components/file-uploader.tsx (lignes 592-609)
  12. 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 UseTranslationSubmitReturn interface
  • 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 }
  • 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_step textuel (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)
  • 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)
  • 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 useTranslationSubmit hook
    • 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 handleTranslatesubmitTranslation(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

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

  1. AC #6 Not Fully Implemented (HIGH) - Error toast notification added in page.tsx useEffect
  2. Silent Polling Failures (HIGH) - Polling failures now tracked and surfaced to user after 3 consecutive failures
  3. Race Condition (HIGH) - Added isPollingRef to prevent overlapping poll requests

Medium Issues Fixed

  1. Memory Leak (MEDIUM) - Blob URL now properly managed with useRef and cleanup on unmount
  2. No Upload Progress (MEDIUM) - Submit button now shows "Uploading..." with spinner during file upload
  3. No Retry Tracking (MEDIUM) - Added pollingFailures state and MAX_POLLING_FAILURES constant
  4. Accessibility (MEDIUM) - Added ARIA attributes to Progress component and error alerts

Code Quality Improvements Applied

  • Added isPolling and pollingFailures to 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