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

86 lines
4.8 KiB
Markdown

# 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.