diff --git a/modules/images.py b/modules/images.py index 2db1e7c..534d620 100644 --- a/modules/images.py +++ b/modules/images.py @@ -229,7 +229,8 @@ from PIL import Image, ImageDraw, ImageFont def stringToImageOutline(text, width, height, font_path="fonts/TsunagiGothic.ttf", scale_factor=4): # Outline - outline_color = (0, 0, 0, 255) + outline_color = (255, 255, 255, 255) + text_color = (0, 0, 0, 255) outline_thickness = 4 # Increase the resolution @@ -264,7 +265,7 @@ def stringToImageOutline(text, width, height, font_path="fonts/TsunagiGothic.ttf draw.text((x + dx, y + dy), text, font=font, fill=outline_color) # Draw the main text - draw.text((x, y), text, font=font, fill=(60, 160, 230, 255)) + draw.text((x, y), text, font=font, fill=text_color) # Resize back to the original dimensions to get a clearer text rendering image = image.resize((width, height), Image.LANCZOS) diff --git a/modules/rpgmakermvmz.py b/modules/rpgmakermvmz.py index 09575c6..ac7b81d 100644 --- a/modules/rpgmakermvmz.py +++ b/modules/rpgmakermvmz.py @@ -80,12 +80,12 @@ POSITION = 0 LEAVE = False # Dialogue / Scroll / Choices (Main Codes) -CODE401 = True -CODE405 = True -CODE102 = True +CODE401 = False +CODE405 = False +CODE102 = False # Optional -CODE101 = True # Turn this one when names exist in 101 +CODE101 = False # Turn this one when names exist in 101 CODE408 = False # Warning, translates comments and can inflate costs. # Variables @@ -256,6 +256,10 @@ def parseMap(data, filename): totalTokens[0] += response[1][0] totalTokens[1] += response[1][1] event["name"] = response[0].replace('"', "") + if "", False) + totalTokens[0] += tokensResponse[0] + totalTokens[1] += tokensResponse[1] for page in event["pages"]: totalLines += len(page["list"]) @@ -291,7 +295,7 @@ def parseMap(data, filename): return [data, totalTokens, None] -def translateNote(event, regex): +def translateNote(event, regex, wordwrap=True): # Regex String jaString = event["note"] match = re.findall(regex, jaString, re.DOTALL) @@ -314,8 +318,10 @@ def translateNote(event, regex): tokens[1] += response[1][1] # Textwrap - translatedText = textwrap.fill(translatedText, width=NOTEWIDTH) - translatedText = translatedText.replace('"', "") + if wordwrap: + translatedText = textwrap.fill(translatedText, width=NOTEWIDTH) + translatedText = translatedText.replace('"', "") + jaString = jaString.replace(initialJAString, translatedText) event["note"] = jaString i += 1 @@ -1184,7 +1190,7 @@ def searchCodes(page, pbar, jobList, filename): ## Event Code: 122 [Set Variables] if "code" in codeList[i] and codeList[i]["code"] == 122 and CODE122 is True: # This is going to be the var being set. (IMPORTANT) - if codeList[i]["parameters"][0] not in list(range(18, 19)): + if codeList[i]["parameters"][0] not in list(range(20, 150)): i += 1 continue @@ -1205,6 +1211,11 @@ def searchCodes(page, pbar, jobList, filename): i += 1 continue + # Validate Japanese Text + if not re.search(LANGREGEX, jaString): + i += 1 + continue + # Set String matchedText = None if len(re.findall(r"([\'\"\`])", jaString)) >= 2: @@ -1283,8 +1294,8 @@ def searchCodes(page, pbar, jobList, filename): translatedText = translatedText.replace(char, "") # Textwrap - translatedText = textwrap.fill(translatedText, 80) - translatedText = translatedText.replace("\n", "\\n") + # translatedText = textwrap.fill(translatedText, 80) + # translatedText = translatedText.replace("\n", "\\n") # translatedText = re.sub(r"[\\]+c", r"\\\\c", translatedText) translatedText = re.sub(r"[\\]+\*item", r"\\\\*item", translatedText) @@ -1313,6 +1324,7 @@ def searchCodes(page, pbar, jobList, filename): "SoR_GabWindow": ("arg1", None), "DarkPlasma_CharacterText": ("text", None), "DTextPicture": ("text", None), + "TextPicture": ("text", None), } for key, (argVar, font) in headerMappings.items(): @@ -2392,7 +2404,7 @@ def translateText(system, user, history, penalty, format, model=MODEL): # History if isinstance(history, list): - msg.append({"role": "assistant", "content": "Translation History:"}) + msg.append({"role": "system", "content": "Translation History:"}) msg.extend([{"role": "assistant", "content": h} for h in history]) else: msg.append({"role": "assistant", "content": history}) diff --git a/modules/unity.py b/modules/unity.py index 81b00d1..513c5a3 100644 --- a/modules/unity.py +++ b/modules/unity.py @@ -200,17 +200,21 @@ def translateUnity(data, pbar, filename, translatedList): # Dialogue while i < len(data): # Lines - regex = r".*?=(.*)" + regex = r"(.*?)=(.*)" match = re.search(regex, data[i]) - if match != None and match.group(1) != "": - originalString = match.group(1) + if match: + leftString = match.group(1) + rightString = match.group(2) + + # Validate Japanese Text + if not re.search(LANGREGEX, rightString) and IGNORETLTEXT: + i += 1 + continue + # Pass 1 if translatedList == []: - # Grab Consecutive Strings - jaString = match.group(1) - # Remove textwrap - jaString = jaString.replace("\n", "") + jaString = leftString.replace("\n", "") # Add String stringList.append(jaString.strip()) @@ -236,7 +240,7 @@ def translateUnity(data, pbar, filename, translatedList): translatedText = translatedText.replace("=", "->") # Set Data - data[i] = f"{originalString}{originalString}={translatedText}\n" + data[i] = f"{leftString}={translatedText}\n" i += 1 # Nothing relevant. Skip Line. @@ -269,72 +273,43 @@ def translateUnity(data, pbar, filename, translatedList): # Save some money and enter the character before translation def getSpeaker(speaker): - if speaker not in str(NAMESLIST): - response = translateGPT( - speaker, - "Reply with the " + LANGUAGE + " translation of the NPC name.", - True, - ) - response[0] = response[0].title() - response[0] = response[0].replace("'S", "'s") + match speaker: + case "ファイン": + return ["Fine", [0, 0]] + case "": + return ["", [0, 0]] + case _: + # Find Speaker + for i in range(len(NAMESLIST)): + if speaker == NAMESLIST[i][0]: + return [NAMESLIST[i][1], [0, 0]] - # Retry if name doesn't translate for some reason - if re.search(r"([a-zA-Z??])", response[0]) == None: + # Translate and Store Speaker response = translateGPT( - speaker, + f"{speaker}", "Reply with the " + LANGUAGE + " translation of the NPC name.", False, ) response[0] = response[0].title() response[0] = response[0].replace("'S", "'s") + response[0] = response[0].replace("Speaker: ", "") - speakerList = [speaker, response[0]] - NAMESLIST.append(speakerList) - return response - - # Find Speaker - else: - for i in range(len(NAMESLIST)): - if speaker == NAMESLIST[i][0]: - return [NAMESLIST[i][1], [0, 0]] + # Retry if name doesn't translate for some reason + if re.search(r"([a-zA-Z??])", response[0]) == None: + response = translateGPT( + f"{speaker}", + "Reply with the " + LANGUAGE + " translation of the NPC name.", + False, + ) + response[0] = response[0].title() + response[0] = response[0].replace("'S", "'s") + speakerList = [speaker, response[0]] + NAMESLIST.append(speakerList) + return response return [speaker, [0, 0]] -def subVars(jaString): - jaString = jaString.replace("\u3000", " ") - - # Formatting - count = 0 - codeList = re.findall(r"[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]", jaString) - codeList = set(codeList) - if len(codeList) != 0: - for var in codeList: - jaString = jaString.replace(var, "[FCode_" + str(count) + "]") - count += 1 - - # Put all lists in list and return - return [jaString, codeList] - - -def resubVars(translatedText, codeList): - # Fix Spacing and ChatGPT Nonsense - matchList = re.findall(r"\[\s?.+?\s?\]", translatedText) - if len(matchList) > 0: - for match in matchList: - text = match.strip() - translatedText = translatedText.replace(match, text) - - # Formatting - count = 0 - if len(codeList) != 0: - for var in codeList: - translatedText = translatedText.replace("[FCode_" + str(count) + "]", var) - count += 1 - - return translatedText - - def batchList(input_list, batch_size): if not isinstance(batch_size, int) or batch_size <= 0: raise ValueError("batch_size must be a positive integer") @@ -372,9 +347,10 @@ def translateText(system, user, history, penalty, format, model=MODEL): # History if isinstance(history, list): - msg.extend([{"role": "system", "content": h} for h in history]) + msg.append({"role": "system", "content": "Translation History:"}) + msg.extend([{"role": "assistant", "content": h} for h in history]) else: - msg.append({"role": "system", "content": history}) + msg.append({"role": "assistant", "content": history}) # Response Format if format == "json": @@ -394,7 +370,7 @@ def translateText(system, user, history, penalty, format, model=MODEL): return response -def cleanTranslatedText(translatedText, varResponse): +def cleanTranslatedText(translatedText): placeholders = { f"{LANGUAGE} Translation: ": "", "Translation: ": "", @@ -405,15 +381,24 @@ def cleanTranslatedText(translatedText, varResponse): "「": '\\"', "」": '\\"', "- ": "-", + "—": "―", + "】": "]", + "【": "[", + "é": "e", + "this guy": "this bastard", + "This guy": "This bastard", "Placeholder Text": "", # Add more replacements as needed } for target, replacement in placeholders.items(): translatedText = translatedText.replace(target, replacement) + # Remove Repeating Characters + pattern = re.compile(r"(.)\s*\1(?:\s*\1){" + str(20 - 1) + r",}") + translatedText = pattern.sub(lambda match: match.group(0).replace(" ", "")[:20], translatedText) + # Elongate Long Dashes (Since GPT Ignores them...) translatedText = elongateCharacters(translatedText) - translatedText = resubVars(translatedText, varResponse[1]) return translatedText @@ -434,6 +419,8 @@ def elongateCharacters(text): def extractTranslation(translatedTextList, is_list): try: + translatedTextList = re.sub(r'\\"+\"([^,\n}])', r'\\"\1', translatedTextList) + translatedTextList = re.sub(r"(?