From c74fde4f40d866c07c49b4789a9086c8264c277b Mon Sep 17 00:00:00 2001 From: Vadym Samoilenko Date: Wed, 6 May 2026 12:13:39 +0100 Subject: [PATCH] fix(translation): approve_source triggers translation for any role MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit approve_source is callable by any qualified role (reviewer, linguist, production, admin) — not just linguists. Now correctly dispatches the translation pipeline when target languages are untranslated, regardless of who approves the source. Without this fix, only language_qc.approve_language (EN path) would trigger translation, leaving other roles stuck. Co-Authored-By: Claude Sonnet 4.6 --- backend/app/api/v1/routes_jobs.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/backend/app/api/v1/routes_jobs.py b/backend/app/api/v1/routes_jobs.py index 55df8b5..b6ca2a1 100644 --- a/backend/app/api/v1/routes_jobs.py +++ b/backend/app/api/v1/routes_jobs.py @@ -873,9 +873,22 @@ async def approve_source( detail="Job not in pending QC status" ) - # Transition directly to PENDING_FINAL_REVIEW - # Translation, TTS, and accessible video rendering now happen BEFORE QC - new_status = JobStatus.PENDING_FINAL_REVIEW + # Determine if there are target languages that still need translation. + source_language = job_doc["source"].get("language", "en") + requested_langs = job_doc.get("requested_outputs", {}).get("languages", []) + target_languages = [lg for lg in requested_langs if lg != source_language] + existing_outputs = job_doc.get("outputs") or {} + untranslated = [ + lg for lg in target_languages + if not (existing_outputs.get(lg) or {}).get("captions_vtt_gcs") + ] + + # If untranslated target languages exist, dispatch translation instead of + # jumping straight to final review. Any role can trigger this. + if untranslated: + new_status = JobStatus.TRANSLATING + else: + new_status = JobStatus.PENDING_FINAL_REVIEW # Build update operations update_set = { @@ -917,8 +930,11 @@ async def approve_source( detail="Job not found or not in pending QC status" ) - # No need to trigger translate_and_synthesize_task - all processing done before QC - logger.info(f"Job {job_id} approved, transitioning directly to final review") + if untranslated: + await _cr_dispatch("translate", job_doc["_id"], languages=untranslated) + logger.info(f"Job {job_id} source approved — dispatching translation for {untranslated}") + else: + logger.info(f"Job {job_id} approved, transitioning directly to final review") await log_job_action( AuditAction.JOB_APPROVE, job_id, current_user, http_request,