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:
@@ -107,5 +107,6 @@
|
||||
"dashboard.topbar.premiumAccess": "وصول مميز",
|
||||
"dashboard.checkoutSyncError": "خطأ في مزامنة الدفع.",
|
||||
"dashboard.networkRefresh": "خطأ في الشبكة. يرجى تحديث الصفحة.",
|
||||
"dashboard.continueToTranslate": "متابعة إلى الترجمة"
|
||||
"dashboard.continueToTranslate": "متابعة إلى الترجمة",
|
||||
"dashboard.nav.teams": "الفريق"
|
||||
}
|
||||
|
||||
@@ -107,5 +107,6 @@
|
||||
"dashboard.topbar.premiumAccess": "Premium-Zugang",
|
||||
"dashboard.checkoutSyncError": "Fehler beim Synchronisieren der Zahlung.",
|
||||
"dashboard.networkRefresh": "Netzwerkfehler. Bitte aktualisieren Sie die Seite.",
|
||||
"dashboard.continueToTranslate": "Weiter zur Übersetzung"
|
||||
"dashboard.continueToTranslate": "Weiter zur Übersetzung",
|
||||
"dashboard.nav.teams": "Team"
|
||||
}
|
||||
|
||||
@@ -111,5 +111,6 @@
|
||||
"dashboard.topbar.premiumAccess": "Premium Access",
|
||||
"dashboard.checkoutSyncError": "Error syncing payment.",
|
||||
"dashboard.networkRefresh": "Network error. Please refresh the page.",
|
||||
"dashboard.continueToTranslate": "Continue to translation"
|
||||
"dashboard.continueToTranslate": "Continue to translation",
|
||||
"dashboard.nav.teams": "Team"
|
||||
}
|
||||
|
||||
@@ -107,5 +107,6 @@
|
||||
"dashboard.topbar.premiumAccess": "Acceso Premium",
|
||||
"dashboard.checkoutSyncError": "Error al sincronizar el pago.",
|
||||
"dashboard.networkRefresh": "Error de red. Por favor, actualice la página.",
|
||||
"dashboard.continueToTranslate": "Continuar a la traducción"
|
||||
"dashboard.continueToTranslate": "Continuar a la traducción",
|
||||
"dashboard.nav.teams": "Equipo"
|
||||
}
|
||||
|
||||
@@ -107,5 +107,6 @@
|
||||
"dashboard.topbar.premiumAccess": "دسترسی ویژه",
|
||||
"dashboard.checkoutSyncError": "خطا در همگامسازی پرداخت.",
|
||||
"dashboard.networkRefresh": "خطای شبکه. لطفاً صفحه را تازهسازی کنید.",
|
||||
"dashboard.continueToTranslate": "ادامه به ترجمه"
|
||||
"dashboard.continueToTranslate": "ادامه به ترجمه",
|
||||
"dashboard.nav.teams": "تیم"
|
||||
}
|
||||
|
||||
@@ -111,5 +111,6 @@
|
||||
"dashboard.topbar.premiumAccess": "Accès Premium",
|
||||
"dashboard.checkoutSyncError": "Erreur lors de la synchronisation du paiement.",
|
||||
"dashboard.networkRefresh": "Erreur réseau. Veuillez rafraîchir la page.",
|
||||
"dashboard.continueToTranslate": "Continuer vers la traduction"
|
||||
"dashboard.continueToTranslate": "Continuer vers la traduction",
|
||||
"dashboard.nav.teams": "Équipe"
|
||||
}
|
||||
|
||||
@@ -107,5 +107,6 @@
|
||||
"dashboard.topbar.premiumAccess": "Accesso Premium",
|
||||
"dashboard.checkoutSyncError": "Errore di sincronizzazione del pagamento.",
|
||||
"dashboard.networkRefresh": "Errore di rete. Aggiorna la pagina.",
|
||||
"dashboard.continueToTranslate": "Vai alla traduzione"
|
||||
"dashboard.continueToTranslate": "Vai alla traduzione",
|
||||
"dashboard.nav.teams": "Squadra"
|
||||
}
|
||||
|
||||
@@ -107,5 +107,6 @@
|
||||
"dashboard.topbar.premiumAccess": "プレミアムアクセス",
|
||||
"dashboard.checkoutSyncError": "支払いの同期エラー。",
|
||||
"dashboard.networkRefresh": "ネットワークエラー。ページを更新してください。",
|
||||
"dashboard.continueToTranslate": "翻訳に進む"
|
||||
"dashboard.continueToTranslate": "翻訳に進む",
|
||||
"dashboard.nav.teams": "チーム"
|
||||
}
|
||||
|
||||
@@ -107,5 +107,6 @@
|
||||
"dashboard.topbar.premiumAccess": "프리미엄 액세스",
|
||||
"dashboard.checkoutSyncError": "결제 동기화 오류.",
|
||||
"dashboard.networkRefresh": "네트워크 오류. 페이지를 새로 고치세요.",
|
||||
"dashboard.continueToTranslate": "번역으로 계속"
|
||||
"dashboard.continueToTranslate": "번역으로 계속",
|
||||
"dashboard.nav.teams": "팀"
|
||||
}
|
||||
|
||||
@@ -107,5 +107,6 @@
|
||||
"dashboard.topbar.premiumAccess": "Premium-toegang",
|
||||
"dashboard.checkoutSyncError": "Fout bij synchroniseren van betaling.",
|
||||
"dashboard.networkRefresh": "Netwerkfout. Vernieuw de pagina.",
|
||||
"dashboard.continueToTranslate": "Doorgaan naar vertaling"
|
||||
"dashboard.continueToTranslate": "Doorgaan naar vertaling",
|
||||
"dashboard.nav.teams": "Team"
|
||||
}
|
||||
|
||||
@@ -107,5 +107,6 @@
|
||||
"dashboard.topbar.premiumAccess": "Acesso Premium",
|
||||
"dashboard.checkoutSyncError": "Erro ao sincronizar o pagamento.",
|
||||
"dashboard.networkRefresh": "Erro de rede. Atualize a página.",
|
||||
"dashboard.continueToTranslate": "Continuar para a tradução"
|
||||
"dashboard.continueToTranslate": "Continuar para a tradução",
|
||||
"dashboard.nav.teams": "Equipe"
|
||||
}
|
||||
|
||||
@@ -107,5 +107,6 @@
|
||||
"dashboard.topbar.premiumAccess": "Премиум-доступ",
|
||||
"dashboard.checkoutSyncError": "Ошибка синхронизации платежа.",
|
||||
"dashboard.networkRefresh": "Ошибка сети. Обновите страницу.",
|
||||
"dashboard.continueToTranslate": "Перейти к переводу"
|
||||
"dashboard.continueToTranslate": "Перейти к переводу",
|
||||
"dashboard.nav.teams": "Команда"
|
||||
}
|
||||
|
||||
@@ -107,5 +107,6 @@
|
||||
"dashboard.topbar.premiumAccess": "高级访问",
|
||||
"dashboard.checkoutSyncError": "同步付款时出错。",
|
||||
"dashboard.networkRefresh": "网络错误。请刷新页面。",
|
||||
"dashboard.continueToTranslate": "继续翻译"
|
||||
"dashboard.continueToTranslate": "继续翻译",
|
||||
"dashboard.nav.teams": "团队"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user