fix(rpgmaker): normalize English text and ignore editor comments in QA
This commit is contained in:
parent
d38a8a2725
commit
ea45b3c626
5 changed files with 50 additions and 3 deletions
|
|
@ -51,8 +51,9 @@ present.
|
|||
same path on the owning object. Numeric string keys in `_original` usually address list indexes
|
||||
in the live object, as in `System.json` lists and `terms` arrays.
|
||||
- For event code 102, pair each `_original[index]` choice with `parameters[0][index]`.
|
||||
- For scalar event-command `_original` values, resolve the live display value by command shape:
|
||||
- 401, 405, 408, 657, 356, 108: visible text in `parameters[0]`.
|
||||
- For scalar event-command `_original` values, resolve the live value by command shape:
|
||||
- 401, 405, 657, 356, 108: visible text in `parameters[0]`.
|
||||
- 408: internal editor comment in `parameters[0]`; it is not player-facing text.
|
||||
- 101: visible name field in `parameters[4]`, or `parameters[0]` for the variable-name form.
|
||||
- 122: translated inner quoted/backticked string in `parameters[4]`, excluding its script
|
||||
wrapper and trailing semicolon.
|
||||
|
|
@ -71,6 +72,8 @@ Check every resolvable pair for:
|
|||
counts, empty output, or accidental type changes.
|
||||
2. Japanese or other source-language residue, unchanged source copied as translation, truncation,
|
||||
mojibake, model commentary, refusal text, Markdown fences, or JSON fragments inside player text.
|
||||
Do not count unchanged code-408 editor comments as player-facing residue or actionable findings.
|
||||
Report their coverage separately only when the user requests editor-facing localization.
|
||||
3. Lost, added, duplicated, reordered, malformed, or altered runtime tokens. Include RPG Maker
|
||||
control codes such as `\C[n]`, `\N[n]`, `\V[n]`, `\I[n]`, `\{`, `\}`, `\.`, `\|`, `\!`,
|
||||
`\>`, `\<`, and `\^`; custom backslash codes; `__PROTECTED_n__`; printf-style placeholders;
|
||||
|
|
|
|||
|
|
@ -928,6 +928,18 @@ def _apply_system_terms_message_original(data, key: str, raw: str) -> None:
|
|||
msg[key] = raw
|
||||
|
||||
|
||||
def _normalize_system_message_translation(key: str, translated: str) -> str:
|
||||
"""Repair narrowly known English RPG Maker system-message failures."""
|
||||
text = str(translated or "").strip()
|
||||
target = str(LANGUAGE or "").strip().casefold().replace("_", "-")
|
||||
is_english = target in {"en", "eng", "english"} or target.startswith("en-")
|
||||
if key == "escapeFailure" and is_english and re.fullmatch(
|
||||
r"but\s+couldn['’]t\s+escape!?", text, flags=re.IGNORECASE
|
||||
):
|
||||
return "But escape failed!"
|
||||
return text
|
||||
|
||||
|
||||
_COLOR_SPEAKER_RE = re.compile(
|
||||
r"^[\\]+[cC]\[\d+\]【?(.+?)】?[\\]+[cC]\[\d+\](?:[\\]+[A-Za-z]+(?:\[[^\]]*\])?)*[\\]*$"
|
||||
)
|
||||
|
|
@ -4851,7 +4863,7 @@ def searchSystem(data, pbar):
|
|||
|
||||
# Assign back translations to corresponding keys
|
||||
for n, key in enumerate(msg_keys[: len(tl_list)]):
|
||||
translatedText = tl_list[n]
|
||||
translatedText = _normalize_system_message_translation(key, tl_list[n])
|
||||
for char in charList:
|
||||
translatedText = translatedText.replace(char, "")
|
||||
messages[key] = translatedText
|
||||
|
|
@ -4914,6 +4926,8 @@ def _normalize_speaker_nameplate(translated: str) -> str:
|
|||
elif len(words) > 4:
|
||||
words = words[:3]
|
||||
out = " ".join(words).title().replace("'S", "'s")
|
||||
# str.title() capitalizes after apostrophes ("Ma'am" -> "Ma'Am").
|
||||
out = re.sub(r"\bMa['’]Am\b", "Ma'am", out, flags=re.IGNORECASE)
|
||||
out = re.sub(
|
||||
r"(\d)(St|Nd|Rd|Th)\b",
|
||||
lambda m: m.group(1) + m.group(2).lower(),
|
||||
|
|
|
|||
|
|
@ -279,6 +279,32 @@ class TestStatesOriginal(unittest.TestCase):
|
|||
|
||||
|
||||
class TestSystemOriginal(unittest.TestCase):
|
||||
def test_normalizes_english_escape_failure(self):
|
||||
original_language = mvmz.LANGUAGE
|
||||
mvmz.LANGUAGE = "English"
|
||||
try:
|
||||
self.assertEqual(
|
||||
mvmz._normalize_system_message_translation(
|
||||
"escapeFailure", "But couldn't escape!"
|
||||
),
|
||||
"But escape failed!",
|
||||
)
|
||||
finally:
|
||||
mvmz.LANGUAGE = original_language
|
||||
|
||||
def test_does_not_rewrite_custom_escape_failure(self):
|
||||
original_language = mvmz.LANGUAGE
|
||||
mvmz.LANGUAGE = "English"
|
||||
try:
|
||||
self.assertEqual(
|
||||
mvmz._normalize_system_message_translation(
|
||||
"escapeFailure", "However, escape was impossible!"
|
||||
),
|
||||
"However, escape was impossible!",
|
||||
)
|
||||
finally:
|
||||
mvmz.LANGUAGE = original_language
|
||||
|
||||
def test_first_pass_writes_original(self):
|
||||
data = json.loads((FIXTURES / "System_original_fixture.json").read_text(encoding="utf-8"))
|
||||
result, _ = _run_search_system(data)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ class SpeakerNameplateNormalizeTests(unittest.TestCase):
|
|||
"Electrician Guy From",
|
||||
)
|
||||
|
||||
def test_preserves_maam_casing(self):
|
||||
self.assertEqual(_normalize_speaker_nameplate("ma'am"), "Ma'am")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ class WorkflowTranslationPromptTests(unittest.TestCase):
|
|||
self.assertIn("mechanically check 100%", lowered)
|
||||
self.assertIn("deterministic stratified sample", lowered)
|
||||
self.assertIn("control-code scope and placement", lowered)
|
||||
self.assertIn("do not count unchanged code-408 editor comments", lowered)
|
||||
self.assertIn("do not edit during the first pass", lowered)
|
||||
self.assertIn("stop and wait for approval", lowered)
|
||||
self.assertIn("never modify or remove `_original`", lowered)
|
||||
|
|
|
|||
Loading…
Reference in a new issue