# Chantier « fondations produit » — relecture, équipes, XLIFF (2026-08-29) > Décision de la session : **aucune intégration DeepL**. Tout ce qui suit est > 100 % moteur maison/LLM existants. ## 1. Fondation : persistance des segments par job - **Modèle `TranslationSegment`** (`database/models.py`) : paires (source, traduction) par job et par utilisateur, avec statut de relecture (`pending | approved | edited`), texte relu, index, horodatages. - **Migration `f7e8d9c0b1a2`** (alembic) : `translation_segments`, `workspaces`, `workspace_members`, `glossaries.workspace_id`. Appliquée et vérifiée sur base vierge (chaîne complète 001→tête) et sur la base de dev. - **Capture** (`translators/segments.py`) : un `SegmentRecorder` est injecté par la route dans les 4 traducteurs (docx/xlsx/pptx/pdf). Il enregistre chaque paire unique dans l'ordre du document ; les paires identiques (non traduites) sont ignorées pour garder la liste actionnable. - **Overrides** : `set_segment_overrides()` applique les traductions **relues par l'humain** mot pour mot lors de la reconstruction — priorité maximale (avant TM et provider), zéro appel API, zéro dérive. - **Persistance** : après un job réussi, la route stocke les segments en base (best-effort, n'échoue jamais le job). ## 2. API de relecture (`routes/review_routes.py`) | Endpoint | Rôle | |---|---| | `GET /api/v1/translations/{job_id}/segments` | Liste des segments + compteurs (accès propriétaire ou token du job) | | `PATCH /api/v1/segments/{id}` | Éditer (`reviewed_text` + `status=edited`) ou approuver — alimente aussi la TM par utilisateur (les traductions relues sont réutilisées dans les jobs suivants) | | `POST /api/v1/translations/{job_id}/rebuild` | Reconstruit le document avec les segments approuvés/modifiés (le texte relu est appliqué tel quel) puis pointe le téléchargement dessus | | `GET /api/v1/translations/{job_id}/xliff` | Export **XLIFF 1.2** (les segments modifiés exportent leur texte relu) | | `POST /api/v1/translations/{job_id}/xliff` | Import XLIFF : met à jour les segments (cible ≠ machine → `edited`, sinon `approved`) | Note UX : la reconstruction nécessite le fichier source encore présent (rétention 30 min). Au-delà, le messageInvite à re-téléverser — et les segments approuvés étant dans la TM, la nouvelle traduction les réutilise automatiquement. ## 3. Éditeur de relecture (frontend) - **`/dashboard/reviews/[jobId]`** — tableau côte à côte Source | Traduction, édition inline, badges de statut, approbation unitaire ou « Tout approuver », **Reconstruire et télécharger** (blob authentifié), export/import XLIFF. Libellés 13 locales. - **Lien « Relire et corriger la traduction »** sur l'écran de fin de traduction (`TranslationComplete`). ## 4. Espaces de travail équipes (`routes/workspace_routes.py`) - Modèles `Workspace` / `WorkspaceMember` (rôles `owner | admin | member`). - Endpoints : création (plan **Business** requis), liste (avec rôle, sièges utilisés/limite), ajout de membre **par e-mail** avec **application de la limite de sièges** du plan du propriétaire (Business = 5, Enterprise illimité), retrait (owner impossible à retirer). - **Glossaires partagés** : `glossaries.workspace_id` — le contrôle d'accès (`get_glossary_terms`, `validate_glossary_access`) accepte désormais le propriétaire **et les membres du workspace**. - **Page `/dashboard/teams`** : création d'espace, liste des membres, invitation (e-mail + rôle), retrait, compteur de sièges, gate Business. - Facturation multi-sièges : v1 = application de la limite de sièges du plan. (La facturation au siège réel côté Stripe — subscription items — reste un chantier facturation à part.) ## 5. Tests & vérifications - Nouveaux tests (`tests/test_review_foundation.py`, 11) : recorder, overrides, **capture→rebuild de bout en bout sur un vrai docx** (le texte relu atterrit dans le fichier reconstruit, le reste reste machine), structure XLIFF + échappement XML, sièges, CRUD workspace, glossaire partagé (membre OK / extérieur refusé). - Suite backend complète : voir résultat final ci-dessous. - `tsc --noEmit` OK sur les deux frontends ; navigation « Équipe » (Pro+) et lien « Relire » ajoutés. ## 6. Non livré (justifié) - **IDML / DITA** : spécifications de formats complètes à part entière (structure InDesign / arbres DITA) — nouveaux parseurs dédiés, à chiffrer séparément. - **Facturation Stripe au siège** (mètre temps réel des sièges) : la limite plan est appliquée ; le mètre Stripe nécessite des subscription items et un webhooks sièges. - **Éditeur de relecture temps réel multi-utilisateur** (verrouillage de segment, présence) : nécessite WebSocket + verrous — v1 = relecture solo/équipe asynchrone.