sjadfoajiofs

This commit is contained in:
dazedanon 2026-03-12 22:41:28 -05:00
parent 174fbcad98
commit f758e13073

View file

@ -71,6 +71,26 @@ PHASE1_CONFIG = {
"CODE108": False,
}
PHASE1B_CONFIG = {
# Dialogue OFF (handled by Phase 1)
"CODE101": False,
"CODE401": False,
"CODE405": False,
"CODE102": False,
"CODE408": False,
# Only 111 ON — build the var-translation cache from string comparisons
"CODE111": True,
"CODE122": False,
"CODE357": False,
"CODE355655": False,
"CODE657": False,
"CODE356": False,
"CODE320": False,
"CODE324": False,
"CODE325": False,
"CODE108": False,
}
PHASE2_CONFIG = {
# Dialogue OFF (already handled by Phase 1)
"CODE101": False,
@ -78,10 +98,10 @@ PHASE2_CONFIG = {
"CODE405": False,
"CODE102": False,
"CODE408": False,
# Risky codes ON
# Risky codes ON (111 OFF — cache already built by Phase 1b)
"CODE122": True,
"CODE357": True,
"CODE111": True,
"CODE111": False,
"CODE356": False, # plugin cmd — user can enable manually if needed
"CODE108": False, # comment — rarely needed
}
@ -755,6 +775,102 @@ class WorkflowTab(QWidget):
"(e.g. padding estimates, windows whose pixel width could not be determined directly).\n"
)
_RISKY_PROMPT = (
"You are helping me safely translate a Japanese RPGMaker MV/MZ game.\n"
"Before I run Phase 2 (risky codes), I need you to audit four code types\n"
"and tell me exactly what is safe to translate and what must be left alone.\n"
"\n"
"Attach the game's event files (CommonEvents.json, Troops.json, Map*.json)\n"
"and plugins.js before running this prompt.\n"
"\n"
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
"## AUDIT 1 — Code 111 (Conditional Branch) string comparisons\n"
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
"\n"
"Search all event lists for code 111 entries that compare a string value\n"
"(operationType 0 or where parameters[3] is a string literal).\n"
"\n"
"For each one found, report:\n"
" - The variable or switch being tested\n"
" - The string it is compared against (e.g. === 'ノーマル')\n"
" - Whether the same string appears as a value SET by a code 122 elsewhere\n"
" (meaning translating code 122 would break this 111 comparison)\n"
"\n"
"Verdict for each: SAFE TO TRANSLATE / DO NOT TRANSLATE / NEEDS MANUAL CHECK\n"
"\n"
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
"## AUDIT 2 — Code 122 (Control Variables) string values\n"
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
"\n"
"Search for code 122 entries where parameters[4] is a quoted string.\n"
"For each unique string value found:\n"
" - Is this string also tested in a 111 comparison? → DO NOT TRANSLATE\n"
" - Is this string used as a key / ID in a plugin call or script? → DO NOT TRANSLATE\n"
" - Is this string purely display text (shown to the player)? → SAFE TO TRANSLATE\n"
"\n"
"List any variables by variable-ID that should be blacklisted from translation.\n"
"\n"
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
"## AUDIT 3 — Code 357 (Plugin Commands) — which plugins need enabling\n"
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
"\n"
"Search all event lists for code 357 entries and collect every unique\n"
"parameters[0] (plugin header string) that contains translatable Japanese text\n"
"in its parameters[3] dict.\n"
"\n"
"The translation module already has built-in handlers for these headers:\n"
" AdvExtentionllk, VisuMZ_4_ProximityMessages, LL_GalgeChoiceWindow\n"
"\n"
"For every OTHER header you find with Japanese text, check whether it matches\n"
"one of these commented-out entries in the module's headerMappings dict:\n"
"\n"
" LL_InfoPopupWIndow → messageText\n"
" QuestSystem → DetailNote\n"
" BalloonInBattle → text\n"
" MNKR_CommonPopupCoreMZ → text\n"
" DestinationWindow → destination\n"
" _TMLogWindowMZ → text\n"
" TorigoyaMZ_NotifyMessage → message\n"
" SoR_GabWindow → arg1\n"
" DarkPlasma_CharacterText → text\n"
" DTextPicture → text\n"
" TextPicture → text\n"
" TRP_SkitMZ → name\n"
" LogWindow → text\n"
" BattleLogOutput → message\n"
" TorigoyaMZ_NotifyMessage_CommandMessage → message\n"
" NUUN_SaveScreen → AnyName\n"
" build/ARPG_Core → Text, SkillByName\n"
"\n"
"For each match, output the EXACT line to uncomment in headerMappings, e.g.:\n"
" \"LL_InfoPopupWIndow\": ([\"messageText\"], None),\n"
"\n"
"For headers with Japanese text that do NOT appear in the list above, describe\n"
"the parameters[3] structure so a new entry can be written manually.\n"
"\n"
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
"## Required output format\n"
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
"\n"
"Reply with four sections using these exact headers:\n"
"\n"
"### Code 111 — Dangerous Comparisons\n"
"<table of: variable | compared string | also set by 122? | verdict>\n"
"If none found: 'No dangerous string comparisons found.'\n"
"\n"
"### Code 122 — Variable String Safety\n"
"<list of variable IDs with their string values and SAFE / DO NOT TRANSLATE verdict>\n"
"If all safe: 'All code 122 string values appear to be display text only.'\n"
"\n"
"### Code 357 — Plugin Handlers to Enable\n"
"For each plugin header with Japanese text:\n"
" • Already handled : <header> — no action needed\n"
" • Enable in module : uncomment this line in headerMappings:\n"
" \"<header>\": ([\"<key>\"], None),\n"
" • New entry needed : <header> — parameters[3] looks like: <description>\n"
"If no 357 codes with Japanese found: 'No code 357 plugin text found.'\n"
)
# ── Step 1 (Optional): Pre-process ────────────────────────────────
def _build_preprocess(self, layout: QVBoxLayout):
@ -1182,6 +1298,32 @@ class WorkflowTab(QWidget):
p1_inner.addLayout(p1_row)
layout.addWidget(p1_box)
p1b_box = QGroupBox("Phase 1b Build Variable Cache (code 111)")
p1b_box.setStyleSheet(
"QGroupBox{color:#ccc;border:1px solid #444;border-radius:3px;"
"margin-top:8px;font-size:11px;}"
"QGroupBox::title{padding:0 6px;}"
)
p1b_inner = QVBoxLayout(p1b_box)
p1b_desc = QLabel(
"Code ON: 111 (Conditional Branch string comparisons)\n"
"Scans all 111 branches that compare \u2018$gameVariables\u2019 against string values and "
"builds the var_translation_map cache.\n"
"Run this before Phase 2 so that code 122 translated strings are automatically "
"matched when those same strings appear in 111 comparisons."
)
p1b_desc.setStyleSheet("color:#888;font-size:10px;")
p1b_desc.setWordWrap(True)
p1b_inner.addWidget(p1b_desc)
p1b_row = QHBoxLayout()
run_p1b = _make_btn("⚙ Set Codes \u2192 Go to Translation", "#2a5a7a")
run_p1b.setToolTip("Applies Phase 1b code settings (111 only) and switches to the Translation tab")
run_p1b.clicked.connect(lambda: self._run_phase("1b"))
p1b_row.addWidget(run_p1b)
p1b_row.addStretch()
p1b_inner.addLayout(p1b_row)
layout.addWidget(p1b_box)
p2_box = QGroupBox("Phase 2 Risky Codes (variables + conditionals)")
p2_box.setStyleSheet(
"QGroupBox{color:#ccc;border:1px solid #444;border-radius:3px;"
@ -1190,7 +1332,7 @@ class WorkflowTab(QWidget):
)
p2_inner = QVBoxLayout(p2_box)
p2_desc = QLabel(
"Codes ON: 122 (Control Variables), 357 (Plugin Commands), 111 (Conditional Branch)\n"
"Codes ON: 122 (Control Variables), 357 (Plugin Commands)\n"
"Strings here are often used in script comparisons — mistranslations can break game "
"logic. Use Scan first to preview what will be translated, then apply and go translate."
)
@ -1198,15 +1340,18 @@ class WorkflowTab(QWidget):
p2_desc.setWordWrap(True)
p2_inner.addWidget(p2_desc)
p2_row = QHBoxLayout()
scan_p2 = _make_btn("🔍 Scan Risky Strings", "#555")
scan_p2.setToolTip(
"Preview all unique string values in codes 122 / 357 / 111 "
"before deciding what to translate."
copy_risky_row = QHBoxLayout()
copy_risky_btn = _make_btn("📋 Copy Risky Prompt", "#555")
copy_risky_btn.setToolTip(
"Copy a Copilot prompt that audits code 111 string comparisons, "
"code 122 variable safety, and code 357 plugin handlers."
)
scan_p2.clicked.connect(self._scan_risky_strings)
p2_row.addWidget(scan_p2)
copy_risky_btn.clicked.connect(self._copy_risky_prompt)
copy_risky_row.addWidget(copy_risky_btn)
copy_risky_row.addStretch()
p2_inner.addLayout(copy_risky_row)
p2_row = QHBoxLayout()
run_p2 = _make_btn("⚙ Set Codes \u2192 Go to Translation", "#7a4a00")
run_p2.setToolTip("Applies Phase 2 code settings and switches to the Translation tab")
run_p2.clicked.connect(lambda: self._run_phase(2))
@ -1511,6 +1656,10 @@ class WorkflowTab(QWidget):
QApplication.clipboard().setText(self._WRAP_PROMPT)
self._log("Text-wrap analysis prompt copied to clipboard.")
def _copy_risky_prompt(self):
QApplication.clipboard().setText(self._RISKY_PROMPT)
self._log("Risky codes analysis prompt copied to clipboard.")
def _apply_wrap_config(self):
"""Write width / listWidth / noteWidth back into .env."""
import re as _re
@ -1566,9 +1715,16 @@ class WorkflowTab(QWidget):
# Step 4 Translation phases
# ─────────────────────────────────────────────────────────────────────────
def _run_phase(self, phase: int):
config = PHASE1_CONFIG if phase == 1 else PHASE2_CONFIG
label = "Phase 1 (safe codes)" if phase == 1 else "Phase 2 (risky codes)"
def _run_phase(self, phase):
if phase == 1:
config = PHASE1_CONFIG
label = "Phase 1 (safe codes)"
elif phase == "1b":
config = PHASE1B_CONFIG
label = "Phase 1b (code 111 cache)"
else:
config = PHASE2_CONFIG
label = "Phase 2 (risky codes)"
# Apply config profile so the Translation tab uses the right codes
try:
@ -1607,12 +1763,21 @@ class WorkflowTab(QWidget):
self._log(" If names are missing or garbled, stop the run and")
self._log(" revisit Step 2 (speaker flags) before continuing.")
self._log("" * 54)
elif phase == "1b":
self._log("")
self._log("" * 54)
self._log("👉 Switch to the Translation tab and start the run.")
self._log(" Phase 1b translates code 111 string comparisons and")
self._log(" writes a var_translation_map cache to log/.")
self._log(" Run Phase 2 afterwards — code 122 strings that match")
self._log(" a cached 111 comparison will reuse the same translation.")
self._log("" * 54)
else:
self._log("")
self._log("" * 54)
self._log("👉 Switch to the Translation tab and start the run.")
self._log(" Phase 2 targets script/variable strings — review")
self._log(" the Risky String scan output before proceeding.")
self._log(" Phase 2 targets script/variable strings — make sure")
self._log(" Phase 1b has been run first to build the 111 cache.")
self._log("" * 54)
# Navigate to the Translation tab (index 0 in content_stack)
@ -1626,50 +1791,6 @@ class WorkflowTab(QWidget):
except Exception:
pass
# ─────────────────────────────────────────────────────────────────────────
# Risky string scanner (preview mode)
# ─────────────────────────────────────────────────────────────────────────
def _scan_risky_strings(self):
risky_codes = {122, 357, 111}
collected: dict[int, list[str]] = {c: [] for c in risky_codes}
files_dir = Path("files")
try:
for fp in sorted(files_dir.glob("*.json")):
data = json.loads(fp.read_text(encoding="utf-8-sig"))
self._collect_risky(data, risky_codes, collected)
self._log("=" * 50)
self._log("Risky Code String Scan (preview — nothing modified):")
total = 0
for code in sorted(risky_codes):
strings = sorted(set(collected[code]))
total += len(strings)
self._log(f"\n CODE {code}{len(strings)} unique string(s):")
for s in strings[:50]:
self._log(f" {repr(s)}")
if len(strings) > 50:
self._log(f" … ({len(strings) - 50} more)")
self._log(f"\n Total unique strings: {total}")
self._log("=" * 50)
except Exception as exc:
self._log(f"❌ Scan error: {exc}")
def _collect_risky(self, obj, risky_codes: set, collected: dict):
if isinstance(obj, list):
for item in obj:
self._collect_risky(item, risky_codes, collected)
elif isinstance(obj, dict):
code = obj.get("code")
if code in risky_codes:
params = obj.get("parameters") or []
for p in params:
if isinstance(p, str) and p.strip():
collected[code].append(p)
for v in obj.values():
self._collect_risky(v, risky_codes, collected)
# ─────────────────────────────────────────────────────────────────────────
# Step 5 Export to game
# ─────────────────────────────────────────────────────────────────────────