# Copyright 2026 Umbra Tools (umbratools.com) # SPDX-License-Identifier: Apache-2.0 """Tests for the translation delivery ingest (spec 31 section 8). UmbraTrans delivers one row per utterance per target language. The two behaviours pinned here are the ones that would make a reviewer distrust the delivery: * a delivery stored under a locale code (``zh-Hans``) must still be found when the reviewer asks about the base code (``zh``); * a source utterance the target does not voice must be *kept*, with its reason, so the gap between the English and the translation stays visible instead of silently disappearing. """ from __future__ import annotations import importlib.util import sqlite3 from pathlib import Path import pytest from umbraaudio import translations as tr _SCRIPT = Path(__file__).resolve().parents[1] / "scripts" / "import_translations.py" _spec = importlib.util.spec_from_file_location("import_translations", _SCRIPT) assert _spec is not None and _spec.loader is not None import_translations = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(import_translations) def _seed(conn: sqlite3.Connection) -> None: conn.executescript( """ CREATE TABLE project (id INTEGER PRIMARY KEY, name TEXT); CREATE TABLE chapters (id INTEGER PRIMARY KEY, chapter_index INTEGER); CREATE TABLE utterances ( id INTEGER PRIMARY KEY, chapter_id INTEGER, utterance_index INTEGER, speaker_name TEXT, text TEXT, context_before TEXT, context_after TEXT, language_code TEXT, language_origin TEXT ); INSERT INTO project (id, name) VALUES (1, 'Test'); INSERT INTO chapters (id, chapter_index) VALUES (1, 1), (2, 2); INSERT INTO utterances (id, chapter_id, utterance_index, speaker_name, text) VALUES (1, 1, 0, 'narrator', 'The ship landed.'), (2, 1, 1, 'Kainda', 'Welcome to the ship.'), (3, 1, 2, 'Kainda', 'It is very large.'), (4, 2, 0, 'narrator', 'Later that day.'), (5, 2, 1, 'Nanny', 'Danger.'); """ ) conn.commit() @pytest.fixture def conn() -> sqlite3.Connection: c = sqlite3.connect(":memory:") c.row_factory = sqlite3.Row _seed(c) tr.ensure_tables(c) yield c c.close() def _delivery(**overrides: object) -> dict: payload = { "target_language": "zh", "utterances": [ {"utterance_id": 1, "text": "飞船降落了。", "voiced": True}, {"utterance_id": 2, "text": "欢迎登船。", "voiced": True}, {"utterance_id": 3, "text": "", "voiced": False, "reason": "absorbed into utt-2"}, ], } payload.update(overrides) return payload # --- ingest --------------------------------------------------------------- def test_delivery_writes_one_row_per_utterance(conn: sqlite3.Connection) -> None: report = tr.import_translations(conn, 1, _delivery()) assert report.accepted == 3 assert report.not_voiced == 1 rows = conn.execute( "SELECT utterance_id, text, voiced, status FROM utterance_translations " "ORDER BY utterance_id" ).fetchall() assert len(rows) == 3 assert rows[0]["text"] == "飞船降落了。" assert rows[0]["status"] == tr.STATUS_DRAFT def test_a_collapsed_utterance_is_kept_with_its_reason(conn: sqlite3.Connection) -> None: tr.import_translations(conn, 1, _delivery()) row = conn.execute( "SELECT text, voiced, review_reason FROM utterance_translations WHERE utterance_id=3" ).fetchone() assert row is not None assert row["voiced"] == 0 assert "absorbed" in (row["review_reason"] or "") # The row exists, so the gap is visible; it was not deleted. assert conn.execute("SELECT COUNT(*) FROM utterances WHERE id=3").fetchone()[0] == 1 def test_confirmed_rows_are_not_overwritten(conn: sqlite3.Connection) -> None: tr.import_translations(conn, 1, _delivery(), confirm=True) report = tr.import_translations(conn, 1, _delivery()) assert report.skipped_confirmed == 3 row = conn.execute("SELECT text FROM utterance_translations WHERE utterance_id=1").fetchone() assert row["text"] == "飞船降落了。" # --- the locale-code bug -------------------------------------------------- def test_coverage_finds_a_delivery_stored_under_a_locale_code( conn: sqlite3.Connection, ) -> None: """UmbraTrans writes ``zh-Hans``; the reviewer asks about ``zh``.""" tr.import_translations(conn, 1, _delivery(target_language="zh-Hans")) assert ( conn.execute("SELECT DISTINCT language_code FROM utterance_translations").fetchone()[0] == "zh" ) report = tr.coverage(conn, "zh") assert report["delivered"] == 3 assert report["voiced"] == 2 assert report["not_voiced"] == 1 def test_coverage_finds_a_row_written_with_a_script_subtag( conn: sqlite3.Connection, ) -> None: """A row stored directly as ``zh-Hans`` must not read as "nothing".""" conn.execute( "INSERT INTO utterance_translations " "(project_id, utterance_id, language_code, language_name, text, status, origin) " "VALUES (1, 1, 'zh-Hans', 'Chinese', '飞船降落了。', 'draft', 'umbratrans')" ) conn.commit() report = tr.coverage(conn, "zh") assert report["delivered"] == 1 assert report["missing"] == 4 def test_not_voiced_rows_are_found_under_a_locale_code(conn: sqlite3.Connection) -> None: conn.execute( "INSERT INTO utterance_translations " "(project_id, utterance_id, language_code, language_name, text, status, origin, " "voiced, review_reason) " "VALUES (1, 3, 'zh-Hans', 'Chinese', '', 'draft', 'umbratrans', 0, 'absorbed into utt-2')" ) conn.commit() rows = tr.not_voiced_rows(conn, "zh") assert len(rows) == 1 assert rows[0]["utterance_id"] == 3 assert rows[0]["chapter_id"] == 1 def test_coverage_of_an_undelivered_language_is_zero(conn: sqlite3.Connection) -> None: report = tr.coverage(conn, "de") assert report["delivered"] == 0 assert report["missing"] == 5 # --- replacing a delivery ------------------------------------------------- def test_replace_clears_drafts_and_keeps_confirmed(conn: sqlite3.Connection) -> None: """A re-delivery must not leave a stale row behind. A confirmed translation is an approval, so it is never deleted - and the import skips it, so the approved text survives a re-delivery. """ tr.import_translations(conn, 1, _delivery(), confirm=True) conn.execute( "INSERT INTO utterance_translations " "(project_id, utterance_id, language_code, language_name, text, status, origin) " "VALUES (1, 4, 'zh', 'Chinese', '陈旧的草稿。', 'draft', 'umbratrans')" ) conn.commit() removed = import_translations._clear_drafts(conn, "zh") assert removed == 1 remaining = conn.execute( "SELECT utterance_id, status FROM utterance_translations ORDER BY utterance_id" ).fetchall() assert [row["utterance_id"] for row in remaining] == [1, 2, 3] assert all(row["status"] == tr.STATUS_CONFIRMED for row in remaining) def test_replace_matches_a_locale_code(conn: sqlite3.Connection) -> None: conn.execute( "INSERT INTO utterance_translations " "(project_id, utterance_id, language_code, language_name, text, status, origin) " "VALUES (1, 1, 'zh-Hans', 'Chinese', '飞船降落了。', 'draft', 'umbratrans')" ) conn.commit() assert import_translations._clear_drafts(conn, "zh") == 1 assert conn.execute("SELECT COUNT(*) FROM utterance_translations").fetchone()[0] == 0