Simplify
This commit is contained in:
parent
47b0936a75
commit
fb628f5f85
2 changed files with 74 additions and 102 deletions
|
|
@ -330,8 +330,8 @@ Open the **Workflow** tab and choose **Wolf RPG (WolfDawn)** from the engine sel
|
|||
| **3 Names** | Translate `names.json` (item/skill/enemy/map value names). WolfDawn tags each name with a per-entry **safety** badge (`safe`, `refs`, or `verify`). Phase 0 translates only `safe` entries; `refs` and `verify` names stay Japanese so inject skips them. Review the category breakdown for this game, pick **Translation mode** (Normal or Batch), and run **Translate safe names (Phase 0)**. |
|
||||
| **4 Database** | Review the **discovery summary** to see where this game's text lives (standard RPG sheets vs custom dialogue tables). Database sheets are classified as foundation (items, skills, descriptions — translate first) or narrative (custom event/profile sheets — translate after foundation). Use **Translate foundation DB** then **Translate narrative DB**, or tick specific sheets and run **Translate checked sheets only**. Optional: copy the **DB structure prompt** for an AI audit and import the returned JSON into `wolf_json/db_profile.json`. |
|
||||
| **5 Maps/Events** | Translate map scripts (`.mps`), common events (`CommonEvent.dat`), `Game.dat`, and Evtext. Run after Steps 3–4 so vocab and database terms are consistent. Configure speaker handling for low-confidence nameplate guesses. Batch mode is recommended for large `CommonEvent.dat` files. |
|
||||
| **6 Precheck** | Dry-run selected JSON for safety-guard skips; fix those lines before writing binaries. |
|
||||
| **7 Inject** | Always **Inject all** translated JSON from `translated/` into Data/ in one pass (keeps `names.json` and DB/map files in sync). Each file is reported individually; failures open a dialog with details. Uses pristine originals from `wolf_json/originals/`, then preserves name-only fields after names-inject. Optional **Layout-restore** re-applies source whitespace pads. |
|
||||
| **6 Precheck** | Runs name reconcile + consistency check, then dry-runs selected JSON for safety-guard skips; fix those lines before writing binaries. |
|
||||
| **7 Inject** | Always **Inject all** translated JSON from `translated/` into Data/ in one pass (keeps `names.json` and DB/map files in sync). Optional **Convert Japanese punctuation to ASCII**. Font-size drift from wrap is allowed automatically. Optional **Layout-restore** re-applies source whitespace pads. |
|
||||
| **8 Package** | Run from loose `Data/` (backs up `Data.wolf` → `.bak`) or repack `Data.wolf` so you can playtest and see overflow in-game. Optionally rewrite existing `.sav` files so old Japanese saves load in the translated build. |
|
||||
| **9 Fix wrap** | After packaging, paste overflowing in-game text to **search** `translated/` JSON and jump to the database sheet and row (sheet names match Step 4 and `names.json` notes, e.g. `├■街の噂(MOB)`). Edit the line, set wrap width, **Wrap this row** or **Wrap all overflowing rows in this sheet**, save, then **Inject all** (Step 7) and re-package to verify. Per-sheet widths are remembered in `wolf_json/wrap_profile.json`. **Advanced:** **wolf relayout** for event message boxes (maps/CommonEvent only — not bulletin-style DB UI) and **wolf desc-relayout** for standard 説明 description fields. |
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ Mirrors the RPGMaker WorkflowTab, driven by the vendored WolfDawn ``wolf`` CLI
|
|||
(items, skills, descriptions) before narrative custom sheets;
|
||||
harvests short label fields (map names, titles) into vocab.txt
|
||||
Step 5 Maps/Events - .mps maps, CommonEvent, Game.dat, Evtext; speaker handling
|
||||
Step 6 Precheck - dry-run selected JSON for safety-guard skips; edit those
|
||||
lines before writing binaries
|
||||
Step 6 Precheck - name consistency + reconcile, then dry-run inject for
|
||||
safety-guard skips; edit those lines before writing binaries
|
||||
Step 7 Inject - always inject every translated JSON into Data/ and
|
||||
refresh wolf_json/ (full pass avoids name/DB wipe bugs);
|
||||
optional layout-restore re-applies source whitespace pads
|
||||
|
|
@ -2436,9 +2436,10 @@ class WolfWorkflowTab(QWidget):
|
|||
def _build_step6_precheck(self, layout: QVBoxLayout):
|
||||
layout.addWidget(_make_section_label("Step 6 · Inject Precheck"))
|
||||
layout.addWidget(self._desc(
|
||||
"Dry-run selected translated JSON before writing binaries. Lists only real "
|
||||
"safety skips: control-code mismatch, or text not Shift-JIS encodable. "
|
||||
"Fix those lines here, then continue to Step 7 (Inject)."
|
||||
"Before inject: reconcile names.json → extract glossary spellings, "
|
||||
"report name inconsistencies, then dry-run the selected JSON for real "
|
||||
"safety skips (control-code mismatch, or text not Shift-JIS encodable). "
|
||||
"Fix safety rows here, then continue to Step 7 (Inject)."
|
||||
))
|
||||
|
||||
layout.addWidget(self._subheading("Translated files"))
|
||||
|
|
@ -2467,8 +2468,15 @@ class WolfWorkflowTab(QWidget):
|
|||
|
||||
precheck_row = QHBoxLayout()
|
||||
precheck_btn = self._register(_make_btn("Precheck selected", "#007acc"))
|
||||
precheck_btn.setToolTip(
|
||||
"Reconcile names → glossary, run names-check, then dry-run inject "
|
||||
"safety guards on the ticked files."
|
||||
)
|
||||
precheck_btn.clicked.connect(self._precheck_inject_selected)
|
||||
precheck_all_btn = self._register(_make_btn("Precheck all", "#007acc"))
|
||||
precheck_all_btn.setToolTip(
|
||||
"Same as Precheck selected, for every injectable file in translated/."
|
||||
)
|
||||
precheck_all_btn.clicked.connect(self._precheck_inject_all)
|
||||
precheck_row.addWidget(precheck_btn)
|
||||
precheck_row.addWidget(precheck_all_btn)
|
||||
|
|
@ -2533,37 +2541,15 @@ class WolfWorkflowTab(QWidget):
|
|||
|
||||
self.en_punct_cb = QCheckBox("Convert Japanese punctuation to ASCII (--en-punct)")
|
||||
self.en_punct_cb.setChecked(self._setting("en_punct", "true") == "true")
|
||||
self.en_punct_cb.setToolTip(
|
||||
"Fold fullwidth JP punctuation to ASCII on inject. "
|
||||
"Inline-code drift for \\f shrink is applied automatically."
|
||||
)
|
||||
self.en_punct_cb.stateChanged.connect(
|
||||
lambda: self._save_setting("en_punct", "true" if self.en_punct_cb.isChecked() else "false")
|
||||
)
|
||||
layout.addWidget(self.en_punct_cb)
|
||||
|
||||
self.drift_cb = QCheckBox(
|
||||
"Allow inline-code drift (--allow-code-drift; auto for names-wrap \\f shrink)"
|
||||
)
|
||||
self.drift_cb.setChecked(self._setting("allow_code_drift", "false") == "true")
|
||||
self.drift_cb.stateChanged.connect(
|
||||
lambda: self._save_setting(
|
||||
"allow_code_drift", "true" if self.drift_cb.isChecked() else "false"
|
||||
)
|
||||
)
|
||||
layout.addWidget(self.drift_cb)
|
||||
|
||||
check_row = QHBoxLayout()
|
||||
check_btn = self._register(_make_btn("Check name consistency", "#3a3a3a"))
|
||||
check_btn.clicked.connect(self._names_check)
|
||||
reconcile_btn = self._register(_make_btn("Reconcile names → glossary", "#007acc"))
|
||||
reconcile_btn.setToolTip(
|
||||
"Rewrite extract lines so each names.json source uses one English value. "
|
||||
"Translated names.json entries win; if the glossary is still Japanese "
|
||||
"(refs/verify), divergent extracts are unified to the majority spelling."
|
||||
)
|
||||
reconcile_btn.clicked.connect(self._names_reconcile)
|
||||
check_row.addWidget(check_btn)
|
||||
check_row.addWidget(reconcile_btn)
|
||||
check_row.addStretch()
|
||||
layout.addLayout(check_row)
|
||||
|
||||
layout.addWidget(_make_hr())
|
||||
layout.addWidget(self._subheading("Files that will be injected"))
|
||||
|
||||
|
|
@ -3605,7 +3591,6 @@ class WolfWorkflowTab(QWidget):
|
|||
return
|
||||
manifest = self._read_manifest()
|
||||
en_punct = self._inject_flag_en_punct()
|
||||
allow_drift = self._inject_flag_allow_drift()
|
||||
game_json_dir = self._work_dir()
|
||||
|
||||
def task(log, progress=None):
|
||||
|
|
@ -3618,6 +3603,7 @@ class WolfWorkflowTab(QWidget):
|
|||
|
||||
self._ensure_originals(manifest, log, progress, quiet=True)
|
||||
|
||||
# allow_code_drift=False: inject still auto-passes it for \\f shrink.
|
||||
report = wolf_inject.inject_selected(
|
||||
sorted(selected),
|
||||
manifest_entries=entries,
|
||||
|
|
@ -3625,7 +3611,7 @@ class WolfWorkflowTab(QWidget):
|
|||
originals_dir=originals_dir,
|
||||
translated_dir=self._tool_root() / "translated",
|
||||
game_root=game_root,
|
||||
allow_code_drift=allow_drift,
|
||||
allow_code_drift=False,
|
||||
en_punct=en_punct,
|
||||
log_fn=log,
|
||||
)
|
||||
|
|
@ -3830,37 +3816,75 @@ class WolfWorkflowTab(QWidget):
|
|||
return self.en_punct_cb.isChecked()
|
||||
return self._setting("en_punct", "true") == "true"
|
||||
|
||||
def _inject_flag_allow_drift(self) -> bool:
|
||||
if hasattr(self, "drift_cb"):
|
||||
return self.drift_cb.isChecked()
|
||||
return self._setting("allow_code_drift", "false") == "true"
|
||||
|
||||
def _run_inject_precheck(self, selected: set[str]):
|
||||
manifest = self._read_manifest()
|
||||
en_punct = self._inject_flag_en_punct()
|
||||
allow_drift = self._inject_flag_allow_drift()
|
||||
state: dict = {}
|
||||
|
||||
def task(log, progress=None):
|
||||
from util import wolfdawn
|
||||
from util.wolfdawn import inject_precheck as wolf_pre
|
||||
from util.wolfdawn import names as wolf_names
|
||||
|
||||
translated = self._tool_root() / "translated"
|
||||
name_notes: list[str] = []
|
||||
|
||||
# Name hygiene first (same work the old Step 7 buttons did).
|
||||
if (translated / "names.json").is_file():
|
||||
report_names = wolf_names.reconcile_translated_dir(
|
||||
translated, dry_run=False
|
||||
)
|
||||
reconcile_msg = wolf_names.format_reconcile_summary(report_names)
|
||||
log(reconcile_msg)
|
||||
for change in report_names.changes[:40]:
|
||||
log(
|
||||
f" {change.json_file}: {change.source!r} "
|
||||
f"{change.old_text!r} → {change.new_text!r} ({change.reason})"
|
||||
)
|
||||
if len(report_names.changes) > 40:
|
||||
log(f" … and {len(report_names.changes) - 40} more")
|
||||
name_notes.append(reconcile_msg)
|
||||
else:
|
||||
log("Name reconcile skipped (no translated/names.json).")
|
||||
|
||||
json_files = []
|
||||
for entry in manifest["entries"]:
|
||||
p = self._translated_or_source(entry["json"])
|
||||
if p:
|
||||
json_files.append(str(p))
|
||||
if json_files:
|
||||
check = wolfdawn.names_check(json_files, log_fn=log)
|
||||
if check.returncode == 0:
|
||||
name_notes.append("Name usage is consistent across files.")
|
||||
else:
|
||||
name_notes.append(
|
||||
"names-check reported inconsistencies (see log)."
|
||||
)
|
||||
else:
|
||||
name_notes.append("names-check skipped (no JSON found).")
|
||||
|
||||
entries = manifest["entries"]
|
||||
data_dir_path = Path(manifest["data_dir"])
|
||||
game_root = Path(manifest.get("root") or self._game_root)
|
||||
originals_dir = game_root / WORK_DIR_NAME / "originals"
|
||||
self._ensure_originals(manifest, log, progress, quiet=True)
|
||||
# Font-size drift from wrap/names-wrap is auto-allowed inside precheck.
|
||||
report = wolf_pre.precheck_selected(
|
||||
sorted(selected),
|
||||
manifest_entries=entries,
|
||||
data_dir=data_dir_path,
|
||||
originals_dir=originals_dir,
|
||||
translated_dir=self._tool_root() / "translated",
|
||||
allow_code_drift=allow_drift,
|
||||
translated_dir=translated,
|
||||
allow_code_drift=False,
|
||||
en_punct=en_punct,
|
||||
log_fn=log,
|
||||
)
|
||||
state["report"] = report
|
||||
return True, wolf_pre.format_precheck_summary(report)
|
||||
state["name_notes"] = name_notes
|
||||
summary = wolf_pre.format_precheck_summary(report)
|
||||
if name_notes:
|
||||
summary = " · ".join(name_notes) + "\n" + summary
|
||||
return True, summary
|
||||
|
||||
def _after(ok: bool, msg: str):
|
||||
from util.wolfdawn import inject_precheck as wolf_pre
|
||||
|
|
@ -3870,12 +3894,16 @@ class WolfWorkflowTab(QWidget):
|
|||
self._inject_precheck_label.setText(msg or "Precheck failed.")
|
||||
return
|
||||
self._populate_inject_precheck(report)
|
||||
self._inject_precheck_label.setText(wolf_pre.format_precheck_summary(report))
|
||||
label = wolf_pre.format_precheck_summary(report)
|
||||
notes = state.get("name_notes") or []
|
||||
if notes:
|
||||
label = " · ".join(notes) + "\n" + label
|
||||
self._inject_precheck_label.setText(label)
|
||||
if report.safety_issues:
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"Inject precheck",
|
||||
wolf_pre.format_precheck_summary(report)
|
||||
(msg or label)
|
||||
+ "\n\nSelect a safety row below, fix the text, Save line, then re-run precheck.",
|
||||
)
|
||||
else:
|
||||
|
|
@ -3996,62 +4024,6 @@ class WolfWorkflowTab(QWidget):
|
|||
|
||||
self._run_task(task, on_done=_after)
|
||||
|
||||
def _names_check(self):
|
||||
if not self._require_manifest():
|
||||
return
|
||||
manifest = self._read_manifest()
|
||||
|
||||
def task(log, progress=None):
|
||||
from util import wolfdawn
|
||||
|
||||
json_files = []
|
||||
for entry in manifest["entries"]:
|
||||
p = self._translated_or_source(entry["json"])
|
||||
if p:
|
||||
json_files.append(str(p))
|
||||
if not json_files:
|
||||
return False, "No translated JSON found. Run Steps 4-5 first."
|
||||
res = wolfdawn.names_check(json_files, log_fn=log)
|
||||
if res.returncode == 0:
|
||||
return True, "Name usage is consistent across files."
|
||||
return True, "names-check reported inconsistencies (see log above)."
|
||||
|
||||
self._run_task(task)
|
||||
|
||||
def _names_reconcile(self):
|
||||
"""Force extract JSON to one English per glossary name (names.json wins)."""
|
||||
translated = self._tool_root() / "translated"
|
||||
if not (translated / "names.json").is_file():
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"Reconcile names",
|
||||
"translated/names.json not found. Finish Step 3 first.",
|
||||
)
|
||||
return
|
||||
|
||||
def task(log, progress=None):
|
||||
from util.wolfdawn import names as wolf_names
|
||||
|
||||
report = wolf_names.reconcile_translated_dir(translated, dry_run=False)
|
||||
summary = wolf_names.format_reconcile_summary(report)
|
||||
log(summary)
|
||||
for change in report.changes[:40]:
|
||||
log(
|
||||
f" {change.json_file}: {change.source!r} "
|
||||
f"{change.old_text!r} → {change.new_text!r} ({change.reason})"
|
||||
)
|
||||
if len(report.changes) > 40:
|
||||
log(f" … and {len(report.changes) - 40} more")
|
||||
return True, summary
|
||||
|
||||
def _after(ok: bool, msg: str):
|
||||
if ok:
|
||||
QMessageBox.information(self, "Reconcile names", msg)
|
||||
else:
|
||||
QMessageBox.warning(self, "Reconcile names", msg or "Reconcile failed.")
|
||||
|
||||
self._run_task(task, on_done=_after)
|
||||
|
||||
# ── Step 8: Package (+ optional saves) ─────────────────────────────────────
|
||||
|
||||
def _build_step8_package(self, layout: QVBoxLayout):
|
||||
|
|
|
|||
Loading…
Reference in a new issue