Files
office_translator/docs/CHANTIER_FONDATIONS_2026-08-29.md
sepehr b4e873ad2c
Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 2m14s
feat(review,teams): review foundation — segments, side-by-side editor, rebuild, XLIFF, team workspaces
Foundations:
- TranslationSegment model + migration f7e8d9c0b1a2 (segments, workspaces,
  workspace_members, glossaries.workspace_id)
- SegmentRecorder injected into all 4 translators: unique (source,
  translation) pairs captured per job and persisted (best-effort)
- set_segment_overrides: human-reviewed translations applied verbatim on
  rebuild — top priority over TM and provider, zero API calls

Review API (routes/review_routes.py):
- GET /translations/{id}/segments (owner or job token)
- PATCH /segments/{id} edit/approve — feeds the per-user TM so approved
  translations are reused in later jobs
- POST /translations/{id}/rebuild — rebuild document with reviewed text
- GET/POST /translations/{id}/xliff — XLIFF 1.2 export/import (edited
  segments export their reviewed text)

Review editor (frontend /dashboard/reviews/[jobId]):
- side-by-side source/translation table, inline edit, approve (single or
  all), rebuild & download (auth blob), XLIFF export/import, 13 locales
- 'Relire et corriger' link on the translation-complete screen

Team workspaces (routes/workspace_routes.py + /dashboard/teams):
- Workspace/WorkspaceMember models, roles owner/admin/member
- create (Business plan), list with seat usage, invite by email with
  seat-limit enforcement (Business=5, Enterprise unlimited), removal
- shared glossaries: workspace members can use a glossary shared to their
  workspace (access check extended)

Tests: 1184 passed / 0 failed (11 new: recorder, overrides, docx
capture->rebuild e2e, XLIFF structure/escaping, seats, workspace CRUD,
shared glossary access)
2026-08-29 19:04:32 +02:00

4.8 KiB

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.