feat(review,teams): review foundation — segments, side-by-side editor, rebuild, XLIFF, team workspaces
Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 2m14s
Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 2m14s
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)
This commit is contained in:
85
docs/CHANTIER_FONDATIONS_2026-08-29.md
Normal file
85
docs/CHANTIER_FONDATIONS_2026-08-29.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user