feat(rpgmaker): add project-aware layout and code 408 setup
This commit is contained in:
parent
ea45b3c626
commit
c9bca5b66f
6 changed files with 151 additions and 22 deletions
|
|
@ -8,10 +8,12 @@ Work in the game repository. Scan files; do not invent content you did not see.
|
|||
## Task
|
||||
|
||||
In **one pass**, discover everything needed for translation setup and emit the labeled output blocks below.
|
||||
Do **not** translate the game. Do **not** rewrite formatting codes, wrap widths, or tool pipeline settings.
|
||||
Do **not** translate the game or edit its files. Recommend formatting and pipeline settings only in
|
||||
the designated configuration block.
|
||||
|
||||
Default: emit **all four** blocks.
|
||||
Regenerate mode: if the user asks for only one block (`glossary`, `speakers`, `translation_quirks`, or `game_skill`), emit **only** that block using the same schema and exclusivity rules.
|
||||
Default: emit every block specified for the selected engine.
|
||||
Regenerate mode: if the user asks for only one block, emit **only** that block using the same
|
||||
schema and exclusivity rules.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -23,6 +25,7 @@ Regenerate mode: if the user asks for only one block (`glossary`, `speakers`, `t
|
|||
| `speakers` | Tool flag ENABLE/SKIP + short evidence | Character bios; quirks; full glossary |
|
||||
| `translation_quirks` | Cross-cutting voice rules (battle-log person, global dialect, item-description style, **unusual** honorific habits) | Per-character register; "always keep -san" (tool base prompt already does); codes/wrap/line counts; speaker flags |
|
||||
| `game_skill` | **Translation Frame** for the API (theme / era / register / naming / optional myth) saved at `skills/game.md` | File inventories; quirks bullets; glossary; per-character register; IDE scaffolding; restating base honorific/formatting policy |
|
||||
| `rpgmaker_config` (RPG Maker only) | Code-408 Phase 1 decision + measured wrap/font recommendations | Translation prose; glossary; voice rules; speculative settings without evidence |
|
||||
|
||||
Hard rules:
|
||||
1. Per-character voice → `glossary` only.
|
||||
|
|
@ -30,6 +33,7 @@ Hard rules:
|
|||
3. Default honorifics policy is owned by the tool base prompt - only note **unusual** honorific habits in quirks.
|
||||
4. `game_skill` is the title's Translation Frame for the translation API - keep it compact; do not reprint quirks or glossary.
|
||||
5. `speakers` is config, not lore.
|
||||
6. `rpgmaker_config` is measured setup advice, not content to merge into the translation prompt.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -39,7 +43,7 @@ Map / event files can be huge. Do **not** read them sequentially end-to-end.
|
|||
|
||||
1. Read small DB files in full first (richest, always small).
|
||||
2. For large event/map files: **search/grep**; sample early story maps; stop when patterns stabilize.
|
||||
3. One scan feeds all four blocks - do not rescan from scratch per block.
|
||||
3. One scan feeds every output block - do not rescan from scratch per block.
|
||||
|
||||
<!-- engine:rpgmaker -->
|
||||
|
||||
|
|
@ -54,6 +58,11 @@ Map / event files can be huge. Do **not** read them sequentially end-to-end.
|
|||
- Prefer code `401` dialogue + nearby `101` speaker/name params; `405` scrolling text when present
|
||||
- Speaker markup evidence: `【Name】`, `[Name]`, `Name:`, `\\n<Name>`, `\\k<Name>`, colour-wrapped name lines
|
||||
|
||||
**Runtime/UI evidence:**
|
||||
- `js/plugins.js` plus source for enabled plugins in `js/plugins/`
|
||||
- `js/rpg_windows.js`, `js/rpg_scenes.js`, `js/rpg_managers.js`, or MZ equivalents
|
||||
- `System.json` resolution/font fields, custom fonts, window skins, and relevant image dimensions
|
||||
|
||||
--- attach your game data files / open the game repo before continuing ---
|
||||
|
||||
### Speakers analysis (for `speakers` block)
|
||||
|
|
@ -119,6 +128,68 @@ Do **not** include:
|
|||
- Quirks (API): ``skills/quirks.md`` (never ``translation_quirks.txt``)
|
||||
- Optional custom API overlays: other ``skills/*.md`` except those two
|
||||
|
||||
### Phase 1 and layout analysis (for `rpgmaker_config` block)
|
||||
|
||||
#### Code 408
|
||||
|
||||
Code `408` is a continuation of an editor comment. It is normally internal, but plugins can parse
|
||||
`108`/`408` comment blocks and display their contents to players.
|
||||
|
||||
1. Inventory code-408 values and group them with their preceding code-108 command.
|
||||
2. Search enabled plugin sources and event-handling code for the discovered comment tags,
|
||||
prefixes, or parsing APIs. Do not infer runtime visibility from Japanese text alone.
|
||||
3. Choose `ENABLE` only when evidence shows that code-408 content is rendered or otherwise shown
|
||||
to players. Show representative plugin + event locators and an affected count.
|
||||
4. Choose `SKIP` when values are editor notes, disabled-plugin metadata, or have no runtime
|
||||
consumer. If evidence is inconclusive, choose `SKIP` and state what must be playtested.
|
||||
5. Tell the user to set the **Translate code 408 plugin/comment text** checkbox in Phase 1 to the
|
||||
recommended state. This is a user choice; do not edit tool configuration yourself.
|
||||
|
||||
#### Window geometry, wrapping, and fonts
|
||||
|
||||
Calculate recommendations separately for `Dialogue`, `List/Help`, and `Notes`. Use actual game
|
||||
geometry rather than generic RPG Maker defaults whenever project code is available.
|
||||
|
||||
1. Resolve the game resolution and each relevant window's outer width/height, padding, text inset,
|
||||
line height, columns, face/portrait reservation, icons, and plugin-added margins.
|
||||
2. Resolve the actual font face and base size plus runtime changes such as `\\{`, `\\}`,
|
||||
`\\FS[n]`, custom font codes, bold/outline changes, and plugin-specific scaling. Treat icons and
|
||||
inline images as pixel width, not zero-width text.
|
||||
3. Calculate usable pixels: inner window size minus padding, portraits/faces, columns, icons, and
|
||||
other fixed reservations. Derive visible row capacity from usable height and the largest
|
||||
applicable line height.
|
||||
4. Convert usable pixels to DazedTL's character-count wrap setting by measuring representative
|
||||
English glyphs in the real font when possible. Otherwise use a conservative documented average
|
||||
glyph width. Never copy a pixel width directly into `width`, `listWidth`, or `noteWidth`.
|
||||
5. Test representative short, median, long, control-code-heavy, icon-heavy, and font-changed values.
|
||||
Use the largest effective font when one shared setting must cover several variants.
|
||||
6. For dialogue, verify the recommendation against the actual message-row limit, commonly four.
|
||||
If a long message cannot fit without unreadable font reduction or horizontal overflow, flag it
|
||||
for pagination/manual reflow instead of forcing an unsafe four-line wrap.
|
||||
7. Recommend one conservative shared width and one readable font size for each category. If the
|
||||
current font should remain unchanged, say `keep current` and report its measured size. Cite the
|
||||
files/functions/plugin parameters supporting every recommendation and give a confidence level.
|
||||
|
||||
Emit this additional RPG Maker-only block:
|
||||
|
||||
### Block `rpgmaker_config`
|
||||
|
||||
Label the fence language as `rpgmaker_config`. Inside:
|
||||
|
||||
```text
|
||||
CODE408 : ENABLE|SKIP - <runtime evidence, affected count, and confidence>
|
||||
|
||||
Dialogue : width=<DazedTL width> ; font=<px or keep current (measured px)> ; rows=<count>
|
||||
List/Help: listWidth=<DazedTL width> ; font=<px or keep current (measured px)> ; rows=<count or varies>
|
||||
Notes : noteWidth=<DazedTL width> ; font=<px or keep current (measured px)> ; rows=<count or varies>
|
||||
|
||||
Evidence:
|
||||
- <resolution/window/font/plugin locator and calculation>
|
||||
|
||||
Exceptions / playtests:
|
||||
- <variant windows, uncertain plugin behavior, or messages requiring pagination>
|
||||
```
|
||||
|
||||
<!-- /engine:rpgmaker -->
|
||||
|
||||
<!-- engine:wolf -->
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ present.
|
|||
- For event code 102, pair each `_original[index]` choice with `parameters[0][index]`.
|
||||
- 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.
|
||||
- 408: comment continuation in `parameters[0]`; classify its runtime visibility from the
|
||||
preceding 108 block and enabled plugin code before treating it as internal or player-facing.
|
||||
- 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.
|
||||
|
|
@ -72,8 +73,9 @@ 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.
|
||||
Do not count unchanged code-408 values as player-facing residue when they are editor-only.
|
||||
When enabled plugin code consumes a 108/408 comment block and displays its content, audit that
|
||||
content as player-facing text. Report uncertain code-408 groups separately instead of guessing.
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ class ConfigIntegration:
|
|||
"CODE405": "Show Text (Scrolling) - Longer dialogue",
|
||||
"CODE102": "Show Choices - Player choice options",
|
||||
"CODE101": "Character Names - Turn on when names exist in 101",
|
||||
"CODE408": "Comments - WARNING: Can inflate costs significantly",
|
||||
"CODE408": "Comment continuations - enable only for plugin-displayed player text",
|
||||
"CODE122": "Control Variables - Text stored in variables",
|
||||
|
||||
"CODE355655": "Scripts - Text within script commands",
|
||||
|
|
|
|||
|
|
@ -323,9 +323,11 @@ class RPGMakerTab(QWidget):
|
|||
# Extended Content in column 2
|
||||
col2.addWidget(create_section_label("📝 Extended Content"))
|
||||
|
||||
self.code408_cb, layout = self._create_checkbox_with_description(
|
||||
"Comments (408)", "⚠️ Plugin text in comments (costly!)", "Plugin dialogue in comment text."
|
||||
)
|
||||
self.code408_cb, layout = self._create_checkbox_with_description(
|
||||
"Comment Text (408)",
|
||||
"⚠️ Enable only when a plugin displays it",
|
||||
"Continuation lines from 108/408 comment blocks; usually internal, sometimes player-facing.",
|
||||
)
|
||||
self.code408_cb.setStyleSheet("QCheckBox { font-size: 11px; color: #ffaa66; }")
|
||||
col2.addLayout(layout)
|
||||
|
||||
|
|
@ -678,8 +680,11 @@ class RPGMakerTab(QWidget):
|
|||
warnings.append("No Main Codes are enabled. You may not get any translated content.")
|
||||
|
||||
# Check for high-cost options
|
||||
if self.code408_cb.isChecked():
|
||||
warnings.append("CODE 408 (Comments) is enabled. This can significantly increase translation costs!")
|
||||
if self.code408_cb.isChecked():
|
||||
warnings.append(
|
||||
"CODE 408 (comment continuation text) is enabled. Confirm an enabled plugin "
|
||||
"shows it to players; otherwise this can significantly increase translation costs!"
|
||||
)
|
||||
|
||||
# Check for conflicting options
|
||||
if self.brflag_cb.isChecked() and self.fixtextwrap_cb.isChecked():
|
||||
|
|
|
|||
|
|
@ -99,7 +99,9 @@ PHASE1_CONFIG = {
|
|||
"CODE401": True,
|
||||
"CODE405": True,
|
||||
"CODE102": True,
|
||||
"CODE408": True,
|
||||
# Comment continuations are project-dependent: plugins sometimes display
|
||||
# them, but most games use them only as internal editor notes.
|
||||
"CODE408": False,
|
||||
# Risky codes OFF
|
||||
"CODE122": False,
|
||||
"CODE355655": False,
|
||||
|
|
@ -488,6 +490,9 @@ _STEP_HELP: dict[int, str] = {
|
|||
"(<code>skills/quirks.md</code>)<br>"
|
||||
"• <code>game_skill</code> → Game skills → translation tab "
|
||||
"(<code>skills/game.md</code> - Translation Frame, merged into the API prompt)<br><br>"
|
||||
"• <code>rpgmaker_config</code> → apply the code-408 checkbox recommendation in "
|
||||
"Phase 1 and the measured wrap widths in Step 3; review its font recommendations "
|
||||
"against the game UI<br><br>"
|
||||
"Optional: <b>+</b> on Game skills adds custom <code>skills/*.md</code> "
|
||||
"overlays (also merged into the API prompt - can hurt quality; use sparingly).<br><br>"
|
||||
"Use one game folder per translation run so frame/quirks stay in the prompt cache."
|
||||
|
|
@ -495,7 +500,8 @@ _STEP_HELP: dict[int, str] = {
|
|||
3: (
|
||||
"<b>Step 3 - TL Phase 1</b><br><br>"
|
||||
"Safe dialogue / database translation.<br><br>"
|
||||
"• Set text-wrap widths if needed (or copy the wrap analysis prompt)<br>"
|
||||
"• Apply Project Setup's measured dialogue, list/help, and note wrap widths<br>"
|
||||
"• Set the code-408 checkbox from Project Setup's runtime/plugin evidence<br>"
|
||||
"• Phase 0 - database names/descriptions<br>"
|
||||
"• Phase 1 - dialogue / choices<br>"
|
||||
"• Phase 1b - build the code 111 variable-translation cache<br><br>"
|
||||
|
|
@ -1546,7 +1552,7 @@ class WorkflowTab(QWidget):
|
|||
copy_btn.setFixedHeight(32)
|
||||
copy_btn.setToolTip(
|
||||
"Clipboard skill for the game repo IDE. Returns glossary, speakers, "
|
||||
"translation_quirks, and game_skill code blocks."
|
||||
"translation_quirks, game_skill, and RPG Maker configuration recommendations."
|
||||
)
|
||||
copy_btn.clicked.connect(self._copy_project_setup_prompt)
|
||||
actions.addWidget(copy_btn)
|
||||
|
|
@ -1737,7 +1743,8 @@ class WorkflowTab(QWidget):
|
|||
wrap_inner.setSpacing(4)
|
||||
|
||||
wrap_hint = QLabel(
|
||||
"Adjust if lines overflow or wrap too early in-game, then click Apply to write to .env."
|
||||
"Use Project Setup's measured rpgmaker_config recommendations, then apply the three "
|
||||
"wrap widths to .env. Font recommendations describe the game UI and are not applied here."
|
||||
)
|
||||
wrap_hint.setWordWrap(True)
|
||||
wrap_hint.setStyleSheet("color:#9d9d9d;font-size:13px;")
|
||||
|
|
@ -1820,12 +1827,28 @@ class WorkflowTab(QWidget):
|
|||
p1_inner.setContentsMargins(10, 8, 10, 8)
|
||||
p1_inner.setSpacing(4)
|
||||
p1_desc = QLabel(
|
||||
"Codes ON: 101 (Name), 401 (Show Text), 405 (continued), 102 (Choices), 408 (extra lines). "
|
||||
"Speaker lines in the log should look like [Speaker]: Dialogue."
|
||||
"Codes ON: 101 (Name), 401 (Show Text), 405 (Scrolling Text), 102 (Choices). "
|
||||
"Code 408 is optional because it may be internal comments or plugin-displayed text. "
|
||||
"Speaker lines in the log should look like [Speaker]: Dialogue."
|
||||
)
|
||||
p1_desc.setStyleSheet("color:#9d9d9d;font-size:13px;")
|
||||
p1_desc.setWordWrap(True)
|
||||
p1_inner.addWidget(p1_desc)
|
||||
self._phase1_code408_cb = QCheckBox(
|
||||
"Translate code 408 plugin/comment text"
|
||||
)
|
||||
saved_408 = self._setting("phase1_code408", False)
|
||||
if isinstance(saved_408, str):
|
||||
saved_408 = saved_408.strip().casefold() in {"1", "true", "yes", "on"}
|
||||
self._phase1_code408_cb.setChecked(bool(saved_408))
|
||||
self._phase1_code408_cb.setToolTip(
|
||||
"Enable only when Project Setup finds an enabled plugin that displays text from "
|
||||
"108/408 comment blocks. Leave off for ordinary editor comments."
|
||||
)
|
||||
self._phase1_code408_cb.stateChanged.connect(
|
||||
lambda state: self._save_setting("phase1_code408", bool(state))
|
||||
)
|
||||
p1_inner.addWidget(self._phase1_code408_cb)
|
||||
p1_row = QHBoxLayout()
|
||||
p1_row.setSpacing(10)
|
||||
self._run_p1_btn = _make_btn("► Run Phase 1", "#007acc")
|
||||
|
|
@ -3916,7 +3939,11 @@ class WorkflowTab(QWidget):
|
|||
label = "Phase 0 (core DB files)" + (" — batch" if batch else "")
|
||||
file_preset = "db"
|
||||
elif phase == 1:
|
||||
config = PHASE1_CONFIG
|
||||
config = dict(PHASE1_CONFIG)
|
||||
config["CODE408"] = bool(
|
||||
getattr(self, "_phase1_code408_cb", None)
|
||||
and self._phase1_code408_cb.isChecked()
|
||||
)
|
||||
label = "Phase 1 (safe codes)" + (" — batch" if batch else "")
|
||||
file_preset = "events"
|
||||
elif phase == "1b":
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from util.skills import load_clipboard_skill
|
||||
from util.skills import load_clipboard_skill, load_project_setup
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
|
@ -41,7 +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("enabled plugin code consumes a 108/408 comment block", 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)
|
||||
|
|
@ -52,6 +52,30 @@ class WorkflowTranslationPromptTests(unittest.TestCase):
|
|||
):
|
||||
self.assertIn(placeholder, prompt)
|
||||
|
||||
def test_rpgmaker_project_setup_recommends_408_and_layout_geometry(self):
|
||||
prompt = load_project_setup("rpgmaker")
|
||||
lowered = prompt.casefold()
|
||||
|
||||
self.assertIn("code408 : enable|skip", lowered)
|
||||
self.assertIn("translate code 408 plugin/comment text", lowered)
|
||||
self.assertIn("dialogue : width=", lowered)
|
||||
self.assertIn("list/help: listwidth=", lowered)
|
||||
self.assertIn("notes : notewidth=", lowered)
|
||||
self.assertIn("face/portrait reservation", lowered)
|
||||
self.assertIn("applicable line height", lowered)
|
||||
self.assertIn("pagination/manual reflow", lowered)
|
||||
|
||||
wolf_prompt = load_project_setup("wolf")
|
||||
self.assertNotIn("code408 : enable|skip", wolf_prompt.casefold())
|
||||
|
||||
def test_phase1_code408_is_user_controlled(self):
|
||||
from gui.workflow_tab import PHASE1_CONFIG
|
||||
|
||||
self.assertFalse(PHASE1_CONFIG["CODE408"])
|
||||
workflow_source = (ROOT / "gui/workflow_tab.py").read_text(encoding="utf-8")
|
||||
self.assertIn("Translate code 408 plugin/comment text", workflow_source)
|
||||
self.assertIn('config["CODE408"] = bool(', workflow_source)
|
||||
|
||||
def test_static_clipboard_prompts_live_under_data_skills(self):
|
||||
expected = (
|
||||
"wrap_config.md",
|
||||
|
|
|
|||
Loading…
Reference in a new issue