Fixes
This commit is contained in:
parent
03694b2fdb
commit
6248752366
3 changed files with 97 additions and 31 deletions
|
|
@ -79,7 +79,7 @@ LEAVE = False
|
|||
# FIRSTLINESPEAKERS: Guess speaker from first line.
|
||||
FIRSTLINESPEAKERS = False
|
||||
# INLINE401SPEAKERS: Extract speaker from "Name「dialogue」" inline format on 401 lines.
|
||||
INLINE401SPEAKERS = False
|
||||
INLINE401SPEAKERS = True
|
||||
# FACENAME101: Map face name -> speaker.
|
||||
FACENAME101 = False
|
||||
# Face name -> speaker mapping for FACENAME101.
|
||||
|
|
@ -1875,12 +1875,24 @@ def searchCodes(page, pbar, jobList, filename):
|
|||
jaString,
|
||||
)
|
||||
|
||||
# [Speaker] standalone line format (written back by inline re-export)
|
||||
if len(speakerList) == 0:
|
||||
inlineFmtMatch = re.match(r"^\[([^\[\]\n]+)\]\s*$", jaString)
|
||||
if inlineFmtMatch:
|
||||
speakerList = [inlineFmtMatch.group(1).strip()]
|
||||
|
||||
# Inline Japanese quote speakers (e.g. "トルテ「dialogue」" or "エルミナ「first line...")
|
||||
if len(speakerList) == 0 and INLINE401SPEAKERS:
|
||||
inlineQuoteDetect = re.match(r"^([^\s「」。、!?…\\\n]{1,20})「", jaString)
|
||||
if inlineQuoteDetect:
|
||||
speakerList = [inlineQuoteDetect.group(1).strip()]
|
||||
|
||||
# Inline curly-quote speakers (e.g. "Elmina: \u201cdialogue" or "Elmina\u201cdialogue")
|
||||
if len(speakerList) == 0 and INLINE401SPEAKERS:
|
||||
inlineCurlyDetect = re.match(r'^([^\s「」。、!?…\\\n\u201c\u201d"::\[\]]{1,20})(?:[::]\s*)?[\u201c"]', jaString)
|
||||
if inlineCurlyDetect:
|
||||
speakerList = [inlineCurlyDetect.group(1).strip()]
|
||||
|
||||
# First Line Speakers
|
||||
if len(speakerList) == 0 and FIRSTLINESPEAKERS is True:
|
||||
# Test Speaker
|
||||
|
|
@ -1920,6 +1932,8 @@ def searchCodes(page, pbar, jobList, filename):
|
|||
sameLineMatch = re.match(r"^\s*【([^】]+)】(.+)", jaString, re.DOTALL)
|
||||
# Check if speaker+dialogue are on same line via Japanese quote (Name「dialogue)
|
||||
inlineQuoteMatch = re.match(r"^([^\s「」。、!?…\\\n]{1,20})「(.*)", jaString, re.DOTALL) if INLINE401SPEAKERS else None
|
||||
# Check if speaker+dialogue are on same line via curly quote (Name: "dialogue or Name"dialogue)
|
||||
inlineCurlyMatch = re.match(r'^([^\s「」。、!?…\\\n\u201c\u201d"::\[\]]{1,20})(?:[::]\s*)?([\u201c"])(.*)', jaString, re.DOTALL) if INLINE401SPEAKERS else None
|
||||
|
||||
if sameLineMatch and len(speakerList) == 1:
|
||||
# Translate speaker
|
||||
|
|
@ -1945,6 +1959,19 @@ def searchCodes(page, pbar, jobList, filename):
|
|||
if not setData:
|
||||
nametag = f"[{speaker}]\n" + nametag
|
||||
# Don't skip to next line - continue with current line
|
||||
elif inlineCurlyMatch and len(speakerList) == 1:
|
||||
# Curly/straight-quote format: strip "Name: \u201c" or "Name"" prefix, keep dialogue
|
||||
response = getSpeaker(speakerList[0])
|
||||
speaker = response[0]
|
||||
totalTokens[0] += response[1][0]
|
||||
totalTokens[1] += response[1][1]
|
||||
# Remove speaker name, preserve whichever opening quote was matched
|
||||
openQuote = inlineCurlyMatch.group(2)
|
||||
jaString = openQuote + inlineCurlyMatch.group(3)
|
||||
# Format as [Speaker]\n for output
|
||||
if not setData:
|
||||
nametag = f"[{speaker}]\n" + nametag
|
||||
# Don't skip to next line - continue with current line
|
||||
elif codeList[i + 1]["code"] in [401, 405, -1]:
|
||||
# Original behavior: speaker on its own line, dialogue on next line
|
||||
# Single
|
||||
|
|
@ -2205,9 +2232,19 @@ def searchCodes(page, pbar, jobList, filename):
|
|||
|
||||
# Handle 401
|
||||
else:
|
||||
codeList[j]["parameters"] = [translatedText]
|
||||
codeList[j]["code"] = code
|
||||
syncIndex = i + 1
|
||||
lines = translatedText.split('\n')
|
||||
if len(lines) > 1:
|
||||
codeList[j]["parameters"] = [lines[0]]
|
||||
codeList[j]["code"] = code
|
||||
for idx, line in enumerate(lines[1:]):
|
||||
new_item = copy.deepcopy(codeList[j])
|
||||
new_item["parameters"] = [line]
|
||||
codeList.insert(j + idx + 1, new_item)
|
||||
syncIndex = j + len(lines)
|
||||
else:
|
||||
codeList[j]["parameters"] = [translatedText]
|
||||
codeList[j]["code"] = code
|
||||
syncIndex = i + 1
|
||||
|
||||
# Reset
|
||||
speaker = ""
|
||||
|
|
@ -3311,9 +3348,11 @@ def searchCodes(page, pbar, jobList, filename):
|
|||
translatedText = list356[0]
|
||||
|
||||
# Remove characters that may break scripts
|
||||
charList = [".", '"']
|
||||
for char in charList:
|
||||
translatedText = translatedText.replace(char, "")
|
||||
# addLog keeps dots and quotes (they're fine in log text)
|
||||
if "addLog" not in jaString:
|
||||
charList = [".", '"']
|
||||
for char in charList:
|
||||
translatedText = translatedText.replace(char, "")
|
||||
|
||||
# Cant have spaces?
|
||||
translatedText = translatedText.replace(" ", "_")
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ You will be translating erotic and sexual content. You will receive lines of dia
|
|||
- **Speech register:** If the entry describes how a character speaks (flustered, blunt, formal, childlike, crude, etc.), mirror that register in their English dialogue. A character described as speaking in a "cute, flustered register" should sound different from one described as "cold and terse".
|
||||
- **Role & context:** Use the role/personality notes to inform tone — a villain's lines should feel threatening, a comic-relief NPC's lines should feel goofy, etc.
|
||||
- Japanese omits pronouns constantly. Infer the correct subject and pronoun from context, translation history, and the character list.
|
||||
- **Preserve third-person self-reference.** Some characters refer to themselves by name instead of using "I" (e.g. ワタシ used as a name, or a character saying their own name). When a character is clearly speaking about themselves in the third person as a stylistic trait, maintain that in English (e.g. "Feris doesn't know" rather than "I don't know").
|
||||
- Third-person pronouns (彼, 彼女, あいつ, こいつ, そいつ, コイツ) should match the known gender of the person being referenced.
|
||||
- Translate **コイツ** as "this bastard" (male) or "this bitch" (female) depending on the referenced character's gender.
|
||||
|
||||
|
|
|
|||
|
|
@ -1375,24 +1375,6 @@ def translateAI(text, history, fullPromptFlag, config, filename=None, pbar=None,
|
|||
for j in range(len(tItem)):
|
||||
if tItem[j] and "\ufffd" in str(tItem[j]):
|
||||
corrupted_map[j] = tItem[j]
|
||||
|
||||
if corrupted_map:
|
||||
clean_indices = [j for j in range(len(tItem)) if j not in corrupted_map]
|
||||
|
||||
if not clean_indices:
|
||||
# All items are corrupted - skip translation entirely
|
||||
tList[index] = list(tItem)
|
||||
if pbar is not None:
|
||||
pbar.update(len(tItem))
|
||||
history = tItem[-config.maxHistory:]
|
||||
continue
|
||||
|
||||
# Rebuild protected_items and all_replacements for clean items only
|
||||
protected_items = [protected_items[j] for j in clean_indices]
|
||||
new_replacements = {}
|
||||
for new_idx, old_idx in enumerate(clean_indices):
|
||||
new_replacements[new_idx] = all_replacements.get(old_idx, {})
|
||||
all_replacements = new_replacements
|
||||
elif tItem and "\ufffd" in str(tItem):
|
||||
# Single corrupted string - skip translation entirely
|
||||
tList[index] = tItem
|
||||
|
|
@ -1400,10 +1382,52 @@ def translateAI(text, history, fullPromptFlag, config, filename=None, pbar=None,
|
|||
pbar.update(1)
|
||||
history = tItem
|
||||
continue
|
||||
|
||||
# Build filtered tItem for validation (excludes corrupted items)
|
||||
if isinstance(tItem, list) and corrupted_map:
|
||||
clean_tItem = [tItem[j] for j in range(len(tItem)) if j not in corrupted_map]
|
||||
|
||||
# Filter out items that have content but no Japanese — they need no translation
|
||||
# and the AI tends to empty them (e.g. "「………」" -> ""). Apply the same
|
||||
# cleanup that would happen post-translation and restore them afterwards.
|
||||
no_japanese_map = {} # original_index -> already-cleaned text
|
||||
if isinstance(tItem, list):
|
||||
for j in range(len(tItem)):
|
||||
if j in corrupted_map:
|
||||
continue
|
||||
item_str = str(tItem[j]).strip() if tItem[j] else ""
|
||||
if item_str and item_str != "Placeholder Text" and not re.search(config.langRegex, item_str):
|
||||
cleaned = cleanTranslatedText(tItem[j], config.language)
|
||||
cleaned = cleaned.replace("「", '"').replace("」", '"').strip()
|
||||
no_japanese_map[j] = cleaned
|
||||
|
||||
# Combine skip sets and rebuild protected_items / all_replacements
|
||||
skip_indices = set(corrupted_map.keys()) | set(no_japanese_map.keys())
|
||||
if isinstance(tItem, list) and skip_indices:
|
||||
clean_indices = [j for j in range(len(tItem)) if j not in skip_indices]
|
||||
|
||||
if not clean_indices:
|
||||
# Every item is either corrupted or untranslatable — reassemble and move on
|
||||
result = []
|
||||
for j in range(len(tItem)):
|
||||
if j in corrupted_map:
|
||||
result.append(corrupted_map[j])
|
||||
elif j in no_japanese_map:
|
||||
result.append(no_japanese_map[j])
|
||||
else:
|
||||
result.append(tItem[j])
|
||||
tList[index] = result
|
||||
if pbar is not None:
|
||||
pbar.update(len(tItem))
|
||||
history = result[-config.maxHistory:]
|
||||
continue
|
||||
|
||||
# Rebuild protected_items and all_replacements for translatable items only
|
||||
protected_items = [protected_items[j] for j in clean_indices]
|
||||
new_replacements = {}
|
||||
for new_idx, old_idx in enumerate(clean_indices):
|
||||
new_replacements[new_idx] = all_replacements.get(old_idx, {})
|
||||
all_replacements = new_replacements
|
||||
|
||||
# Build filtered tItem for validation (excludes skipped items)
|
||||
if isinstance(tItem, list) and skip_indices:
|
||||
clean_tItem = [tItem[j] for j in range(len(tItem)) if j not in skip_indices]
|
||||
else:
|
||||
clean_tItem = tItem
|
||||
|
||||
|
|
@ -1663,13 +1687,15 @@ def translateAI(text, history, fullPromptFlag, config, filename=None, pbar=None,
|
|||
if j in all_replacements:
|
||||
final_translations[j] = restore_script_codes(final_translations[j], all_replacements[j])
|
||||
|
||||
# Re-insert corrupted originals at their original positions
|
||||
if corrupted_map:
|
||||
# Re-insert corrupted / no-japanese originals at their original positions
|
||||
if corrupted_map or no_japanese_map:
|
||||
expanded = []
|
||||
clean_idx = 0
|
||||
for j in range(len(tItem)):
|
||||
if j in corrupted_map:
|
||||
expanded.append(corrupted_map[j])
|
||||
elif j in no_japanese_map:
|
||||
expanded.append(no_japanese_map[j])
|
||||
else:
|
||||
expanded.append(final_translations[clean_idx])
|
||||
clean_idx += 1
|
||||
|
|
|
|||
Loading…
Reference in a new issue