More fixes

This commit is contained in:
dazedanon 2026-04-01 15:00:47 -05:00
parent b2baa5e463
commit 600ce598df
3 changed files with 41 additions and 11 deletions

View file

@ -437,6 +437,17 @@ def _make_toggle_btn(text: str) -> QPushButton:
return btn
# ─────────────────────────────────────────────────────────────────────────────
# Helpers
# ─────────────────────────────────────────────────────────────────────────────
class _PlainPasteTextEdit(QTextEdit):
"""QTextEdit that always pastes as plain text to avoid spurious newlines."""
def insertFromMimeData(self, source): # noqa: N802
self.insertPlainText(source.text())
# ─────────────────────────────────────────────────────────────────────────────
# Main widget
# ─────────────────────────────────────────────────────────────────────────────
@ -813,11 +824,27 @@ class WorkflowTab(QWidget):
"\n"
"\n"
" 101 param[4] name { \"code\": 101, \"parameters\": [\"\", 0, 2, 2, \"るな\"] }\n"
" \\\\n<Name> or \\\\k<Name> escape code anywhere inside a 401 line\n"
" \\\\n<Name> or \\\\k<Name> escape code with ANGLE BRACKETS anywhere inside a 401 line\n"
" 【Name】 alone on a line, or 【Name】dialogue on the same line\n"
" [Name] alone on a line, or [Name]dialogue on the same line\n"
" \\\\c[N]Name\\\\c[0] color-wrapped name on its own 401 line\n"
" Name line ending with a full-width colon\n"
"\n"
"## CRITICAL — \\\\N[X] / \\\\n[X] (square bracket + number) is NOT a speaker format\n"
"\n"
" \\\\N[ActorID] and \\\\n[ActorID] (e.g. \\\\N[1], \\\\n[2]) are RPGMaker actor variable\n"
" substitution codes. They expand to an actor's name at runtime, but the translation tool\n"
" handles them purely as text substitution during translation — they are NEVER treated as\n"
" a speaker name tag.\n"
"\n"
" A 401 line containing ONLY \\\\N[X], or narration text that embeds \\\\N[X] (e.g.\n"
" \"ローターが\\\\N[1]の乳首に装着される!\"), does NOT match any always-on speaker format.\n"
" Do NOT count \\\\N[X] / \\\\n[X] codes as always-on speaker detection hits.\n"
"\n"
" If a game's ONLY speaker indicator is a standalone \\\\N[X] line followed by dialogue,\n"
" check whether FIRSTLINESPEAKERS would catch it (the standalone line must be < 40 chars\n"
" AND contain at least one Japanese character — a bare \\\\N[1] with no Japanese text does\n"
" NOT qualify for FIRSTLINESPEAKERS either).\n"
"</always_on_formats>\n"
"\n"
"<flags>\n"
@ -1586,7 +1613,7 @@ class WorkflowTab(QWidget):
)
layout.addWidget(format_hint)
self.vocab_editor = QTextEdit()
self.vocab_editor = _PlainPasteTextEdit()
self.vocab_editor.setMinimumHeight(80)
self.vocab_editor.setMaximumHeight(160)
self.vocab_editor.setFont(QFont("Consolas", 9))

View file

@ -148,8 +148,8 @@ CODE408 = False
# Variables
CODE122 = False
CODE122_VAR_MIN = 0
CODE122_VAR_MAX = 2000
CODE122_VAR_MIN = 890
CODE122_VAR_MAX = 891
# Plugins / Scripts
CODE355655 = False
@ -218,7 +218,7 @@ PATTERNS_355655 = {
"AddAddress": (r'AddAddress\(\d+,\s*\\?"(.+?)\\?"', False),
}
# Subset of PATTERNS_355655 keys that should be processed (empty = none).
ENABLED_PATTERNS_355655: set = set()
ENABLED_PATTERNS_355655: set = {"BattleManager._logWindow.push('addText'"}
def handleMVMZ(filename, estimate):
@ -1886,7 +1886,7 @@ def searchCodes(page, pbar, jobList, filename):
# Inline speaker detection — Name「/Name: "/Name: (/[Name] "/[Name] (
if len(speakerList) == 0 and INLINE401SPEAKERS:
inlineSpeakerMatch = re.match(
r'^(?:\[([^\]]{1,30})\]\s*|([^\s「」。、\\\n“”"(:\[\]]{1,20})(?:[::]\s*)?(?=[「“"(]))(.*)',
r'^(?:\[([^\]]{1,30})\]\s*|([^\s「」。、\\\n“”"(:\[\]]{1,20})(?:[::]?\s*)(?=[「“"(]))(.*)',
jaString, re.DOTALL
)
if inlineSpeakerMatch:
@ -2623,8 +2623,10 @@ def searchCodes(page, pbar, jobList, filename):
if isinstance(codeList[i]["parameters"][0], str) and codeList[i]["parameters"][0].strip():
reduceWidthFlag = True
jaString = codeList[i]["parameters"][4]
# Check for Var
elif len(codeList[i]["parameters"]) > 0:
# Check for Var (only when parameters[0] is not a face file,
# i.e. fewer than 4 params — standard code 101 always has 4:
# [faceFile, faceIndex, background, position])
elif 0 < len(codeList[i]["parameters"]) < 4:
jaString = codeList[i]["parameters"][0]
isVar = True
if not isinstance(jaString, str):

View file

@ -1398,11 +1398,11 @@ def translateAI(text, history, config, filename=None, pbar=None, lock=None, mism
# Ellipsis-only bypass: strings whose translatable content is purely '…' characters
# (e.g. "「………」") should never be sent to the AI — just convert brackets and pass through.
def _is_ellipsis_only(s):
inner = str(s).strip().lstrip('').rstrip('').strip()
return bool(inner) and all(c == '\u2026' for c in inner)
inner = str(s).strip().lstrip('').rstrip('').strip()
return bool(inner) and all(c in '\u2026\u30FC' for c in inner)
def _convert_ellipsis(s):
return str(s).replace('', '"').replace('', '"')
return str(s).replace('', '"').replace('', '"').replace('', '"').replace('', '"')
if isinstance(tItem, list):
if all(_is_ellipsis_only(s) for s in tItem):
@ -1717,6 +1717,7 @@ def translateAI(text, history, config, filename=None, pbar=None, lock=None, mism
return line
line = line.replace("Placeholder Text", "").strip()
line = line.replace("", '"').replace("", '"')
line = line.replace("", '"').replace("", '"')
return line
final_translations = [_clean_extracted_line(line) for line in extracted]
else: