Pass 1 should TL Speakers
This commit is contained in:
parent
f25ce9f990
commit
4abb10df15
2 changed files with 69 additions and 12 deletions
|
|
@ -412,28 +412,37 @@ def _body_after_dropped_tag(text: str, original_speaker: str) -> str:
|
||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
def _maybe_fix_nameplate(entry, total_tokens: list) -> None:
|
def _maybe_fix_nameplate(entry, total_tokens: list) -> bool:
|
||||||
"""Swap a Japanese first-line nameplate for English on an otherwise-done line."""
|
"""Resolve a Japanese first-line nameplate on an otherwise-done line.
|
||||||
if ESTIMATE or _batch_phase() == "collect":
|
|
||||||
return
|
Returns True when the nameplate was rewritten. During batch collect the
|
||||||
|
in-memory rewrite is discarded (translated/ is not written), but
|
||||||
|
``getSpeaker`` still runs so the English gloss is cached before dialogue
|
||||||
|
batches are queued - otherwise those live speaker calls only show up in
|
||||||
|
Pass 2.
|
||||||
|
"""
|
||||||
|
if ESTIMATE:
|
||||||
|
return False
|
||||||
speaker_src = entry.get("speaker_src", "")
|
speaker_src = entry.get("speaker_src", "")
|
||||||
if not wolf_speakers.is_firstline_enabled(speaker_src, SPEAKER_CONFIG):
|
if not wolf_speakers.is_firstline_enabled(speaker_src, SPEAKER_CONFIG):
|
||||||
return
|
return False
|
||||||
txt = entry.get("text")
|
txt = entry.get("text")
|
||||||
if not isinstance(txt, str) or not txt.strip():
|
if not isinstance(txt, str) or not txt.strip():
|
||||||
return
|
return False
|
||||||
# Only touch finished dialogue (body already English / skip-translated).
|
# Only touch finished dialogue (body already English / skip-translated).
|
||||||
if _text_still_needs_translation(entry):
|
if _text_still_needs_translation(entry):
|
||||||
return
|
return False
|
||||||
split = wolf_speakers.split_source(txt, speaker_src, SPEAKER_CONFIG)
|
split = wolf_speakers.split_source(txt, speaker_src, SPEAKER_CONFIG)
|
||||||
if split is None:
|
if split is None:
|
||||||
return
|
return False
|
||||||
prefix, speaker, body = split
|
prefix, speaker, body = split
|
||||||
if not re.search(LANGREGEX, speaker):
|
if not re.search(LANGREGEX, speaker):
|
||||||
return
|
return False
|
||||||
speaker_en = _resolve_nameplate(speaker, total_tokens)
|
speaker_en = _resolve_nameplate(speaker, total_tokens)
|
||||||
if speaker_en and speaker_en != speaker:
|
if speaker_en and speaker_en != speaker:
|
||||||
entry["text"] = wolf_speakers.restore_source(prefix, speaker_en, body)
|
entry["text"] = wolf_speakers.restore_source(prefix, speaker_en, body)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def parseDocument(data, filename):
|
def parseDocument(data, filename):
|
||||||
|
|
@ -457,9 +466,11 @@ def parseDocument(data, filename):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Fix Japanese nameplates on lines whose dialogue body is already done, so
|
# Resolve Japanese nameplates on lines whose dialogue body is already done.
|
||||||
# resume / re-wrap runs do not leave ``セルリア\\nPlease hold on...`` behind.
|
# Must run during batch collect too: those lines are skip-translated so they
|
||||||
if IGNORETLTEXT and not ESTIMATE and _batch_phase() != "collect":
|
# never hit the reshape/getSpeaker path, and deferring to consume is what
|
||||||
|
# made speaker Input/Output spam show up in Pass 2 after the batch returned.
|
||||||
|
if IGNORETLTEXT and not ESTIMATE:
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
if _translatable(entry):
|
if _translatable(entry):
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -470,6 +470,52 @@ class TestTranslationWriteback(unittest.TestCase):
|
||||||
# Short-string speaker resolve, then the remaining dialogue batch.
|
# Short-string speaker resolve, then the remaining dialogue batch.
|
||||||
self.assertEqual(captured, ["司祭", ["まだだ"]])
|
self.assertEqual(captured, ["司祭", ["まだだ"]])
|
||||||
|
|
||||||
|
def test_collect_resolves_japanese_nameplate_before_queueing(self):
|
||||||
|
"""Pass 1 must live-translate skip-translated JP nameplates (not defer to Pass 2)."""
|
||||||
|
doc = {
|
||||||
|
"kind": "map",
|
||||||
|
"scenes": [
|
||||||
|
{
|
||||||
|
"event": 1,
|
||||||
|
"name": "ev",
|
||||||
|
"lines": [
|
||||||
|
{
|
||||||
|
"cmd": 0,
|
||||||
|
"str": 0,
|
||||||
|
"speaker": "客F",
|
||||||
|
"speaker_src": "literal_line1_lowconf",
|
||||||
|
"source": "客F\nまぁまぁ。",
|
||||||
|
"text": "客F\nNow, now.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmd": 1,
|
||||||
|
"str": 0,
|
||||||
|
"speaker": "UI",
|
||||||
|
"speaker_src": "ui",
|
||||||
|
"source": "まだだ",
|
||||||
|
"text": "まだだ",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
orig_phase = os.environ.get("BATCH_PHASE")
|
||||||
|
os.environ["BATCH_PHASE"] = "collect"
|
||||||
|
try:
|
||||||
|
(data, _t, err), captured = _WolfTranslateHarness().run(doc, "collect_nameplate.mps.json")
|
||||||
|
finally:
|
||||||
|
if orig_phase is None:
|
||||||
|
os.environ.pop("BATCH_PHASE", None)
|
||||||
|
else:
|
||||||
|
os.environ["BATCH_PHASE"] = orig_phase
|
||||||
|
|
||||||
|
self.assertIsNone(err)
|
||||||
|
# Speaker resolved live during collect; dialogue list is also seen (queued).
|
||||||
|
self.assertEqual(captured[0], "客F")
|
||||||
|
self.assertEqual(captured[1], ["まだだ"])
|
||||||
|
# Collect does not persist translated/, but in-memory text is updated.
|
||||||
|
self.assertEqual(data["scenes"][0]["lines"][0]["text"], "En_客F\nNow, now.")
|
||||||
|
|
||||||
def test_ignore_tl_text_false_retranslates(self):
|
def test_ignore_tl_text_false_retranslates(self):
|
||||||
doc = {
|
doc = {
|
||||||
"kind": "map",
|
"kind": "map",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue