diff --git a/README.md b/README.md index 10f7366..ccac711 100644 --- a/README.md +++ b/README.md @@ -327,7 +327,7 @@ Open the **Workflow** tab and choose **Wolf RPG (WolfDawn)** from the engine sel | **0 Project** | Select the game folder, **Unpack** the `.wolf` archives into a loose `Data/` folder, then **Extract text** (maps, common events, databases, `Game.dat`, external event text, and the project-wide name glossary). Everything is staged into `files/` for translation, including `names.json` (translated later in Phase 0 only). Extraction also snapshots the pristine (untranslated) binaries into `wolf_json/originals/` so Step 4 can inject idempotently. **Set up git tracking** by copying the `gameupdate/` folder (updater scripts, `patch.sh`/`patch.ps1`, and a `.gitignore` that excludes the original game files) into the game root, so the translation project can be tracked with git and later shipped as a git-based patch players apply themselves. Finally, **Format extracted JSON** (dazedformat) normalises `wolf_json/` and `files/` to the same layout the translator writes back (`json.dump`, indent 4) — run it once and commit it as your baseline so later injects produce clean, line-level git diffs instead of reformatting whole files. | | **1 Glossary** | Build `vocab.txt` before translating: copy the WOLF-tailored prompt into Cursor/Copilot with the extracted `files/` JSON, let it discover character names, speech registers, and lore terms, then paste the result into the in-tab editor and save (the shared `vocab.txt` is used by every translation batch to keep names and voice consistent). Item/skill/enemy value names (`names.json`) are curated in Step 2 and harvested into `vocab.txt` automatically during Phase 0 — do not list them here. | | **2 Names** | Curate `names.json` (item/skill/enemy/variable value names). **Translating all of them breaks the game** - many WOLF value names double as logic keys (compared by value, used as variable/file/event names), so by default none are translated. WolfDawn tags each name with its WOLF database **category** (the `note` field), so instead of judging thousands of names you pick which *categories* are safe. Copy the **names-safety prompt** into a repo-aware AI (Cursor/Copilot with `files/` open); it groups names by category, checks how each is used, and returns a JSON list of the safe categories in a code block. Paste that list and click **Apply** to tick the matching rows (or tick them by hand - each row shows the category, its name count, and an example), then **Save** to `data/wolf_safe_notes.json`. Pick the **Translation mode** here (Normal or Batch - Batch uses the Anthropic Batches API, ~50% cheaper, Claude only); the same choice applies to all later phases. Run **Translate safe names (Phase 0)** once categories are saved - this is the first translation step and harvests item/skill/term names into `vocab.txt`. | -| **3 Translate** | Run the `Wolf RPG (WolfDawn)` module in three ordered phases (RPG Maker's DB-first strategy): **Phase 0 · Names → vocab.txt** translates only the safe name categories from Step 2 and harvests them into `vocab.txt` (grouped by bilingual category headers such as `Weapon · 武器`); **Phase 1 · Database text** translates item/skill/state descriptions and system messages from `DataBase.project.json` / `CDataBase.project.json`; **Phase 2 · Dialogue & events** translates maps (`.mps`), `CommonEvent.dat.json`, `Game.dat`, and `Evtext`. Run them in order so later phases benefit from the glossary seeded in Phase 0. Under **Speaker handling**, speaker attribution is automatic - WolfDawn already tags who speaks on each line, so lines with a real nameplate (a face window precedes the name) are always reshaped into the `[Speaker]: line` convention the prompt understands (translating the speaker tag), then restored to WOLF's native `Speaker⏎line` layout on inject. The only judgement call is WolfDawn's low-confidence guesses (a short first line with no face window that may or may not be a name); copy the **speaker-format prompt** to have the repo-aware AI inspect `files/` and recommend ENABLE/DISABLE, then set the single low-confidence checkbox to match (there is no toggle for the reliable nameplates - they need no configuration). Under **Text wrap width**, set whether/where translated dialogue re-wraps to fit WOLF's message box (same `dazedwrap` engine the RPG Maker workflow uses, saved to `.env` as `wolfWrap` / `wolfWidth`); only the dialogue body is wrapped - a speaker's nameplate line is always kept separate so the `⏎` after a name is never folded into the text. Only the `text` fields are filled in; `source` is preserved so injection can verify each line. | +| **3 Translate** | Run the `Wolf RPG (WolfDawn)` module in three ordered phases (RPG Maker's DB-first strategy): **Phase 0 · Names → vocab.txt** translates only the safe name categories from Step 2 and harvests them into `vocab.txt` (grouped by bilingual category headers such as `Weapon · 武器`); **Phase 1 · Database text** translates item/skill/state descriptions and system messages from `DataBase.project.json` / `CDataBase.project.json`; **Phase 2 · Dialogue & events** translates maps (`.mps`), `CommonEvent.dat.json`, `Game.dat`, and `Evtext`. Run them in order so later phases benefit from the glossary seeded in Phase 0. **Speaker handling** and **Text wrap width** sit under Phase 2 because they only affect dialogue: speaker attribution is automatic for real nameplates (face window → name → line, reshaped to `[Speaker]: line` for the prompt and restored to WOLF's `Speaker⏎line` on inject); copy the **speaker-format prompt** so a repo-aware AI can recommend whether to enable low-confidence first-line names. Text wrap re-flows translated dialogue to fit WOLF's message box (`wolfWrap` / `wolfWidth` in `.env`; nameplate lines stay separate). Only the `text` fields are filled in; `source` is preserved so injection can verify each line. | | **4 Inject** | Write the translations back into the game's `Data/` binaries **and** refresh the git-tracked `wolf_json/` with the translated JSON, so the game project's git diff shows both the JSON source and the injected binaries. Injection always reads from a **pristine snapshot** of the original binaries (`wolf_json/originals/`, captured during Step 0 extraction and rebuilt from the `.wolf`/`.wolf.bak` archives if missing) and writes the result into the live `Data/` file. This keeps injection **idempotent** - WolfDawn locates each Japanese source string in the original, so re-injecting after fixing a few lines actually updates the binary instead of silently no-op'ing (the old in-place inject broke once a file had already been translated). Toggle `--en-punct` (convert Japanese punctuation to ASCII) and `--allow-code-drift` (relax the inline-code guard) as needed, and use **Check name consistency** to catch names translated differently across files. **Quick inject** lists the files you've translated so far (present in `translated/`) so you can tick just a few, inject them straight into `Data/`, and review the git diff / test in-game - ideal for iterating. **Inject all translations** writes every document, including the safe name values from Phase 0, across `Data/`. | | **5 Package** | Either run from the loose `Data/` folder (backs up `Data.wolf` → `Data.wolf.bak`), or **Repack** a fresh `Data.wolf`, inheriting the original archive's encryption. | | **6 Saves** | *(Optional)* Update existing `.sav` files so old Japanese saves load cleanly in the translated build. Originals are backed up automatically. | diff --git a/gui/wolf_workflow_tab.py b/gui/wolf_workflow_tab.py index 08b5db2..13efa7f 100644 --- a/gui/wolf_workflow_tab.py +++ b/gui/wolf_workflow_tab.py @@ -22,7 +22,9 @@ Mirrors the RPGMaker WorkflowTab, driven by the vendored WolfDawn ``wolf`` CLI name translations into vocab.txt Phase 1 Database - item/skill/state descriptions and system messages (DataBase/CDataBase.project) - Phase 2 Dialogue - maps, CommonEvent, Game.dat, Evtext + Phase 2 Dialogue - maps, CommonEvent, Game.dat, Evtext; + speaker handling and text-wrap settings + live under this phase in Step 3 Step 4 Inject - inject translations + curated names back into the Data/ binaries and refresh the git-tracked wolf_json/ with the translated JSON; quick-inject picks just a few translated files for @@ -1092,9 +1094,6 @@ class WolfWorkflowTab(QWidget): self._add_phase_buttons(layout) - self._add_speaker_options(layout) - self._add_wrap_options(layout) - def _add_phase_buttons(self, layout: QVBoxLayout): """Three ordered translation phases selected by manifest kind.""" layout.addWidget(_make_hr()) @@ -1126,8 +1125,11 @@ class WolfWorkflowTab(QWidget): layout.addWidget(self._subheading("Phase 2 · Dialogue & events")) layout.addWidget(self._desc( "The bulk of the script: map events (.mps), CommonEvent, Game.dat and Evtext. Run last " - "so it benefits from the names and terms translated in the earlier phases." + "so it benefits from the names and terms translated in the earlier phases. Speaker " + "handling and text wrap below apply only to this phase." )) + self._add_speaker_options(layout) + self._add_wrap_options(layout) p2 = self._register(_make_btn("▶ Phase 2 · Translate dialogue & events", "#00a86b")) p2.clicked.connect( lambda: self._navigate_to_translation(kinds=PHASE_DIALOGUE_KINDS, auto_start=True)