diff --git a/modules/alice.py b/modules/alice.py
index 5d38bb2..e02e99e 100644
--- a/modules/alice.py
+++ b/modules/alice.py
@@ -15,52 +15,53 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
NOTEWIDTH = 70
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = True # Overwrites textwrap
-IGNORETLTEXT = False # Ignores all translated text.
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = False # Ignores all translated text.
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .01
- OUTPUTAPICOST = .03
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.01
+ OUTPUTAPICOST = 0.03
BATCHSIZE = 1
+
def handleAlice(filename, estimate):
global ESTIMATE
- totalTokens = [0,0]
+ totalTokens = [0, 0]
ESTIMATE = estimate
if estimate:
@@ -75,17 +76,19 @@ def handleAlice(filename, estimate):
totalTokens[1] += translatedData[1][1]
# Print Total
- totalString = getResultString(['', totalTokens, None], end - start, 'TOTAL')
+ totalString = getResultString(["", totalTokens, None], end - start, "TOTAL")
# Print any errors on maps
if len(MISMATCH) > 0:
- return totalString + Fore.RED + f'\nMismatch Errors: {MISMATCH}' + Fore.RESET
+ return (
+ totalString + Fore.RED + f"\nMismatch Errors: {MISMATCH}" + Fore.RESET
+ )
else:
return totalString
-
+
else:
try:
- with open('translated/' + filename, 'w', encoding='UTF-8') as outFile:
+ with open("translated/" + filename, "w", encoding="UTF-8") as outFile:
start = time.time()
translatedData = openFiles(filename)
@@ -98,29 +101,43 @@ def handleAlice(filename, estimate):
totalTokens[1] += translatedData[1][1]
except Exception:
traceback.print_exc()
- return 'Fail'
+ return "Fail"
+
+ return getResultString(["", totalTokens, None], end - start, "TOTAL")
- return getResultString(['', totalTokens, None], end - start, 'TOTAL')
def openFiles(filename):
- with open('files/' + filename, 'r', encoding='UTF-8') as f:
+ with open("files/" + filename, "r", encoding="UTF-8") as f:
translatedData = parseText(f, filename)
-
+
return translatedData
+
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] == None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
@@ -129,19 +146,30 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
-
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
+
def parseText(data, filename):
# Get total for progress bar
linesList = data.readlines()
totalTokens = [0, 0]
totalLines = len(linesList)
global LOCK
-
- with tqdm(bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE) as pbar:
- pbar.desc=filename
- pbar.total=totalLines
+
+ with tqdm(
+ bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE
+ ) as pbar:
+ pbar.desc = filename
+ pbar.total = totalLines
try:
result = translateLines(linesList, pbar)
totalTokens[0] += result[1][0]
@@ -151,6 +179,7 @@ def parseText(data, filename):
return [linesList, totalTokens, e]
return [linesList, totalTokens, None]
+
# Grab scenario data from text file
def translateLines(linesList, pbar):
currentGroup = []
@@ -165,54 +194,67 @@ def translateLines(linesList, pbar):
try:
while i < len(linesList):
# Check if Proper Message
- match = re.findall(r's\[[0-9]+\] = \"(.*)\"', linesList[i])
+ match = re.findall(r"s\[[0-9]+\] = \"(.*)\"", linesList[i])
if len(match) > 0:
jaString = match[0]
# Skip Files
- if '/' in jaString:
+ if "/" in jaString:
i += 1
continue
### Translate
# Remove any textwrap
- jaString = re.sub(r'\\n', ' ', jaString)
+ jaString = re.sub(r"\\n", " ", jaString)
# Grab Speaker
- speakerMatch = re.findall(r's\[[0-9]+\] = \"([^/]+)\"', linesList[i-1])
+ speakerMatch = re.findall(
+ r"s\[[0-9]+\] = \"([^/]+)\"", linesList[i - 1]
+ )
if len(speakerMatch) > 0:
# If there isn't any Japanese in the text just skip
- if re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString) and '_' not in speakerMatch[0]:
+ if (
+ re.search(r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+", jaString)
+ and "_" not in speakerMatch[0]
+ ):
speaker = speakerMatch[0]
else:
- speaker = ''
+ speaker = ""
else:
- speaker = ''
+ speaker = ""
# Grab rest of the messages
currentGroup.append(jaString)
# Check if next line should be merged
if insertBool is True:
- linesList[i] = re.sub(r'(s\[[0-9]+\]) = \"(.+)\"', r'\1 = ""', linesList[i])
- linesList[i] = linesList[i].replace(';', '')
+ linesList[i] = re.sub(
+ r"(s\[[0-9]+\]) = \"(.+)\"", r'\1 = ""', linesList[i]
+ )
+ linesList[i] = linesList[i].replace(";", "")
start = i
- while (len(linesList) > i+1 and re.search(r's\[[0-9]+\] = \"\s+(.*)\"', linesList[i+1]) != None):
+ while (
+ len(linesList) > i + 1
+ and re.search(r"s\[[0-9]+\] = \"\s+(.*)\"", linesList[i + 1])
+ != None
+ ):
multiLine = True
i += 1
- match = re.findall(r's\[[0-9]+\] = \"\s+(.*)\"', linesList[i])
+ match = re.findall(r"s\[[0-9]+\] = \"\s+(.*)\"", linesList[i])
currentGroup.append(match[0])
if insertBool is True:
- linesList[i] = re.sub(r'(s\[[0-9]+\]) = \"\s+(.+)\"', r'\1 = ""', linesList[i])
- linesList[i] = linesList[i].replace(';', '')
+ linesList[i] = re.sub(
+ r"(s\[[0-9]+\]) = \"\s+(.+)\"", r'\1 = ""', linesList[i]
+ )
+ linesList[i] = linesList[i].replace(";", "")
i += 1
# Combine Groups and Add Speaker
- finalJAString = ' '.join(currentGroup)
- if speaker != '':
- finalJAString = f'{speaker}: {finalJAString}'
+ finalJAString = " ".join(currentGroup)
+ if speaker != "":
+ finalJAString = f"{speaker}: {finalJAString}"
else:
- finalJAString = f'{finalJAString}'
+ finalJAString = f"{finalJAString}"
# [Passthrough 1] Pulling From File
if insertBool is False:
@@ -235,7 +277,7 @@ def translateLines(linesList, pbar):
# Mismatch
else:
- pbar.write(f'Mismatch: {batchStartIndex} - {i}')
+ pbar.write(f"Mismatch: {batchStartIndex} - {i}")
MISMATCH.append(batch)
batchStartIndex = i
batch.clear()
@@ -249,33 +291,41 @@ def translateLines(linesList, pbar):
translatedText = translatedBatch[0]
# Remove added speaker and quotes
- translatedText = re.sub(r'^.+?:\s', '', translatedText)
+ translatedText = re.sub(r"^.+?:\s", "", translatedText)
# Textwrap
- translatedText = translatedText.replace('\"', '\\"')
+ translatedText = translatedText.replace('"', '\\"')
translatedText = textwrap.fill(translatedText, width=WIDTH)
# Set Data
if multiLine:
textList = translatedText.split("\n")
for t in textList:
- translatedText = translatedText.replace(';', '')
- translatedText = re.sub(r'(s\[[0-9]+\]) = \"(.*)\"', rf'\1 = "{t}"', linesList[start])
- translatedText = translatedText.replace(';', '')
+ translatedText = translatedText.replace(";", "")
+ translatedText = re.sub(
+ r"(s\[[0-9]+\]) = \"(.*)\"",
+ rf'\1 = "{t}"',
+ linesList[start],
+ )
+ translatedText = translatedText.replace(";", "")
linesList[start] = translatedText
pbar.update(1)
start += 1
multiLine = False
- translatedText = translatedText.replace(';', '')
- translatedBatch.pop(0)
+ translatedText = translatedText.replace(";", "")
+ translatedBatch.pop(0)
else:
# Remove any textwrap
- translatedText = translatedText.replace('\n', ' ')
- translatedText = re.sub(r'(s\[[0-9]+\]) = \"(.*)\"', rf'\1 = "{translatedText}"', linesList[start])
- translatedText = translatedText.replace(';', '')
+ translatedText = translatedText.replace("\n", " ")
+ translatedText = re.sub(
+ r"(s\[[0-9]+\]) = \"(.*)\"",
+ rf'\1 = "{translatedText}"',
+ linesList[start],
+ )
+ translatedText = translatedText.replace(";", "")
linesList[start] = translatedText
pbar.update(1)
- translatedBatch.pop(0)
+ translatedBatch.pop(0)
# If Batch is empty. Move on.
if len(translatedBatch) == 0:
@@ -283,7 +333,7 @@ def translateLines(linesList, pbar):
batchStartIndex = i
pbar.update(1)
batch.clear()
-
+
currentGroup = []
else:
if insertBool is True:
@@ -295,70 +345,72 @@ def translateLines(linesList, pbar):
traceback.print_exc()
return [linesList, tokens]
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Nested
count = 0
- nestedList = re.findall(r'[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]', jaString)
+ nestedList = re.findall(r"[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]", jaString)
nestedList = set(nestedList)
if len(nestedList) != 0:
for icon in nestedList:
- jaString = jaString.replace(icon, '{Nested_' + str(count) + '}')
+ jaString = jaString.replace(icon, "{Nested_" + str(count) + "}")
count += 1
# Icons
count = 0
- iconList = re.findall(r'[\\]+[iIkKwWaA]+\[[0-9]+\]', jaString)
+ iconList = re.findall(r"[\\]+[iIkKwWaA]+\[[0-9]+\]", jaString)
iconList = set(iconList)
if len(iconList) != 0:
for icon in iconList:
- jaString = jaString.replace(icon, '{Ascii_' + str(count) + '}')
+ jaString = jaString.replace(icon, "{Ascii_" + str(count) + "}")
count += 1
# Colors
count = 0
- colorList = re.findall(r'[\\]+[cC]\[[0-9]+\]', jaString)
+ colorList = re.findall(r"[\\]+[cC]\[[0-9]+\]", jaString)
colorList = set(colorList)
if len(colorList) != 0:
for color in colorList:
- jaString = jaString.replace(color, '{Color_' + str(count) + '}')
+ jaString = jaString.replace(color, "{Color_" + str(count) + "}")
count += 1
# Names
count = 0
- nameList = re.findall(r'[\\]+[nN]\[.+?\]+', jaString)
+ nameList = re.findall(r"[\\]+[nN]\[.+?\]+", jaString)
nameList = set(nameList)
if len(nameList) != 0:
for name in nameList:
- jaString = jaString.replace(name, '{Noun_' + str(count) + '}')
+ jaString = jaString.replace(name, "{Noun_" + str(count) + "}")
count += 1
# Variables
count = 0
- varList = re.findall(r'[\\]+[vV]\[[0-9]+\]', jaString)
+ varList = re.findall(r"[\\]+[vV]\[[0-9]+\]", jaString)
varList = set(varList)
if len(varList) != 0:
for var in varList:
- jaString = jaString.replace(var, '{Var_' + str(count) + '}')
+ jaString = jaString.replace(var, "{Var_" + str(count) + "}")
count += 1
# Formatting
count = 0
- formatList = re.findall(r'[\\]+[\w]+\[.+?\]', jaString)
+ formatList = re.findall(r"[\\]+[\w]+\[.+?\]", jaString)
formatList = set(formatList)
if len(formatList) != 0:
for var in formatList:
- jaString = jaString.replace(var, '{FCode_' + str(count) + '}')
+ jaString = jaString.replace(var, "{FCode_" + str(count) + "}")
count += 1
# Put all lists in list and return
allList = [nestedList, iconList, colorList, nameList, varList, formatList]
return [jaString, allList]
+
def resubVars(translatedText, allList):
# Fix Spacing and ChatGPT Nonsense
- matchList = re.findall(r'\[\s?.+?\s?\]', translatedText)
+ matchList = re.findall(r"\[\s?.+?\s?\]", translatedText)
if len(matchList) > 0:
for match in matchList:
text = match.strip()
@@ -368,54 +420,58 @@ def resubVars(translatedText, allList):
count = 0
if len(allList[0]) != 0:
for var in allList[0]:
- translatedText = translatedText.replace('{Nested_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Nested_" + str(count) + "}", var)
count += 1
# Icons
count = 0
if len(allList[1]) != 0:
for var in allList[1]:
- translatedText = translatedText.replace('{Ascii_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Ascii_" + str(count) + "}", var)
count += 1
# Colors
count = 0
if len(allList[2]) != 0:
for var in allList[2]:
- translatedText = translatedText.replace('{Color_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Color_" + str(count) + "}", var)
count += 1
# Names
count = 0
if len(allList[3]) != 0:
for var in allList[3]:
- translatedText = translatedText.replace('{Noun_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Noun_" + str(count) + "}", var)
count += 1
# Vars
count = 0
if len(allList[4]) != 0:
for var in allList[4]:
- translatedText = translatedText.replace('{Var_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Var_" + str(count) + "}", var)
count += 1
-
+
# Formatting
count = 0
if len(allList[5]) != 0:
for var in allList[5]:
- translatedText = translatedText.replace('{FCode_' + str(count) + '}', var)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
林つかさ (Tsukasa Hayashi) - Female\n\
山田美兎 (Miyato Yamada) - Female\n\
鈴木赤音 (Akane Suzuki) - Female\n\
@@ -428,13 +484,17 @@ def createContext(fullPromptFlag, subbedT):
モリー・ボイド (Molly Boyd) - Female\n\
オルガ・ブヤチッチ (Olga Buyachich) - Female\n\
アッチャラー ギッティ (Atchara Gitti) - Female\n\
-'
-
- system = PROMPT if fullPromptFlag else \
- f'Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`'
- user = f'{subbedT}'
+"
+
+ system = (
+ PROMPT
+ if fullPromptFlag
+ else f"Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`"
+ )
+ user = f"{subbedT}"
return characters, system, user
+
def translateText(characters, system, user, history):
# Prompt
msg = [{"role": "system", "content": system + characters}]
@@ -447,9 +507,9 @@ def translateText(characters, system, user, history):
msg.extend([{"role": "assistant", "content": h} for h in history])
else:
msg.append({"role": "assistant", "content": history})
-
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0.1,
frequency_penalty=0.1,
@@ -458,40 +518,47 @@ def translateText(characters, system, user, history):
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- 'Placeholder Text': ''
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "Placeholder Text": "",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
translatedText = translatedText.replace(target, replacement)
translatedText = resubVars(translatedText, varResponse[1])
- if '\n' in translatedText:
- return [line for line in translatedText.split('\n') if line]
+ if "\n" in translatedText:
+ return [line for line in translatedText.split("\n") if line]
else:
- return [line for line in translatedText.split('\\n') if line]
+ return [line for line in translatedText.split("\\n") if line]
+
def extractTranslation(translatedTextList, is_list):
- pattern = r'[\\]*`?(.*?)[\\]*?`??Line\d+>'
+ pattern = r"[\\]*`?(.*?)[\\]*?`??Line\d+>"
# If it's a batch (i.e., list), extract with tags; otherwise, return the single item.
if is_list:
- return [re.findall(pattern, line)[0][1] for line in translatedTextList if re.search(pattern, line)]
+ return [
+ re.findall(pattern, line)[0][1]
+ for line in translatedTextList
+ if re.search(pattern, line)
+ ]
else:
matchList = re.findall(pattern, translatedTextList)
return matchList[0][1] if matchList else translatedTextList
+
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -503,15 +570,17 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*3)
+ outputTotalTokens += round(len(enc.encode(user)) * 3)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag):
totalTokens = [0, 0]
@@ -523,8 +592,10 @@ def translateGPT(text, history, fullPromptFlag):
for index, tItem in enumerate(tList):
# Before sending to translation, if we have a list of items, add the formatting
if isinstance(tItem, list):
- payload = '\n'.join([f'`{item}`' for i, item in enumerate(tItem)])
- payload = payload.replace('``', '`Placeholder Text`')
+ payload = "\n".join(
+ [f"`{item}`" for i, item in enumerate(tItem)]
+ )
+ payload = payload.replace("``", "`Placeholder Text`")
varResponse = subVars(payload)
subbedT = varResponse[0]
else:
@@ -532,7 +603,7 @@ def translateGPT(text, history, fullPromptFlag):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
continue
# Create Message
@@ -557,11 +628,13 @@ def translateGPT(text, history, fullPromptFlag):
extractedTranslations = extractTranslation(translatedTextList, True)
tList[index] = extractedTranslations
if len(tItem) != len(translatedTextList):
- mismatch = True # Just here so breakpoint can be set
+ mismatch = True # Just here so breakpoint can be set
history = extractedTranslations[-10:] # Update history if we have a list
else:
# Ensure we're passing a single string to extractTranslation
- extractedTranslations = extractTranslation('\n'.join(translatedTextList), False)
+ extractedTranslations = extractTranslation(
+ "\n".join(translatedTextList), False
+ )
tList[index] = extractedTranslations
finalList = combineList(tList, text)
diff --git a/modules/anim.py b/modules/anim.py
index bab2169..fa1888e 100644
--- a/modules/anim.py
+++ b/modules/anim.py
@@ -16,52 +16,53 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
NOTEWIDTH = 70
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = True # Overwrites textwrap
-IGNORETLTEXT = False # Ignores all translated text.
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = False # Ignores all translated text.
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .01
- OUTPUTAPICOST = .03
- BATCHSIZE = 50
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.01
+ OUTPUTAPICOST = 0.03
+ BATCHSIZE = 50
+
def handleAnim(filename, estimate):
global ESTIMATE
- totalTokens = [0,0]
+ totalTokens = [0, 0]
ESTIMATE = estimate
if estimate:
@@ -76,17 +77,19 @@ def handleAnim(filename, estimate):
totalTokens[1] += translatedData[1][1]
# Print Total
- totalString = getResultString(['', totalTokens, None], end - start, 'TOTAL')
+ totalString = getResultString(["", totalTokens, None], end - start, "TOTAL")
# Print any errors on maps
if len(MISMATCH) > 0:
- return totalString + Fore.RED + f'\nMismatch Errors: {MISMATCH}' + Fore.RESET
+ return (
+ totalString + Fore.RED + f"\nMismatch Errors: {MISMATCH}" + Fore.RESET
+ )
else:
return totalString
-
+
else:
try:
- with open('translated/' + filename, 'w', encoding='UTF-8') as outFile:
+ with open("translated/" + filename, "w", encoding="UTF-8") as outFile:
start = time.time()
translatedData = openFiles(filename)
@@ -98,36 +101,50 @@ def handleAnim(filename, estimate):
totalTokens[0] += translatedData[1][0]
totalTokens[1] += translatedData[1][1]
except Exception:
- return 'Fail'
+ return "Fail"
+
+ return getResultString(["", totalTokens, None], end - start, "TOTAL")
- return getResultString(['', totalTokens, None], end - start, 'TOTAL')
def openFiles(filename):
- with open('files/' + filename, 'r', encoding='UTF-8-sig') as f:
+ with open("files/" + filename, "r", encoding="UTF-8-sig") as f:
data = json.load(f)
# Map Files
- if '.json' in filename:
+ if ".json" in filename:
translatedData = parseJSON(data, filename)
else:
- raise NameError(filename + ' Not Supported')
-
+ raise NameError(filename + " Not Supported")
+
return translatedData
+
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] == None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
@@ -136,20 +153,31 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
-
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
+
def parseJSON(data, filename):
keys = list(data.keys())
- batches = [keys[i:i + BATCHSIZE] for i in range(0, len(keys), BATCHSIZE)]
+ batches = [keys[i : i + BATCHSIZE] for i in range(0, len(keys), BATCHSIZE)]
totalTokens = [0, 0]
totalLines = 0
totalLines = len(batches)
global LOCK
-
- with tqdm(bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE) as pbar:
- pbar.desc=filename
- pbar.total=totalLines
+
+ with tqdm(
+ bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE
+ ) as pbar:
+ pbar.desc = filename
+ pbar.total = totalLines
try:
result = translateJSON(batches, data, pbar)
totalTokens[0] += result[0]
@@ -159,6 +187,7 @@ def parseJSON(data, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def translateJSON(keys, data, pbar):
translatedBatch = []
textHistory = []
@@ -172,20 +201,20 @@ def translateJSON(keys, data, pbar):
needTL = False
for i in range(len(batch)):
t = data[batch[i]]
- if re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', t) or t == '':
+ if re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", t) or t == "":
needTL = True
if needTL is False and IGNORETLTEXT is True:
pbar.update(1)
- continue
+ continue
# Remove any textwrap and Furigana
for i in range(len(batch)):
if FIXTEXTWRAP == True:
# Textwrap
- data[originalBatch[i]] = data[originalBatch[i]].replace('@b', ' ')
+ data[originalBatch[i]] = data[originalBatch[i]].replace("@b", " ")
# Furigana
- rcodeMatch = re.findall(r'(@\[(.+?):.+?\])', batch[i])
+ rcodeMatch = re.findall(r"(@\[(.+?):.+?\])", batch[i])
if len(rcodeMatch) > 0:
for match in rcodeMatch:
batch[i] = batch[i].replace(match[0], match[1])
@@ -203,23 +232,22 @@ def translateJSON(keys, data, pbar):
# Format and Set Text
if len(batch) == len(translatedBatch):
for i in range(len(translatedBatch)):
-
# Remove added speaker
translatedText = translatedBatch[i]
- translatedText = re.sub(r'^.+?\s\|\s?', '', translatedText)
+ translatedText = re.sub(r"^.+?\s\|\s?", "", translatedText)
# Textwrap
- if '@n' in translatedText:
- match = re.search(r'.*@n(.*)', translatedText)
+ if "@n" in translatedText:
+ match = re.search(r".*@n(.*)", translatedText)
if match != None:
tlText = match.group(1)
tlText = textwrap.fill(tlText, width=WIDTH)
- tlText = tlText.replace('\n', '@b')
+ tlText = tlText.replace("\n", "@b")
translatedText = translatedText.replace(match.group(1), tlText)
-
- elif '@b' not in translatedText:
+
+ elif "@b" not in translatedText:
translatedText = textwrap.fill(translatedText, width=WIDTH)
- translatedText = translatedText.replace('\n', '@b')
+ translatedText = translatedText.replace("\n", "@b")
# Set Data
data[originalBatch[i]] = translatedText
@@ -232,72 +260,74 @@ def translateJSON(keys, data, pbar):
continue
pbar.update(1)
- return tokens
+ return tokens
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Nested
count = 0
- nestedList = re.findall(r'[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]', jaString)
+ nestedList = re.findall(r"[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]", jaString)
nestedList = set(nestedList)
if len(nestedList) != 0:
for icon in nestedList:
- jaString = jaString.replace(icon, '[Nested_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Nested_" + str(count) + "]")
count += 1
# Icons
count = 0
- iconList = re.findall(r'[\\]+[iIkKwWaA]+\[[0-9]+\]', jaString)
+ iconList = re.findall(r"[\\]+[iIkKwWaA]+\[[0-9]+\]", jaString)
iconList = set(iconList)
if len(iconList) != 0:
for icon in iconList:
- jaString = jaString.replace(icon, '[Ascii_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Ascii_" + str(count) + "]")
count += 1
# Colors
count = 0
- colorList = re.findall(r'[\\]+[cC]\[[0-9]+\]', jaString)
+ colorList = re.findall(r"[\\]+[cC]\[[0-9]+\]", jaString)
colorList = set(colorList)
if len(colorList) != 0:
for color in colorList:
- jaString = jaString.replace(color, '[Color_' + str(count) + ']')
+ jaString = jaString.replace(color, "[Color_" + str(count) + "]")
count += 1
# Names
count = 0
- nameList = re.findall(r'[\\]+[nN]\[.+?\]+', jaString)
+ nameList = re.findall(r"[\\]+[nN]\[.+?\]+", jaString)
nameList = set(nameList)
if len(nameList) != 0:
for name in nameList:
- jaString = jaString.replace(name, '[Noun_' + str(count) + ']')
+ jaString = jaString.replace(name, "[Noun_" + str(count) + "]")
count += 1
# Variables
count = 0
- varList = re.findall(r'[\\]+[vV]\[[0-9]+\]', jaString)
+ varList = re.findall(r"[\\]+[vV]\[[0-9]+\]", jaString)
varList = set(varList)
if len(varList) != 0:
for var in varList:
- jaString = jaString.replace(var, '[Var_' + str(count) + ']')
+ jaString = jaString.replace(var, "[Var_" + str(count) + "]")
count += 1
# Formatting
count = 0
- formatList = re.findall(r'[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
+ formatList = re.findall(r"[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]", jaString)
formatList = set(formatList)
if len(formatList) != 0:
for var in formatList:
- jaString = jaString.replace(var, '[FCode_' + str(count) + ']')
+ jaString = jaString.replace(var, "[FCode_" + str(count) + "]")
count += 1
# Put all lists in list and return
allList = [nestedList, iconList, colorList, nameList, varList, formatList]
return [jaString, allList]
+
def resubVars(translatedText, allList):
# Fix Spacing and ChatGPT Nonsense
- matchList = re.findall(r'\[\s?.+?\s?\]', translatedText)
+ matchList = re.findall(r"\[\s?.+?\s?\]", translatedText)
if len(matchList) > 0:
for match in matchList:
text = match.strip()
@@ -307,64 +337,70 @@ def resubVars(translatedText, allList):
count = 0
if len(allList[0]) != 0:
for var in allList[0]:
- translatedText = translatedText.replace('[Nested_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Nested_" + str(count) + "]", var)
count += 1
# Icons
count = 0
if len(allList[1]) != 0:
for var in allList[1]:
- translatedText = translatedText.replace('[Ascii_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Ascii_" + str(count) + "]", var)
count += 1
# Colors
count = 0
if len(allList[2]) != 0:
for var in allList[2]:
- translatedText = translatedText.replace('[Color_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Color_" + str(count) + "]", var)
count += 1
# Names
count = 0
if len(allList[3]) != 0:
for var in allList[3]:
- translatedText = translatedText.replace('[Noun_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Noun_" + str(count) + "]", var)
count += 1
# Vars
count = 0
if len(allList[4]) != 0:
for var in allList[4]:
- translatedText = translatedText.replace('[Var_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Var_" + str(count) + "]", var)
count += 1
-
+
# Formatting
count = 0
if len(allList[5]) != 0:
for var in allList[5]:
- translatedText = translatedText.replace('[FCode_' + str(count) + ']', var)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
達也 (Tatsuya) - Male\n\
香織 (Kaori) - Female\n\
岩瀬 (Iwase)\n\
万蔵 (Manzou) - Male\n\
結奈 (Yuuna) - Female\n\
茅部 (Kayabe)\n\
-'
-
- system = PROMPT + VOCAB if fullPromptFlag else \
- f"\
+"
+
+ system = (
+ PROMPT + VOCAB
+ if fullPromptFlag
+ else f"\
You are an expert Eroge Game translator who translates Japanese text to {LANGUAGE}.\n\
Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`\n\
- You translate everything, including erotic and explicit content.\n\
@@ -376,9 +412,11 @@ Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{
- `...` can be a part of the dialogue. Translate it as it is.\n\
{VOCAB}\n\
"
- user = f'{subbedT}'
+ )
+ user = f"{subbedT}"
return characters, system, user
+
def translateText(characters, system, user, history, penalty):
# Prompt
msg = [{"role": "system", "content": system + characters}]
@@ -391,9 +429,9 @@ def translateText(characters, system, user, history, penalty):
msg.extend([{"role": "system", "content": h} for h in history])
else:
msg.append({"role": "system", "content": history})
-
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0,
frequency_penalty=penalty,
@@ -402,18 +440,19 @@ def translateText(characters, system, user, history, penalty):
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- 'Placeholder Text': '',
- 'é' : 'e',
- '—' : '-',
- 'ū' : 'u',
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "Placeholder Text": "",
+ "é": "e",
+ "—": "-",
+ "ū": "u",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
@@ -424,11 +463,12 @@ def cleanTranslatedText(translatedText, varResponse):
translatedText = resubVars(translatedText, varResponse[1])
return translatedText
+
def elongateCharacters(text):
# Define a pattern to match one character followed by one or more `ー` characters
# Using a positive lookbehind assertion to capture the preceding character
- pattern = r'(?<=(.))ー+'
-
+ pattern = r"(?<=(.))ー+"
+
# Define a replacement function that elongates the captured character
def repl(match):
char = match.group(1) # The character before the ー sequence
@@ -438,8 +478,9 @@ def elongateCharacters(text):
# Use re.sub() to replace the pattern in the text
return re.sub(pattern, repl, text)
+
def extractTranslation(translatedTextList, is_list):
- pattern = r'`?<[Ll]ine\d+>([\\]*.*?[\\]*?)<\/?[Ll]ine\d+>`?'
+ pattern = r"`?<[Ll]ine\d+>([\\]*.*?[\\]*?)<\/?[Ll]ine\d+>`?"
# If it's a batch (i.e., list), extract with tags; otherwise, return the single item.
if is_list:
matchList = re.findall(pattern, translatedTextList)
@@ -448,11 +489,12 @@ def extractTranslation(translatedTextList, is_list):
matchList = re.findall(pattern, translatedTextList)
return matchList[0][0] if matchList else translatedTextList
+
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -464,15 +506,17 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*3)
+ outputTotalTokens += round(len(enc.encode(user)) * 3)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag):
mismatch = False
@@ -485,8 +529,12 @@ def translateGPT(text, history, fullPromptFlag):
for index, tItem in enumerate(tList):
# Before sending to translation, if we have a list of items, add the formatting
if isinstance(tItem, list):
- payload = '\n'.join([f'`{item}`' for i, item in enumerate(tItem)])
- payload = re.sub(r'(<)(\/Line\d+>)', r'\1>Placeholder Text<\3', payload)
+ payload = "\n".join(
+ [f"`{item}`" for i, item in enumerate(tItem)]
+ )
+ payload = re.sub(
+ r"(<)(\/Line\d+>)", r"\1>Placeholder Text<\3", payload
+ )
varResponse = subVars(payload)
subbedT = varResponse[0]
else:
@@ -494,7 +542,7 @@ def translateGPT(text, history, fullPromptFlag):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
continue
# Create Message
@@ -531,11 +579,13 @@ def translateGPT(text, history, fullPromptFlag):
extractedTranslations = extractTranslation(translatedText, True)
tList[index] = extractedTranslations
if len(tItem) != len(extractedTranslations):
- mismatch = True # Just here for breakpoint
+ mismatch = True # Just here for breakpoint
# Create History
if not mismatch:
- history = extractedTranslations[-10:] # Update history if we have a list
+ history = extractedTranslations[
+ -10:
+ ] # Update history if we have a list
else:
history = text[-10:]
else:
diff --git a/modules/atelier.py b/modules/atelier.py
index 6cfde80..61b389d 100644
--- a/modules/atelier.py
+++ b/modules/atelier.py
@@ -14,38 +14,41 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE=os.getenv('language').capitalize()
-INPUTAPICOST = .002 # Depends on the model https://openai.com/pricing
-OUTPUTAPICOST = .002
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads')) # Controls how many threads are working on a single file (May have to drop this)
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+INPUTAPICOST = 0.002 # Depends on the model https://openai.com/pricing
+OUTPUTAPICOST = 0.002
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(
+ os.getenv("threads")
+) # Controls how many threads are working on a single file (May have to drop this)
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
NOTEWIDTH = 40
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
totalTokens = [0, 0]
NAMESLIST = []
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
-POSITION=0
-LEAVE=False
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
+POSITION = 0
+LEAVE = False
# Translation Flags
FIXTEXTWRAP = True
IGNORETLTEXT = True
+
def handleAtelier(filename, estimate):
global ESTIMATE, totalTokens
ESTIMATE = estimate
@@ -61,11 +64,11 @@ def handleAtelier(filename, estimate):
totalTokens[0] += translatedData[1][0]
totalTokens[1] += translatedData[1][1]
- return getResultString(['', totalTokens, None], end - start, 'TOTAL')
+ return getResultString(["", totalTokens, None], end - start, "TOTAL")
else:
try:
- with open('translated/' + filename, 'w', encoding='utf-8') as outFile:
+ with open("translated/" + filename, "w", encoding="utf-8") as outFile:
start = time.time()
translatedData = openFiles(filename)
outFile.writelines(translatedData[0])
@@ -77,29 +80,43 @@ def handleAtelier(filename, estimate):
totalTokens[0] += translatedData[1][0]
totalTokens[1] += translatedData[1][1]
except Exception:
- return 'Fail'
+ return "Fail"
+
+ return getResultString(["", totalTokens, None], end - start, "TOTAL")
- return getResultString(['', totalTokens, None], end - start, 'TOTAL')
def openFiles(filename):
- with open('files/' + filename, 'r', encoding='UTF-8') as f:
+ with open("files/" + filename, "r", encoding="UTF-8") as f:
translatedData = parseText(f, filename)
-
+
return translatedData
+
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] is None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
@@ -107,9 +124,18 @@ def getResultString(translatedData, translationTime, filename):
raise translatedData[2]
except Exception as e:
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
-
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
+
def parseText(data, filename):
totalLines = 0
global LOCK
@@ -117,10 +143,12 @@ def parseText(data, filename):
# Get total for progress bar
linesList = data.readlines()
totalLines = len(linesList)
-
- with tqdm(bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE) as pbar:
- pbar.desc=filename
- pbar.total=totalLines
+
+ with tqdm(
+ bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE
+ ) as pbar:
+ pbar.desc = filename
+ pbar.total = totalLines
try:
response = translateText(linesList, pbar)
except Exception as e:
@@ -128,32 +156,37 @@ def parseText(data, filename):
return [linesList, 0, e]
return [response[0], response[1], None]
+
def translateText(data, pbar):
textHistory = []
maxHistory = MAXHISTORY
- totalTokens = [0,0]
+ totalTokens = [0, 0]
syncIndex = 0
for i in range(len(data)):
if syncIndex > i:
i = syncIndex
- match = re.findall(r'◆.+◆(.+)', data[i])
+ match = re.findall(r"◆.+◆(.+)", data[i])
if len(match) > 0:
jaString = match[0]
### Translate
# Remove any textwrap
- finalJAString = re.sub(r'\\n', ' ', jaString)
-
+ finalJAString = re.sub(r"\\n", " ", jaString)
+
# Translate
- response = translateGPT(finalJAString, 'Previous Text for Context: ' + ' '.join(textHistory), True)
+ response = translateGPT(
+ finalJAString,
+ "Previous Text for Context: " + " ".join(textHistory),
+ True,
+ )
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
translatedText = response[0]
-
+
# TextHistory is what we use to give GPT Context, so thats appended here.
- textHistory.append('\"' + translatedText + '\"')
+ textHistory.append('"' + translatedText + '"')
# Keep textHistory list at length maxHistory
if len(textHistory) > maxHistory:
@@ -161,81 +194,83 @@ def translateText(data, pbar):
# Textwrap
translatedText = textwrap.fill(translatedText, width=WIDTH)
- translatedText = translatedText.replace('\n', '\\n')
+ translatedText = translatedText.replace("\n", "\\n")
# Write
data[i] = data[i].replace(match[0], translatedText)
-
+
syncIndex = i + 1
pbar.update()
return [data, totalTokens]
-
+
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Nested
count = 0
- nestedList = re.findall(r'[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]', jaString)
+ nestedList = re.findall(r"[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]", jaString)
nestedList = set(nestedList)
if len(nestedList) != 0:
for icon in nestedList:
- jaString = jaString.replace(icon, '{Nested_' + str(count) + '}')
+ jaString = jaString.replace(icon, "{Nested_" + str(count) + "}")
count += 1
# Icons
count = 0
- iconList = re.findall(r'[\\]+[iIkKwWaA]+\[[0-9]+\]', jaString)
+ iconList = re.findall(r"[\\]+[iIkKwWaA]+\[[0-9]+\]", jaString)
iconList = set(iconList)
if len(iconList) != 0:
for icon in iconList:
- jaString = jaString.replace(icon, '{Ascii_' + str(count) + '}')
+ jaString = jaString.replace(icon, "{Ascii_" + str(count) + "}")
count += 1
# Colors
count = 0
- colorList = re.findall(r'[\\]+[cC]\[[0-9]+\]', jaString)
+ colorList = re.findall(r"[\\]+[cC]\[[0-9]+\]", jaString)
colorList = set(colorList)
if len(colorList) != 0:
for color in colorList:
- jaString = jaString.replace(color, '{Color_' + str(count) + '}')
+ jaString = jaString.replace(color, "{Color_" + str(count) + "}")
count += 1
# Names
count = 0
- nameList = re.findall(r'[\\]+[nN]\[.+?\]+', jaString)
+ nameList = re.findall(r"[\\]+[nN]\[.+?\]+", jaString)
nameList = set(nameList)
if len(nameList) != 0:
for name in nameList:
- jaString = jaString.replace(name, '{N_' + str(count) + '}')
+ jaString = jaString.replace(name, "{N_" + str(count) + "}")
count += 1
# Variables
count = 0
- varList = re.findall(r'[\\]+[vV]\[[0-9]+\]', jaString)
+ varList = re.findall(r"[\\]+[vV]\[[0-9]+\]", jaString)
varList = set(varList)
if len(varList) != 0:
for var in varList:
- jaString = jaString.replace(var, '{Var_' + str(count) + '}')
+ jaString = jaString.replace(var, "{Var_" + str(count) + "}")
count += 1
# Formatting
count = 0
- if '笑えるよね.' in jaString:
- print('t')
- formatList = re.findall(r'[\\]+[\w]+\[.+?\]', jaString)
+ if "笑えるよね." in jaString:
+ print("t")
+ formatList = re.findall(r"[\\]+[\w]+\[.+?\]", jaString)
formatList = set(formatList)
if len(formatList) != 0:
for var in formatList:
- jaString = jaString.replace(var, '{FCode_' + str(count) + '}')
+ jaString = jaString.replace(var, "{FCode_" + str(count) + "}")
count += 1
# Put all lists in list and return
allList = [nestedList, iconList, colorList, nameList, varList, formatList]
return [jaString, allList]
+
def resubVars(translatedText, allList):
# Fix Spacing and ChatGPT Nonsense
- matchList = re.findall(r'\[\s?.+?\s?\]', translatedText)
+ matchList = re.findall(r"\[\s?.+?\s?\]", translatedText)
if len(matchList) > 0:
for match in matchList:
text = match.strip()
@@ -245,42 +280,42 @@ def resubVars(translatedText, allList):
count = 0
if len(allList[0]) != 0:
for var in allList[0]:
- translatedText = translatedText.replace('{Nested_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Nested_" + str(count) + "}", var)
count += 1
# Icons
count = 0
if len(allList[1]) != 0:
for var in allList[1]:
- translatedText = translatedText.replace('{Ascii_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Ascii_" + str(count) + "}", var)
count += 1
# Colors
count = 0
if len(allList[2]) != 0:
for var in allList[2]:
- translatedText = translatedText.replace('{Color_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Color_" + str(count) + "}", var)
count += 1
# Names
count = 0
if len(allList[3]) != 0:
for var in allList[3]:
- translatedText = translatedText.replace('{N_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{N_" + str(count) + "}", var)
count += 1
# Vars
count = 0
if len(allList[4]) != 0:
for var in allList[4]:
- translatedText = translatedText.replace('{Var_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Var_" + str(count) + "}", var)
count += 1
-
+
# Formatting
count = 0
if len(allList[5]) != 0:
for var in allList[5]:
- translatedText = translatedText.replace('{FCode_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{FCode_" + str(count) + "}", var)
count += 1
# Remove Color Variables Spaces
@@ -289,6 +324,7 @@ def resubVars(translatedText, allList):
# translatedText = re.sub(r'\s*(\\+c\[0+\])', r'\1', translatedText)
return translatedText
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(t, history, fullPromptFlag):
# Sub Vars
@@ -296,13 +332,13 @@ def translateGPT(t, history, fullPromptFlag):
subbedT = varResponse[0]
# If there isn't any Japanese in the text just skip
- if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴ]+|[\uFF00-\uFFEF]', subbedT):
- return(t, [0,0])
-
+ if not re.search(r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴ]+|[\uFF00-\uFFEF]", subbedT):
+ return (t, [0, 0])
+
# If ESTIMATE is True just count this as an execution and return.
if ESTIMATE:
- enc = tiktoken.encoding_for_model('gpt-4')
- historyRaw = ''
+ enc = tiktoken.encoding_for_model("gpt-4")
+ historyRaw = ""
if isinstance(history, list):
for line in history:
historyRaw += line
@@ -310,26 +346,34 @@ def translateGPT(t, history, fullPromptFlag):
historyRaw = history
inputTotalTokens = len(enc.encode(historyRaw)) + len(enc.encode(PROMPT))
- outputTotalTokens = len(enc.encode(t)) * 2 # Estimating 2x the size of the original text
+ outputTotalTokens = (
+ len(enc.encode(t)) * 2
+ ) # Estimating 2x the size of the original text
totalTokens = [inputTotalTokens, outputTotalTokens]
return (t, totalTokens)
# Characters
- context = 'Game Characters:\
+ context = "Game Characters:\
Character: Surname:久高 Name:有史 == Surname:Kudaka Name:Yuushi - Gender: Male\
Character: Surname:葛城 Name:碧璃 == Surname:Katsuragi Name:Midori - Gender: Female\
Character: Surname:葛城 Name:依理子 == Surname:Katsuragi Name:Yoriko - Gender: Female\
Character: Surname:桐乃木 Name:奏 == Surname:Kirinogi Name:Kanade - Gender: Female\
Character: Surname:葛城 Name:光男 == Surname:Katsuragi Name:Mitsuo - Gender: Male\
- Character: Surname:尾木 Name:優真 == Surname:Ogi Name:Yuuma - Gender: Male'
+ Character: Surname:尾木 Name:優真 == Surname:Ogi Name:Yuuma - Gender: Male"
# Prompt
if fullPromptFlag:
system = PROMPT
- user = 'Line to Translate = ' + subbedT
+ user = "Line to Translate = " + subbedT
else:
- system = 'Output ONLY the '+ LANGUAGE +' translation in the following format: `Translation: <'+ LANGUAGE.upper() +'_TRANSLATION>`'
- user = 'Line to Translate = ' + subbedT
+ system = (
+ "Output ONLY the "
+ + LANGUAGE
+ + " translation in the following format: `Translation: <"
+ + LANGUAGE.upper()
+ + "_TRANSLATION>`"
+ )
+ user = "Line to Translate = " + subbedT
# Create Message List
msg = []
@@ -359,26 +403,29 @@ def translateGPT(t, history, fullPromptFlag):
translatedText = resubVars(translatedText, varResponse[1])
# Remove Placeholder Text
- translatedText = translatedText.replace(LANGUAGE +' Translation: ', '')
- translatedText = translatedText.replace('Translation: ', '')
- translatedText = translatedText.replace('Line to Translate = ', '')
- translatedText = translatedText.replace('Translation = ', '')
- translatedText = translatedText.replace('Translate = ', '')
- translatedText = translatedText.replace(LANGUAGE +' Translation:', '')
- translatedText = translatedText.replace('Translation:', '')
- translatedText = translatedText.replace('Line to Translate =', '')
- translatedText = translatedText.replace('Translation =', '')
- translatedText = translatedText.replace('Translate =', '')
- translatedText = translatedText.replace('っ', '')
- translatedText = translatedText.replace('ッ', '')
- translatedText = translatedText.replace('ぁ', '')
- translatedText = translatedText.replace('。', '.')
- translatedText = translatedText.replace('、', ',')
- translatedText = translatedText.replace('?', '?')
- translatedText = translatedText.replace('!', '!')
+ translatedText = translatedText.replace(LANGUAGE + " Translation: ", "")
+ translatedText = translatedText.replace("Translation: ", "")
+ translatedText = translatedText.replace("Line to Translate = ", "")
+ translatedText = translatedText.replace("Translation = ", "")
+ translatedText = translatedText.replace("Translate = ", "")
+ translatedText = translatedText.replace(LANGUAGE + " Translation:", "")
+ translatedText = translatedText.replace("Translation:", "")
+ translatedText = translatedText.replace("Line to Translate =", "")
+ translatedText = translatedText.replace("Translation =", "")
+ translatedText = translatedText.replace("Translate =", "")
+ translatedText = translatedText.replace("っ", "")
+ translatedText = translatedText.replace("ッ", "")
+ translatedText = translatedText.replace("ぁ", "")
+ translatedText = translatedText.replace("。", ".")
+ translatedText = translatedText.replace("、", ",")
+ translatedText = translatedText.replace("?", "?")
+ translatedText = translatedText.replace("!", "!")
# Return Translation
- if len(translatedText) > 15 * len(t) or "I'm sorry, but I'm unable to assist with that translation" in translatedText:
+ if (
+ len(translatedText) > 15 * len(t)
+ or "I'm sorry, but I'm unable to assist with that translation" in translatedText
+ ):
raise Exception
else:
- return [translatedText, totalTokens]
\ No newline at end of file
+ return [translatedText, totalTokens]
diff --git a/modules/csv.py b/modules/csv.py
index 1e4ad49..ca3f873 100644
--- a/modules/csv.py
+++ b/modules/csv.py
@@ -17,63 +17,66 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
-NOTEWIDTH = int(os.getenv('noteWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
+NOTEWIDTH = int(os.getenv("noteWidth"))
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = True # Overwrites textwrap
-IGNORETLTEXT = True # Ignores all translated text.
-MISMATCH = [] # Lists files that thdata a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = True # Ignores all translated text.
+MISMATCH = [] # Lists files that thdata a mismatch error (Length of GPT list response is wrong)
BRACKETNAMES = False
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
FREQUENCY_PENALTY = 0.2
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .005
- OUTPUTAPICOST = .015
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.005
+ OUTPUTAPICOST = 0.015
BATCHSIZE = 20
FREQUENCY_PENALTY = 0.1
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
PBAR = None
+
def handleCSV(filename, estimate):
global ESTIMATE, TOKENS
ESTIMATE = estimate
if not ESTIMATE:
- with open('translated/' + filename, 'w+t', newline='', encoding='utf-8-sig') as writeFile:
+ with open(
+ "translated/" + filename, "w+t", newline="", encoding="utf-8-sig"
+ ) as writeFile:
# Translate
start = time.time()
translatedData = openFiles(filename, writeFile)
-
+
# Print Result
end = time.time()
tqdm.write(getResultString(translatedData, end - start, filename))
@@ -84,7 +87,7 @@ def handleCSV(filename, estimate):
# Translate
start = time.time()
translatedData = openFilesEstimate(filename)
-
+
# Print Result
end = time.time()
tqdm.write(getResultString(translatedData, end - start, filename))
@@ -92,41 +95,55 @@ def handleCSV(filename, estimate):
TOKENS[0] += translatedData[1][0]
TOKENS[1] += translatedData[1][1]
-
# Print Total
- totalString = getResultString(['', TOKENS, None], end - start, 'TOTAL')
+ totalString = getResultString(["", TOKENS, None], end - start, "TOTAL")
# Print any errors on maps
if len(MISMATCH) > 0:
- return totalString + Fore.RED + f'\nMismatch Errors: {MISMATCH}' + Fore.RESET
+ return totalString + Fore.RED + f"\nMismatch Errors: {MISMATCH}" + Fore.RESET
else:
return totalString
+
def openFiles(filename, writeFile):
- with open('files/' + filename, 'r', encoding='utf-8-sig') as readFile, writeFile:
+ with open("files/" + filename, "r", encoding="utf-8-sig") as readFile, writeFile:
translatedData = parseCSV(readFile, writeFile, filename)
return translatedData
+
def openFilesEstimate(filename):
- with open('files/' + filename, 'r', encoding='utf-8-sig') as readFile:
- translatedData = parseCSV(readFile, '', filename)
+ with open("files/" + filename, "r", encoding="utf-8-sig") as readFile:
+ translatedData = parseCSV(readFile, "", filename)
return translatedData
+
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] is None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
try:
@@ -134,38 +151,51 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
-
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
+
def parseCSV(readFile, writeFile, filename):
- totalTokens = [0,0]
+ totalTokens = [0, 0]
totalLines = 0
global LOCK
- format = ''
- while format not in ['1', '2', '3']:
- format = input('\n\nSelect the CSV Format:\n\n1. Translator++\n2. Single\n3. Multiple\n')
+ format = ""
+ while format not in ["1", "2", "3"]:
+ format = input(
+ "\n\nSelect the CSV Format:\n\n1. Translator++\n2. Single\n3. Multiple\n"
+ )
match format:
- case '1':
- format = '1'
- case '2':
- format = '2'
- case '3':
- format = '3'
+ case "1":
+ format = "1"
+ case "2":
+ format = "2"
+ case "3":
+ format = "3"
# Get total for progress bar
totalLines = len(readFile.readlines())
readFile.seek(0)
- reader = csv.reader(readFile, delimiter=',')
+ reader = csv.reader(readFile, delimiter=",")
if not ESTIMATE:
- writer = csv.writer(writeFile, delimiter=',', quotechar='\"')
+ writer = csv.writer(writeFile, delimiter=",", quotechar='"')
else:
- writer = ''
+ writer = ""
- with tqdm(bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE) as pbar:
- pbar.desc=filename
- pbar.total=totalLines
+ with tqdm(
+ bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE
+ ) as pbar:
+ pbar.desc = filename
+ pbar.total = totalLines
# Grab All Rows
data = []
@@ -180,11 +210,12 @@ def parseCSV(readFile, writeFile, filename):
traceback.print_exc()
return [data, totalTokens, None]
+
def translateCSV(data, pbar, writer, filename, translatedList, format):
global LOCK, ESTIMATE, PBAR
PBAR = pbar
- translatedText = ''
- totalTokens = [0,0]
+ translatedText = ""
+ totalTokens = [0, 0]
i = 0
stringList = []
@@ -193,7 +224,7 @@ def translateCSV(data, pbar, writer, filename, translatedList, format):
while i < len(data):
match format:
# T++ Format: Source Text on column 1. TL Target on Column 2
- case '1':
+ case "1":
# Get String
if i != 0:
if data[i][1] == "":
@@ -202,7 +233,7 @@ def translateCSV(data, pbar, writer, filename, translatedList, format):
jaString = data[i][1]
# Remove Textwrap
- jaString = jaString.replace('\\n', ' ')
+ jaString = jaString.replace("\\n", " ")
# Pass 1
if not translatedList:
@@ -216,16 +247,16 @@ def translateCSV(data, pbar, writer, filename, translatedList, format):
# Add Wordwrap
translatedText = textwrap.fill(translatedText, WIDTH)
- translatedText = translatedText.replace('\n', '\\n')
+ translatedText = translatedText.replace("\n", "\\n")
# Set Data
data[i][1] = translatedText
-
+
# Iterate
i += 1
-
+
# Target Format
- case '2':
+ case "2":
# Set Values
sourceColumn = 0
targetColumn = 1
@@ -234,7 +265,7 @@ def translateCSV(data, pbar, writer, filename, translatedList, format):
jaString = data[i][sourceColumn]
# Remove Textwrap
- jaString = jaString.replace('\\n', ' ')
+ jaString = jaString.replace("\\n", " ")
# Pass 1
if not translatedList:
@@ -248,22 +279,22 @@ def translateCSV(data, pbar, writer, filename, translatedList, format):
# Add Wordwrap
translatedText = textwrap.fill(translatedText, WIDTH)
- translatedText = translatedText.replace('\n', '\\n')
+ translatedText = translatedText.replace("\n", "\\n")
# Set Data
data[i][targetColumn] = translatedText
-
+
# Iterate
i += 1
# All Format
- case '3':
+ case "3":
# Set columns to translate. Leave empty to translate all.
targetColumns = []
# False - Place translation in source column
# True - Place translation in next column
- targetNextRow = True
+ targetNextRow = True
for j in range(len(data[i])):
if j not in targetColumns:
@@ -271,7 +302,7 @@ def translateCSV(data, pbar, writer, filename, translatedList, format):
jaString = data[i][j]
# Remove Textwrap
- jaString = jaString.replace('\\n', ' ')
+ jaString = jaString.replace("\\n", " ")
# Pass 1
if not translatedList:
@@ -285,14 +316,14 @@ def translateCSV(data, pbar, writer, filename, translatedList, format):
# Add Wordwrap
translatedText = textwrap.fill(translatedText, WIDTH)
- translatedText = translatedText.replace('\n', '\\n')
+ translatedText = translatedText.replace("\n", "\\n")
# Set Data
if targetNextRow:
data[i][j + 1] = translatedText
else:
data[i][j] = translatedText
-
+
# Iterate
i += 1
@@ -301,9 +332,9 @@ def translateCSV(data, pbar, writer, filename, translatedList, format):
# Set Progress
pbar.total = len(stringList)
pbar.refresh()
-
+
# Translate
- response = translateGPT(stringList, '', True)
+ response = translateGPT(stringList, "", True)
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
translatedList = response[0]
@@ -333,27 +364,35 @@ def translateCSV(data, pbar, writer, filename, translatedList, format):
for row in data:
writer.writerow(row)
return totalTokens
-
+
return totalTokens
-
+
# Save some money and enter the character before translation
def getSpeaker(speaker):
match speaker:
- case 'ファイン':
- return ['Fine', [0,0]]
- case '':
- return ['', [0,0]]
+ case "ファイン":
+ return ["Fine", [0, 0]]
+ case "":
+ return ["", [0, 0]]
case _:
# Store Speaker
if speaker not in str(NAMESLIST):
- response = translateGPT(speaker, 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ response = translateGPT(
+ speaker,
+ "Reply with the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
response[0] = response[0].replace("'S", "'s")
# Retry if name doesn't translate for some reason
- if re.search(r'([a-zA-Z??])', response[0]) == None:
- response = translateGPT(speaker, 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ if re.search(r"([a-zA-Z??])", response[0]) == None:
+ response = translateGPT(
+ speaker,
+ "Reply with the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
response[0] = response[0].replace("'S", "'s")
@@ -364,74 +403,76 @@ def getSpeaker(speaker):
else:
for i in range(len(NAMESLIST)):
if speaker == NAMESLIST[i][0]:
- return [NAMESLIST[i][1],[0,0]]
-
- return [speaker,[0,0]]
+ return [NAMESLIST[i][1], [0, 0]]
+
+ return [speaker, [0, 0]]
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Nested
count = 0
- nestedList = re.findall(r'[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]', jaString)
+ nestedList = re.findall(r"[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]", jaString)
nestedList = set(nestedList)
if len(nestedList) != 0:
for icon in nestedList:
- jaString = jaString.replace(icon, '[Nested_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Nested_" + str(count) + "]")
count += 1
# Icons
count = 0
- iconList = re.findall(r'[\\]+[iIkKwWaA]+\[[0-9]+\]', jaString)
+ iconList = re.findall(r"[\\]+[iIkKwWaA]+\[[0-9]+\]", jaString)
iconList = set(iconList)
if len(iconList) != 0:
for icon in iconList:
- jaString = jaString.replace(icon, '[Ascii_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Ascii_" + str(count) + "]")
count += 1
# Colors
count = 0
- colorList = re.findall(r'([\\]+c\[\d+\][\\]+c|[\\]+c\[\d+\])', jaString)
+ colorList = re.findall(r"([\\]+c\[\d+\][\\]+c|[\\]+c\[\d+\])", jaString)
colorList = set(colorList)
if len(colorList) != 0:
for color in colorList:
- jaString = jaString.replace(color, '[Color_' + str(count) + ']')
+ jaString = jaString.replace(color, "[Color_" + str(count) + "]")
count += 1
# Names
count = 0
- nameList = re.findall(r'[\\]+[nN]\[.+?\]+', jaString)
+ nameList = re.findall(r"[\\]+[nN]\[.+?\]+", jaString)
nameList = set(nameList)
if len(nameList) != 0:
for name in nameList:
- jaString = jaString.replace(name, '[Noun_' + str(count) + ']')
+ jaString = jaString.replace(name, "[Noun_" + str(count) + "]")
count += 1
# Variables
count = 0
- varList = re.findall(r'[\\]+[vV]\[[0-9]+\]', jaString)
+ varList = re.findall(r"[\\]+[vV]\[[0-9]+\]", jaString)
varList = set(varList)
if len(varList) != 0:
for var in varList:
- jaString = jaString.replace(var, '[Var_' + str(count) + ']')
+ jaString = jaString.replace(var, "[Var_" + str(count) + "]")
count += 1
# Formatting
count = 0
- formatList = re.findall(r'[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
+ formatList = re.findall(r"[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]", jaString)
formatList = set(formatList)
if len(formatList) != 0:
for var in formatList:
- jaString = jaString.replace(var, '[FCode_' + str(count) + ']')
+ jaString = jaString.replace(var, "[FCode_" + str(count) + "]")
count += 1
# Put all lists in list and return
allList = [nestedList, iconList, colorList, nameList, varList, formatList]
return [jaString, allList]
+
def resubVars(translatedText, allList):
# Fix Spacing and ChatGPT Nonsense
- matchList = re.findall(r'\[\s?.+?\s?\]', translatedText)
+ matchList = re.findall(r"\[\s?.+?\s?\]", translatedText)
if len(matchList) > 0:
for match in matchList:
text = match.strip()
@@ -441,60 +482,66 @@ def resubVars(translatedText, allList):
count = 0
if len(allList[0]) != 0:
for var in allList[0]:
- translatedText = translatedText.replace('[Nested_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Nested_" + str(count) + "]", var)
count += 1
# Icons
count = 0
if len(allList[1]) != 0:
for var in allList[1]:
- translatedText = translatedText.replace('[Ascii_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Ascii_" + str(count) + "]", var)
count += 1
# Colors
count = 0
if len(allList[2]) != 0:
for var in allList[2]:
- translatedText = translatedText.replace('[Color_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Color_" + str(count) + "]", var)
count += 1
# Names
count = 0
if len(allList[3]) != 0:
for var in allList[3]:
- translatedText = translatedText.replace('[Noun_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Noun_" + str(count) + "]", var)
count += 1
# Vars
count = 0
if len(allList[4]) != 0:
for var in allList[4]:
- translatedText = translatedText.replace('[Var_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Var_" + str(count) + "]", var)
count += 1
-
+
# Formatting
count = 0
if len(allList[5]) != 0:
for var in allList[5]:
- translatedText = translatedText.replace('[FCode_' + str(count) + ']', var)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
クリスティーナ (Christina) - Female\n\
リズ (Liz) - Female\n\
-'
-
- system = PROMPT + VOCAB if fullPromptFlag else \
- f"\
+"
+
+ system = (
+ PROMPT + VOCAB
+ if fullPromptFlag
+ else f"\
You are an expert Eroge Game translator who translates Japanese text to {LANGUAGE}.\n\
Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`\n\
- You translate everything, including erotic and explicit content.\n\
@@ -506,12 +553,14 @@ Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{
- `...` can be a part of the dialogue. Translate it as it is.\n\
{VOCAB}\n\
"
+ )
if isinstance(subbedT, list):
- user = f'```json\n{subbedT}```'
+ user = f"```json\n{subbedT}```"
else:
user = subbedT
return characters, system, user
+
def translateText(characters, system, user, history, penalty, format):
# Prompt
msg = [{"role": "system", "content": system + characters}]
@@ -526,13 +575,13 @@ def translateText(characters, system, user, history, penalty, format):
msg.append({"role": "system", "content": history})
# Response Format
- if format == 'json':
- responseFormat = { "type": "json_object" }
+ if format == "json":
+ responseFormat = {"type": "json_object"}
else:
- responseFormat = { "type": "text" }
-
+ responseFormat = {"type": "text"}
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0,
frequency_penalty=penalty,
@@ -542,18 +591,19 @@ def translateText(characters, system, user, history, penalty, format):
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- '「': '\\"',
- '」': '\\"',
- '- ': '-',
- 'Placeholder Text': '',
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "「": '\\"',
+ "」": '\\"',
+ "- ": "-",
+ "Placeholder Text": "",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
@@ -564,11 +614,12 @@ def cleanTranslatedText(translatedText, varResponse):
translatedText = resubVars(translatedText, varResponse[1])
return translatedText
+
def elongateCharacters(text):
# Define a pattern to match one character followed by one or more `ー` characters
# Using a positive lookbehind assertion to capture the preceding character
- pattern = r'(?<=(.))ー+'
-
+ pattern = r"(?<=(.))ー+"
+
# Define a replacement function that elongates the captured character
def repl(match):
char = match.group(1) # The character before the ー sequence
@@ -578,6 +629,7 @@ def elongateCharacters(text):
# Use re.sub() to replace the pattern in the text
return re.sub(pattern, repl, text)
+
def extractTranslation(translatedTextList, is_list):
try:
translatedTextList = re.sub(r'\\"+\"([^,\n}])', r'\\"\1', translatedTextList)
@@ -590,15 +642,15 @@ def extractTranslation(translatedTextList, is_list):
return string_list[0]
except Exception as e:
- PBAR.write(f'extractTranslation Error: {e} on String {translatedTextList}')
+ PBAR.write(f"extractTranslation Error: {e} on String {translatedTextList}")
return None
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -610,26 +662,28 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*3)
+ outputTotalTokens += round(len(enc.encode(user)) * 3)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag):
global PBAR
-
+
mismatch = False
totalTokens = [0, 0]
if isinstance(text, list):
- format = 'json'
+ format = "json"
tList = batchList(text, BATCHSIZE)
else:
- format = 'text'
+ format = "text"
tList = [text]
for index, tItem in enumerate(tList):
@@ -644,7 +698,7 @@ def translateGPT(text, history, fullPromptFlag):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
if PBAR is not None:
PBAR.update(len(tItem))
continue
@@ -669,9 +723,13 @@ def translateGPT(text, history, fullPromptFlag):
translatedText = cleanTranslatedText(translatedText, varResponse)
if isinstance(tItem, list):
extractedTranslations = extractTranslation(translatedText, True)
- if extractedTranslations == None or len(tItem) != len(extractedTranslations):
+ if extractedTranslations == None or len(tItem) != len(
+ extractedTranslations
+ ):
# Mismatch. Try Again
- response = translateText(characters, system, user, history, 0.05, format)
+ response = translateText(
+ characters, system, user, history, 0.05, format
+ )
translatedText = response.choices[0].message.content
totalTokens[0] += response.usage.prompt_tokens
totalTokens[1] += response.usage.completion_tokens
@@ -680,13 +738,17 @@ def translateGPT(text, history, fullPromptFlag):
translatedText = cleanTranslatedText(translatedText, varResponse)
if isinstance(tItem, list):
extractedTranslations = extractTranslation(translatedText, True)
- if extractedTranslations == None or len(tItem) != len(extractedTranslations):
- mismatch = True # Just here for breakpoint
-
+ if extractedTranslations == None or len(tItem) != len(
+ extractedTranslations
+ ):
+ mismatch = True # Just here for breakpoint
+
# Set if no mismatch
if mismatch == False:
tList[index] = extractedTranslations
- history = extractedTranslations[-10:] # Update history if we have a list
+ history = extractedTranslations[
+ -10:
+ ] # Update history if we have a list
else:
history = text[-10:]
mismatch = False
@@ -697,7 +759,7 @@ def translateGPT(text, history, fullPromptFlag):
PBAR.update(len(tItem))
else:
# Ensure we're passing a single string to extractTranslation
- tList[index] = translatedText
+ tList[index] = translatedText
finalList = combineList(tList, text)
return [finalList, totalTokens]
diff --git a/modules/eushully.py b/modules/eushully.py
index 7c291a1..447fe7f 100644
--- a/modules/eushully.py
+++ b/modules/eushully.py
@@ -15,34 +15,34 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
NOTEWIDTH = 70
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = True # Overwrites textwrap
-IGNORETLTEXT = False # Ignores all translated text.
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = False # Ignores all translated text.
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
PBAR = None
@@ -50,15 +50,16 @@ PBAR = None
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .005
- OUTPUTAPICOST = .015
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.005
+ OUTPUTAPICOST = 0.015
BATCHSIZE = 40
+
def handleEushully(filename, estimate):
global ESTIMATE
ESTIMATE = estimate
@@ -75,17 +76,21 @@ def handleEushully(filename, estimate):
TOKENS[1] += translatedData[1][1]
# Print Total
- totalString = getResultString(['', TOKENS, None], end - start, 'TOTAL')
+ totalString = getResultString(["", TOKENS, None], end - start, "TOTAL")
# Print any errors on maps
if len(MISMATCH) > 0:
- return totalString + Fore.RED + f'\nMismatch Errors: {MISMATCH}' + Fore.RESET
+ return (
+ totalString + Fore.RED + f"\nMismatch Errors: {MISMATCH}" + Fore.RESET
+ )
else:
return totalString
-
+
else:
try:
- with open('translated/' + filename, 'w', encoding='utf-8', errors='ignore') as outFile:
+ with open(
+ "translated/" + filename, "w", encoding="utf-8", errors="ignore"
+ ) as outFile:
start = time.time()
translatedData = openFiles(filename)
@@ -98,23 +103,36 @@ def handleEushully(filename, estimate):
TOKENS[1] += translatedData[1][1]
except Exception:
traceback.print_exc()
- return 'Fail'
+ return "Fail"
+
+ return getResultString(["", TOKENS, None], end - start, "TOTAL")
- return getResultString(['', TOKENS, None], end - start, 'TOTAL')
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] == None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
@@ -123,31 +141,41 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
def openFiles(filename):
- with open('files/' + filename, 'r', encoding='utf-8') as readFile:
+ with open("files/" + filename, "r", encoding="utf-8") as readFile:
translatedData = parseRegex(readFile, filename)
# Delete lines marked for deletion
finalData = []
for line in translatedData[0]:
- if line != '\\d\n':
+ if line != "\\d\n":
finalData.append(line)
translatedData[0] = finalData
-
+
return translatedData
+
def parseRegex(readFile, filename):
- totalTokens = [0,0]
+ totalTokens = [0, 0]
# Read File into data
data = readFile.readlines()
# Create Progress Bar
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
try:
result = translateEushully(data, pbar, filename, [])
@@ -158,11 +186,12 @@ def parseRegex(readFile, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def translateEushully(data, pbar, filename, translatedList):
stringList = []
currentGroup = []
- tokens = [0,0]
- speaker = ''
+ tokens = [0, 0]
+ speaker = ""
voice = False
global LOCK, ESTIMATE, PBAR
i = 0
@@ -170,9 +199,9 @@ def translateEushully(data, pbar, filename, translatedList):
while i < len(data):
voice = False
# Speaker
- if 'mov (global-int 46e2)' in data[i]:
+ if "mov (global-int 46e2)" in data[i]:
# Get Speaker
- speaker = re.search(r'mov \(global-int 46e2\)\s(.+)', data[i]).group(1)
+ speaker = re.search(r"mov \(global-int 46e2\)\s(.+)", data[i]).group(1)
response = getSpeaker(speaker)
speaker = response[0]
tokens[0] += response[1][0]
@@ -180,32 +209,34 @@ def translateEushully(data, pbar, filename, translatedList):
i += 1
# Show Text
- if any(x in data[i] for x in ['show-text']):
+ if any(x in data[i] for x in ["show-text"]):
# Lines
regex = r'(.*?)"(.*)"'
match = re.search(regex, data[i])
# Grab Strings
- if match != None and match.group(2) != '':
+ if match != None and match.group(2) != "":
originalString = match.group(2)
jaString = match.group(2)
currentGroup = [jaString]
- while 'end-text-line' in data[i+1] and any(x in data[i+2] for x in ['show-text']):
- match = re.search(regex, data[i+2])
+ while "end-text-line" in data[i + 1] and any(
+ x in data[i + 2] for x in ["show-text"]
+ ):
+ match = re.search(regex, data[i + 2])
if match != None:
currentGroup.append(match.group(2))
if translatedList == []:
- del(data[i])
- del(data[i])
- jaString = ' '.join(currentGroup)
-
+ del data[i]
+ del data[i]
+ jaString = " ".join(currentGroup)
+
# Pass 1
if translatedList == []:
# Add String
if speaker:
- stringList.append(f'[{speaker}]: {jaString.strip()}')
+ stringList.append(f"[{speaker}]: {jaString.strip()}")
else:
stringList.append(jaString.strip())
-
+
# Pass 2
else:
# Get Text
@@ -222,51 +253,58 @@ def translateEushully(data, pbar, filename, translatedList):
translatedText = translatedText.replace('"', "'")
# Remove speaker
- if speaker != '':
- translatedText = re.sub(r'^\[?(.+?)\]?\s?[|:]\s?', '', translatedText)
+ if speaker != "":
+ translatedText = re.sub(
+ r"^\[?(.+?)\]?\s?[|:]\s?", "", translatedText
+ )
# Textwrap
translatedText = textwrap.fill(translatedText, width=WIDTH)
- translatedTextList = translatedText.split('\n')
+ translatedTextList = translatedText.split("\n")
# Set Data
if len(translatedTextList) > 1:
for j in range(len(translatedTextList)):
- if any(x in data[i] for x in ['show-text', 'set-string', 'concat']):
- del(data[i])
- data.insert(i, f'{match.group(1)}"{translatedTextList[j]}"\n')
+ if any(
+ x in data[i]
+ for x in ["show-text", "set-string", "concat"]
+ ):
+ del data[i]
+ data.insert(
+ i, f'{match.group(1)}"{translatedTextList[j]}"\n'
+ )
i += 1
- if 'end-text-line' not in data[i]:
- data.insert(i, 'end-text-line 0\n')
+ if "end-text-line" not in data[i]:
+ data.insert(i, "end-text-line 0\n")
i += 1
else:
data[i] = f'{match.group(1)}"{translatedTextList[0]}"\n'
- speaker = ''
+ speaker = ""
i += 1
-
+
# Nothing relevant. Skip Line.
else:
i += 1
# Set String
- elif 'set-string' in data[i]:
+ elif "set-string" in data[i]:
# Lines
regex = r'(.*?)"(.*)"'
match = re.search(regex, data[i])
# Grab Strings
- if match != None and match.group(2) != '':
+ if match != None and match.group(2) != "":
originalString = match.group(2)
jaString = match.group(2)
currentGroup = [jaString]
-
+
# Remove Textwrap
- jaString = jaString.replace('\\n', ' ')
-
+ jaString = jaString.replace("\\n", " ")
+
# Pass 1
if translatedList == []:
# Add String
stringList.append(jaString.strip())
-
+
# Pass 2
else:
# Get Text
@@ -284,11 +322,11 @@ def translateEushully(data, pbar, filename, translatedList):
# Textwrap
translatedText = textwrap.fill(translatedText, width=LISTWIDTH)
- translatedText = translatedText.replace('\n', '\\n')
+ translatedText = translatedText.replace("\n", "\\n")
# Set Data
- data[i] = data[i].replace(originalString, translatedText)
- speaker = ''
+ data[i] = data[i].replace(originalString, translatedText)
+ speaker = ""
i += 1
# Nothing relevant. Skip Line.
@@ -302,10 +340,10 @@ def translateEushully(data, pbar, filename, translatedList):
# Set Progress
pbar.total = len(stringList)
pbar.refresh()
-
+
# Translate
PBAR = pbar
- response = translateGPT(stringList, '', True)
+ response = translateGPT(stringList, "", True)
tokens[0] += response[1][0]
tokens[1] += response[1][1]
translatedList = response[0]
@@ -321,140 +359,143 @@ def translateEushully(data, pbar, filename, translatedList):
MISMATCH.append(filename)
return tokens
+
# Save some money and enter the character before translation
def getSpeaker(speaker):
match speaker:
- case '1':
- return ['Klaus', [0,0]]
- case '2':
- return ['Helmina', [0,0]]
- case '3':
- return ['Juliana', [0,0]]
- case '4':
- return ['Reginia', [0,0]]
- case '5':
- return ['Luciel', [0,0]]
- case '6':
- return ['Mavislaine', [0,0]]
- case '7':
- return ['Cerouge', [0,0]]
- case '8':
- return ['Maize', [0,0]]
- case '9':
- return ['Elvire', [0,0]]
- case 'a':
- return ['Beatrice', [0,0]]
- case '295':
- return ['Orc', [0,0]]
- case '232':
- return ['Archangel', [0,0]]
- case '238':
- return ['False Juliana', [0,0]]
- case '239':
- return ['False Regina', [0,0]]
- case '23a':
- return ['False Luciel', [0,0]]
- case '23d':
- return ['False Mavislaine', [0,0]]
- case 'cb':
- return ['Olga Niza Kite', [0,0]]
- case 'c9':
- return ['Demon Beast Lupus', [0,0]]
- case 'ca':
- return ['Evelinael', [0,0]]
- case '10':
- return ['Eukleia', [0,0]]
- case '15':
- return ['Lily', [0,0]]
- case '16':
- return ['Kupuko', [0,0]]
- case 'b':
- return ['Ramiel', [0,0]]
- case 'c':
- return ['Henriette', [0,0]]
- case 'd':
- return ['Camilla', [0,0]]
- case 'cc':
- return ['Gogonaua', [0,0]]
- case '65':
- return ['Demon Lord Reyvalois', [0,0]]
- case 'd0':
- return ['Demon Ranwald', [0,0]]
- case '205':
- return ['Vanqueor', [0,0]]
- case '66':
- return ['Angel Martina', [0,0]]
- case '21f':
- return ['Hiten Demon', [0,0]]
- case 'd2':
- return ['Lena Eli', [0,0]]
+ case "1":
+ return ["Klaus", [0, 0]]
+ case "2":
+ return ["Helmina", [0, 0]]
+ case "3":
+ return ["Juliana", [0, 0]]
+ case "4":
+ return ["Reginia", [0, 0]]
+ case "5":
+ return ["Luciel", [0, 0]]
+ case "6":
+ return ["Mavislaine", [0, 0]]
+ case "7":
+ return ["Cerouge", [0, 0]]
+ case "8":
+ return ["Maize", [0, 0]]
+ case "9":
+ return ["Elvire", [0, 0]]
+ case "a":
+ return ["Beatrice", [0, 0]]
+ case "295":
+ return ["Orc", [0, 0]]
+ case "232":
+ return ["Archangel", [0, 0]]
+ case "238":
+ return ["False Juliana", [0, 0]]
+ case "239":
+ return ["False Regina", [0, 0]]
+ case "23a":
+ return ["False Luciel", [0, 0]]
+ case "23d":
+ return ["False Mavislaine", [0, 0]]
+ case "cb":
+ return ["Olga Niza Kite", [0, 0]]
+ case "c9":
+ return ["Demon Beast Lupus", [0, 0]]
+ case "ca":
+ return ["Evelinael", [0, 0]]
+ case "10":
+ return ["Eukleia", [0, 0]]
+ case "15":
+ return ["Lily", [0, 0]]
+ case "16":
+ return ["Kupuko", [0, 0]]
+ case "b":
+ return ["Ramiel", [0, 0]]
+ case "c":
+ return ["Henriette", [0, 0]]
+ case "d":
+ return ["Camilla", [0, 0]]
+ case "cc":
+ return ["Gogonaua", [0, 0]]
+ case "65":
+ return ["Demon Lord Reyvalois", [0, 0]]
+ case "d0":
+ return ["Demon Ranwald", [0, 0]]
+ case "205":
+ return ["Vanqueor", [0, 0]]
+ case "66":
+ return ["Angel Martina", [0, 0]]
+ case "21f":
+ return ["Hiten Demon", [0, 0]]
+ case "d2":
+ return ["Lena Eli", [0, 0]]
case _:
- return ['Unknown', [0,0]]
+ return ["Unknown", [0, 0]]
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Nested
count = 0
- nestedList = re.findall(r'[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]', jaString)
+ nestedList = re.findall(r"[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]", jaString)
nestedList = set(nestedList)
if len(nestedList) != 0:
for icon in nestedList:
- jaString = jaString.replace(icon, '[Nested_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Nested_" + str(count) + "]")
count += 1
# Icons
count = 0
- iconList = re.findall(r'[\\]+[iIkKwWaA]+\[[0-9]+\]', jaString)
+ iconList = re.findall(r"[\\]+[iIkKwWaA]+\[[0-9]+\]", jaString)
iconList = set(iconList)
if len(iconList) != 0:
for icon in iconList:
- jaString = jaString.replace(icon, '[Ascii_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Ascii_" + str(count) + "]")
count += 1
# Colors
count = 0
- colorList = re.findall(r'[\\]+[cC]\[[0-9]+\]', jaString)
+ colorList = re.findall(r"[\\]+[cC]\[[0-9]+\]", jaString)
colorList = set(colorList)
if len(colorList) != 0:
for color in colorList:
- jaString = jaString.replace(color, '[Color_' + str(count) + ']')
+ jaString = jaString.replace(color, "[Color_" + str(count) + "]")
count += 1
# Names
count = 0
- nameList = re.findall(r'[\\]+[nN]\[.+?\]+', jaString)
+ nameList = re.findall(r"[\\]+[nN]\[.+?\]+", jaString)
nameList = set(nameList)
if len(nameList) != 0:
for name in nameList:
- jaString = jaString.replace(name, '[Noun_' + str(count) + ']')
+ jaString = jaString.replace(name, "[Noun_" + str(count) + "]")
count += 1
# Variables
count = 0
- varList = re.findall(r'[\\]+[vV]\[[0-9]+\]', jaString)
+ varList = re.findall(r"[\\]+[vV]\[[0-9]+\]", jaString)
varList = set(varList)
if len(varList) != 0:
for var in varList:
- jaString = jaString.replace(var, '[Var_' + str(count) + ']')
+ jaString = jaString.replace(var, "[Var_" + str(count) + "]")
count += 1
# Formatting
count = 0
- formatList = re.findall(r'[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
+ formatList = re.findall(r"[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]", jaString)
formatList = set(formatList)
if len(formatList) != 0:
for var in formatList:
- jaString = jaString.replace(var, '[FCode_' + str(count) + ']')
+ jaString = jaString.replace(var, "[FCode_" + str(count) + "]")
count += 1
# Put all lists in list and return
allList = [nestedList, iconList, colorList, nameList, varList, formatList]
return [jaString, allList]
+
def resubVars(translatedText, allList):
# Fix Spacing and ChatGPT Nonsense
- matchList = re.findall(r'\[\s?.+?\s?\]', translatedText)
+ matchList = re.findall(r"\[\s?.+?\s?\]", translatedText)
if len(matchList) > 0:
for match in matchList:
text = match.strip()
@@ -464,59 +505,65 @@ def resubVars(translatedText, allList):
count = 0
if len(allList[0]) != 0:
for var in allList[0]:
- translatedText = translatedText.replace('[Nested_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Nested_" + str(count) + "]", var)
count += 1
# Icons
count = 0
if len(allList[1]) != 0:
for var in allList[1]:
- translatedText = translatedText.replace('[Ascii_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Ascii_" + str(count) + "]", var)
count += 1
# Colors
count = 0
if len(allList[2]) != 0:
for var in allList[2]:
- translatedText = translatedText.replace('[Color_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Color_" + str(count) + "]", var)
count += 1
# Names
count = 0
if len(allList[3]) != 0:
for var in allList[3]:
- translatedText = translatedText.replace('[Noun_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Noun_" + str(count) + "]", var)
count += 1
# Vars
count = 0
if len(allList[4]) != 0:
for var in allList[4]:
- translatedText = translatedText.replace('[Var_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Var_" + str(count) + "]", var)
count += 1
-
+
# Formatting
count = 0
if len(allList[5]) != 0:
for var in allList[5]:
- translatedText = translatedText.replace('[FCode_' + str(count) + ']', var)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
グレイス (Grace) - Female\n\
-'
-
- system = PROMPT + VOCAB if fullPromptFlag else \
- f"\
+"
+
+ system = (
+ PROMPT + VOCAB
+ if fullPromptFlag
+ else f"\
You are an expert Eroge Game translator who translates Japanese text to {LANGUAGE}.\n\
Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`\n\
- You translate everything, including erotic and explicit content.\n\
@@ -528,9 +575,11 @@ Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{
- `...` can be a part of the dialogue. Translate it as it is.\n\
{VOCAB}\n\
"
- user = f'{subbedT}'
+ )
+ user = f"{subbedT}"
return characters, system, user
+
def translateText(characters, system, user, history, penalty):
# Prompt
msg = [{"role": "system", "content": system + characters}]
@@ -543,9 +592,9 @@ def translateText(characters, system, user, history, penalty):
msg.extend([{"role": "system", "content": h} for h in history])
else:
msg.append({"role": "system", "content": history})
-
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0,
frequency_penalty=penalty,
@@ -554,23 +603,24 @@ def translateText(characters, system, user, history, penalty):
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- '< ': '<',
- ' ': '',
- ' >': '>',
- '「': '\"',
- '」': '\"',
- 'Placeholder Text': '',
- '- chan': '-chan',
- '- kun': '-kun',
- '- san': '-san',
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "< ": "<",
+ " ": "",
+ " >": ">",
+ "「": '"',
+ "」": '"',
+ "Placeholder Text": "",
+ "- chan": "-chan",
+ "- kun": "-kun",
+ "- san": "-san",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
@@ -581,11 +631,12 @@ def cleanTranslatedText(translatedText, varResponse):
translatedText = resubVars(translatedText, varResponse[1])
return translatedText
+
def elongateCharacters(text):
# Define a pattern to match one character followed by one or more `ー` characters
# Using a positive lookbehind assertion to capture the preceding character
- pattern = r'(?<=(.))ー+'
-
+ pattern = r"(?<=(.))ー+"
+
# Define a replacement function that elongates the captured character
def repl(match):
char = match.group(1) # The character before the ー sequence
@@ -595,8 +646,9 @@ def elongateCharacters(text):
# Use re.sub() to replace the pattern in the text
return re.sub(pattern, repl, text)
+
def extractTranslation(translatedTextList, is_list):
- pattern = r'`?<[Ll]ine\d+>([\\]*.*?[\\]*?)<\/?[Ll]ine\d+>`?'
+ pattern = r"`?<[Ll]ine\d+>([\\]*.*?[\\]*?)<\/?[Ll]ine\d+>`?"
# If it's a batch (i.e., list), extract with tags; otherwise, return the single item.
if is_list:
matchList = re.findall(pattern, translatedTextList)
@@ -605,11 +657,12 @@ def extractTranslation(translatedTextList, is_list):
matchList = re.findall(pattern, translatedTextList)
return matchList[0][0] if matchList else translatedTextList
+
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -621,19 +674,21 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*3)
+ outputTotalTokens += round(len(enc.encode(user)) * 3)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag):
global PBAR
-
+
mismatch = False
totalTokens = [0, 0]
if isinstance(text, list):
@@ -644,8 +699,12 @@ def translateGPT(text, history, fullPromptFlag):
for index, tItem in enumerate(tList):
# Before sending to translation, if we have a list of items, add the formatting
if isinstance(tItem, list):
- payload = '\n'.join([f'`{item}`' for i, item in enumerate(tItem)])
- payload = re.sub(r'(<)(\/Line\d+>)', r'\1>Placeholder Text<\3', payload)
+ payload = "\n".join(
+ [f"`{item}`" for i, item in enumerate(tItem)]
+ )
+ payload = re.sub(
+ r"(<)(\/Line\d+>)", r"\1>Placeholder Text<\3", payload
+ )
varResponse = subVars(payload)
subbedT = varResponse[0]
else:
@@ -653,7 +712,7 @@ def translateGPT(text, history, fullPromptFlag):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
if PBAR is not None:
PBAR.update(len(tItem))
continue
@@ -692,14 +751,16 @@ def translateGPT(text, history, fullPromptFlag):
extractedTranslations = extractTranslation(translatedText, True)
tList[index] = extractedTranslations
if len(tItem) != len(extractedTranslations):
- mismatch = True # Just here for breakpoint
+ mismatch = True # Just here for breakpoint
# Create History
with LOCK:
if PBAR is not None:
PBAR.update(len(tItem))
if not mismatch:
- history = extractedTranslations[-10:] # Update history if we have a list
+ history = extractedTranslations[
+ -10:
+ ] # Update history if we have a list
else:
history = text[-10:]
else:
diff --git a/modules/images.py b/modules/images.py
index 2f70a13..7177878 100644
--- a/modules/images.py
+++ b/modules/images.py
@@ -14,72 +14,77 @@ from dotenv import load_dotenv
from retry import retry
from tqdm import tqdm
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
PBAR = None
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
-NOTEWIDTH = int(os.getenv('noteWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
+NOTEWIDTH = int(os.getenv("noteWidth"))
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
FREQUENCY_PENALTY = 0.2
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .005
- OUTPUTAPICOST = .015
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.005
+ OUTPUTAPICOST = 0.015
BATCHSIZE = 20
FREQUENCY_PENALTY = 0.1
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
+
def handleImages(folderName, estimate):
global ESTIMATE, TOKENS
ESTIMATE = estimate
start = time.time()
# Translate Strings
- translatedData = openFiles(f'files/{folderName}')
+ translatedData = openFiles(f"files/{folderName}")
# Write Strings to Images
if not ESTIMATE:
- if not os.path.exists(f'translated/{folderName}'):
- os.mkdir(f'translated/{folderName}')
+ if not os.path.exists(f"translated/{folderName}"):
+ os.mkdir(f"translated/{folderName}")
for i in range(len(translatedData[0][0])):
try:
translatedList = translatedData[0][0]
originalList = translatedData[0][1]
dimensionsList = translatedData[0][2]
- image = stringToImage(translatedList[i], dimensionsList[i][0], dimensionsList[i][1])
- image.save(rf'translated/{folderName}/{translatedList[i]}.png', quality=100)
+ image = stringToImage(
+ translatedList[i], dimensionsList[i][0], dimensionsList[i][1]
+ )
+ image.save(
+ rf"translated/{folderName}/{translatedList[i]}.png", quality=100
+ )
except Exception as e:
- PBAR.write(f'{translatedList[i]}: {str(e)}')
- #Ignore Error
+ PBAR.write(f"{translatedList[i]}: {str(e)}")
+ # Ignore Error
# Print File
end = time.time()
@@ -89,43 +94,67 @@ def handleImages(folderName, estimate):
TOKENS[1] += translatedData[1][1]
# Print Total
- totalString = getResultString(['', TOKENS, None], end - start, 'TOTAL')
+ totalString = getResultString(["", TOKENS, None], end - start, "TOTAL")
# Print any errors on maps
if len(MISMATCH) > 0:
- return totalString + Fore.RED + f'\nMismatch Errors: {MISMATCH}' + Fore.RESET
+ return totalString + Fore.RED + f"\nMismatch Errors: {MISMATCH}" + Fore.RESET
else:
return totalString
-
+
+
def openFiles(folderName):
global PBAR
if os.path.isdir(folderName):
- imageList = [[],[]]
+ imageList = [[], []]
imageList = processImagesDir(folderName, imageList)
-
+
# Start Translation
- with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE, desc=folderName, total=len(imageList[0])) as PBAR:
+ with tqdm(
+ bar_format=BAR_FORMAT,
+ position=POSITION,
+ leave=LEAVE,
+ desc=folderName,
+ total=len(imageList[0]),
+ ) as PBAR:
translatedData = translateImages(imageList)
- translatedData = [[translatedData[0], imageList[0], imageList[1]], translatedData[1], translatedData[2]]
-
+ translatedData = [
+ [translatedData[0], imageList[0], imageList[1]],
+ translatedData[1],
+ translatedData[2],
+ ]
+
return translatedData
else:
print("The provided directory path does not exist.")
+
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] is None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
try:
@@ -133,8 +162,17 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
def getFontSize(text, image_width, image_height, font_path):
# Start with a high font size and keep reducing it until the text fits within the image bounds
@@ -142,50 +180,59 @@ def getFontSize(text, image_width, image_height, font_path):
while font_size > 0:
font = ImageFont.truetype(font_path, font_size)
- text_bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).textbbox((0, 0), text, font=font)
+ text_bbox = ImageDraw.Draw(Image.new("RGB", (1, 1))).textbbox(
+ (0, 0), text, font=font
+ )
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1] + 5
-
+
if text_width <= image_width and text_height <= image_height:
return font_size
font_size -= 1
return font_size
-def stringToImage(text, width, height, font_path='fonts/TsunagiGothic.ttf', scale_factor=4):
+
+def stringToImage(
+ text, width, height, font_path="fonts/TsunagiGothic.ttf", scale_factor=4
+):
# Increase the resolution
scaled_width = int(width * scale_factor)
scaled_height = int(height * scale_factor)
-
+
# Find the appropriate font size for the scaled up image
font_size = getFontSize(text, scaled_width, scaled_height, font_path)
if font_size == 0:
raise ValueError("Text is too long to fit in the supplied dimensions.")
-
+
# Create a new image with the scaled width and height and a transparent background
- image = Image.new('RGBA', (scaled_width, scaled_height), (255, 255, 255, 0))
-
+ image = Image.new("RGBA", (scaled_width, scaled_height), (255, 255, 255, 0))
+
# Create a drawing context
draw = ImageDraw.Draw(image)
-
+
# Load the appropriate font
font = ImageFont.truetype(font_path, font_size)
-
+
# Calculate the size of the text to center it
text_bbox = draw.textbbox((0, 0), text, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
x = (scaled_width - text_width) // 2
y = (scaled_height - text_height) // 2
-
+
# Draw the text on the image
draw.text((x, y), text, font=font, fill=(255, 255, 255, 255))
-
+
# Resize back to the original dimensions to get a clearer text rendering
- image = image.resize((width, height), Image.LANCZOS,)
-
+ image = image.resize(
+ (width, height),
+ Image.LANCZOS,
+ )
+
return image
+
def getImageDimensions(file_path):
try:
with Image.open(file_path) as img:
@@ -195,10 +242,11 @@ def getImageDimensions(file_path):
print(f"Error reading {file_path}: {e}")
return None, None
+
def processImagesDir(directory_path, imageList):
for file_name in os.listdir(directory_path):
# .png and Japanese
- if '.png' in file_name and file_name.replace('.png', '') in VOCAB:
+ if ".png" in file_name and file_name.replace(".png", "") in VOCAB:
file_path = os.path.join(directory_path, file_name)
if os.path.isfile(file_path):
# Check if the file is an image
@@ -206,7 +254,7 @@ def processImagesDir(directory_path, imageList):
width, height = getImageDimensions(file_path)
if width is not None and height is not None:
placeholders = {
- '.png': '',
+ ".png": "",
}
for target, replacement in placeholders.items():
file_name = file_name.replace(target, replacement)
@@ -214,37 +262,49 @@ def processImagesDir(directory_path, imageList):
imageList[1].append([width, height])
except Exception as e:
print(f"Error processing {file_name}: {e}")
-
+
return imageList
+
def translateImages(imageList):
- totalTokens = [0,0]
+ totalTokens = [0, 0]
# Translate GPT
- response = translateGPT(imageList[0], 'Keep the Translation as brief as possible', True)
+ response = translateGPT(
+ imageList[0], "Keep the Translation as brief as possible", True
+ )
translatedList = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
- return [translatedList, totalTokens, None]
+ return [translatedList, totalTokens, None]
+
# Save some money and enter the character before translation
def getSpeaker(speaker):
match speaker:
- case 'ファイン':
- return ['Fine', [0,0]]
- case '':
- return ['', [0,0]]
+ case "ファイン":
+ return ["Fine", [0, 0]]
+ case "":
+ return ["", [0, 0]]
case _:
# Store Speaker
if speaker not in str(NAMESLIST):
- response = translateGPT(speaker, 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ response = translateGPT(
+ speaker,
+ "Reply with the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
response[0] = response[0].replace("'S", "'s")
# Retry if name doesn't translate for some reason
- if re.search(r'([a-zA-Z??])', response[0]) == None:
- response = translateGPT(speaker, 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ if re.search(r"([a-zA-Z??])", response[0]) == None:
+ response = translateGPT(
+ speaker,
+ "Reply with the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
response[0] = response[0].replace("'S", "'s")
@@ -255,50 +315,56 @@ def getSpeaker(speaker):
else:
for i in range(len(NAMESLIST)):
if speaker == NAMESLIST[i][0]:
- return [NAMESLIST[i][1],[0,0]]
-
- return [speaker,[0,0]]
+ return [NAMESLIST[i][1], [0, 0]]
+
+ return [speaker, [0, 0]]
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Formatting
count = 0
- codeList = re.findall(r'[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
+ 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) + ']')
+ 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)
+ 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)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT, format):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
ロラン (Roland) - Male\n\
リュカ (Ryuka) - Male\n\
レックス (Rex) - Male\n\
@@ -341,10 +407,12 @@ def createContext(fullPromptFlag, subbedT, format):
ブライ (Buraimu) - Male\n\
ハッサン (Hassan) - Male\n\
アロマ (Aroma) - Female\n\
-'
-
- system = PROMPT + VOCAB if fullPromptFlag else \
- f"\
+"
+
+ system = (
+ PROMPT + VOCAB
+ if fullPromptFlag
+ else f"\
You are an expert Eroge Game translator who translates Japanese text to {LANGUAGE}.\n\
Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`\n\
- You translate everything, including erotic and explicit content.\n\
@@ -356,12 +424,14 @@ Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{
- `...` can be a part of the dialogue. Translate it as it is.\n\
{VOCAB}\n\
"
- if format == 'json':
- user = f'```json\n{subbedT}\n```'
+ )
+ if format == "json":
+ user = f"```json\n{subbedT}\n```"
else:
user = subbedT
return characters, system, user
+
def translateText(characters, system, user, history, penalty, format):
# Prompt
msg = [{"role": "system", "content": system + characters}]
@@ -376,13 +446,13 @@ def translateText(characters, system, user, history, penalty, format):
msg.append({"role": "system", "content": history})
# Response Format
- if format == 'json':
- responseFormat = { "type": "json_object" }
+ if format == "json":
+ responseFormat = {"type": "json_object"}
else:
- responseFormat = { "type": "text" }
-
+ responseFormat = {"type": "text"}
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0,
frequency_penalty=penalty,
@@ -392,18 +462,19 @@ def translateText(characters, system, user, history, penalty, format):
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- '「': '\\"',
- '」': '\\"',
- '- ': '-',
- 'Placeholder Text': '',
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "「": '\\"',
+ "」": '\\"',
+ "- ": "-",
+ "Placeholder Text": "",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
@@ -414,11 +485,12 @@ def cleanTranslatedText(translatedText, varResponse):
translatedText = resubVars(translatedText, varResponse[1])
return translatedText
+
def elongateCharacters(text):
# Define a pattern to match one character followed by one or more `ー` characters
# Using a positive lookbehind assertion to capture the preceding character
- pattern = r'(?<=(.))ー+'
-
+ pattern = r"(?<=(.))ー+"
+
# Define a replacement function that elongates the captured character
def repl(match):
char = match.group(1) # The character before the ー sequence
@@ -428,6 +500,7 @@ def elongateCharacters(text):
# Use re.sub() to replace the pattern in the text
return re.sub(pattern, repl, text)
+
def extractTranslation(translatedTextList, is_list):
try:
line_dict = json.loads(translatedTextList)
@@ -439,15 +512,15 @@ def extractTranslation(translatedTextList, is_list):
return string_list[0]
except Exception as e:
- print(f'extractTranslation Error: {e}')
+ print(f"extractTranslation Error: {e}")
return None
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -459,26 +532,28 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*3)
+ outputTotalTokens += round(len(enc.encode(user)) * 3)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag):
global PBAR
-
+
mismatch = False
totalTokens = [0, 0]
if isinstance(text, list):
- format = 'json'
+ format = "json"
tList = batchList(text, BATCHSIZE)
else:
- format = 'text'
+ format = "text"
tList = [text]
for index, tItem in enumerate(tList):
@@ -493,7 +568,7 @@ def translateGPT(text, history, fullPromptFlag):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
if PBAR is not None:
PBAR.update(len(tItem))
continue
@@ -518,9 +593,13 @@ def translateGPT(text, history, fullPromptFlag):
translatedText = cleanTranslatedText(translatedText, varResponse)
if isinstance(tItem, list):
extractedTranslations = extractTranslation(translatedText, True)
- if extractedTranslations == None or len(tItem) != len(extractedTranslations):
+ if extractedTranslations == None or len(tItem) != len(
+ extractedTranslations
+ ):
# Mismatch. Try Again
- response = translateText(characters, system, user, history, 0.05, format)
+ response = translateText(
+ characters, system, user, history, 0.05, format
+ )
translatedText = response.choices[0].message.content
totalTokens[0] += response.usage.prompt_tokens
totalTokens[1] += response.usage.completion_tokens
@@ -529,13 +608,17 @@ def translateGPT(text, history, fullPromptFlag):
translatedText = cleanTranslatedText(translatedText, varResponse)
if isinstance(tItem, list):
extractedTranslations = extractTranslation(translatedText, True)
- if extractedTranslations == None or len(tItem) != len(extractedTranslations):
- mismatch = True # Just here for breakpoint
-
+ if extractedTranslations == None or len(tItem) != len(
+ extractedTranslations
+ ):
+ mismatch = True # Just here for breakpoint
+
# Set if no mismatch
if mismatch == False:
tList[index] = extractedTranslations
- history = extractedTranslations[-10:] # Update history if we have a list
+ history = extractedTranslations[
+ -10:
+ ] # Update history if we have a list
else:
history = text[-10:]
mismatch = False
@@ -546,7 +629,7 @@ def translateGPT(text, history, fullPromptFlag):
PBAR.update(len(tItem))
else:
# Ensure we're passing a single string to extractTranslation
- tList[index] = translatedText
+ tList[index] = translatedText
finalList = combineList(tList, text)
return [finalList, totalTokens]
diff --git a/modules/irissoft.py b/modules/irissoft.py
index 733d081..20759be 100644
--- a/modules/irissoft.py
+++ b/modules/irissoft.py
@@ -15,49 +15,50 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
NOTEWIDTH = 70
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = True # Overwrites textwrap
-IGNORETLTEXT = False # Ignores all translated text.
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = False # Ignores all translated text.
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .005
- OUTPUTAPICOST = .015
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.005
+ OUTPUTAPICOST = 0.015
BATCHSIZE = 40
+
def handleIris(filename, estimate):
global ESTIMATE
ESTIMATE = estimate
@@ -74,17 +75,21 @@ def handleIris(filename, estimate):
TOKENS[1] += translatedData[1][1]
# Print Total
- totalString = getResultString(['', TOKENS, None], end - start, 'TOTAL')
+ totalString = getResultString(["", TOKENS, None], end - start, "TOTAL")
# Print any errors on maps
if len(MISMATCH) > 0:
- return totalString + Fore.RED + f'\nMismatch Errors: {MISMATCH}' + Fore.RESET
+ return (
+ totalString + Fore.RED + f"\nMismatch Errors: {MISMATCH}" + Fore.RESET
+ )
else:
return totalString
-
+
else:
try:
- with open('translated/' + filename, 'w', encoding='cp932', errors='ignore') as outFile:
+ with open(
+ "translated/" + filename, "w", encoding="cp932", errors="ignore"
+ ) as outFile:
start = time.time()
translatedData = openFiles(filename)
@@ -97,23 +102,36 @@ def handleIris(filename, estimate):
TOKENS[1] += translatedData[1][1]
except Exception:
traceback.print_exc()
- return 'Fail'
+ return "Fail"
+
+ return getResultString(["", TOKENS, None], end - start, "TOTAL")
- return getResultString(['', TOKENS, None], end - start, 'TOTAL')
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] == None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
@@ -122,31 +140,41 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
def openFiles(filename):
- with open('files/' + filename, 'r', encoding='shift_jis') as readFile:
+ with open("files/" + filename, "r", encoding="shift_jis") as readFile:
translatedData = parseIris(readFile, filename)
# Delete lines marked for deletion
finalData = []
for line in translatedData[0]:
- if line != '\\d\n':
+ if line != "\\d\n":
finalData.append(line)
translatedData[0] = finalData
-
+
return translatedData
+
def parseIris(readFile, filename):
- totalTokens = [0,0]
+ totalTokens = [0, 0]
# Read File into data
data = readFile.readlines()
# Create Progress Bar
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
try:
result = translateIris(data, pbar, filename, [])
@@ -157,83 +185,87 @@ def parseIris(readFile, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def translateIris(data, pbar, filename, translatedList):
stringList = []
currentGroup = []
- tokens = [0,0]
- speaker = ''
+ tokens = [0, 0]
+ speaker = ""
voice = False
global LOCK, ESTIMATE
i = 0
while i < len(data):
voice = False
- speaker = ''
- if '#MSGVOICE' in data[i]:
+ speaker = ""
+ if "#MSGVOICE" in data[i]:
i += 1
voice = True
voiceVar = data[i]
- if '#MSG,' in data[i] or '#MSG\n' in data[i] or voice == True:
+ if "#MSG," in data[i] or "#MSG\n" in data[i] or voice == True:
i += 1
# Speaker
- if re.search(r'^ ?([^#\/."、。*!!()\(\)\[\] \n]+)\n', data[i]) and len(data[i]) < 30:
- match = re.search(r'(.*)', data[i])
+ if (
+ re.search(r'^ ?([^#\/."、。*!!()\(\)\[\] \n]+)\n', data[i])
+ and len(data[i]) < 30
+ ):
+ match = re.search(r"(.*)", data[i])
if match != None:
speaker = match.group(1)
- if speaker[0] == '\u3000':
+ if speaker[0] == "\u3000":
speaker = speaker[1:]
response = getSpeaker(speaker, pbar, filename)
speaker = response[0]
tokens[0] += response[1][0]
tokens[1] += response[1][1]
if translatedList != []:
- speaker = speaker.replace(' ', '\u3000')
- data[i] = f'\u3000{speaker}\n'
+ speaker = speaker.replace(" ", "\u3000")
+ data[i] = f"\u3000{speaker}\n"
else:
- speaker = ''
+ speaker = ""
i += 1
# Lines
- match = re.search(r'(.*)', data[i])
- if match != None and match.group(1) != '':
+ match = re.search(r"(.*)", data[i])
+ if match != None and match.group(1) != "":
# Pass 1
if translatedList == []:
# Grab Consecutive Strings
jaString = data[i]
- if data[i] != '\n':
- if data[i][0] == '\u3000':
+ if data[i] != "\n":
+ if data[i][0] == "\u3000":
jaString = data[i][1:]
currentGroup.append(jaString)
i += 1
- while data[i] != '\n':
+ while data[i] != "\n":
jaString = data[i]
- if data[i] != '\n':
+ if data[i] != "\n":
jaString = data[i][1:]
currentGroup.append(jaString)
i += 1
-
+
# Join up 401 groups for better translation.
if len(currentGroup) > 0:
- jaString = ''.join(currentGroup)
+ jaString = "".join(currentGroup)
currentGroup = []
-
+
# Remove any textwrap
- jaString = jaString.replace('\n', ' ')
+ jaString = jaString.replace("\n", " ")
# Temporarily convert spaces (For Textwrap Later)
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Add Speaker (If there is one)
- if speaker != '':
- jaString = f'{speaker}: {jaString}'
+ if speaker != "":
+ jaString = f"{speaker}: {jaString}"
# Add String
stringList.append(jaString.strip())
-
+
# Pass 2
else:
# Insert Strings
- while data[i] != '\n':
+ while data[i] != "\n":
data.pop(i)
# Get Text
@@ -244,21 +276,21 @@ def translateIris(data, pbar, filename, translatedList):
translatedList = None
# Remove added speaker
- translatedText = re.sub(r'^.+?:\s', '', translatedText)
+ translatedText = re.sub(r"^.+?:\s", "", translatedText)
# Textwrap
translatedText = textwrap.fill(translatedText, width=WIDTH)
- translatedText = translatedText.replace('\n', '\n\u3000')
+ translatedText = translatedText.replace("\n", "\n\u3000")
# Replace Whitespace and Commas
- translatedText = translatedText.replace(', ', '、')
- translatedText = translatedText.replace(',\u3000', '、')
- translatedText = translatedText.replace(',', '、')
- translatedText = translatedText.replace(' ', '\u3000')
+ translatedText = translatedText.replace(", ", "、")
+ translatedText = translatedText.replace(",\u3000", "、")
+ translatedText = translatedText.replace(",", "、")
+ translatedText = translatedText.replace(" ", "\u3000")
# Set Data
# Game crashes on more than 3 lines. Will need to create a new MSG for long translations
- if translatedText.count('\n') > 2:
+ if translatedText.count("\n") > 2:
# Split List
translatedTextList = splitNewlines(translatedText)
@@ -267,34 +299,34 @@ def translateIris(data, pbar, filename, translatedList):
for text in translatedTextList:
if count != 0:
if voice == True:
- #MSG for each item in the list
- data.insert(i, '#MSGVOICE,\n')
+ # MSG for each item in the list
+ data.insert(i, "#MSGVOICE,\n")
i += 1
- data.insert(i, f'{voiceVar}')
+ data.insert(i, f"{voiceVar}")
i += 1
else:
- data.insert(i, '#MSG,\n')
+ data.insert(i, "#MSG,\n")
i += 1
if speaker:
- data[i] = f'\u3000{speaker}\n'
+ data[i] = f"\u3000{speaker}\n"
i += 1
- if text[0] == '\u3000':
- data.insert(i, f'{text}\n')
+ if text[0] == "\u3000":
+ data.insert(i, f"{text}\n")
else:
- data.insert(i, f'\u3000{text}\n')
+ data.insert(i, f"\u3000{text}\n")
i += 1
count += 1
- if data[i] != '\n':
- data.insert(i, '\n')
- data[i] = f'\n{data[i]}'
+ if data[i] != "\n":
+ data.insert(i, "\n")
+ data[i] = f"\n{data[i]}"
else:
- data.insert(i, f'\u3000{translatedText}\n')
+ data.insert(i, f"\u3000{translatedText}\n")
i += 1
- if data[i] != '\n':
- data[i] = f'\n{data[i]}'
+ if data[i] != "\n":
+ data[i] = f"\n{data[i]}"
- elif '#SELECT' in data[i] and translatedList == []:
- Iris = r'(.+?) +\d$'
+ elif "#SELECT" in data[i] and translatedList == []:
+ Iris = r"(.+?) +\d$"
i += 1
match = re.search(Iris, data[i])
if match:
@@ -302,14 +334,20 @@ def translateIris(data, pbar, filename, translatedList):
choiceList.append(match.group(1))
i += 1
match = re.search(Iris, data[i])
- while(match):
+ while match:
choiceList.append(match.group(1))
i += 1
match = re.search(Iris, data[i])
-
+
# Translate
question = stringList[len(stringList) - 1]
- response = translateGPT(choiceList, f'Previous text for context: {question}\n\nThis will be a dialogue option', True, pbar, filename)
+ response = translateGPT(
+ choiceList,
+ f"Previous text for context: {question}\n\nThis will be a dialogue option",
+ True,
+ pbar,
+ filename,
+ )
tokens[0] += response[1][0]
tokens[1] += response[1][1]
choiceListTL = response[0]
@@ -318,10 +356,10 @@ def translateIris(data, pbar, filename, translatedList):
i = i - len(choiceListTL)
for j in range(len(choiceListTL)):
# Replace Whitespace and Commas
- choiceListTL[j] = choiceListTL[j].replace(', ', '、')
- choiceListTL[j] = choiceListTL[j].replace(',\u3000', '、')
- choiceListTL[j] = choiceListTL[j].replace(',', '、')
- choiceListTL[j] = choiceListTL[j].replace(' ', '\u3000')
+ choiceListTL[j] = choiceListTL[j].replace(", ", "、")
+ choiceListTL[j] = choiceListTL[j].replace(",\u3000", "、")
+ choiceListTL[j] = choiceListTL[j].replace(",", "、")
+ choiceListTL[j] = choiceListTL[j].replace(" ", "\u3000")
data[i] = data[i].replace(choiceList[j], choiceListTL[j])
i += 1
@@ -336,9 +374,9 @@ def translateIris(data, pbar, filename, translatedList):
# Set Progress
pbar.total = len(stringList)
pbar.refresh()
-
+
# Translate
- response = translateGPT(stringList, '', True, pbar, filename)
+ response = translateGPT(stringList, "", True, pbar, filename)
tokens[0] += response[1][0]
tokens[1] += response[1][1]
translatedList = response[0]
@@ -354,20 +392,21 @@ def translateIris(data, pbar, filename, translatedList):
MISMATCH.append(filename)
return tokens
+
def splitNewlines(text):
parts = []
newline_count = 0 # Counts the number of newline characters encountered
start_index = 0 # Start index of the current string part
for i, char in enumerate(text):
- if char == '\n':
+ if char == "\n":
newline_count += 1
if newline_count == 3:
# Append the string part from start_index to current index (inclusive)
- parts.append(text[start_index:i+1])
+ parts.append(text[start_index : i + 1])
# Reset newline count and update start_index for the next string part
newline_count = 0
- start_index = i+1
+ start_index = i + 1
# Edge case: if the text does not end with a newline, we still need to append the last part
if start_index < len(text):
@@ -375,94 +414,103 @@ def splitNewlines(text):
return parts
+
# Save some money and enter the character before translation
def getSpeaker(speaker, pbar, filename):
match speaker:
- case 'ファイン':
- return ['Fine', [0,0]]
- case '':
- return ['', [0,0]]
+ case "ファイン":
+ return ["Fine", [0, 0]]
+ case "":
+ return ["", [0, 0]]
case _:
# Store Speaker
if speaker not in str(NAMESLIST):
- response = translateGPT(speaker, 'Reply with only the '+ LANGUAGE +' translation of the NPC name.', False, pbar, filename)
+ response = translateGPT(
+ speaker,
+ "Reply with only the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ pbar,
+ filename,
+ )
response[0] = response[0].replace("'S", "'s")
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]]
-
- return [speaker,[0,0]]
+ return [NAMESLIST[i][1], [0, 0]]
+
+ return [speaker, [0, 0]]
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Nested
count = 0
- nestedList = re.findall(r'[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]', jaString)
+ nestedList = re.findall(r"[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]", jaString)
nestedList = set(nestedList)
if len(nestedList) != 0:
for icon in nestedList:
- jaString = jaString.replace(icon, '[Nested_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Nested_" + str(count) + "]")
count += 1
# Icons
count = 0
- iconList = re.findall(r'[\\]+[iIkKwWaA]+\[[0-9]+\]', jaString)
+ iconList = re.findall(r"[\\]+[iIkKwWaA]+\[[0-9]+\]", jaString)
iconList = set(iconList)
if len(iconList) != 0:
for icon in iconList:
- jaString = jaString.replace(icon, '[Ascii_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Ascii_" + str(count) + "]")
count += 1
# Colors
count = 0
- colorList = re.findall(r'[\\]+[cC]\[[0-9]+\]', jaString)
+ colorList = re.findall(r"[\\]+[cC]\[[0-9]+\]", jaString)
colorList = set(colorList)
if len(colorList) != 0:
for color in colorList:
- jaString = jaString.replace(color, '[Color_' + str(count) + ']')
+ jaString = jaString.replace(color, "[Color_" + str(count) + "]")
count += 1
# Names
count = 0
- nameList = re.findall(r'[\\]+[nN]\[.+?\]+', jaString)
+ nameList = re.findall(r"[\\]+[nN]\[.+?\]+", jaString)
nameList = set(nameList)
if len(nameList) != 0:
for name in nameList:
- jaString = jaString.replace(name, '[Noun_' + str(count) + ']')
+ jaString = jaString.replace(name, "[Noun_" + str(count) + "]")
count += 1
# Variables
count = 0
- varList = re.findall(r'[\\]+[vV]\[[0-9]+\]', jaString)
+ varList = re.findall(r"[\\]+[vV]\[[0-9]+\]", jaString)
varList = set(varList)
if len(varList) != 0:
for var in varList:
- jaString = jaString.replace(var, '[Var_' + str(count) + ']')
+ jaString = jaString.replace(var, "[Var_" + str(count) + "]")
count += 1
# Formatting
count = 0
- formatList = re.findall(r'[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
+ formatList = re.findall(r"[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]", jaString)
formatList = set(formatList)
if len(formatList) != 0:
for var in formatList:
- jaString = jaString.replace(var, '[FCode_' + str(count) + ']')
+ jaString = jaString.replace(var, "[FCode_" + str(count) + "]")
count += 1
# Put all lists in list and return
allList = [nestedList, iconList, colorList, nameList, varList, formatList]
return [jaString, allList]
+
def resubVars(translatedText, allList):
# Fix Spacing and ChatGPT Nonsense
- matchList = re.findall(r'\[\s?.+?\s?\]', translatedText)
+ matchList = re.findall(r"\[\s?.+?\s?\]", translatedText)
if len(matchList) > 0:
for match in matchList:
text = match.strip()
@@ -472,54 +520,58 @@ def resubVars(translatedText, allList):
count = 0
if len(allList[0]) != 0:
for var in allList[0]:
- translatedText = translatedText.replace('[Nested_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Nested_" + str(count) + "]", var)
count += 1
# Icons
count = 0
if len(allList[1]) != 0:
for var in allList[1]:
- translatedText = translatedText.replace('[Ascii_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Ascii_" + str(count) + "]", var)
count += 1
# Colors
count = 0
if len(allList[2]) != 0:
for var in allList[2]:
- translatedText = translatedText.replace('[Color_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Color_" + str(count) + "]", var)
count += 1
# Names
count = 0
if len(allList[3]) != 0:
for var in allList[3]:
- translatedText = translatedText.replace('[Noun_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Noun_" + str(count) + "]", var)
count += 1
# Vars
count = 0
if len(allList[4]) != 0:
for var in allList[4]:
- translatedText = translatedText.replace('[Var_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Var_" + str(count) + "]", var)
count += 1
-
+
# Formatting
count = 0
if len(allList[5]) != 0:
for var in allList[5]:
- translatedText = translatedText.replace('[FCode_' + str(count) + ']', var)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
フィリア (Philia) - Female\n\
アルネット (Annett) - Female\n\
ラピュセナ (Rapusena) - Female\n\
@@ -529,10 +581,12 @@ def createContext(fullPromptFlag, subbedT):
カルナ (Karna) - Female\n\
ラフィング=スピア (Laughing Spear) - Female\n\
ノーラ (Nora) - Female\n\
-'
-
- system = PROMPT + VOCAB if fullPromptFlag else \
- f"\
+"
+
+ system = (
+ PROMPT + VOCAB
+ if fullPromptFlag
+ else f"\
You are an expert Eroge Game translator who translates Japanese text to {LANGUAGE}.\n\
Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`\n\
- You translate everything, including erotic and explicit content.\n\
@@ -544,9 +598,11 @@ Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{
- `...` can be a part of the dialogue. Translate it as it is.\n\
{VOCAB}\n\
"
- user = f'{subbedT}'
+ )
+ user = f"{subbedT}"
return characters, system, user
+
def translateText(characters, system, user, history):
# Prompt
msg = [{"role": "system", "content": system + characters}]
@@ -559,9 +615,9 @@ def translateText(characters, system, user, history):
msg.extend([{"role": "system", "content": h} for h in history])
else:
msg.append({"role": "system", "content": history})
-
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0.1,
frequency_penalty=0.1,
@@ -570,15 +626,16 @@ def translateText(characters, system, user, history):
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- 'Placeholder Text': ''
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "Placeholder Text": "",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
@@ -589,11 +646,12 @@ def cleanTranslatedText(translatedText, varResponse):
translatedText = resubVars(translatedText, varResponse[1])
return translatedText
+
def elongateCharacters(text):
# Define a pattern to match one character followed by one or more `ー` characters
# Using a positive lookbehind assertion to capture the preceding character
- pattern = r'(?<=(.))ー+'
-
+ pattern = r"(?<=(.))ー+"
+
# Define a replacement function that elongates the captured character
def repl(match):
char = match.group(1) # The character before the ー sequence
@@ -603,8 +661,9 @@ def elongateCharacters(text):
# Use re.sub() to replace the pattern in the text
return re.sub(pattern, repl, text)
+
def extractTranslation(translatedTextList, is_list):
- pattern = r'`?<[Ll]ine\d+>([\\]*.*?[\\]*?)<\/?[Ll]ine\d+>`?'
+ pattern = r"`?<[Ll]ine\d+>([\\]*.*?[\\]*?)<\/?[Ll]ine\d+>`?"
# If it's a batch (i.e., list), extract with tags; otherwise, return the single item.
if is_list:
matchList = re.findall(pattern, translatedTextList)
@@ -613,11 +672,12 @@ def extractTranslation(translatedTextList, is_list):
matchList = re.findall(pattern, translatedTextList)
return matchList[0][0] if matchList else translatedTextList
+
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -629,15 +689,17 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*2)
+ outputTotalTokens += round(len(enc.encode(user)) * 2)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag, pbar, filename):
mismatch = False
@@ -650,8 +712,12 @@ def translateGPT(text, history, fullPromptFlag, pbar, filename):
for index, tItem in enumerate(tList):
# Before sending to translation, if we have a list of items, add the formatting
if isinstance(tItem, list):
- payload = '\n'.join([f'`{item}`' for i, item in enumerate(tItem)])
- payload = re.sub(r'(<)(\/Line\d+>)', r'\1>Placeholder Text<\3', payload)
+ payload = "\n".join(
+ [f"`{item}`" for i, item in enumerate(tItem)]
+ )
+ payload = re.sub(
+ r"(<)(\/Line\d+>)", r"\1>Placeholder Text<\3", payload
+ )
varResponse = subVars(payload)
subbedT = varResponse[0]
else:
@@ -659,7 +725,7 @@ def translateGPT(text, history, fullPromptFlag, pbar, filename):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
continue
# Create Message
diff --git a/modules/javascript.py b/modules/javascript.py
index 8080db0..89c9c3e 100644
--- a/modules/javascript.py
+++ b/modules/javascript.py
@@ -15,49 +15,50 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
NOTEWIDTH = 70
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = True # Overwrites textwrap
-IGNORETLTEXT = False # Ignores all translated text.
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = False # Ignores all translated text.
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .005
- OUTPUTAPICOST = .015
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.005
+ OUTPUTAPICOST = 0.015
BATCHSIZE = 40
+
def handleJavascript(filename, estimate):
global ESTIMATE
ESTIMATE = estimate
@@ -74,17 +75,21 @@ def handleJavascript(filename, estimate):
TOKENS[1] += translatedData[1][1]
# Print Total
- totalString = getResultString(['', TOKENS, None], end - start, 'TOTAL')
+ totalString = getResultString(["", TOKENS, None], end - start, "TOTAL")
# Print any errors on maps
if len(MISMATCH) > 0:
- return totalString + Fore.RED + f'\nMismatch Errors: {MISMATCH}' + Fore.RESET
+ return (
+ totalString + Fore.RED + f"\nMismatch Errors: {MISMATCH}" + Fore.RESET
+ )
else:
return totalString
-
+
else:
try:
- with open('translated/' + filename, 'w', encoding='utf8', errors='ignore') as outFile:
+ with open(
+ "translated/" + filename, "w", encoding="utf8", errors="ignore"
+ ) as outFile:
start = time.time()
translatedData = openFiles(filename)
@@ -97,23 +102,36 @@ def handleJavascript(filename, estimate):
TOKENS[1] += translatedData[1][1]
except Exception:
traceback.print_exc()
- return 'Fail'
+ return "Fail"
+
+ return getResultString(["", TOKENS, None], end - start, "TOTAL")
- return getResultString(['', TOKENS, None], end - start, 'TOTAL')
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] == None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
@@ -122,21 +140,31 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
def openFiles(filename):
- with open('files/' + filename, 'r', encoding='utf-8') as readFile:
+ with open("files/" + filename, "r", encoding="utf-8") as readFile:
translatedData = parseJS(readFile, filename)
-
+
return translatedData
+
def parseJS(readFile, filename):
- totalTokens = [0,0]
+ totalTokens = [0, 0]
data = readFile.readlines()
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
try:
result = translateJS(data, pbar)
@@ -147,8 +175,9 @@ def parseJS(readFile, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def translateJS(data, pbar):
- tokens = [0,0]
+ tokens = [0, 0]
i = 0
# Regex & Plugin Name
@@ -165,10 +194,14 @@ def translateJS(data, pbar):
# Remove Wordwrap [Optional]
for j in range(len(modifiedStringList)):
- modifiedStringList[j] = modifiedStringList[j].replace(r'\\\\\\\\n', r' ')
+ modifiedStringList[j] = modifiedStringList[j].replace(
+ r"\\\\\\\\n", r" "
+ )
# Translate
- response = translateGPT(modifiedStringList, f'Reply with the {LANGUAGE} translation', True, pbar)
+ response = translateGPT(
+ modifiedStringList, f"Reply with the {LANGUAGE} translation", True, pbar
+ )
translatedList = response[0]
tokens[0] = response[1][0]
tokens[0] = response[1][1]
@@ -181,82 +214,83 @@ def translateJS(data, pbar):
# Wordwrap [Optional]
translatedList[j] = textwrap.fill(translatedList[j], LISTWIDTH)
- translatedList[j] = translatedList[j].replace('\n', r'\\\\\\\\n')
+ translatedList[j] = translatedList[j].replace("\n", r"\\\\\\\\n")
# Set
data[i] = data[i].replace(stringList[j], translatedList[j])
# Mismatch
else:
- pbar.write('Mismatch Error')
+ pbar.write("Mismatch Error")
i += 1
-
return tokens
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Nested
count = 0
- nestedList = re.findall(r'[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]', jaString)
+ nestedList = re.findall(r"[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]", jaString)
nestedList = set(nestedList)
if len(nestedList) != 0:
for icon in nestedList:
- jaString = jaString.replace(icon, '[Nested_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Nested_" + str(count) + "]")
count += 1
# Icons
count = 0
- iconList = re.findall(r'[\\]+[iIkKwWaA]+\[[0-9]+\]', jaString)
+ iconList = re.findall(r"[\\]+[iIkKwWaA]+\[[0-9]+\]", jaString)
iconList = set(iconList)
if len(iconList) != 0:
for icon in iconList:
- jaString = jaString.replace(icon, '[Ascii_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Ascii_" + str(count) + "]")
count += 1
# Colors
count = 0
- colorList = re.findall(r'[\\]+[cC]\[[0-9]+\]', jaString)
+ colorList = re.findall(r"[\\]+[cC]\[[0-9]+\]", jaString)
colorList = set(colorList)
if len(colorList) != 0:
for color in colorList:
- jaString = jaString.replace(color, '[Color_' + str(count) + ']')
+ jaString = jaString.replace(color, "[Color_" + str(count) + "]")
count += 1
# Names
count = 0
- nameList = re.findall(r'[\\]+[nN]\[.+?\]+', jaString)
+ nameList = re.findall(r"[\\]+[nN]\[.+?\]+", jaString)
nameList = set(nameList)
if len(nameList) != 0:
for name in nameList:
- jaString = jaString.replace(name, '[Noun_' + str(count) + ']')
+ jaString = jaString.replace(name, "[Noun_" + str(count) + "]")
count += 1
# Variables
count = 0
- varList = re.findall(r'[\\]+[vV]\[[0-9]+\]', jaString)
+ varList = re.findall(r"[\\]+[vV]\[[0-9]+\]", jaString)
varList = set(varList)
if len(varList) != 0:
for var in varList:
- jaString = jaString.replace(var, '[Var_' + str(count) + ']')
+ jaString = jaString.replace(var, "[Var_" + str(count) + "]")
count += 1
# Formatting
count = 0
- formatList = re.findall(r'[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
+ formatList = re.findall(r"[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]", jaString)
formatList = set(formatList)
if len(formatList) != 0:
for var in formatList:
- jaString = jaString.replace(var, '[FCode_' + str(count) + ']')
+ jaString = jaString.replace(var, "[FCode_" + str(count) + "]")
count += 1
# Put all lists in list and return
allList = [nestedList, iconList, colorList, nameList, varList, formatList]
return [jaString, allList]
+
def resubVars(translatedText, allList):
# Fix Spacing and ChatGPT Nonsense
- matchList = re.findall(r'\[\s?.+?\s?\]', translatedText)
+ matchList = re.findall(r"\[\s?.+?\s?\]", translatedText)
if len(matchList) > 0:
for match in matchList:
text = match.strip()
@@ -266,64 +300,70 @@ def resubVars(translatedText, allList):
count = 0
if len(allList[0]) != 0:
for var in allList[0]:
- translatedText = translatedText.replace('[Nested_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Nested_" + str(count) + "]", var)
count += 1
# Icons
count = 0
if len(allList[1]) != 0:
for var in allList[1]:
- translatedText = translatedText.replace('[Ascii_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Ascii_" + str(count) + "]", var)
count += 1
# Colors
count = 0
if len(allList[2]) != 0:
for var in allList[2]:
- translatedText = translatedText.replace('[Color_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Color_" + str(count) + "]", var)
count += 1
# Names
count = 0
if len(allList[3]) != 0:
for var in allList[3]:
- translatedText = translatedText.replace('[Noun_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Noun_" + str(count) + "]", var)
count += 1
# Vars
count = 0
if len(allList[4]) != 0:
for var in allList[4]:
- translatedText = translatedText.replace('[Var_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Var_" + str(count) + "]", var)
count += 1
-
+
# Formatting
count = 0
if len(allList[5]) != 0:
for var in allList[5]:
- translatedText = translatedText.replace('[FCode_' + str(count) + ']', var)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
皆月 (Minazuki)\n\
さやか (Sayaka)\n\
皆月 さやか (Minazuki Sayaka) - Female\n\
広瀬 (Hirose)\n\
智恵 (Chie) - Female\n\
広瀬 智恵 (Hirose Chie) - Female\n\
-'
-
- system = PROMPT + VOCAB if fullPromptFlag else \
- f"\
+"
+
+ system = (
+ PROMPT + VOCAB
+ if fullPromptFlag
+ else f"\
You are an expert Eroge Game translator who translates Japanese text to {LANGUAGE}.\n\
Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`\n\
- You translate everything, including erotic and explicit content.\n\
@@ -335,9 +375,11 @@ Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{
- `...` can be a part of the dialogue. Translate it as it is.\n\
{VOCAB}\n\
"
- user = f'{subbedT}'
+ )
+ user = f"{subbedT}"
return characters, system, user
+
def translateText(characters, system, user, history):
# Prompt
msg = [{"role": "system", "content": system + characters}]
@@ -350,9 +392,9 @@ def translateText(characters, system, user, history):
msg.extend([{"role": "system", "content": h} for h in history])
else:
msg.append({"role": "system", "content": history})
-
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0.1,
frequency_penalty=0.1,
@@ -361,15 +403,16 @@ def translateText(characters, system, user, history):
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- 'Placeholder Text': ''
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "Placeholder Text": "",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
@@ -380,11 +423,12 @@ def cleanTranslatedText(translatedText, varResponse):
translatedText = resubVars(translatedText, varResponse[1])
return translatedText
+
def elongateCharacters(text):
# Define a pattern to match one character followed by one or more `ー` characters
# Using a positive lookbehind assertion to capture the preceding character
- pattern = r'(?<=(.))ー+'
-
+ pattern = r"(?<=(.))ー+"
+
# Define a replacement function that elongates the captured character
def repl(match):
char = match.group(1) # The character before the ー sequence
@@ -394,8 +438,9 @@ def elongateCharacters(text):
# Use re.sub() to replace the pattern in the text
return re.sub(pattern, repl, text)
+
def extractTranslation(translatedTextList, is_list):
- pattern = r'`?<[Ll]ine\d+>([\\]*.*?[\\]*?)<\/?[Ll]ine\d+>`?'
+ pattern = r"`?<[Ll]ine\d+>([\\]*.*?[\\]*?)<\/?[Ll]ine\d+>`?"
# If it's a batch (i.e., list), extract with tags; otherwise, return the single item.
if is_list:
matchList = re.findall(pattern, translatedTextList)
@@ -404,11 +449,12 @@ def extractTranslation(translatedTextList, is_list):
matchList = re.findall(pattern, translatedTextList)
return matchList[0][0] if matchList else translatedTextList
+
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -420,15 +466,17 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*3)
+ outputTotalTokens += round(len(enc.encode(user)) * 3)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag, pbar):
mismatch = False
@@ -441,8 +489,12 @@ def translateGPT(text, history, fullPromptFlag, pbar):
for index, tItem in enumerate(tList):
# Before sending to translation, if we have a list of items, add the formatting
if isinstance(tItem, list):
- payload = '\n'.join([f'`{item}`' for i, item in enumerate(tItem)])
- payload = re.sub(r'(<)(\/Line\d+>)', r'\1>Placeholder Text<\3', payload)
+ payload = "\n".join(
+ [f"`{item}`" for i, item in enumerate(tItem)]
+ )
+ payload = re.sub(
+ r"(<)(\/Line\d+>)", r"\1>Placeholder Text<\3", payload
+ )
varResponse = subVars(payload)
subbedT = varResponse[0]
else:
@@ -450,7 +502,7 @@ def translateGPT(text, history, fullPromptFlag, pbar):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
continue
# Create Message
@@ -488,7 +540,7 @@ def translateGPT(text, history, fullPromptFlag, pbar):
if len(tItem) == len(extractedTranslations):
tList[index] = extractedTranslations
else:
- mismatch = True # Just here for breakpoint
+ mismatch = True # Just here for breakpoint
# Create History
history = tList[index] # Update history if we have a list
diff --git a/modules/json.py b/modules/json.py
index b67431c..d686a5f 100644
--- a/modules/json.py
+++ b/modules/json.py
@@ -16,49 +16,50 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
NOTEWIDTH = 70
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = True # Overwrites textwrap
-IGNORETLTEXT = False # Ignores all translated text.
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = False # Ignores all translated text.
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .01
- OUTPUTAPICOST = .03
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.01
+ OUTPUTAPICOST = 0.03
BATCHSIZE = 50
+
def handleJSON(filename, estimate):
global ESTIMATE, totalTokens
ESTIMATE = estimate
@@ -74,11 +75,11 @@ def handleJSON(filename, estimate):
TOKENS[0] += translatedData[1][0]
TOKENS[1] += translatedData[1][1]
- return getResultString(['', TOKENS, None], end - start, 'TOTAL')
-
+ return getResultString(["", TOKENS, None], end - start, "TOTAL")
+
else:
try:
- with open('translated/' + filename, 'w', encoding='UTF-8') as outFile:
+ with open("translated/" + filename, "w", encoding="UTF-8") as outFile:
start = time.time()
translatedData = openFiles(filename)
@@ -90,36 +91,50 @@ def handleJSON(filename, estimate):
TOKENS[0] += translatedData[1][0]
TOKENS[1] += translatedData[1][1]
except Exception:
- return 'Fail'
+ return "Fail"
+
+ return getResultString(["", TOKENS, None], end - start, "TOTAL")
- return getResultString(['', TOKENS, None], end - start, 'TOTAL')
def openFiles(filename):
- with open('files/' + filename, 'r', encoding='UTF-8-sig') as f:
+ with open("files/" + filename, "r", encoding="UTF-8-sig") as f:
data = json.load(f)
# Map Files
- if '.json' in filename:
+ if ".json" in filename:
translatedData = parseJSON(data, filename)
else:
- raise NameError(filename + ' Not Supported')
-
+ raise NameError(filename + " Not Supported")
+
return translatedData
+
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] == None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
@@ -128,18 +143,29 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
-
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
+
def parseJSON(data, filename):
totalTokens = [0, 0]
totalLines = 0
totalLines = len(data)
global LOCK
-
- with tqdm(bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE) as pbar:
- pbar.desc=filename
- pbar.total=totalLines
+
+ with tqdm(
+ bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE
+ ) as pbar:
+ pbar.desc = filename
+ pbar.total = totalLines
try:
result = translateJSON(data, pbar)
totalTokens[0] += result[0]
@@ -148,12 +174,13 @@ def parseJSON(data, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def translateJSON(data, pbar):
textHistory = []
batch = []
maxHistory = MAXHISTORY
tokens = [0, 0]
- speaker = 'None'
+ speaker = "None"
insertBool = False
i = 0
batchStartIndex = 0
@@ -161,35 +188,43 @@ def translateJSON(data, pbar):
while i < len(data):
item = data[i]
# Speaker
- if 'name' in item:
- if item['name'] not in [None, '-']:
- response = getSpeaker(item['name'])
+ if "name" in item:
+ if item["name"] not in [None, "-"]:
+ response = getSpeaker(item["name"])
speaker = response[0]
tokens[0] += response[1][0]
tokens[1] += response[1][1]
- item['name'] = speaker
+ item["name"] = speaker
else:
- speaker = 'None'
+ speaker = "None"
pbar.update(1)
i += 1
-
# Text
- elif 'me' in item:
- for text in ['text', 'text2', 'help1', 'help2', 'help3', 'like', 'message', 'me']:
+ elif "me" in item:
+ for text in [
+ "text",
+ "text2",
+ "help1",
+ "help2",
+ "help3",
+ "like",
+ "message",
+ "me",
+ ]:
if text in item:
if item[text] != None:
jaString = item[text]
# Remove any textwrap
if FIXTEXTWRAP == True:
- finalJAString = jaString.replace('\n', ' ')
+ finalJAString = jaString.replace("\n", " ")
# [Passthrough 1] Pulling From File
if insertBool is False:
# Append to List and Clear Values
batch.append(finalJAString)
- speaker = ''
+ speaker = ""
# Translate Batch if Full
if len(batch) == BATCHSIZE:
@@ -207,7 +242,7 @@ def translateJSON(data, pbar):
# Mismatch
else:
- pbar.write(f'Mismatch: {batchStartIndex} - {i}')
+ pbar.write(f"Mismatch: {batchStartIndex} - {i}")
MISMATCH.append(batch)
batchStartIndex = i
batch.clear()
@@ -215,7 +250,7 @@ def translateJSON(data, pbar):
if insertBool is False:
pbar.update(1)
i += 1
-
+
currentGroup = []
# [Passthrough 2] Setting Data
@@ -224,15 +259,15 @@ def translateJSON(data, pbar):
translatedText = translatedBatch[0]
# Remove added speaker
- translatedText = re.sub(r'^.+?:\s', '', translatedText)
+ translatedText = re.sub(r"^.+?:\s", "", translatedText)
# Textwrap
translatedText = textwrap.fill(translatedText, width=WIDTH)
-
+
# Set Text
item[text] = translatedText
translatedBatch.pop(0)
- speaker = ''
+ speaker = ""
currentGroup = []
i += 1
@@ -261,93 +296,99 @@ def translateJSON(data, pbar):
# Mismatch
else:
- pbar.write(f'Mismatch: {batchStartIndex} - {i}')
+ pbar.write(f"Mismatch: {batchStartIndex} - {i}")
MISMATCH.append(batch)
batchStartIndex = i
batch.clear()
currentGroup = []
- return tokens
+ return tokens
+
# Save some money and enter the character before translation
def getSpeaker(speaker):
match speaker:
- case 'セレナ':
- return ['Serena', [0,0]]
- case 'レナ':
- return ['Rena', [0,0]]
- case 'フィルス':
- return ['Phils', [0,0]]
- case 'レイン':
- return ['Meryl', [0,0]]
+ case "セレナ":
+ return ["Serena", [0, 0]]
+ case "レナ":
+ return ["Rena", [0, 0]]
+ case "フィルス":
+ return ["Phils", [0, 0]]
+ case "レイン":
+ return ["Meryl", [0, 0]]
case _:
- return translateGPT(speaker, 'Reply with only the '+ LANGUAGE +' translation of the NPC name.', False)
+ return translateGPT(
+ speaker,
+ "Reply with only the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Nested
count = 0
- nestedList = re.findall(r'[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]', jaString)
+ nestedList = re.findall(r"[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]", jaString)
nestedList = set(nestedList)
if len(nestedList) != 0:
for icon in nestedList:
- jaString = jaString.replace(icon, '{Nested_' + str(count) + '}')
+ jaString = jaString.replace(icon, "{Nested_" + str(count) + "}")
count += 1
# Icons
count = 0
- iconList = re.findall(r'[\\]+[iIkKwWaA]+\[[0-9]+\]', jaString)
+ iconList = re.findall(r"[\\]+[iIkKwWaA]+\[[0-9]+\]", jaString)
iconList = set(iconList)
if len(iconList) != 0:
for icon in iconList:
- jaString = jaString.replace(icon, '{Ascii_' + str(count) + '}')
+ jaString = jaString.replace(icon, "{Ascii_" + str(count) + "}")
count += 1
# Colors
count = 0
- colorList = re.findall(r'[\\]+[cC]\[[0-9]+\]', jaString)
+ colorList = re.findall(r"[\\]+[cC]\[[0-9]+\]", jaString)
colorList = set(colorList)
if len(colorList) != 0:
for color in colorList:
- jaString = jaString.replace(color, '{Color_' + str(count) + '}')
+ jaString = jaString.replace(color, "{Color_" + str(count) + "}")
count += 1
# Names
count = 0
- nameList = re.findall(r'[\\]+[nN]\[.+?\]+', jaString)
+ nameList = re.findall(r"[\\]+[nN]\[.+?\]+", jaString)
nameList = set(nameList)
if len(nameList) != 0:
for name in nameList:
- jaString = jaString.replace(name, '{Noun_' + str(count) + '}')
+ jaString = jaString.replace(name, "{Noun_" + str(count) + "}")
count += 1
# Variables
count = 0
- varList = re.findall(r'[\\]+[vV]\[[0-9]+\]', jaString)
+ varList = re.findall(r"[\\]+[vV]\[[0-9]+\]", jaString)
varList = set(varList)
if len(varList) != 0:
for var in varList:
- jaString = jaString.replace(var, '{Var_' + str(count) + '}')
+ jaString = jaString.replace(var, "{Var_" + str(count) + "}")
count += 1
# Formatting
count = 0
- formatList = re.findall(r'[\\]+[\w]+\[.+?\]', jaString)
+ formatList = re.findall(r"[\\]+[\w]+\[.+?\]", jaString)
formatList = set(formatList)
if len(formatList) != 0:
for var in formatList:
- jaString = jaString.replace(var, '{FCode_' + str(count) + '}')
+ jaString = jaString.replace(var, "{FCode_" + str(count) + "}")
count += 1
# Put all lists in list and return
allList = [nestedList, iconList, colorList, nameList, varList, formatList]
return [jaString, allList]
+
def resubVars(translatedText, allList):
# Fix Spacing and ChatGPT Nonsense
- matchList = re.findall(r'\[\s?.+?\s?\]', translatedText)
+ matchList = re.findall(r"\[\s?.+?\s?\]", translatedText)
if len(matchList) > 0:
for match in matchList:
text = match.strip()
@@ -357,54 +398,58 @@ def resubVars(translatedText, allList):
count = 0
if len(allList[0]) != 0:
for var in allList[0]:
- translatedText = translatedText.replace('{Nested_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Nested_" + str(count) + "}", var)
count += 1
# Icons
count = 0
if len(allList[1]) != 0:
for var in allList[1]:
- translatedText = translatedText.replace('{Ascii_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Ascii_" + str(count) + "}", var)
count += 1
# Colors
count = 0
if len(allList[2]) != 0:
for var in allList[2]:
- translatedText = translatedText.replace('{Color_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Color_" + str(count) + "}", var)
count += 1
# Names
count = 0
if len(allList[3]) != 0:
for var in allList[3]:
- translatedText = translatedText.replace('{Noun_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Noun_" + str(count) + "}", var)
count += 1
# Vars
count = 0
if len(allList[4]) != 0:
for var in allList[4]:
- translatedText = translatedText.replace('{Var_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Var_" + str(count) + "}", var)
count += 1
-
+
# Formatting
count = 0
if len(allList[5]) != 0:
for var in allList[5]:
- translatedText = translatedText.replace('{FCode_' + str(count) + '}', var)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
ルナリア (Lunaria) - Female\n\
ソニア (Sonia) - Female\n\
マナ (Mana) - Female\n\
@@ -419,10 +464,12 @@ def createContext(fullPromptFlag, subbedT):
ツキハ (Tsukiha) - Female\n\
フィリカ (Filica) - Female\n\
レノ (Renno) - Female\n\
-'
-
- system = PROMPT if fullPromptFlag else \
- f"\
+"
+
+ system = (
+ PROMPT
+ if fullPromptFlag
+ else f"\
You are an expert Eroge Game translator who translates Japanese text to {LANGUAGE}.\n\
You are going to be translating text from a videogame.\n\
I will give you lines of text, and you must translate each line to the best of your ability.\n\
@@ -439,9 +486,11 @@ I will give you lines of text, and you must translate each line to the best of y
- Translate 'よかった' as 'thank goodness'\n\
Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`\
"
- user = f'{subbedT}'
+ )
+ user = f"{subbedT}"
return characters, system, user
+
def translateText(characters, system, user, history):
# Prompt
msg = [{"role": "system", "content": system + characters}]
@@ -454,9 +503,9 @@ def translateText(characters, system, user, history):
msg.extend([{"role": "assistant", "content": h} for h in history])
else:
msg.append({"role": "assistant", "content": history})
-
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0.1,
frequency_penalty=0.1,
@@ -466,37 +515,44 @@ def translateText(characters, system, user, history):
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- 'Placeholder Text': ''
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "Placeholder Text": "",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
translatedText = translatedText.replace(target, replacement)
translatedText = resubVars(translatedText, varResponse[1])
- return [line for line in translatedText.split('\n') if line]
+ return [line for line in translatedText.split("\n") if line]
+
def extractTranslation(translatedTextList, is_list):
- pattern = r'`?([\\]*.*?[\\]*?)<\/?Line\d+>`?'
+ pattern = r"`?([\\]*.*?[\\]*?)<\/?Line\d+>`?"
# If it's a batch (i.e., list), extract with tags; otherwise, return the single item.
if is_list:
- return [re.findall(pattern, line)[0][1] for line in translatedTextList if re.search(pattern, line)]
+ return [
+ re.findall(pattern, line)[0][1]
+ for line in translatedTextList
+ if re.search(pattern, line)
+ ]
else:
matchList = re.findall(pattern, translatedTextList)
return matchList[0][1] if matchList else translatedTextList
+
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -508,15 +564,17 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*3)
+ outputTotalTokens += round(len(enc.encode(user)) * 3)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag):
totalTokens = [0, 0]
@@ -528,8 +586,10 @@ def translateGPT(text, history, fullPromptFlag):
for index, tItem in enumerate(tList):
# Before sending to translation, if we have a list of items, add the formatting
if isinstance(tItem, list):
- payload = '\n'.join([f'`{item}`' for i, item in enumerate(tItem)])
- payload = payload.replace('``', '`Placeholder Text`')
+ payload = "\n".join(
+ [f"`{item}`" for i, item in enumerate(tItem)]
+ )
+ payload = payload.replace("``", "`Placeholder Text`")
varResponse = subVars(payload)
subbedT = varResponse[0]
else:
@@ -537,7 +597,7 @@ def translateGPT(text, history, fullPromptFlag):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
continue
# Create Message
@@ -562,12 +622,14 @@ def translateGPT(text, history, fullPromptFlag):
extractedTranslations = extractTranslation(translatedTextList, True)
tList[index] = extractedTranslations
if len(tItem) != len(translatedTextList):
- mismatch = True # Just here so breakpoint can be set
+ mismatch = True # Just here so breakpoint can be set
history = extractedTranslations[-10:] # Update history if we have a list
else:
# Ensure we're passing a single string to extractTranslation
- extractedTranslations = extractTranslation('\n'.join(translatedTextList), False)
+ extractedTranslations = extractTranslation(
+ "\n".join(translatedTextList), False
+ )
tList[index] = extractedTranslations
finalList = combineList(tList, text)
- return [finalList, totalTokens]
\ No newline at end of file
+ return [finalList, totalTokens]
diff --git a/modules/kansen.py b/modules/kansen.py
index fb341bf..178fd3f 100644
--- a/modules/kansen.py
+++ b/modules/kansen.py
@@ -15,49 +15,50 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
NOTEWIDTH = 70
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = False # Overwrites textwrap
-IGNORETLTEXT = False # Ignores all translated text.
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = False # Ignores all translated text.
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .01
- OUTPUTAPICOST = .03
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.01
+ OUTPUTAPICOST = 0.03
BATCHSIZE = 10
+
def handleKansen(filename, estimate):
global ESTIMATE
ESTIMATE = estimate
@@ -74,17 +75,21 @@ def handleKansen(filename, estimate):
TOKENS[1] += translatedData[1][1]
# Print Total
- totalString = getResultString(['', TOKENS, None], end - start, 'TOTAL')
+ totalString = getResultString(["", TOKENS, None], end - start, "TOTAL")
# Print any errors on maps
if len(MISMATCH) > 0:
- return totalString + Fore.RED + f'\nMismatch Errors: {MISMATCH}' + Fore.RESET
+ return (
+ totalString + Fore.RED + f"\nMismatch Errors: {MISMATCH}" + Fore.RESET
+ )
else:
return totalString
-
+
else:
try:
- with open('translated/' + filename, 'w', encoding='shift_jis', errors='ignore') as outFile:
+ with open(
+ "translated/" + filename, "w", encoding="shift_jis", errors="ignore"
+ ) as outFile:
start = time.time()
translatedData = openFiles(filename)
@@ -97,23 +102,36 @@ def handleKansen(filename, estimate):
TOKENS[1] += translatedData[1][1]
except Exception:
traceback.print_exc()
- return 'Fail'
+ return "Fail"
+
+ return getResultString(["", TOKENS, None], end - start, "TOTAL")
- return getResultString(['', TOKENS, None], end - start, 'TOTAL')
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] == None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
@@ -122,33 +140,45 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
def openFiles(filename):
- with open('files/' + filename, 'r', encoding='cp932') as readFile:
+ with open("files/" + filename, "r", encoding="cp932") as readFile:
translatedData = parseTyrano(readFile, filename)
# Delete lines marked for deletion
finalData = []
for line in translatedData[0]:
- if line != '\\d\n':
+ if line != "\\d\n":
finalData.append(line)
translatedData[0] = finalData
-
+
return translatedData
+
def parseTyrano(readFile, filename):
- totalTokens = [0,0]
+ totalTokens = [0, 0]
totalLines = 0
# Get total for progress bar
data = readFile.readlines()
totalLines = len(data)
- with tqdm(bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE) as pbar:
- pbar.desc=filename
- pbar.total=totalLines
+ with tqdm(
+ bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE
+ ) as pbar:
+ pbar.desc = filename
+ pbar.total = totalLines
try:
result = translateTyrano(data, pbar, totalLines)
@@ -159,13 +189,14 @@ def parseTyrano(readFile, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def translateTyrano(data, pbar, totalLines):
textHistory = []
batch = []
currentGroup = []
maxHistory = MAXHISTORY
- tokens = [0,0]
- speaker = ''
+ tokens = [0, 0]
+ speaker = ""
insertBool = False
global LOCK, ESTIMATE
i = 0
@@ -173,108 +204,118 @@ def translateTyrano(data, pbar, totalLines):
while i < len(data):
# Speaker
- if '[ns]' in data[i]:
- matchList = re.findall(r'\[ns\](.+?)\[', data[i])
+ if "[ns]" in data[i]:
+ matchList = re.findall(r"\[ns\](.+?)\[", data[i])
if len(matchList) != 0:
response = getSpeaker(matchList[0])
speaker = response[0]
tokens[0] += response[1][0]
tokens[1] += response[1][1]
- data[i] = '[ns]' + speaker + '[nse]\n'
+ data[i] = "[ns]" + speaker + "[nse]\n"
else:
- speaker = ''
+ speaker = ""
# Choices
- elif '[sel' in data[i]:
+ elif "[sel" in data[i]:
matchList = re.findall(r'\[sel.+text="(.+?)".+', data[i])
if len(matchList) != 0:
originalText = matchList[0]
if len(textHistory) > 0:
- response = translateGPT(matchList[0], 'Keep your translation as brief as possible. Previous text for context: ' + textHistory[len(textHistory)-1] + '\n\nReply in the style of a dialogue option.', False)
+ response = translateGPT(
+ matchList[0],
+ "Keep your translation as brief as possible. Previous text for context: "
+ + textHistory[len(textHistory) - 1]
+ + "\n\nReply in the style of a dialogue option.",
+ False,
+ )
else:
- response = translateGPT(matchList[0], '\n\nReply in the style of a dialogue option.', False)
+ response = translateGPT(
+ matchList[0],
+ "\n\nReply in the style of a dialogue option.",
+ False,
+ )
translatedText = response[0]
tokens[0] += response[1][0]
tokens[1] += response[1][1]
# Remove characters that may break scripts
- charList = ['.', '\"', '\\n']
+ charList = [".", '"', "\\n"]
for char in charList:
- translatedText = translatedText.replace(char, '')
+ translatedText = translatedText.replace(char, "")
# Escape all '
- translatedText = translatedText.replace('\\', '')
+ translatedText = translatedText.replace("\\", "")
# translatedText = translatedText.replace("'", "\\\'")
# Set Data
translatedText = data[i].replace(originalText, translatedText)
- data[i] = translatedText
+ data[i] = translatedText
# Lines
- matchList = re.findall(r'(.+?)\[[rpcms_sel]+\]$', data[i])
+ matchList = re.findall(r"(.+?)\[[rpcms_sel]+\]$", data[i])
if len(matchList) > 0:
- if 'hisout' in matchList[0]:
+ if "hisout" in matchList[0]:
i += 1
continue
currentGroup.append(matchList[0])
- if len(data) > i+1:
- while '[r]' in data[i+1]:
+ if len(data) > i + 1:
+ while "[r]" in data[i + 1]:
if insertBool is True:
- data[i] = r'\d\n'
+ data[i] = r"\d\n"
pbar.update(1)
i += 1
- matchList = re.findall(r'(.+?)\[r\]', data[i])
+ matchList = re.findall(r"(.+?)\[r\]", data[i])
if len(matchList) > 0:
currentGroup.append(matchList[0])
- while '[pcms]' in data[i+1]:
+ while "[pcms]" in data[i + 1]:
if insertBool is True:
- data[i] = r'\d\n'
+ data[i] = r"\d\n"
pbar.update(1)
i += 1
- matchList = re.findall(r'(.+?)\[pcms\]', data[i])
+ matchList = re.findall(r"(.+?)\[pcms\]", data[i])
if len(matchList) > 0:
currentGroup.append(matchList[0])
- while '[pcms_sel]' in data[i+1]:
+ while "[pcms_sel]" in data[i + 1]:
if insertBool is True:
- data[i] = r'\d\n'
+ data[i] = r"\d\n"
pbar.update(1)
i += 1
- matchList = re.findall(r'(.+?)\[pcms_sel\]', data[i])
+ matchList = re.findall(r"(.+?)\[pcms_sel\]", data[i])
if len(matchList) > 0:
currentGroup.append(matchList[0])
# Join up 401 groups for better translation.
if len(currentGroup) > 0:
- finalJAString = ' '.join(currentGroup)
+ finalJAString = " ".join(currentGroup)
oldjaString = finalJAString
# Remove any textwrap
if FIXTEXTWRAP == True:
- finalJAString = finalJAString.replace('[r]', ' ')
+ finalJAString = finalJAString.replace("[r]", " ")
# Remove Extra Stuff bad for translation.
- finalJAString = finalJAString.replace('゙', '')
- finalJAString = finalJAString.replace('・', '.')
- finalJAString = finalJAString.replace('‶', '')
- finalJAString = finalJAString.replace('”', '')
- finalJAString = finalJAString.replace('―', '-')
- finalJAString = finalJAString.replace('…', '...')
- finalJAString = re.sub(r'(\.{3}\.+)', '...', finalJAString)
- finalJAString = finalJAString.replace(' ', ' ')
+ finalJAString = finalJAString.replace("゙", "")
+ finalJAString = finalJAString.replace("・", ".")
+ finalJAString = finalJAString.replace("‶", "")
+ finalJAString = finalJAString.replace("”", "")
+ finalJAString = finalJAString.replace("―", "-")
+ finalJAString = finalJAString.replace("…", "...")
+ finalJAString = re.sub(r"(\.{3}\.+)", "...", finalJAString)
+ finalJAString = finalJAString.replace(" ", " ")
# Furigana Removal
- matchList = re.findall(r'(\[ruby\stext=.+text=\"(.+)\"\])', finalJAString)
+ matchList = re.findall(r"(\[ruby\stext=.+text=\"(.+)\"\])", finalJAString)
if len(matchList) > 0:
finalJAString = finalJAString.replace(matchList[0][0], matchList[0][1])
# Add Speaker (If there is one)
- if speaker != '':
- finalJAString = f'{speaker}: {finalJAString}'
+ if speaker != "":
+ finalJAString = f"{speaker}: {finalJAString}"
# [Passthrough 1] Pulling From File
if insertBool is False:
# Append to List and Clear Values
batch.append(finalJAString)
- speaker = ''
+ speaker = ""
# Translate Batch if Full
if len(batch) == BATCHSIZE:
@@ -292,7 +333,7 @@ def translateTyrano(data, pbar, totalLines):
# Mismatch
else:
- pbar.write(f'Mismatch: {batchStartIndex} - {i}')
+ pbar.write(f"Mismatch: {batchStartIndex} - {i}")
MISMATCH.append(batch)
batchStartIndex = i
batch.clear()
@@ -306,31 +347,31 @@ def translateTyrano(data, pbar, totalLines):
else:
# Get Text
translatedText = translatedBatch[0]
- translatedText = translatedText.replace('\\"', '\"')
- translatedText = translatedText.replace('[', '(')
- translatedText = translatedText.replace(']', ')')
+ translatedText = translatedText.replace('\\"', '"')
+ translatedText = translatedText.replace("[", "(")
+ translatedText = translatedText.replace("]", ")")
# Remove added speaker
- translatedText = re.sub(r'^.+?:\s', '', translatedText)
+ translatedText = re.sub(r"^.+?:\s", "", translatedText)
# Textwrap
translatedText = textwrap.fill(translatedText, width=WIDTH)
- textList = translatedText.split('\n')
-
+ textList = translatedText.split("\n")
+
# Set Text
- data[i] = r'\d\n'
+ data[i] = r"\d\n"
for line in textList:
# Wordwrap Text
- if '[r]' not in line:
+ if "[r]" not in line:
line = textwrap.fill(line, width=WIDTH)
- line = line.replace('\n', '[r]')
-
+ line = line.replace("\n", "[r]")
+
# Set
- data.insert(i, line.strip() + '[r]\n')
- i+=1
- data[i-1] = data[i-1].replace('[r]', '[pcms]')
+ data.insert(i, line.strip() + "[r]\n")
+ i += 1
+ data[i - 1] = data[i - 1].replace("[r]", "[pcms]")
translatedBatch.pop(0)
- speaker = ''
+ speaker = ""
currentGroup = []
# If Batch is empty. Move on.
@@ -361,7 +402,7 @@ def translateTyrano(data, pbar, totalLines):
# Mismatch
else:
- pbar.write(f'Mismatch: {batchStartIndex} - {i}')
+ pbar.write(f"Mismatch: {batchStartIndex} - {i}")
MISMATCH.append(batch)
batchStartIndex = i
batch.clear()
@@ -369,92 +410,99 @@ def translateTyrano(data, pbar, totalLines):
currentGroup = []
return tokens
+
# Save some money and enter the character before translation
def getSpeaker(speaker):
match speaker:
- case '央':
- return ['Akira', [0,0]]
- case '累':
- return ['Rui', [0,0]]
- case '梨里':
- return ['Riri', [0,0]]
- case '純':
- return ['Jun', [0,0]]
- case '美鈴':
- return ['Misuzu', [0,0]]
- case '須田':
- return ['Suda', [0,0]]
- case '高橋':
- return ['Takahashi', [0,0]]
- case '勇二':
- return ['Yuuji', [0,0]]
+ case "央":
+ return ["Akira", [0, 0]]
+ case "累":
+ return ["Rui", [0, 0]]
+ case "梨里":
+ return ["Riri", [0, 0]]
+ case "純":
+ return ["Jun", [0, 0]]
+ case "美鈴":
+ return ["Misuzu", [0, 0]]
+ case "須田":
+ return ["Suda", [0, 0]]
+ case "高橋":
+ return ["Takahashi", [0, 0]]
+ case "勇二":
+ return ["Yuuji", [0, 0]]
case _:
- return translateGPT(speaker, 'Reply with only the '+ LANGUAGE +' translation of the NPC name.', False)
-
+ return translateGPT(
+ speaker,
+ "Reply with only the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
+
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Nested
count = 0
- nestedList = re.findall(r'[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]', jaString)
+ nestedList = re.findall(r"[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]", jaString)
nestedList = set(nestedList)
if len(nestedList) != 0:
for icon in nestedList:
- jaString = jaString.replace(icon, '{Nested_' + str(count) + '}')
+ jaString = jaString.replace(icon, "{Nested_" + str(count) + "}")
count += 1
# Icons
count = 0
- iconList = re.findall(r'[\\]+[iIkKwWaA]+\[[0-9]+\]', jaString)
+ iconList = re.findall(r"[\\]+[iIkKwWaA]+\[[0-9]+\]", jaString)
iconList = set(iconList)
if len(iconList) != 0:
for icon in iconList:
- jaString = jaString.replace(icon, '{Ascii_' + str(count) + '}')
+ jaString = jaString.replace(icon, "{Ascii_" + str(count) + "}")
count += 1
# Colors
count = 0
- colorList = re.findall(r'[\\]+[cC]\[[0-9]+\]', jaString)
+ colorList = re.findall(r"[\\]+[cC]\[[0-9]+\]", jaString)
colorList = set(colorList)
if len(colorList) != 0:
for color in colorList:
- jaString = jaString.replace(color, '{Color_' + str(count) + '}')
+ jaString = jaString.replace(color, "{Color_" + str(count) + "}")
count += 1
# Names
count = 0
- nameList = re.findall(r'[\\]+[nN]\[.+?\]+', jaString)
+ nameList = re.findall(r"[\\]+[nN]\[.+?\]+", jaString)
nameList = set(nameList)
if len(nameList) != 0:
for name in nameList:
- jaString = jaString.replace(name, '{Noun_' + str(count) + '}')
+ jaString = jaString.replace(name, "{Noun_" + str(count) + "}")
count += 1
# Variables
count = 0
- varList = re.findall(r'[\\]+[vV]\[[0-9]+\]', jaString)
+ varList = re.findall(r"[\\]+[vV]\[[0-9]+\]", jaString)
varList = set(varList)
if len(varList) != 0:
for var in varList:
- jaString = jaString.replace(var, '{Var_' + str(count) + '}')
+ jaString = jaString.replace(var, "{Var_" + str(count) + "}")
count += 1
# Formatting
count = 0
- formatList = re.findall(r'[\\]+[\w]+\[.+?\]', jaString)
+ formatList = re.findall(r"[\\]+[\w]+\[.+?\]", jaString)
formatList = set(formatList)
if len(formatList) != 0:
for var in formatList:
- jaString = jaString.replace(var, '{FCode_' + str(count) + '}')
+ jaString = jaString.replace(var, "{FCode_" + str(count) + "}")
count += 1
# Put all lists in list and return
allList = [nestedList, iconList, colorList, nameList, varList, formatList]
return [jaString, allList]
+
def resubVars(translatedText, allList):
# Fix Spacing and ChatGPT Nonsense
- matchList = re.findall(r'\[\s?.+?\s?\]', translatedText)
+ matchList = re.findall(r"\[\s?.+?\s?\]", translatedText)
if len(matchList) > 0:
for match in matchList:
text = match.strip()
@@ -464,54 +512,58 @@ def resubVars(translatedText, allList):
count = 0
if len(allList[0]) != 0:
for var in allList[0]:
- translatedText = translatedText.replace('{Nested_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Nested_" + str(count) + "}", var)
count += 1
# Icons
count = 0
if len(allList[1]) != 0:
for var in allList[1]:
- translatedText = translatedText.replace('{Ascii_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Ascii_" + str(count) + "}", var)
count += 1
# Colors
count = 0
if len(allList[2]) != 0:
for var in allList[2]:
- translatedText = translatedText.replace('{Color_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Color_" + str(count) + "}", var)
count += 1
# Names
count = 0
if len(allList[3]) != 0:
for var in allList[3]:
- translatedText = translatedText.replace('{Noun_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Noun_" + str(count) + "}", var)
count += 1
# Vars
count = 0
if len(allList[4]) != 0:
for var in allList[4]:
- translatedText = translatedText.replace('{Var_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Var_" + str(count) + "}", var)
count += 1
-
+
# Formatting
count = 0
if len(allList[5]) != 0:
for var in allList[5]:
- translatedText = translatedText.replace('{FCode_' + str(count) + '}', var)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
渋江 央 (Shibue Akira) - Male\n\
蘆名 累 (Ashina Rui) - Female\n\
清原 梨里 (Kiyohara Riri) - Female\n\
@@ -520,19 +572,23 @@ def createContext(fullPromptFlag, subbedT):
須田 (Suda) - Male\n\
高橋 (Takahashi) - Female\n\
勇二 (Yuuji) - Male\n\
-'
-
- system = PROMPT + VOCAB if fullPromptFlag else \
- f"\
+"
+
+ system = (
+ PROMPT + VOCAB
+ if fullPromptFlag
+ else f"\
You are an expert Eroge Game translator who translates Japanese text to {LANGUAGE}.\n\
You are going to be translating text from a videogame.\n\
I will give you lines of text, and you must translate each line to the best of your ability.\n\
{VOCAB}\n\
Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`\
"
- user = f'{subbedT}'
+ )
+ user = f"{subbedT}"
return characters, system, user
+
def translateText(characters, system, user, history):
# Prompt
msg = [{"role": "system", "content": system + characters}]
@@ -545,9 +601,9 @@ def translateText(characters, system, user, history):
msg.extend([{"role": "system", "content": h} for h in history])
else:
msg.append({"role": "system", "content": history})
-
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0.1,
frequency_penalty=0.1,
@@ -557,37 +613,44 @@ def translateText(characters, system, user, history):
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- 'Placeholder Text': ''
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "Placeholder Text": "",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
translatedText = translatedText.replace(target, replacement)
translatedText = resubVars(translatedText, varResponse[1])
- return [line for line in translatedText.replace('\\n', '\n').split('\n') if line]
+ return [line for line in translatedText.replace("\\n", "\n").split("\n") if line]
+
def extractTranslation(translatedTextList, is_list):
- pattern = r'`?([\\]*.*?[\\]*?)<\/?Line\d+>`?'
+ pattern = r"`?([\\]*.*?[\\]*?)<\/?Line\d+>`?"
# If it's a batch (i.e., list), extract with tags; otherwise, return the single item.
if is_list:
- return [re.findall(pattern, line)[0][1] for line in translatedTextList if re.search(pattern, line)]
+ return [
+ re.findall(pattern, line)[0][1]
+ for line in translatedTextList
+ if re.search(pattern, line)
+ ]
else:
matchList = re.findall(pattern, translatedTextList)
return matchList[0][1] if matchList else translatedTextList
+
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -599,15 +662,17 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*3)
+ outputTotalTokens += round(len(enc.encode(user)) * 3)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag):
totalTokens = [0, 0]
@@ -619,8 +684,10 @@ def translateGPT(text, history, fullPromptFlag):
for index, tItem in enumerate(tList):
# Before sending to translation, if we have a list of items, add the formatting
if isinstance(tItem, list):
- payload = '\n'.join([f'`{item}`' for i, item in enumerate(tItem)])
- payload = payload.replace('``', '`Placeholder Text`')
+ payload = "\n".join(
+ [f"`{item}`" for i, item in enumerate(tItem)]
+ )
+ payload = payload.replace("``", "`Placeholder Text`")
varResponse = subVars(payload)
subbedT = varResponse[0]
else:
@@ -628,7 +695,7 @@ def translateGPT(text, history, fullPromptFlag):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
continue
# Create Message
@@ -653,11 +720,13 @@ def translateGPT(text, history, fullPromptFlag):
extractedTranslations = extractTranslation(translatedTextList, True)
tList[index] = extractedTranslations
if len(tItem) != len(translatedTextList):
- mismatch = True # Just here so breakpoint can be set
+ mismatch = True # Just here so breakpoint can be set
history = extractedTranslations[-10:] # Update history if we have a list
else:
# Ensure we're passing a single string to extractTranslation
- extractedTranslations = extractTranslation('\n'.join(translatedTextList), False)
+ extractedTranslations = extractTranslation(
+ "\n".join(translatedTextList), False
+ )
tList[index] = extractedTranslations
finalList = combineList(tList, text)
diff --git a/modules/lune.py b/modules/lune.py
index 879e839..ede0654 100644
--- a/modules/lune.py
+++ b/modules/lune.py
@@ -16,49 +16,50 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
NOTEWIDTH = 70
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = True # Overwrites textwrap
-IGNORETLTEXT = False # Ignores all translated text.
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = False # Ignores all translated text.
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .01
- OUTPUTAPICOST = .03
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.01
+ OUTPUTAPICOST = 0.03
BATCHSIZE = 50
+
def handleLune(filename, estimate):
global ESTIMATE, totalTokens
ESTIMATE = estimate
@@ -74,11 +75,11 @@ def handleLune(filename, estimate):
TOKENS[0] += translatedData[1][0]
TOKENS[1] += translatedData[1][1]
- return getResultString(['', TOKENS, None], end - start, 'TOTAL')
-
+ return getResultString(["", TOKENS, None], end - start, "TOTAL")
+
else:
try:
- with open('translated/' + filename, 'w', encoding='UTF-8') as outFile:
+ with open("translated/" + filename, "w", encoding="UTF-8") as outFile:
start = time.time()
translatedData = openFiles(filename)
@@ -90,36 +91,50 @@ def handleLune(filename, estimate):
TOKENS[0] += translatedData[1][0]
TOKENS[1] += translatedData[1][1]
except Exception:
- return 'Fail'
+ return "Fail"
+
+ return getResultString(["", TOKENS, None], end - start, "TOTAL")
- return getResultString(['', TOKENS, None], end - start, 'TOTAL')
def openFiles(filename):
- with open('files/' + filename, 'r', encoding='UTF-8-sig') as f:
+ with open("files/" + filename, "r", encoding="UTF-8-sig") as f:
data = json.load(f)
# Map Files
- if '.json' in filename:
+ if ".json" in filename:
translatedData = parseJSON(data, filename)
else:
- raise NameError(filename + ' Not Supported')
-
+ raise NameError(filename + " Not Supported")
+
return translatedData
+
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] == None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
@@ -128,18 +143,29 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
-
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
+
def parseJSON(data, filename):
totalTokens = [0, 0]
totalLines = 0
totalLines = len(data)
global LOCK
-
- with tqdm(bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE) as pbar:
- pbar.desc=filename
- pbar.total=totalLines
+
+ with tqdm(
+ bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE
+ ) as pbar:
+ pbar.desc = filename
+ pbar.total = totalLines
try:
result = translateJSON(data, pbar)
totalTokens[0] += result[0]
@@ -148,12 +174,13 @@ def parseJSON(data, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def translateJSON(data, pbar):
textHistory = []
batch = []
maxHistory = MAXHISTORY
tokens = [0, 0]
- speaker = 'None'
+ speaker = "None"
insertBool = False
i = 0
batchStartIndex = 0
@@ -161,32 +188,41 @@ def translateJSON(data, pbar):
while i < len(data):
item = data[i]
# Speaker
- if 'name' in item:
- if item['name'] not in [None, '-']:
- response = getSpeaker(item['name'])
+ if "name" in item:
+ if item["name"] not in [None, "-"]:
+ response = getSpeaker(item["name"])
speaker = response[0]
tokens[0] += response[1][0]
tokens[1] += response[1][1]
- item['name'] = speaker
+ item["name"] = speaker
else:
- speaker = 'None'
+ speaker = "None"
# Text
- if 'message' in item:
- for text in ['text', 'text2', 'help1', 'help2', 'help3', 'like', 'message', 'me']:
+ if "message" in item:
+ for text in [
+ "text",
+ "text2",
+ "help1",
+ "help2",
+ "help3",
+ "like",
+ "message",
+ "me",
+ ]:
if text in item:
if item[text] != None:
jaString = item[text]
# Remove any textwrap
if FIXTEXTWRAP == True:
- finalJAString = jaString.replace('\n', ' ')
+ finalJAString = jaString.replace("\n", " ")
# [Passthrough 1] Pulling From File
if insertBool is False:
# Append to List and Clear Values
batch.append(finalJAString)
- speaker = ''
+ speaker = ""
# Translate Batch if Full
if len(batch) == BATCHSIZE:
@@ -204,7 +240,7 @@ def translateJSON(data, pbar):
# Mismatch
else:
- pbar.write(f'Mismatch: {batchStartIndex} - {i}')
+ pbar.write(f"Mismatch: {batchStartIndex} - {i}")
MISMATCH.append(batch)
batchStartIndex = i
batch.clear()
@@ -212,7 +248,7 @@ def translateJSON(data, pbar):
if insertBool is False:
pbar.update(1)
i += 1
-
+
currentGroup = []
# [Passthrough 2] Setting Data
@@ -221,15 +257,15 @@ def translateJSON(data, pbar):
translatedText = translatedBatch[0]
# Remove added speaker
- translatedText = re.sub(r'^.+?:\s', '', translatedText)
+ translatedText = re.sub(r"^.+?:\s", "", translatedText)
# Textwrap
translatedText = textwrap.fill(translatedText, width=WIDTH)
-
+
# Set Text
item[text] = translatedText
translatedBatch.pop(0)
- speaker = ''
+ speaker = ""
currentGroup = []
i += 1
@@ -258,92 +294,99 @@ def translateJSON(data, pbar):
# Mismatch
else:
- pbar.write(f'Mismatch: {batchStartIndex} - {i}')
+ pbar.write(f"Mismatch: {batchStartIndex} - {i}")
MISMATCH.append(batch)
batchStartIndex = i
batch.clear()
currentGroup = []
- return tokens
+ return tokens
+
# Save some money and enter the character before translation
def getSpeaker(speaker):
match speaker:
- case 'セレナ':
- return ['Serena', [0,0]]
- case 'レナ':
- return ['Rena', [0,0]]
- case 'フィルス':
- return ['Phils', [0,0]]
- case 'レイン':
- return ['Meryl', [0,0]]
+ case "セレナ":
+ return ["Serena", [0, 0]]
+ case "レナ":
+ return ["Rena", [0, 0]]
+ case "フィルス":
+ return ["Phils", [0, 0]]
+ case "レイン":
+ return ["Meryl", [0, 0]]
case _:
- return translateGPT(speaker, 'Reply with only the '+ LANGUAGE +' translation of the NPC name.', False)
+ return translateGPT(
+ speaker,
+ "Reply with only the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Nested
count = 0
- nestedList = re.findall(r'[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]', jaString)
+ nestedList = re.findall(r"[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]", jaString)
nestedList = set(nestedList)
if len(nestedList) != 0:
for icon in nestedList:
- jaString = jaString.replace(icon, '{Nested_' + str(count) + '}')
+ jaString = jaString.replace(icon, "{Nested_" + str(count) + "}")
count += 1
# Icons
count = 0
- iconList = re.findall(r'[\\]+[iIkKwWaA]+\[[0-9]+\]', jaString)
+ iconList = re.findall(r"[\\]+[iIkKwWaA]+\[[0-9]+\]", jaString)
iconList = set(iconList)
if len(iconList) != 0:
for icon in iconList:
- jaString = jaString.replace(icon, '{Ascii_' + str(count) + '}')
+ jaString = jaString.replace(icon, "{Ascii_" + str(count) + "}")
count += 1
# Colors
count = 0
- colorList = re.findall(r'[\\]+[cC]\[[0-9]+\]', jaString)
+ colorList = re.findall(r"[\\]+[cC]\[[0-9]+\]", jaString)
colorList = set(colorList)
if len(colorList) != 0:
for color in colorList:
- jaString = jaString.replace(color, '{Color_' + str(count) + '}')
+ jaString = jaString.replace(color, "{Color_" + str(count) + "}")
count += 1
# Names
count = 0
- nameList = re.findall(r'[\\]+[nN]\[.+?\]+', jaString)
+ nameList = re.findall(r"[\\]+[nN]\[.+?\]+", jaString)
nameList = set(nameList)
if len(nameList) != 0:
for name in nameList:
- jaString = jaString.replace(name, '{Noun_' + str(count) + '}')
+ jaString = jaString.replace(name, "{Noun_" + str(count) + "}")
count += 1
# Variables
count = 0
- varList = re.findall(r'[\\]+[vV]\[[0-9]+\]', jaString)
+ varList = re.findall(r"[\\]+[vV]\[[0-9]+\]", jaString)
varList = set(varList)
if len(varList) != 0:
for var in varList:
- jaString = jaString.replace(var, '{Var_' + str(count) + '}')
+ jaString = jaString.replace(var, "{Var_" + str(count) + "}")
count += 1
# Formatting
count = 0
- formatList = re.findall(r'[\\]+[\w]+\[.+?\]', jaString)
+ formatList = re.findall(r"[\\]+[\w]+\[.+?\]", jaString)
formatList = set(formatList)
if len(formatList) != 0:
for var in formatList:
- jaString = jaString.replace(var, '{FCode_' + str(count) + '}')
+ jaString = jaString.replace(var, "{FCode_" + str(count) + "}")
count += 1
# Put all lists in list and return
allList = [nestedList, iconList, colorList, nameList, varList, formatList]
return [jaString, allList]
+
def resubVars(translatedText, allList):
# Fix Spacing and ChatGPT Nonsense
- matchList = re.findall(r'\[\s?.+?\s?\]', translatedText)
+ matchList = re.findall(r"\[\s?.+?\s?\]", translatedText)
if len(matchList) > 0:
for match in matchList:
text = match.strip()
@@ -353,54 +396,58 @@ def resubVars(translatedText, allList):
count = 0
if len(allList[0]) != 0:
for var in allList[0]:
- translatedText = translatedText.replace('{Nested_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Nested_" + str(count) + "}", var)
count += 1
# Icons
count = 0
if len(allList[1]) != 0:
for var in allList[1]:
- translatedText = translatedText.replace('{Ascii_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Ascii_" + str(count) + "}", var)
count += 1
# Colors
count = 0
if len(allList[2]) != 0:
for var in allList[2]:
- translatedText = translatedText.replace('{Color_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Color_" + str(count) + "}", var)
count += 1
# Names
count = 0
if len(allList[3]) != 0:
for var in allList[3]:
- translatedText = translatedText.replace('{Noun_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Noun_" + str(count) + "}", var)
count += 1
# Vars
count = 0
if len(allList[4]) != 0:
for var in allList[4]:
- translatedText = translatedText.replace('{Var_' + str(count) + '}', var)
+ translatedText = translatedText.replace("{Var_" + str(count) + "}", var)
count += 1
-
+
# Formatting
count = 0
if len(allList[5]) != 0:
for var in allList[5]:
- translatedText = translatedText.replace('{FCode_' + str(count) + '}', var)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
林つかさ (Tsukasa Hayashi) - Female\n\
山田美兎 (Miyato Yamada) - Female\n\
鈴木赤音 (Akane Suzuki) - Female\n\
@@ -413,13 +460,17 @@ def createContext(fullPromptFlag, subbedT):
モリー・ボイド (Molly Boyd) - Female\n\
オルガ・ブヤチッチ (Olga Buyachich) - Female\n\
アッチャラー ギッティ (Atchara Gitti) - Female\n\
-'
-
- system = PROMPT if fullPromptFlag else \
- f'Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`'
- user = f'{subbedT}'
+"
+
+ system = (
+ PROMPT
+ if fullPromptFlag
+ else f"Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`"
+ )
+ user = f"{subbedT}"
return characters, system, user
+
def translateText(characters, system, user, history):
# Prompt
msg = [{"role": "system", "content": system + characters}]
@@ -432,9 +483,9 @@ def translateText(characters, system, user, history):
msg.extend([{"role": "assistant", "content": h} for h in history])
else:
msg.append({"role": "assistant", "content": history})
-
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0.1,
frequency_penalty=0.1,
@@ -443,40 +494,47 @@ def translateText(characters, system, user, history):
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- 'Placeholder Text': ''
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "Placeholder Text": "",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
translatedText = translatedText.replace(target, replacement)
translatedText = resubVars(translatedText, varResponse[1])
- if '\n' in translatedText:
- return [line for line in translatedText.split('\n') if line]
+ if "\n" in translatedText:
+ return [line for line in translatedText.split("\n") if line]
else:
- return [line for line in translatedText.split('\\n') if line]
+ return [line for line in translatedText.split("\\n") if line]
+
def extractTranslation(translatedTextList, is_list):
- pattern = r'[\\]*`?(.*?)[\\]*?`??Line\d+>'
+ pattern = r"[\\]*`?(.*?)[\\]*?`??Line\d+>"
# If it's a batch (i.e., list), extract with tags; otherwise, return the single item.
if is_list:
- return [re.findall(pattern, line)[0][1] for line in translatedTextList if re.search(pattern, line)]
+ return [
+ re.findall(pattern, line)[0][1]
+ for line in translatedTextList
+ if re.search(pattern, line)
+ ]
else:
matchList = re.findall(pattern, translatedTextList)
return matchList[0][1] if matchList else translatedTextList
+
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -488,15 +546,17 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*3)
+ outputTotalTokens += round(len(enc.encode(user)) * 3)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag):
totalTokens = [0, 0]
@@ -508,8 +568,10 @@ def translateGPT(text, history, fullPromptFlag):
for index, tItem in enumerate(tList):
# Before sending to translation, if we have a list of items, add the formatting
if isinstance(tItem, list):
- payload = '\n'.join([f'`{item}`' for i, item in enumerate(tItem)])
- payload = payload.replace('``', '`Placeholder Text`')
+ payload = "\n".join(
+ [f"`{item}`" for i, item in enumerate(tItem)]
+ )
+ payload = payload.replace("``", "`Placeholder Text`")
varResponse = subVars(payload)
subbedT = varResponse[0]
else:
@@ -517,7 +579,7 @@ def translateGPT(text, history, fullPromptFlag):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
continue
# Create Message
@@ -542,11 +604,13 @@ def translateGPT(text, history, fullPromptFlag):
extractedTranslations = extractTranslation(translatedTextList, True)
tList[index] = extractedTranslations
if len(tItem) != len(translatedTextList):
- mismatch = True # Just here so breakpoint can be set
+ mismatch = True # Just here so breakpoint can be set
history = extractedTranslations[-10:] # Update history if we have a list
else:
# Ensure we're passing a single string to extractTranslation
- extractedTranslations = extractTranslation('\n'.join(translatedTextList), False)
+ extractedTranslations = extractTranslation(
+ "\n".join(translatedTextList), False
+ )
tList[index] = extractedTranslations
finalList = combineList(tList, text)
diff --git a/modules/main.py b/modules/main.py
index 934f007..5bbd029 100644
--- a/modules/main.py
+++ b/modules/main.py
@@ -10,13 +10,27 @@ from dotenv import load_dotenv
# upon import, in which case if they are unset the script will crash before we can output these messages.
envMissing = False
load_dotenv()
-for env in ['api','key','organization','model','language','timeout','fileThreads','threads','width','listWidth']:
- if os.getenv(env) is None or str(os.getenv(env))[:1] == '<':
- tqdm.write(Fore.RED + f'Environment variable {env} is not set!')
+for env in [
+ "api",
+ "key",
+ "organization",
+ "model",
+ "language",
+ "timeout",
+ "fileThreads",
+ "threads",
+ "width",
+ "listWidth",
+]:
+ if os.getenv(env) is None or str(os.getenv(env))[:1] == "<":
+ tqdm.write(Fore.RED + f"Environment variable {env} is not set!")
envMissing = True
if envMissing:
- tqdm.write(Fore.RED + 'Some of the required environment values may not be set correctly. You can set \
-these values using an .env file, for an example see .env.example')
+ tqdm.write(
+ Fore.RED
+ + "Some of the required environment values may not be set correctly. You can set \
+these values using an .env file, for an example see .env.example"
+ )
from modules.rpgmakermvmz import handleMVMZ
from modules.rpgmakerace import handleACE
@@ -40,7 +54,7 @@ from modules.rpgmakerplugin import handlePlugin
# For GPT4 rate limit will be hit if you have more than 1 thread.
# 1 Thread for each file. Controls how many files are worked on at once.
-THREADS = int(os.getenv('fileThreads'))
+THREADS = int(os.getenv("fileThreads"))
# [Display name, file extension, handle function]
MODULES = [
@@ -66,59 +80,76 @@ MODULES = [
]
# Info Message
-tqdm.write(Fore.LIGHTYELLOW_EX + "WARNING: Once the translation starts do not close it unless you want to lose your \
+tqdm.write(
+ Fore.LIGHTYELLOW_EX
+ + "WARNING: Once the translation starts do not close it unless you want to lose your \
translated data. If a file fails or gets stuck, translated lines will remain translated so you don't have \
to worry about being charged twice. You can simply copy the file generated in /translations back over to \
-/files and start the script again. It will skip over any translated text." + Fore.RESET, end='\n\n')
+/files and start the script again. It will skip over any translated text."
+ + Fore.RESET,
+ end="\n\n",
+)
+
def main():
- estimate = ''
- while estimate == '':
- estimate = input('Select Translation or Cost Estimation:\n\n 1. Translate\n 2. Estimate\n')
+ estimate = ""
+ while estimate == "":
+ estimate = input(
+ "Select Translation or Cost Estimation:\n\n 1. Translate\n 2. Estimate\n"
+ )
match estimate:
- case '1':
+ case "1":
estimate = False
- case '2':
+ case "2":
estimate = True
case _:
- estimate = ''
-
- version = ''
+ estimate = ""
+
+ version = ""
while True:
tqdm.write("Select game engine:\n")
for position, module in enumerate(MODULES):
- tqdm.write(f'{str(position + 1).rjust(2)}. {module[0]} (.{module[1]})')
+ tqdm.write(f"{str(position + 1).rjust(2)}. {module[0]} (.{module[1]})")
version = input()
try:
version = int(version) - 1
except:
continue
if version in range(len(MODULES)):
- break
+ break
- totalCost = Fore.RED + 'Translation module didn\'t return the total cost. Make sure the \
-files to translate are in the /files folder and that you picked the right game engine.'
+ totalCost = (
+ Fore.RED
+ + "Translation module didn't return the total cost. Make sure the \
+files to translate are in the /files folder and that you picked the right game engine."
+ )
# Open File (Threads)
with ThreadPoolExecutor(max_workers=THREADS) as executor:
- futures = [executor.submit(MODULES[version][2], filename, estimate) \
- for filename in os.listdir("files") if filename.endswith(MODULES[version][1]) and filename != '.gitkeep']
+ futures = [
+ executor.submit(MODULES[version][2], filename, estimate)
+ for filename in os.listdir("files")
+ if filename.endswith(MODULES[version][1]) and filename != ".gitkeep"
+ ]
for future in as_completed(futures):
try:
totalCost = future.result()
except Exception as e:
- tracebackLineNo = str(traceback.extract_tb(sys.exc_info()[2])[-1].lineno)
- tqdm.write(Fore.RED + str(e) + '|' + tracebackLineNo + Fore.RESET)
+ tracebackLineNo = str(
+ traceback.extract_tb(sys.exc_info()[2])[-1].lineno
+ )
+ tqdm.write(Fore.RED + str(e) + "|" + tracebackLineNo + Fore.RESET)
- if totalCost != 'Fail':
+ if totalCost != "Fail":
if estimate is False:
# This is to encourage people to grab what's in /translated instead
- deleteFolderFiles('files')
+ deleteFolderFiles("files")
tqdm.write(str(totalCost))
+
def deleteFolderFiles(folderPath):
for filename in os.listdir(folderPath):
file_path = os.path.join(folderPath, filename)
- if file_path.endswith(('.json', '.yaml', '.ks')):
- os.remove(file_path)
+ if file_path.endswith((".json", ".yaml", ".ks")):
+ os.remove(file_path)
diff --git a/modules/nscript.py b/modules/nscript.py
index c22b700..2643b70 100644
--- a/modules/nscript.py
+++ b/modules/nscript.py
@@ -16,57 +16,58 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
NOTEWIDTH = 70
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = True # Overwrites textwrap
-IGNORETLTEXT = False # Ignores all translated text.
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = False # Ignores all translated text.
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
PBAR = None
FILENAME = None
# Full Width
-ascii_to_wide = dict((i, chr(i + 0xfee0)) for i in range(0x21, 0x7f))
-ascii_to_wide.update({0x20: u'\u3000', 0x2D: u'\u2212'}) # space and minus
-wide_to_ascii = dict((i, chr(i - 0xfee0)) for i in range(0xff01, 0xff5f))
-wide_to_ascii.update({0x3000: u' ', 0x2212: u'-'}) # space and minus
+ascii_to_wide = dict((i, chr(i + 0xFEE0)) for i in range(0x21, 0x7F))
+ascii_to_wide.update({0x20: "\u3000", 0x2D: "\u2212"}) # space and minus
+wide_to_ascii = dict((i, chr(i - 0xFEE0)) for i in range(0xFF01, 0xFF5F))
+wide_to_ascii.update({0x3000: " ", 0x2212: "-"}) # space and minus
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .005
- OUTPUTAPICOST = .015
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.005
+ OUTPUTAPICOST = 0.015
BATCHSIZE = 40
+
def handleOnscripter(filename, estimate):
global ESTIMATE, FILENAME
ESTIMATE = estimate
@@ -84,17 +85,21 @@ def handleOnscripter(filename, estimate):
TOKENS[1] += translatedData[1][1]
# Print Total
- totalString = getResultString(['', TOKENS, None], end - start, 'TOTAL')
+ totalString = getResultString(["", TOKENS, None], end - start, "TOTAL")
# Print any errors on maps
if len(MISMATCH) > 0:
- return totalString + Fore.RED + f'\nMismatch Errors: {MISMATCH}' + Fore.RESET
+ return (
+ totalString + Fore.RED + f"\nMismatch Errors: {MISMATCH}" + Fore.RESET
+ )
else:
return totalString
-
+
else:
try:
- with open('translated/' + filename, 'w', encoding='cp932', errors='ignore') as outFile:
+ with open(
+ "translated/" + filename, "w", encoding="cp932", errors="ignore"
+ ) as outFile:
start = time.time()
translatedData = openFiles(filename)
@@ -107,23 +112,36 @@ def handleOnscripter(filename, estimate):
TOKENS[1] += translatedData[1][1]
except Exception:
traceback.print_exc()
- return 'Fail'
+ return "Fail"
+
+ return getResultString(["", TOKENS, None], end - start, "TOTAL")
- return getResultString(['', TOKENS, None], end - start, 'TOTAL')
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] == None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
@@ -132,31 +150,41 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
def openFiles(filename):
- with open('files/' + filename, 'r', encoding='cp932') as readFile:
+ with open("files/" + filename, "r", encoding="cp932") as readFile:
translatedData = parseOnscripter(readFile, filename)
# Delete lines marked for deletion
finalData = []
for line in translatedData[0]:
- if line != '\\d\n':
+ if line != "\\d\n":
finalData.append(line)
translatedData[0] = finalData
-
+
return translatedData
+
def parseOnscripter(readFile, filename):
- totalTokens = [0,0]
+ totalTokens = [0, 0]
# Read File into data
data = readFile.readlines()
# Create Progress Bar
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
try:
result = translateOnscripter(data, pbar, filename, [])
@@ -167,11 +195,12 @@ def parseOnscripter(readFile, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def translateOnscripter(data, pbar, filename, translatedList):
stringList = []
currentGroup = []
- tokens = [0,0]
- speaker = ''
+ tokens = [0, 0]
+ speaker = ""
voice = False
global LOCK, ESTIMATE, PBAR
PBAR = pbar
@@ -180,38 +209,38 @@ def translateOnscripter(data, pbar, filename, translatedList):
# Dialogue
while i < len(data):
# Lines
- regex = r'^([\u3000「(【[][^\n]+)'
+ regex = r"^([\u3000「(【[][^\n]+)"
match = re.search(regex, data[i])
- if match != None and match.group(1) != '':
+ if match != None and match.group(1) != "":
originalString = match.group(1)
# Pass 1
if translatedList == []:
# Grab Consecutive Strings
jaString = match.group(1)
- while len(data) > i+1 and re.match(regex, data[i+1]):
- data[i] = ''
+ while len(data) > i + 1 and re.match(regex, data[i + 1]):
+ data[i] = ""
i += 1
- jaString = f'{jaString} {data[i]}'
+ jaString = f"{jaString} {data[i]}"
# Convert from Wide
jaString = jaString.translate(wide_to_ascii)
-
+
# Remove any textwrap and \u3000 and \
- jaString = jaString.replace('\n', '')
- jaString = jaString.replace('\u3000', '')
- jaString = jaString.replace('\\', '')
- jaString = jaString.replace(' >', ')')
- jaString = jaString.replace('< ', '(')
+ jaString = jaString.replace("\n", "")
+ jaString = jaString.replace("\u3000", "")
+ jaString = jaString.replace("\\", "")
+ jaString = jaString.replace(" >", ")")
+ jaString = jaString.replace("< ", "(")
# Remove Furigana
- furiMatch = re.findall(r'({(.+?)\/(.+?)})', jaString)
+ furiMatch = re.findall(r"({(.+?)\/(.+?)})", jaString)
if furiMatch:
for match in furiMatch:
jaString = jaString.replace(match[0], match[2])
# Add String
stringList.append(jaString.strip())
-
+
# Pass 2
else:
# Get Text
@@ -226,24 +255,24 @@ def translateOnscripter(data, pbar, filename, translatedList):
# Textwrap & Other Text
translatedText = textwrap.fill(translatedText, width=WIDTH)
- translatedText = translatedText.replace('\n', '\n\u3000')
+ translatedText = translatedText.replace("\n", "\n\u3000")
# Split the string into lines
- lines = translatedText.split('\n')
-
+ lines = translatedText.split("\n")
+
# Add a backslash after every 3rd line
j = 0
while j < len(lines):
if j == 4:
- lines[j-1] = f'{lines[j-1]}\\'
- lines[j] = f'\n{lines[j]}'
+ lines[j - 1] = f"{lines[j-1]}\\"
+ lines[j] = f"\n{lines[j]}"
j += 1
-
+
# Join the lines back into a single string
- translatedText = '\n'.join(lines)
+ translatedText = "\n".join(lines)
# Remove Double Spaces
- translatedText = translatedText.replace(' ', ' ')
+ translatedText = translatedText.replace(" ", " ")
# Convert to Wide
translatedText = translatedText.translate(ascii_to_wide)
@@ -252,18 +281,20 @@ def translateOnscripter(data, pbar, filename, translatedList):
translatedText = fixText(translatedText)
# Set Data
- data[i] = data[i].replace(originalString, f'{translatedText}')
+ data[i] = data[i].replace(originalString, f"{translatedText}")
i += 1
# Choices
- elif 'csel' in data[i] and translatedList != []:
+ elif "csel" in data[i] and translatedList != []:
choiceList = []
jaString = data[i]
- choiceList = re.findall(r'\"(.*?)\"', jaString)
+ choiceList = re.findall(r"\"(.*?)\"", jaString)
if len(choiceList) > 0:
# Translate
- response = translateGPT(choiceList, 'This will be a dialogue option', True)
+ response = translateGPT(
+ choiceList, "This will be a dialogue option", True
+ )
translatedTextList = response[0]
tokens[0] += response[1][0]
tokens[1] += response[1][1]
@@ -286,9 +317,9 @@ def translateOnscripter(data, pbar, filename, translatedList):
# Set Progress
pbar.total = len(stringList)
pbar.refresh()
-
+
# Translate
- response = translateGPT(stringList, '', True)
+ response = translateGPT(stringList, "", True)
tokens[0] += response[1][0]
tokens[1] += response[1][1]
translatedList = response[0]
@@ -304,54 +335,72 @@ def translateOnscripter(data, pbar, filename, translatedList):
MISMATCH.append(filename)
return tokens
+
def fixText(translatedText):
# Add Break
- translatedText = translatedText.replace('\"', '\'')
- translatedText = f'\u3000{translatedText}\\'
+ translatedText = translatedText.replace('"', "'")
+ translatedText = f"\u3000{translatedText}\\"
# Unconvert Codes
- matchList = re.findall(r'([$].+?)[^\w]', translatedText)
+ matchList = re.findall(r"([$].+?)[^\w]", translatedText)
if matchList:
for match in matchList:
- translatedText = translatedText.replace(match, match.translate(wide_to_ascii))
+ translatedText = translatedText.replace(
+ match, match.translate(wide_to_ascii)
+ )
# Unconvert Color Codes
- matchList = re.findall(r'([#][\w\d]{6})', translatedText)
+ matchList = re.findall(r"([#][\w\d]{6})", translatedText)
if matchList:
for match in matchList:
- translatedText = translatedText.replace(match, match.translate(wide_to_ascii))
+ translatedText = translatedText.replace(
+ match, match.translate(wide_to_ascii)
+ )
# Unconvert Variables
- matchList = re.findall(r'([%]\w.+?)[^\w_]', translatedText)
+ matchList = re.findall(r"([%]\w.+?)[^\w_]", translatedText)
if matchList:
for match in matchList:
- translatedText = translatedText.replace(match, match.translate(wide_to_ascii))
+ translatedText = translatedText.replace(
+ match, match.translate(wide_to_ascii)
+ )
# Unconvert Backslashes
- matchList = re.findall(r'\', translatedText)
+ matchList = re.findall(r"\", translatedText)
if matchList:
for match in matchList:
- translatedText = translatedText.replace(match, match.translate(wide_to_ascii))
+ translatedText = translatedText.replace(
+ match, match.translate(wide_to_ascii)
+ )
return translatedText
+
# Save some money and enter the character before translation
def getSpeaker(speaker):
match speaker:
- case 'ファイン':
- return ['Fine', [0,0]]
- case '':
- return ['', [0,0]]
+ case "ファイン":
+ return ["Fine", [0, 0]]
+ case "":
+ return ["", [0, 0]]
case _:
# Store Speaker
if speaker not in str(NAMESLIST):
- response = translateGPT(speaker, 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ response = translateGPT(
+ speaker,
+ "Reply with the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
response[0] = response[0].replace("'S", "'s")
# Retry if name doesn't translate for some reason
- if re.search(r'([a-zA-Z??])', response[0]) == None:
- response = translateGPT(speaker, 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ if re.search(r"([a-zA-Z??])", response[0]) == None:
+ response = translateGPT(
+ speaker,
+ "Reply with the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
response[0] = response[0].replace("'S", "'s")
@@ -362,74 +411,76 @@ def getSpeaker(speaker):
else:
for i in range(len(NAMESLIST)):
if speaker == NAMESLIST[i][0]:
- return [NAMESLIST[i][1],[0,0]]
-
- return [speaker,[0,0]]
+ return [NAMESLIST[i][1], [0, 0]]
+
+ return [speaker, [0, 0]]
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Nested
count = 0
- nestedList = re.findall(r'[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]', jaString)
+ nestedList = re.findall(r"[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]", jaString)
nestedList = set(nestedList)
if len(nestedList) != 0:
for icon in nestedList:
- jaString = jaString.replace(icon, '[Nested_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Nested_" + str(count) + "]")
count += 1
# Icons
count = 0
- iconList = re.findall(r'[\\]+[iIkKwWaA]+\[[0-9]+\]', jaString)
+ iconList = re.findall(r"[\\]+[iIkKwWaA]+\[[0-9]+\]", jaString)
iconList = set(iconList)
if len(iconList) != 0:
for icon in iconList:
- jaString = jaString.replace(icon, '[Ascii_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Ascii_" + str(count) + "]")
count += 1
# Colors
count = 0
- colorList = re.findall(r'([\\]+c\[\d+\][\\]+c|[\\]+c\[\d+\])', jaString)
+ colorList = re.findall(r"([\\]+c\[\d+\][\\]+c|[\\]+c\[\d+\])", jaString)
colorList = set(colorList)
if len(colorList) != 0:
for color in colorList:
- jaString = jaString.replace(color, '[Color_' + str(count) + ']')
+ jaString = jaString.replace(color, "[Color_" + str(count) + "]")
count += 1
# Names
count = 0
- nameList = re.findall(r'[\\]+[nN]\[.+?\]+', jaString)
+ nameList = re.findall(r"[\\]+[nN]\[.+?\]+", jaString)
nameList = set(nameList)
if len(nameList) != 0:
for name in nameList:
- jaString = jaString.replace(name, '[Noun_' + str(count) + ']')
+ jaString = jaString.replace(name, "[Noun_" + str(count) + "]")
count += 1
# Variables
count = 0
- varList = re.findall(r'[\\]+[vV]\[[0-9]+\]', jaString)
+ varList = re.findall(r"[\\]+[vV]\[[0-9]+\]", jaString)
varList = set(varList)
if len(varList) != 0:
for var in varList:
- jaString = jaString.replace(var, '[Var_' + str(count) + ']')
+ jaString = jaString.replace(var, "[Var_" + str(count) + "]")
count += 1
# Formatting
count = 0
- formatList = re.findall(r'[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
+ formatList = re.findall(r"[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]", jaString)
formatList = set(formatList)
if len(formatList) != 0:
for var in formatList:
- jaString = jaString.replace(var, '[FCode_' + str(count) + ']')
+ jaString = jaString.replace(var, "[FCode_" + str(count) + "]")
count += 1
# Put all lists in list and return
allList = [nestedList, iconList, colorList, nameList, varList, formatList]
return [jaString, allList]
+
def resubVars(translatedText, allList):
# Fix Spacing and ChatGPT Nonsense
- matchList = re.findall(r'\[\s?.+?\s?\]', translatedText)
+ matchList = re.findall(r"\[\s?.+?\s?\]", translatedText)
if len(matchList) > 0:
for match in matchList:
text = match.strip()
@@ -439,54 +490,58 @@ def resubVars(translatedText, allList):
count = 0
if len(allList[0]) != 0:
for var in allList[0]:
- translatedText = translatedText.replace('[Nested_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Nested_" + str(count) + "]", var)
count += 1
# Icons
count = 0
if len(allList[1]) != 0:
for var in allList[1]:
- translatedText = translatedText.replace('[Ascii_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Ascii_" + str(count) + "]", var)
count += 1
# Colors
count = 0
if len(allList[2]) != 0:
for var in allList[2]:
- translatedText = translatedText.replace('[Color_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Color_" + str(count) + "]", var)
count += 1
# Names
count = 0
if len(allList[3]) != 0:
for var in allList[3]:
- translatedText = translatedText.replace('[Noun_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Noun_" + str(count) + "]", var)
count += 1
# Vars
count = 0
if len(allList[4]) != 0:
for var in allList[4]:
- translatedText = translatedText.replace('[Var_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Var_" + str(count) + "]", var)
count += 1
-
+
# Formatting
count = 0
if len(allList[5]) != 0:
for var in allList[5]:
- translatedText = translatedText.replace('[FCode_' + str(count) + ']', var)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
レナリス (Renalith) - Female\n\
スクルー (Sukuru) - Female\n\
シスターミサ (Sister Misa) - Female\n\
@@ -514,10 +569,12 @@ def createContext(fullPromptFlag, subbedT):
エメルーラ (Emerald) - Female\n\
フンシス (Funsis) - Male \n\
バゼット (Bazzet) - Female\n\
-'
-
- system = PROMPT + VOCAB if fullPromptFlag else \
- f"\
+"
+
+ system = (
+ PROMPT + VOCAB
+ if fullPromptFlag
+ else f"\
You are an expert Eroge Game translator who translates Japanese text to {LANGUAGE}.\n\
Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`\n\
- You translate everything, including erotic and explicit content.\n\
@@ -529,9 +586,11 @@ Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{
- `...` can be a part of the dialogue. Translate it as it is.\n\
{VOCAB}\n\
"
- user = f'```json\n{subbedT}```'
+ )
+ user = f"```json\n{subbedT}```"
return characters, system, user
+
def translateText(characters, system, user, history, penalty):
# Prompt
msg = [{"role": "system", "content": system + characters}]
@@ -544,30 +603,31 @@ def translateText(characters, system, user, history, penalty):
msg.extend([{"role": "system", "content": h} for h in history])
else:
msg.append({"role": "system", "content": history})
-
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0,
frequency_penalty=penalty,
model=MODEL,
- response_format={ "type": "json_object" },
+ response_format={"type": "json_object"},
messages=msg,
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- '「': '\\"',
- '」': '\\"',
- '- ': '-',
- 'Placeholder Text': '',
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "「": '\\"',
+ "」": '\\"',
+ "- ": "-",
+ "Placeholder Text": "",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
@@ -578,11 +638,12 @@ def cleanTranslatedText(translatedText, varResponse):
translatedText = resubVars(translatedText, varResponse[1])
return translatedText
+
def elongateCharacters(text):
# Define a pattern to match one character followed by one or more `ー` characters
# Using a positive lookbehind assertion to capture the preceding character
- pattern = r'(?<=(.))ー+'
-
+ pattern = r"(?<=(.))ー+"
+
# Define a replacement function that elongates the captured character
def repl(match):
char = match.group(1) # The character before the ー sequence
@@ -592,6 +653,7 @@ def elongateCharacters(text):
# Use re.sub() to replace the pattern in the text
return re.sub(pattern, repl, text)
+
def extractTranslation(translatedTextList, is_list):
try:
line_dict = json.loads(translatedTextList)
@@ -603,11 +665,12 @@ def extractTranslation(translatedTextList, is_list):
print(e)
return translatedTextList
+
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -619,19 +682,21 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*3)
+ outputTotalTokens += round(len(enc.encode(user)) * 3)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag):
global PBAR
-
+
mismatch = False
totalTokens = [0, 0]
if isinstance(text, list):
@@ -651,7 +716,7 @@ def translateGPT(text, history, fullPromptFlag):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
if PBAR is not None:
PBAR.update(len(tItem))
continue
@@ -688,12 +753,14 @@ def translateGPT(text, history, fullPromptFlag):
if isinstance(tItem, list):
extractedTranslations = extractTranslation(translatedText, True)
if len(tItem) != len(extractedTranslations):
- mismatch = True # Just here for breakpoint
-
+ mismatch = True # Just here for breakpoint
+
# Set if no mismatch
if mismatch == False:
tList[index] = extractedTranslations
- history = extractedTranslations[-10:] # Update history if we have a list
+ history = extractedTranslations[
+ -10:
+ ] # Update history if we have a list
else:
history = text[-10:]
mismatch = False
diff --git a/modules/regex.py b/modules/regex.py
index 0dccff4..376f100 100644
--- a/modules/regex.py
+++ b/modules/regex.py
@@ -15,49 +15,50 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
NOTEWIDTH = 70
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = True # Overwrites textwrap
-IGNORETLTEXT = False # Ignores all translated text.
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = False # Ignores all translated text.
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .005
- OUTPUTAPICOST = .015
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.005
+ OUTPUTAPICOST = 0.015
BATCHSIZE = 40
+
def handleRegex(filename, estimate):
global ESTIMATE
ESTIMATE = estimate
@@ -74,17 +75,21 @@ def handleRegex(filename, estimate):
TOKENS[1] += translatedData[1][1]
# Print Total
- totalString = getResultString(['', TOKENS, None], end - start, 'TOTAL')
+ totalString = getResultString(["", TOKENS, None], end - start, "TOTAL")
# Print any errors on maps
if len(MISMATCH) > 0:
- return totalString + Fore.RED + f'\nMismatch Errors: {MISMATCH}' + Fore.RESET
+ return (
+ totalString + Fore.RED + f"\nMismatch Errors: {MISMATCH}" + Fore.RESET
+ )
else:
return totalString
-
+
else:
try:
- with open('translated/' + filename, 'w', encoding='cp932', errors='ignore') as outFile:
+ with open(
+ "translated/" + filename, "w", encoding="cp932", errors="ignore"
+ ) as outFile:
start = time.time()
translatedData = openFiles(filename)
@@ -97,23 +102,36 @@ def handleRegex(filename, estimate):
TOKENS[1] += translatedData[1][1]
except Exception:
traceback.print_exc()
- return 'Fail'
+ return "Fail"
+
+ return getResultString(["", TOKENS, None], end - start, "TOTAL")
- return getResultString(['', TOKENS, None], end - start, 'TOTAL')
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] == None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
@@ -122,31 +140,41 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
def openFiles(filename):
- with open('files/' + filename, 'r', encoding='shift_jis') as readFile:
+ with open("files/" + filename, "r", encoding="shift_jis") as readFile:
translatedData = parseRegex(readFile, filename)
# Delete lines marked for deletion
finalData = []
for line in translatedData[0]:
- if line != '\\d\n':
+ if line != "\\d\n":
finalData.append(line)
translatedData[0] = finalData
-
+
return translatedData
+
def parseRegex(readFile, filename):
- totalTokens = [0,0]
+ totalTokens = [0, 0]
# Read File into data
data = readFile.readlines()
# Create Progress Bar
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
try:
result = translateRegex(data, pbar, filename, [])
@@ -157,36 +185,37 @@ def parseRegex(readFile, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def translateRegex(data, pbar, filename, translatedList):
stringList = []
currentGroup = []
- tokens = [0,0]
- speaker = ''
+ tokens = [0, 0]
+ speaker = ""
voice = False
global LOCK, ESTIMATE
i = 0
while i < len(data):
voice = False
- speaker = ''
- if 'actorID' in data[i]:
+ speaker = ""
+ if "actorID" in data[i]:
# Lines
- match = re.search(r'label[\\]+\":[\\]+\"(.*?)\"', data[i])
+ match = re.search(r"label[\\]+\":[\\]+\"(.*?)\"", data[i])
if match == None:
- match = re.search(r'label[\\]+\":[\\]+\"(.*?)\"', data[i])
- if match != None and match.group(1) != '':
+ match = re.search(r"label[\\]+\":[\\]+\"(.*?)\"", data[i])
+ if match != None and match.group(1) != "":
originalString = match.group(1)
# Pass 1
if translatedList == []:
# Grab Consecutive Strings
jaString = match.group(1)
-
+
# Remove any textwrap
- jaString = jaString.replace('\n', ' ')
+ jaString = jaString.replace("\n", " ")
# Add String
stringList.append(jaString.strip())
-
+
# Pass 2
else:
# Get Text
@@ -217,9 +246,15 @@ def translateRegex(data, pbar, filename, translatedList):
# Set Progress
pbar.total = len(stringList)
pbar.refresh()
-
+
# Translate
- response = translateGPT(stringList, 'Reply with the English TL of the NPC Name', True, pbar, filename)
+ response = translateGPT(
+ stringList,
+ "Reply with the English TL of the NPC Name",
+ True,
+ pbar,
+ filename,
+ )
tokens[0] += response[1][0]
tokens[1] += response[1][1]
translatedList = response[0]
@@ -235,94 +270,103 @@ def translateRegex(data, pbar, filename, translatedList):
MISMATCH.append(filename)
return tokens
+
# Save some money and enter the character before translation
def getSpeaker(speaker, pbar, filename):
match speaker:
- case 'ファイン':
- return ['Fine', [0,0]]
- case '':
- return ['', [0,0]]
+ case "ファイン":
+ return ["Fine", [0, 0]]
+ case "":
+ return ["", [0, 0]]
case _:
# Store Speaker
if speaker not in str(NAMESLIST):
- response = translateGPT(speaker, 'Reply with only the '+ LANGUAGE +' translation of the NPC name.', False, pbar, filename)
+ response = translateGPT(
+ speaker,
+ "Reply with only the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ pbar,
+ filename,
+ )
response[0] = response[0].replace("'S", "'s")
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]]
-
- return [speaker,[0,0]]
+ return [NAMESLIST[i][1], [0, 0]]
+
+ return [speaker, [0, 0]]
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Nested
count = 0
- nestedList = re.findall(r'[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]', jaString)
+ nestedList = re.findall(r"[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]", jaString)
nestedList = set(nestedList)
if len(nestedList) != 0:
for icon in nestedList:
- jaString = jaString.replace(icon, '[Nested_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Nested_" + str(count) + "]")
count += 1
# Icons
count = 0
- iconList = re.findall(r'[\\]+[iIkKwWaA]+\[[0-9]+\]', jaString)
+ iconList = re.findall(r"[\\]+[iIkKwWaA]+\[[0-9]+\]", jaString)
iconList = set(iconList)
if len(iconList) != 0:
for icon in iconList:
- jaString = jaString.replace(icon, '[Ascii_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Ascii_" + str(count) + "]")
count += 1
# Colors
count = 0
- colorList = re.findall(r'[\\]+[cC]\[[0-9]+\]', jaString)
+ colorList = re.findall(r"[\\]+[cC]\[[0-9]+\]", jaString)
colorList = set(colorList)
if len(colorList) != 0:
for color in colorList:
- jaString = jaString.replace(color, '[Color_' + str(count) + ']')
+ jaString = jaString.replace(color, "[Color_" + str(count) + "]")
count += 1
# Names
count = 0
- nameList = re.findall(r'[\\]+[nN]\[.+?\]+', jaString)
+ nameList = re.findall(r"[\\]+[nN]\[.+?\]+", jaString)
nameList = set(nameList)
if len(nameList) != 0:
for name in nameList:
- jaString = jaString.replace(name, '[Noun_' + str(count) + ']')
+ jaString = jaString.replace(name, "[Noun_" + str(count) + "]")
count += 1
# Variables
count = 0
- varList = re.findall(r'[\\]+[vV]\[[0-9]+\]', jaString)
+ varList = re.findall(r"[\\]+[vV]\[[0-9]+\]", jaString)
varList = set(varList)
if len(varList) != 0:
for var in varList:
- jaString = jaString.replace(var, '[Var_' + str(count) + ']')
+ jaString = jaString.replace(var, "[Var_" + str(count) + "]")
count += 1
# Formatting
count = 0
- formatList = re.findall(r'[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
+ formatList = re.findall(r"[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]", jaString)
formatList = set(formatList)
if len(formatList) != 0:
for var in formatList:
- jaString = jaString.replace(var, '[FCode_' + str(count) + ']')
+ jaString = jaString.replace(var, "[FCode_" + str(count) + "]")
count += 1
# Put all lists in list and return
allList = [nestedList, iconList, colorList, nameList, varList, formatList]
return [jaString, allList]
+
def resubVars(translatedText, allList):
# Fix Spacing and ChatGPT Nonsense
- matchList = re.findall(r'\[\s?.+?\s?\]', translatedText)
+ matchList = re.findall(r"\[\s?.+?\s?\]", translatedText)
if len(matchList) > 0:
for match in matchList:
text = match.strip()
@@ -332,54 +376,58 @@ def resubVars(translatedText, allList):
count = 0
if len(allList[0]) != 0:
for var in allList[0]:
- translatedText = translatedText.replace('[Nested_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Nested_" + str(count) + "]", var)
count += 1
# Icons
count = 0
if len(allList[1]) != 0:
for var in allList[1]:
- translatedText = translatedText.replace('[Ascii_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Ascii_" + str(count) + "]", var)
count += 1
# Colors
count = 0
if len(allList[2]) != 0:
for var in allList[2]:
- translatedText = translatedText.replace('[Color_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Color_" + str(count) + "]", var)
count += 1
# Names
count = 0
if len(allList[3]) != 0:
for var in allList[3]:
- translatedText = translatedText.replace('[Noun_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Noun_" + str(count) + "]", var)
count += 1
# Vars
count = 0
if len(allList[4]) != 0:
for var in allList[4]:
- translatedText = translatedText.replace('[Var_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Var_" + str(count) + "]", var)
count += 1
-
+
# Formatting
count = 0
if len(allList[5]) != 0:
for var in allList[5]:
- translatedText = translatedText.replace('[FCode_' + str(count) + ']', var)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
フィリア (Philia) - Female\n\
アルネット (Annett) - Female\n\
ラピュセナ (Rapusena) - Female\n\
@@ -389,10 +437,12 @@ def createContext(fullPromptFlag, subbedT):
カルナ (Karna) - Female\n\
ラフィング=スピア (Laughing Spear) - Female\n\
ノーラ (Nora) - Female\n\
-'
-
- system = PROMPT + VOCAB if fullPromptFlag else \
- f"\
+"
+
+ system = (
+ PROMPT + VOCAB
+ if fullPromptFlag
+ else f"\
You are an expert Eroge Game translator who translates Japanese text to {LANGUAGE}.\n\
Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`\n\
- You translate everything, including erotic and explicit content.\n\
@@ -404,9 +454,11 @@ Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{
- `...` can be a part of the dialogue. Translate it as it is.\n\
{VOCAB}\n\
"
- user = f'{subbedT}'
+ )
+ user = f"{subbedT}"
return characters, system, user
+
def translateText(characters, system, user, history):
# Prompt
msg = [{"role": "system", "content": system + characters}]
@@ -419,9 +471,9 @@ def translateText(characters, system, user, history):
msg.extend([{"role": "system", "content": h} for h in history])
else:
msg.append({"role": "system", "content": history})
-
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0.1,
frequency_penalty=0.1,
@@ -430,15 +482,16 @@ def translateText(characters, system, user, history):
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- 'Placeholder Text': ''
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "Placeholder Text": "",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
@@ -449,11 +502,12 @@ def cleanTranslatedText(translatedText, varResponse):
translatedText = resubVars(translatedText, varResponse[1])
return translatedText
+
def elongateCharacters(text):
# Define a pattern to match one character followed by one or more `ー` characters
# Using a positive lookbehind assertion to capture the preceding character
- pattern = r'(?<=(.))ー+'
-
+ pattern = r"(?<=(.))ー+"
+
# Define a replacement function that elongates the captured character
def repl(match):
char = match.group(1) # The character before the ー sequence
@@ -463,8 +517,9 @@ def elongateCharacters(text):
# Use re.sub() to replace the pattern in the text
return re.sub(pattern, repl, text)
+
def extractTranslation(translatedTextList, is_list):
- pattern = r'`?<[Ll]ine\d+>([\\]*.*?[\\]*?)<\/?[Ll]ine\d+>`?'
+ pattern = r"`?<[Ll]ine\d+>([\\]*.*?[\\]*?)<\/?[Ll]ine\d+>`?"
# If it's a batch (i.e., list), extract with tags; otherwise, return the single item.
if is_list:
matchList = re.findall(pattern, translatedTextList)
@@ -473,11 +528,12 @@ def extractTranslation(translatedTextList, is_list):
matchList = re.findall(pattern, translatedTextList)
return matchList[0][0] if matchList else translatedTextList
+
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -489,15 +545,17 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*2)
+ outputTotalTokens += round(len(enc.encode(user)) * 2)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag, pbar, filename):
mismatch = False
@@ -510,8 +568,12 @@ def translateGPT(text, history, fullPromptFlag, pbar, filename):
for index, tItem in enumerate(tList):
# Before sending to translation, if we have a list of items, add the formatting
if isinstance(tItem, list):
- payload = '\n'.join([f'`{item}`' for i, item in enumerate(tItem)])
- payload = re.sub(r'(<)(\/Line\d+>)', r'\1>Placeholder Text<\3', payload)
+ payload = "\n".join(
+ [f"`{item}`" for i, item in enumerate(tItem)]
+ )
+ payload = re.sub(
+ r"(<)(\/Line\d+>)", r"\1>Placeholder Text<\3", payload
+ )
varResponse = subVars(payload)
subbedT = varResponse[0]
else:
@@ -519,7 +581,7 @@ def translateGPT(text, history, fullPromptFlag, pbar, filename):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
continue
# Create Message
diff --git a/modules/rpgmakerace.py b/modules/rpgmakerace.py
index dc5275e..610ef25 100644
--- a/modules/rpgmakerace.py
+++ b/modules/rpgmakerace.py
@@ -19,32 +19,32 @@ from ruamel.yaml import YAML
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
-NOTEWIDTH = int(os.getenv('noteWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
+NOTEWIDTH = int(os.getenv("noteWidth"))
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-FIRSTLINESPEAKERS = True # If 1st line of dialogue is a speaker, set to True
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+FIRSTLINESPEAKERS = True # If 1st line of dialogue is a speaker, set to True
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = True # Overwrites textwrap
-IGNORETLTEXT = False # Ignores all translated text.
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = False # Ignores all translated text.
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
BRACKETNAMES = False
PBAR = None
FILENAME = None
@@ -52,19 +52,19 @@ FILENAME = None
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
FREQUENCY_PENALTY = 0.2
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .0025
- OUTPUTAPICOST = .01
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.0025
+ OUTPUTAPICOST = 0.01
BATCHSIZE = 20
FREQUENCY_PENALTY = 0.1
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
@@ -92,6 +92,7 @@ CODE324 = False
CODE111 = False
CODE108 = False
+
def handleACE(filename, estimate):
global ESTIMATE, TOKENS, FILENAME
ESTIMATE = estimate
@@ -100,19 +101,19 @@ def handleACE(filename, estimate):
# Translate
start = time.time()
translatedData = openFiles(filename)
-
+
# Translate
if not estimate:
try:
- with open('translated/' + filename, 'w', encoding='utf-8') as outFile:
- yaml=YAML(pure=True)
+ with open("translated/" + filename, "w", encoding="utf-8") as outFile:
+ yaml = YAML(pure=True)
yaml.width = 4096
yaml.default_style = "'"
yaml.dump(translatedData[0], outFile)
except Exception:
traceback.print_exc()
- return 'Fail'
-
+ return "Fail"
+
# Print File
end = time.time()
tqdm.write(getResultString(translatedData, end - start, filename))
@@ -121,108 +122,122 @@ def handleACE(filename, estimate):
TOKENS[1] += translatedData[1][1]
# Print Total
- totalString = getResultString(['', TOKENS, None], end - start, 'TOTAL')
+ totalString = getResultString(["", TOKENS, None], end - start, "TOTAL")
# Print any errors on maps
if len(MISMATCH) > 0:
- return totalString + Fore.RED + f'\nMismatch Errors: {MISMATCH}' + Fore.RESET
+ return totalString + Fore.RED + f"\nMismatch Errors: {MISMATCH}" + Fore.RESET
else:
return totalString
+
def openFiles(filename):
- yaml=YAML(pure=True) # Need a yaml instance per thread.
+ yaml = YAML(pure=True) # Need a yaml instance per thread.
yaml.width = 4096
yaml.default_style = "'"
- with open('files/' + filename, 'r', encoding='UTF-8') as f:
+ with open("files/" + filename, "r", encoding="UTF-8") as f:
# Map Files
- if 'Map' in filename and filename != 'MapInfos.json':
+ if "Map" in filename and filename != "MapInfos.json":
data = yaml.load(f)
translatedData = parseMap(data, filename)
# CommonEvents Files
- elif 'CommonEvents' in filename:
+ elif "CommonEvents" in filename:
data = yaml.load(f)
translatedData = parseCommonEvents(data, filename)
# Actor File
- elif 'Actors' in filename:
+ elif "Actors" in filename:
data = yaml.load(f)
- translatedData = parseNames(data, filename, 'Actors')
+ translatedData = parseNames(data, filename, "Actors")
# Armor File
- elif 'Armors' in filename:
+ elif "Armors" in filename:
data = yaml.load(f)
- translatedData = parseNames(data, filename, 'Armors')
+ translatedData = parseNames(data, filename, "Armors")
# Weapons File
- elif 'Weapons' in filename:
+ elif "Weapons" in filename:
data = yaml.load(f)
- translatedData = parseNames(data, filename, 'Weapons')
-
+ translatedData = parseNames(data, filename, "Weapons")
+
# Classes File
- elif 'Classes' in filename:
+ elif "Classes" in filename:
data = yaml.load(f)
- translatedData = parseNames(data, filename, 'Classes')
+ translatedData = parseNames(data, filename, "Classes")
# Enemies File
- elif 'Enemies' in filename:
+ elif "Enemies" in filename:
data = yaml.load(f)
- translatedData = parseNames(data, filename, 'Enemies')
+ translatedData = parseNames(data, filename, "Enemies")
# Items File
- elif 'Items' in filename:
+ elif "Items" in filename:
data = yaml.load(f)
- translatedData = parseNames(data, filename, 'Items')
+ translatedData = parseNames(data, filename, "Items")
# MapInfo File
- elif 'MapInfos' in filename:
+ elif "MapInfos" in filename:
data = yaml.load(f)
- translatedData = parseNames(data, filename, 'MapInfos')
+ translatedData = parseNames(data, filename, "MapInfos")
# Skills File
- elif 'Skills' in filename:
+ elif "Skills" in filename:
data = yaml.load(f)
- translatedData = parseNames(data, filename, 'Skills')
+ translatedData = parseNames(data, filename, "Skills")
# Troops File
- elif 'Troops' in filename:
+ elif "Troops" in filename:
data = yaml.load(f)
translatedData = parseTroops(data, filename)
# States File
- elif 'States' in filename:
+ elif "States" in filename:
data = yaml.load(f)
translatedData = parseSS(data, filename)
# System File
- elif 'System' in filename:
+ elif "System" in filename:
data = yaml.load(f)
translatedData = parseSystem(data, filename)
# Scenario File
- elif 'Scenario' in filename:
+ elif "Scenario" in filename:
data = yaml.load(f)
translatedData = parseScenario(data, filename)
else:
- raise NameError(filename + ' Not Supported')
-
+ raise NameError(filename + " Not Supported")
+
return translatedData
+
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] is None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
try:
@@ -230,29 +245,46 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
def parseMap(data, filename):
totalTokens = [0, 0]
totalLines = 0
- events = data['events']
+ events = data["events"]
global LOCK
# Translate displayName for Map files
- if 'Map' in filename:
- response = translateGPT(data['display_name'], 'Reply with only the '+ LANGUAGE +' translation of the RPG location name', False)
+ if "Map" in filename:
+ response = translateGPT(
+ data["display_name"],
+ "Reply with only the " + LANGUAGE + " translation of the RPG location name",
+ False,
+ )
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
- data['display_name'] = response[0].replace('\"', '')
-
+ data["display_name"] = response[0].replace('"', "")
+
# Thread for each page in file
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
with ThreadPoolExecutor(max_workers=THREADS) as executor:
for key in events:
if key is not None:
- futures = [executor.submit(searchCodes, page, pbar, [], filename) for page in events[key]['pages'] if page is not None]
+ futures = [
+ executor.submit(searchCodes, page, pbar, [], filename)
+ for page in events[key]["pages"]
+ if page is not None
+ ]
for future in as_completed(futures):
try:
totalTokensFuture = future.result()
@@ -263,53 +295,64 @@ def parseMap(data, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def translateNote(event, regex):
# Regex String
- jaString = event['note']
+ jaString = event["note"]
match = re.findall(regex, jaString, re.DOTALL)
if match:
- tokens = [0,0]
+ tokens = [0, 0]
i = 0
while i < len(match):
initialJAString = match[i]
# Remove any textwrap
- modifiedJAString = initialJAString.replace('\n', ' ')
+ modifiedJAString = initialJAString.replace("\n", " ")
# Translate
- response = translateGPT(modifiedJAString, 'Reply with only the '+ LANGUAGE +' translation.', False)
+ response = translateGPT(
+ modifiedJAString,
+ "Reply with only the " + LANGUAGE + " translation.",
+ False,
+ )
translatedText = response[0]
tokens[0] += response[1][0]
tokens[1] += response[1][1]
# Textwrap
translatedText = textwrap.fill(translatedText, width=NOTEWIDTH)
- translatedText = translatedText.replace('\"', '')
+ translatedText = translatedText.replace('"', "")
jaString = jaString.replace(initialJAString, translatedText)
- event['note'] = jaString
+ event["note"] = jaString
i += 1
return tokens
- return [0,0]
+ return [0, 0]
+
# For notes that can't have spaces.
def translateNoteOmitSpace(event, regex):
# Regex that only matches text inside LB.
- jaString = event['note']
+ jaString = event["note"]
match = re.findall(regex, jaString, re.DOTALL)
if match:
oldJAString = match[0]
# Remove any textwrap
- jaString = re.sub(r'\n', ' ', oldJAString)
+ jaString = re.sub(r"\n", " ", oldJAString)
# Translate
- response = translateGPT(jaString, 'Reply with the '+ LANGUAGE +' translation of the location name.', False)
+ response = translateGPT(
+ jaString,
+ "Reply with the " + LANGUAGE + " translation of the location name.",
+ False,
+ )
translatedText = response[0]
- translatedText = translatedText.replace('\"', '')
- translatedText = translatedText.replace(' ', '_')
- event['note'] = event['note'].replace(oldJAString, translatedText)
+ translatedText = translatedText.replace('"', "")
+ translatedText = translatedText.replace(" ", "_")
+ event["note"] = event["note"].replace(oldJAString, translatedText)
return response[1]
- return [0,0]
+ return [0, 0]
+
def parseCommonEvents(data, filename):
totalTokens = [0, 0]
@@ -319,12 +362,16 @@ def parseCommonEvents(data, filename):
# Get total for progress bar
for page in data:
if page is not None:
- totalLines += len(page['list'])
+ totalLines += len(page["list"])
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
with ThreadPoolExecutor(max_workers=THREADS) as executor:
- futures = [executor.submit(searchCodes, page, pbar, [], filename) for page in data if page is not None]
+ futures = [
+ executor.submit(searchCodes, page, pbar, [], filename)
+ for page in data
+ if page is not None
+ ]
for future in as_completed(futures):
try:
totalTokensFuture = future.result()
@@ -335,6 +382,7 @@ def parseCommonEvents(data, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def parseTroops(data, filename):
totalTokens = [0, 0]
totalLines = 0
@@ -343,15 +391,21 @@ def parseTroops(data, filename):
# Get total for progress bar
for troop in data:
if troop is not None:
- for page in troop['pages']:
- totalLines += len(page['list']) + 1 # The +1 is because each page has a name.
+ for page in troop["pages"]:
+ totalLines += (
+ len(page["list"]) + 1
+ ) # The +1 is because each page has a name.
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
for troop in data:
if troop is not None:
with ThreadPoolExecutor(max_workers=THREADS) as executor:
- futures = [executor.submit(searchCodes, page, pbar, [], filename) for page in troop['pages'] if page is not None]
+ futures = [
+ executor.submit(searchCodes, page, pbar, [], filename)
+ for page in troop["pages"]
+ if page is not None
+ ]
for future in as_completed(futures):
try:
totalTokensFuture = future.result()
@@ -361,59 +415,17 @@ def parseTroops(data, filename):
traceback.print_exc()
return [data, totalTokens, e]
return [data, totalTokens, None]
-
+
+
def parseNames(data, filename, context):
totalTokens = [0, 0]
totalLines = 0
totalLines += len(data)
-
- with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
- try:
- result = searchNames(data, pbar, context)
- totalTokens[0] += result[0]
- totalTokens[1] += result[1]
- except Exception as e:
- traceback.print_exc()
- return [data, totalTokens, e]
- return [data, totalTokens, None]
-def parseSS(data, filename):
- totalTokens = [0, 0]
- totalLines = 0
- totalLines += len(data)
-
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
- for ss in data:
- if ss is not None:
- try:
- result = searchSS(ss, pbar)
- totalTokens[0] += result[0]
- totalTokens[1] += result[1]
- except Exception as e:
- traceback.print_exc()
- return [data, totalTokens, e]
- return [data, totalTokens, None]
-
-def parseSystem(data, filename):
- totalTokens = [0, 0]
- totalLines = 0
-
- # Calculate Total Lines
- for term in data['terms']:
- termList = data['terms'][term]
- totalLines += len(termList)
- totalLines += len(data['game_title'])
- totalLines += len(data['variables'])
- totalLines += len(data['weapon_types'])
- totalLines += len(data['armor_types'])
- totalLines += len(data['skill_types'])
-
- with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
try:
- result = searchSystem(data, pbar)
+ result = searchNames(data, pbar, context)
totalTokens[0] += result[0]
totalTokens[1] += result[1]
except Exception as e:
@@ -421,6 +433,52 @@ def parseSystem(data, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
+def parseSS(data, filename):
+ totalTokens = [0, 0]
+ totalLines = 0
+ totalLines += len(data)
+
+ with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
+ pbar.desc = filename
+ for ss in data:
+ if ss is not None:
+ try:
+ result = searchSS(ss, pbar)
+ totalTokens[0] += result[0]
+ totalTokens[1] += result[1]
+ except Exception as e:
+ traceback.print_exc()
+ return [data, totalTokens, e]
+ return [data, totalTokens, None]
+
+
+def parseSystem(data, filename):
+ totalTokens = [0, 0]
+ totalLines = 0
+
+ # Calculate Total Lines
+ for term in data["terms"]:
+ termList = data["terms"][term]
+ totalLines += len(termList)
+ totalLines += len(data["game_title"])
+ totalLines += len(data["variables"])
+ totalLines += len(data["weapon_types"])
+ totalLines += len(data["armor_types"])
+ totalLines += len(data["skill_types"])
+
+ with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
+ pbar.desc = filename
+ try:
+ result = searchSystem(data, pbar)
+ totalTokens[0] += result[0]
+ totalTokens[1] += result[1]
+ except Exception as e:
+ traceback.print_exc()
+ return [data, totalTokens, e]
+ return [data, totalTokens, None]
+
+
def parseScenario(data, filename):
totalTokens = [0, 0]
totalLines = 0
@@ -431,9 +489,13 @@ def parseScenario(data, filename):
totalLines += len(page[1])
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
with ThreadPoolExecutor(max_workers=THREADS) as executor:
- futures = [executor.submit(searchCodes, page[1], pbar, [], filename) for page in data.items() if page[1] is not None]
+ futures = [
+ executor.submit(searchCodes, page[1], pbar, [], filename)
+ for page in data.items()
+ if page[1] is not None
+ ]
for future in as_completed(futures):
try:
totalTokensFuture = future.result()
@@ -444,6 +506,7 @@ def parseScenario(data, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def searchNames(data, pbar, context):
totalTokens = [0, 0]
nameList = []
@@ -451,139 +514,175 @@ def searchNames(data, pbar, context):
nicknameList = []
descriptionList = []
noteList = []
- i = 0 # Counter
- j = 0 # Counter 2
+ i = 0 # Counter
+ j = 0 # Counter 2
filling = False
mismatch = False
batchFull = False
# Set the context of what we are translating
- if 'Actors' in context:
- newContext = 'Reply with only the '+ LANGUAGE +' translation of the NPC name'
- if 'Armors' in context:
- newContext = 'Reply with only the '+ LANGUAGE +' translation of the RPG equipment name'
- if 'Classes' in context:
- newContext = 'Reply with only the '+ LANGUAGE +' translation of the RPG class name'
- if 'MapInfos' in context:
- newContext = 'Reply with only the '+ LANGUAGE +' translation of the location name'
- if 'Enemies' in context:
- newContext = 'Reply with only the '+ LANGUAGE +' translation of the enemy NPC name'
- if 'Weapons' in context:
- newContext = 'Reply with only the '+ LANGUAGE +' translation of the RPG weapon name'
- if 'Items' in context:
- newContext = 'Reply with only the '+ LANGUAGE +' translation of the RPG item name'
- if 'Skills' in context:
- newContext = 'Reply with only the '+ LANGUAGE +' translation of the RPG skill name'
+ if "Actors" in context:
+ newContext = "Reply with only the " + LANGUAGE + " translation of the NPC name"
+ if "Armors" in context:
+ newContext = (
+ "Reply with only the " + LANGUAGE + " translation of the RPG equipment name"
+ )
+ if "Classes" in context:
+ newContext = (
+ "Reply with only the " + LANGUAGE + " translation of the RPG class name"
+ )
+ if "MapInfos" in context:
+ newContext = (
+ "Reply with only the " + LANGUAGE + " translation of the location name"
+ )
+ if "Enemies" in context:
+ newContext = (
+ "Reply with only the " + LANGUAGE + " translation of the enemy NPC name"
+ )
+ if "Weapons" in context:
+ newContext = (
+ "Reply with only the " + LANGUAGE + " translation of the RPG weapon name"
+ )
+ if "Items" in context:
+ newContext = (
+ "Reply with only the " + LANGUAGE + " translation of the RPG item name"
+ )
+ if "Skills" in context:
+ newContext = (
+ "Reply with only the " + LANGUAGE + " translation of the RPG skill name"
+ )
# Names
while i < len(data) or filling == True:
if i < len(data):
# Empty Data
- if data[i] is None or data[i]['name'] == "":
+ if data[i] is None or data[i]["name"] == "":
i += 1
-
- continue
+
+ continue
# Filling up Batch
filling = True
- if context in 'Actors':
+ if context in "Actors":
if len(nameList) < BATCHSIZE:
- if data[i]['name'] != '':
- nameList.append(data[i]['name'])
- if data[i]['nickname'] != '':
- nicknameList.append(data[i]['nickname'])
- if data[i]['description'] != '':
- profileList.append(data[i]['description'].replace('\n', ' '))
+ if data[i]["name"] != "":
+ nameList.append(data[i]["name"])
+ if data[i]["nickname"] != "":
+ nicknameList.append(data[i]["nickname"])
+ if data[i]["description"] != "":
+ profileList.append(data[i]["description"].replace("\n", " "))
# Notes
- if '')
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
-
+
i += 1
else:
batchFull = True
- if context in ['Armors', 'Weapons', 'Items']:
+ if context in ["Armors", "Weapons", "Items"]:
if len(nameList) < BATCHSIZE:
- nameList.append(data[i]['name'])
- if 'description' in data[i]:
- descriptionList.append(data[i]['description'].replace('\n', ' '))
- if '')
+ nameList.append(data[i]["name"])
+ if "description" in data[i]:
+ descriptionList.append(
+ data[i]["description"].replace("\n", " ")
+ )
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if '')
+ if ""
+ )
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if '')
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if '')
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if '')
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if '')
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if '')
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if 'Switch Shop Description' in data[i]['note']:
- tokensResponse = translateNote(data[i], r'\n(.*)\n')
+ if "Switch Shop Description" in data[i]["note"]:
+ tokensResponse = translateNote(
+ data[i], r"\n(.*)\n"
+ )
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if '')
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
-
+
i += 1
else:
batchFull = True
- if context in ['Skills']:
+ if context in ["Skills"]:
if len(nameList) < BATCHSIZE:
- nameList.append(data[i]['name'])
- descriptionList.append(data[i]['description'].replace('\n', ' '))
-
+ nameList.append(data[i]["name"])
+ descriptionList.append(data[i]["description"].replace("\n", " "))
+
# Messages
number = 1
while number < 5:
- if f'message{number}' in data[i]:
- if len(data[i][f'message{number}']) > 0 and data[i][f'message{number}'][0] in ['は', 'を', 'の', 'に', 'が']:
- msgResponse = translateGPT('Taro' + data[i][f'message{number}'], 'reply with only the gender neutral '+ LANGUAGE +' translation of the action log. Always start the sentence with Taro. For example, Translate \'Taroを倒した!\' as \'Taro was defeated!\'', False)
- data[i][f'message{number}'] = msgResponse[0].replace('Taro', '')
+ if f"message{number}" in data[i]:
+ if len(data[i][f"message{number}"]) > 0 and data[i][
+ f"message{number}"
+ ][0] in ["は", "を", "の", "に", "が"]:
+ msgResponse = translateGPT(
+ "Taro" + data[i][f"message{number}"],
+ "reply with only the gender neutral "
+ + LANGUAGE
+ + " translation of the action log. Always start the sentence with Taro. For example, Translate 'Taroを倒した!' as 'Taro was defeated!'",
+ False,
+ )
+ data[i][f"message{number}"] = msgResponse[0].replace(
+ "Taro", ""
+ )
totalTokens[0] += msgResponse[1][0]
totalTokens[1] += msgResponse[1][1]
number += 1
else:
- msgResponse = translateGPT(data[i][f'message{number}'], 'reply with only the gender neutral '+ LANGUAGE +' translation', False)
- data[i][f'message{number}'] = msgResponse[0]
+ msgResponse = translateGPT(
+ data[i][f"message{number}"],
+ "reply with only the gender neutral "
+ + LANGUAGE
+ + " translation",
+ False,
+ )
+ data[i][f"message{number}"] = msgResponse[0]
totalTokens[0] += msgResponse[1][0]
totalTokens[1] += msgResponse[1][1]
number += 1
else:
number += 1
-
+
i += 1
else:
batchFull = True
- if context in ['Enemies', 'Classes', 'MapInfos']:
+ if context in ["Enemies", "Classes", "MapInfos"]:
if len(nameList) < BATCHSIZE:
- nameList.append(data[i]['name'])
+ nameList.append(data[i]["name"])
# Notes
- if '')
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
i += 1
@@ -592,8 +691,8 @@ def searchNames(data, pbar, context):
# Batch Full
if batchFull == True or i >= len(data):
- k = j # Original Index
- if context in 'Actors':
+ k = j # Original Index
+ if context in "Actors":
# Name
response = translateGPT(nameList, newContext, True)
translatedNameBatch = response[0]
@@ -607,7 +706,7 @@ def searchNames(data, pbar, context):
totalTokens[1] += response[1][1]
# Profile
- response = translateGPT(profileList, '', True)
+ response = translateGPT(profileList, "", True)
translatedProfileBatch = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
@@ -617,19 +716,21 @@ def searchNames(data, pbar, context):
j = k
while j < i:
# Empty Data
- if data[j] is None or data[j]['name'] == "":
+ if data[j] is None or data[j]["name"] == "":
j += 1
- continue
+ continue
else:
# Get Text
- if data[j]['name'] != '':
- data[j]['name'] = translatedNameBatch[0]
+ if data[j]["name"] != "":
+ data[j]["name"] = translatedNameBatch[0]
translatedNameBatch.pop(0)
- if data[j]['nickname'] != '':
- data[j]['nickname'] = translatedNicknameBatch[0]
+ if data[j]["nickname"] != "":
+ data[j]["nickname"] = translatedNicknameBatch[0]
translatedNicknameBatch.pop(0)
- if data[j]['description'] != '':
- data[j]['description'] = textwrap.fill(translatedProfileBatch[0], LISTWIDTH)
+ if data[j]["description"] != "":
+ data[j]["description"] = textwrap.fill(
+ translatedProfileBatch[0], LISTWIDTH
+ )
translatedProfileBatch.pop(0)
# If Batch is empty. Move on.
@@ -640,7 +741,7 @@ def searchNames(data, pbar, context):
else:
mismatch = True
- if context in ['Armors', 'Weapons', 'Items', 'Skills']:
+ if context in ["Armors", "Weapons", "Items", "Skills"]:
# Name
response = translateGPT(nameList, newContext, True)
translatedNameBatch = response[0]
@@ -648,7 +749,11 @@ def searchNames(data, pbar, context):
totalTokens[1] += response[1][1]
# Description
- response = translateGPT(descriptionList, f'Reply with only the {LANGUAGE} translation of the text.', True)
+ response = translateGPT(
+ descriptionList,
+ f"Reply with only the {LANGUAGE} translation of the text.",
+ True,
+ )
translatedDescriptionBatch = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
@@ -658,14 +763,16 @@ def searchNames(data, pbar, context):
j = k
while j < i:
# Empty Data
- if data[j] is None or data[j]['name'] == "":
+ if data[j] is None or data[j]["name"] == "":
j += 1
- continue
+ continue
else:
# Get Text
- data[j]['name'] = translatedNameBatch[0]
- if 'description' in data[j]:
- data[j]['description'] = textwrap.fill(translatedDescriptionBatch[0], LISTWIDTH)
+ data[j]["name"] = translatedNameBatch[0]
+ if "description" in data[j]:
+ data[j]["description"] = textwrap.fill(
+ translatedDescriptionBatch[0], LISTWIDTH
+ )
translatedNameBatch.pop(0)
translatedDescriptionBatch.pop(0)
@@ -678,7 +785,7 @@ def searchNames(data, pbar, context):
j += 1
else:
mismatch = True
- if context in ['Enemies', 'Classes', 'MapInfos']:
+ if context in ["Enemies", "Classes", "MapInfos"]:
response = translateGPT(nameList, newContext, True)
translatedNameBatch = response[0]
totalTokens[0] += response[1][0]
@@ -689,12 +796,12 @@ def searchNames(data, pbar, context):
j = k
while j < i:
# Empty Data
- if data[j] is None or data[j]['name'] == "":
+ if data[j] is None or data[j]["name"] == "":
j += 1
- continue
+ continue
else:
# Get Text
- data[j]['name'] = translatedNameBatch[0]
+ data[j]["name"] = translatedNameBatch[0]
translatedNameBatch.pop(0)
# If Batch is empty. Move on.
@@ -714,11 +821,12 @@ def searchNames(data, pbar, context):
descriptionList.clear()
filling = False
mismatch = False
-
+
i += 1
return totalTokens
+
def searchCodes(page, pbar, jobList, filename):
if len(jobList) > 0:
list401 = jobList[0]
@@ -736,10 +844,10 @@ def searchCodes(page, pbar, jobList, filename):
textHistory = []
match = []
totalTokens = [0, 0]
- translatedText = ''
- speaker = ''
+ translatedText = ""
+ speaker = ""
speakerID = None
- nametag = ''
+ nametag = ""
syncIndex = 0
CLFlag = False
maxHistory = MAXHISTORY
@@ -752,12 +860,11 @@ def searchCodes(page, pbar, jobList, filename):
with LOCK:
PBAR = pbar
-
# Begin Parsing File
try:
# Normal Format
- if 'list' in page:
- codeList = page['list']
+ if "list" in page:
+ codeList = page["list"]
# Special Format (Scenario)
else:
@@ -766,7 +873,7 @@ def searchCodes(page, pbar, jobList, filename):
# Iterate through page
i = 0
while i < len(codeList):
- with LOCK:
+ with LOCK:
# syncIndex will keep i in sync when it gets modified
if syncIndex > i:
i = syncIndex
@@ -774,18 +881,22 @@ def searchCodes(page, pbar, jobList, filename):
break
## Event Code: 401 Show Text
- if 'c' in codeList[i] and codeList[i]['c'] in [401, 405, -1] and (CODE401 or CODE405):
+ if (
+ "c" in codeList[i]
+ and codeList[i]["c"] in [401, 405, -1]
+ and (CODE401 or CODE405)
+ ):
# Save Code and starting index (j)
- code = codeList[i]['c']
+ code = codeList[i]["c"]
j = i
- endtag = ''
+ endtag = ""
# Grab String
- if len(codeList[i]['p']) > 0:
- jaString = codeList[i]['p'][0]
+ if len(codeList[i]["p"]) > 0:
+ jaString = codeList[i]["p"][0]
oldjaString = jaString
else:
- codeList[i]['c'] = -1
+ codeList[i]["c"] = -1
i += 1
continue
@@ -808,89 +919,103 @@ def searchCodes(page, pbar, jobList, filename):
speakerList = []
# m and z Codes
- match = re.search(r'(.*?)[\\]+m\[\d+?\][\\]+z\[\d+?\]', jaString)
+ match = re.search(r"(.*?)[\\]+m\[\d+?\][\\]+z\[\d+?\]", jaString)
if match:
speakerList.append(match.group(1))
- if '\\c' in speakerList[0]:
- speakerList = re.findall(r'^[\\]+[cC]\[[\d]+\](.+?)[\\]+[Cc]\[[\d]\]\\?\\?$', speakerList[0])
+ if "\\c" in speakerList[0]:
+ speakerList = re.findall(
+ r"^[\\]+[cC]\[[\d]+\](.+?)[\\]+[Cc]\[[\d]\]\\?\\?$",
+ speakerList[0],
+ )
# Brackets
if len(speakerList) == 0:
- speakerList = re.findall(r'^【(.*?)】$', jaString)
+ speakerList = re.findall(r"^【(.*?)】$", jaString)
# Colors
if len(speakerList) == 0:
- speakerList = re.findall(r'^[\\]+[cC]\[[\d]+\](.+?)[\\]+[Cc]\[[\d]\]\\?\\?$', jaString)
+ speakerList = re.findall(
+ r"^[\\]+[cC]\[[\d]+\](.+?)[\\]+[Cc]\[[\d]\]\\?\\?$", jaString
+ )
# None
if len(speakerList) == 0 and FIRSTLINESPEAKERS is True:
- if len(jaString) < 40 \
- and 'c' in codeList[i+1] \
- and codeList[i+1]['c'] in [401, 405, -1] \
- and len(codeList[i+1]['p']) > 0 \
- and len(codeList[i+1]['p'][0]) > 0:
- if codeList[i+1]['p'][0].strip()[0] in ['「', '"', '(', '(', '*', '[']:
+ if (
+ len(jaString) < 40
+ and "c" in codeList[i + 1]
+ and codeList[i + 1]["c"] in [401, 405, -1]
+ and len(codeList[i + 1]["p"]) > 0
+ and len(codeList[i + 1]["p"][0]) > 0
+ ):
+ if codeList[i + 1]["p"][0].strip()[0] in [
+ "「",
+ '"',
+ "(",
+ "(",
+ "*",
+ "[",
+ ]:
# Make sure there aren't any codes.
- speakerList = re.findall(r'[\\]\w\[.*?\](.*)', jaString)
+ speakerList = re.findall(r"[\\]\w\[.*?\](.*)", jaString)
if len(speakerList) == 0:
- speakerList = re.findall(r'.*', jaString)
+ speakerList = re.findall(r".*", jaString)
- if len(speakerList) != 0 and codeList[i+1]['c'] in [401, 405, -1]:
+ if len(speakerList) != 0 and codeList[i + 1]["c"] in [401, 405, -1]:
# Get Speaker
response = getSpeaker(speakerList[0])
speaker = response[0]
totalTokens[0] += response[1][0]
- totalTokens[1] += response[1][1]
+ totalTokens[1] += response[1][1]
# Set Data
- codeList[i]['p'][0] = jaString.replace(speakerList[0], speaker)
+ codeList[i]["p"][0] = jaString.replace(speakerList[0], speaker)
# Iterate to next string
i += 1
j = i
- while codeList[i]['c'] in [-1]:
+ while codeList[i]["c"] in [-1]:
i += 1
j = i
- jaString = codeList[i]['p'][0]
+ jaString = codeList[i]["p"][0]
# Using this to keep track of 401's in a row.
currentGroup.append(jaString)
# Join Up 401's into single string
- if len(codeList) > i+1:
- while codeList[i+1]['c'] in [401, 405, -1]:
+ if len(codeList) > i + 1:
+ while codeList[i + 1]["c"] in [401, 405, -1]:
if setData == True:
- codeList[i]['p'] = []
- codeList[i]['c'] = -1
+ codeList[i]["p"] = []
+ codeList[i]["c"] = -1
i += 1
j = i
# Only add if not empty
- if len(codeList[i]['p']) > 0:
- jaString = codeList[i]['p'][0]
+ if len(codeList[i]["p"]) > 0:
+ jaString = codeList[i]["p"][0]
currentGroup.append(jaString)
# Make sure not the end of the list.
- if len(codeList) <= i+1:
+ if len(codeList) <= i + 1:
break
# Format String
if len(currentGroup) > 0:
- finalJAString = ' '.join(currentGroup).replace('?', '?')
+ finalJAString = " ".join(currentGroup).replace("?", "?")
oldjaString = finalJAString
# Check if Empty
- if finalJAString == '':
+ if finalJAString == "":
i += 1
continue
# Set Back
if setData == True:
- codeList[i]['p'] = [finalJAString]
+ codeList[i]["p"] = [finalJAString]
### \\n
nCase = None
- regex = r'([\\]+[kKnN][wWcCrRrEe]?[\[<](.*?)[>\]])'
+ regex = r"([\\]+[kKnN][wWcCrRrEe]?[\[<](.*?)[>\]])"
match = re.search(regex, finalJAString)
# Set Name
@@ -898,20 +1023,20 @@ def searchCodes(page, pbar, jobList, filename):
nametag = match.group(1)
speaker = match.group(2)
- # Translate Speaker
+ # Translate Speaker
response = getSpeaker(speaker)
tledSpeaker = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Set Nametag and Remove from Final String
- finalJAString = finalJAString.replace(nametag, '')
+ finalJAString = finalJAString.replace(nametag, "")
nametag = nametag.replace(speaker, tledSpeaker)
speaker = tledSpeaker
-
+
# Bracket Names
if BRACKETNAMES is True and len(matchList) != 0:
- if matchList[0][0] != '':
+ if matchList[0][0] != "":
match0 = matchList[0][0]
match1 = matchList[0][1]
else:
@@ -927,127 +1052,144 @@ def searchCodes(page, pbar, jobList, filename):
# Set Nametag and Remove from Final String
fullSpeaker = match0.replace(match1, speaker)
- finalJAString = finalJAString.replace(match0, '')
+ finalJAString = finalJAString.replace(match0, "")
# Set next item as dialogue
- if codeList[j + 1]['c'] == 401 or codeList[j + 1]['c'] == -1:
+ if codeList[j + 1]["c"] == 401 or codeList[j + 1]["c"] == -1:
# Set name var to top of list
- codeList[j]['p'] = [fullSpeaker]
- codeList[j]['c'] = code
+ codeList[j]["p"] = [fullSpeaker]
+ codeList[j]["c"] = code
j += 1
- codeList[j]['p'] = [finalJAString]
- codeList[j]['c'] = code
+ codeList[j]["p"] = [finalJAString]
+ codeList[j]["c"] = code
else:
# Set nametag in string
- codeList[j]['p'] = [fullSpeaker + finalJAString]
- codeList[j]['c'] = code
+ codeList[j]["p"] = [fullSpeaker + finalJAString]
+ codeList[j]["c"] = code
# Remove any textwrap
if FIXTEXTWRAP is True:
- finalJAString = re.sub(r'\n', ' ', finalJAString)
- finalJAString = finalJAString.replace('
', ' ')
+ finalJAString = re.sub(r"\n", " ", finalJAString)
+ finalJAString = finalJAString.replace("
", " ")
# Remove Extra Stuff bad for translation.
- finalJAString = finalJAString.replace('゙', '')
- finalJAString = finalJAString.replace('―', '-')
- finalJAString = finalJAString.replace('…', '...')
- finalJAString = finalJAString.replace('。', '.')
- finalJAString = re.sub(r'(\.{3}\.+)', '...', finalJAString)
- finalJAString = finalJAString.replace(' ', '')
- finalJAString = finalJAString.replace('「', '\"')
- finalJAString = finalJAString.replace('」', '\"')
+ finalJAString = finalJAString.replace("゙", "")
+ finalJAString = finalJAString.replace("―", "-")
+ finalJAString = finalJAString.replace("…", "...")
+ finalJAString = finalJAString.replace("。", ".")
+ finalJAString = re.sub(r"(\.{3}\.+)", "...", finalJAString)
+ finalJAString = finalJAString.replace(" ", "")
+ finalJAString = finalJAString.replace("「", '"')
+ finalJAString = finalJAString.replace("」", '"')
### Remove format codes
# Furigana
- rcodeMatch = re.findall(r'([\\]+[r][b]?\[.*?,(.*?)\])', finalJAString)
+ rcodeMatch = re.findall(
+ r"([\\]+[r][b]?\[.*?,(.*?)\])", finalJAString
+ )
if len(rcodeMatch) > 0:
for match in rcodeMatch:
- finalJAString = finalJAString.replace(match[0],match[1])
+ finalJAString = finalJAString.replace(match[0], match[1])
# Formatting
- formatMatch = re.findall(r'[\\]+[!><.|#^{}]', finalJAString)
+ formatMatch = re.findall(r"[\\]+[!><.|#^{}]", finalJAString)
if len(formatMatch) > 0:
for match in formatMatch:
- finalJAString = finalJAString.replace(match, '')
+ finalJAString = finalJAString.replace(match, "")
# Remove any RPGMaker Code at start
- ffMatch = re.search(r'^([.\\]+[aAbBcCdDeEfFgGhHiIjJlLmMoOpPqQrRsStTuUvVwWxXyYzZ]+\[.+?\]\]?)+', finalJAString)
+ ffMatch = re.search(
+ r"^([.\\]+[aAbBcCdDeEfFgGhHiIjJlLmMoOpPqQrRsStTuUvVwWxXyYzZ]+\[.+?\]\]?)+",
+ finalJAString,
+ )
if ffMatch != None:
- finalJAString = finalJAString.replace(ffMatch.group(0), '')
+ finalJAString = finalJAString.replace(ffMatch.group(0), "")
nametag += ffMatch.group(0)
# Remove _ABL Codes
- ffMatch = re.search(r'^(_ABL).*', finalJAString)
+ ffMatch = re.search(r"^(_ABL).*", finalJAString)
if ffMatch != None:
- finalJAString = finalJAString.replace(ffMatch.group(1), '')
+ finalJAString = finalJAString.replace(ffMatch.group(1), "")
nametag += ffMatch.group(1)
# Center Lines
- if '\\CL' in finalJAString or '\\ac' in finalJAString:
- finalJAString = finalJAString.replace('\\CL ', '')
- finalJAString = finalJAString.replace('\\CL', '')
- finalJAString = finalJAString.replace('\\ac ', '')
- finalJAString = finalJAString.replace('\\ac', '')
+ if "\\CL" in finalJAString or "\\ac" in finalJAString:
+ finalJAString = finalJAString.replace("\\CL ", "")
+ finalJAString = finalJAString.replace("\\CL", "")
+ finalJAString = finalJAString.replace("\\ac ", "")
+ finalJAString = finalJAString.replace("\\ac", "")
CLFlag = True
# If there isn't any Japanese in the text just skip
if IGNORETLTEXT is True:
- if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', finalJAString):
+ if not re.search(
+ r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+", finalJAString
+ ):
# Keep textHistory list at length maxHistory
- textHistory.append('\"' + finalJAString + '\"')
+ textHistory.append('"' + finalJAString + '"')
if len(textHistory) > maxHistory:
textHistory.pop(0)
- currentGroup = []
+ currentGroup = []
i += 1
continue
# 1st Passthrough (Grabbing Data)
if setData == False:
- if finalJAString != '':
- if speaker == '' and finalJAString != '':
+ if finalJAString != "":
+ if speaker == "" and finalJAString != "":
list401.append(finalJAString)
- elif finalJAString != '':
- list401.append(f'[{speaker}]: {finalJAString}')
+ elif finalJAString != "":
+ list401.append(f"[{speaker}]: {finalJAString}")
else:
list401.append(speaker)
- speaker = ''
+ speaker = ""
match = []
currentGroup = []
- syncIndex = i + 1
+ syncIndex = i + 1
- # 2nd Passthrough (Setting Data)
+ # 2nd Passthrough (Setting Data)
else:
# Grab Translated String
if len(list401) > 0:
translatedText = list401[0]
-
+
# Remove speaker
- if speaker != '':
- matchSpeakerList = re.findall(r'^\[?(.+?)\]?\s?[|:]\s?', translatedText)
+ if speaker != "":
+ matchSpeakerList = re.findall(
+ r"^\[?(.+?)\]?\s?[|:]\s?", translatedText
+ )
if len(matchSpeakerList) > 0:
newSpeaker = matchSpeakerList[0]
nametag = nametag.replace(speaker, newSpeaker)
- translatedText = re.sub(r'^\[?(.+?)\]?\s?[|:]\s?', '', translatedText)
+ translatedText = re.sub(
+ r"^\[?(.+?)\]?\s?[|:]\s?", "", translatedText
+ )
# Fix '- '
- translatedText = translatedText.replace('- ', '-')
+ translatedText = translatedText.replace("- ", "-")
# Textwrap
- if FIXTEXTWRAP is True and '_ABL' in nametag:
- translatedText = textwrap.fill(translatedText, width=100)
+ if FIXTEXTWRAP is True and "_ABL" in nametag:
+ translatedText = textwrap.fill(
+ translatedText, width=100
+ )
elif FIXTEXTWRAP is True:
- translatedText = textwrap.fill(translatedText, width=WIDTH)
-
+ translatedText = textwrap.fill(
+ translatedText, width=WIDTH
+ )
+
# BR Flag
if BRFLAG is True:
- translatedText = translatedText.replace('\n', '
')
+ translatedText = translatedText.replace("\n", "
")
### Add Var Strings
# CL Flag
if CLFlag:
- translatedText = '\\ac ' + translatedText
- translatedText = translatedText.replace('\n', '\n\\ac ')
- translatedText = re.sub(r'[\\]+?ac\s+', r'\\ac ', translatedText)
+ translatedText = "\\ac " + translatedText
+ translatedText = translatedText.replace("\n", "\n\\ac ")
+ translatedText = re.sub(
+ r"[\\]+?ac\s+", r"\\ac ", translatedText
+ )
CLFlag = False
# Nametag
@@ -1055,38 +1197,38 @@ def searchCodes(page, pbar, jobList, filename):
translatedText = translatedText + nametag
else:
translatedText = nametag + translatedText
- nametag = ''
+ nametag = ""
# Endtag
- if endtag != '':
+ if endtag != "":
translatedText = translatedText + endtag
- endtag = ''
+ endtag = ""
# Set Data
if speakerID != None:
- codeList[speakerID]['p'] = [fullSpeaker]
- codeList[j]['p'] = [translatedText]
- codeList[j]['c'] = code
- speaker = ''
+ codeList[speakerID]["p"] = [fullSpeaker]
+ codeList[j]["p"] = [translatedText]
+ codeList[j]["c"] = code
+ speaker = ""
match = []
currentGroup = []
syncIndex = i + 1
- list401.pop(0)
+ list401.pop(0)
## Event Code: 122 [Set Variables]
- if 'c' in codeList[i] and codeList[i]['c'] == 122 and CODE122 is True:
+ if "c" in codeList[i] and codeList[i]["c"] == 122 and CODE122 is True:
# This is going to be the var being set. (IMPORTANT)
- if codeList[i]['p'][0] not in list(range(150, 180)):
+ if codeList[i]["p"][0] not in list(range(150, 180)):
i += 1
continue
-
- jaString = codeList[i]['p'][4]
+
+ jaString = codeList[i]["p"][4]
# # For Retarded Devs
# VNameValue = jaString
# i += 1
# continue
-
+
# Definitely don't want to mess with files
# if 'gameV' in jaString or '_' in jaString:
# i += 1
@@ -1096,7 +1238,7 @@ def searchCodes(page, pbar, jobList, filename):
if not isinstance(jaString, str):
i += 1
continue
-
+
# Set String
matchedText = None
if len(re.findall(r"([\'\"])", jaString)) == 2:
@@ -1107,121 +1249,129 @@ def searchCodes(page, pbar, jobList, filename):
# Last Check
if matchedText != None:
# Remove Textwrap
- finalJAString = matchedText.group(1).replace('\\n', ' ')
+ finalJAString = matchedText.group(1).replace("\\n", " ")
# Pass 1
if setData == False:
- if finalJAString != '':
+ if finalJAString != "":
list122.append(finalJAString)
# Pass 2
- else:
- if len(list122) > 0:
+ else:
+ if len(list122) > 0:
# Grab and Replace
translatedText = list122[0]
translatedText = jaString.replace(jaString, translatedText)
# Remove characters that may break scripts
- charList = ['\"', '\\n']
+ charList = ['"', "\\n"]
for char in charList:
- translatedText = translatedText.replace(char, '')
-
+ translatedText = translatedText.replace(char, "")
+
# Textwrap
translatedText = textwrap.fill(translatedText, width=80)
- translatedText = translatedText.replace('\n', '\\n')
+ translatedText = translatedText.replace("\n", "\\n")
# Set
- codeList[i]['p'][4] = jaString.replace(finalJAString, translatedText)
+ codeList[i]["p"][4] = jaString.replace(
+ finalJAString, translatedText
+ )
list122.pop(0)
## Event Code: 357 [Picture Text] [Optional]
- if 'c' in codeList[i] and codeList[i]['c'] == 357 and CODE357 is True:
- headerString = codeList[i]['p'][0]
+ if "c" in codeList[i] and codeList[i]["c"] == 357 and CODE357 is True:
+ headerString = codeList[i]["p"][0]
- if headerString == 'LL_GalgeChoiceWindow':
+ if headerString == "LL_GalgeChoiceWindow":
### Message Text First
- jaString = codeList[i]['p'][3]['messageText']
+ jaString = codeList[i]["p"][3]["messageText"]
# Remove any textwrap & TL
- jaString = re.sub(r'\n', ' ', jaString)
- response = translateGPT(jaString, '', False)
+ jaString = re.sub(r"\n", " ", jaString)
+ response = translateGPT(jaString, "", False)
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Textwrap & Set
translatedText = textwrap.fill(translatedText, width=WIDTH)
- codeList[i]['p'][3]['messageText'] = translatedText
+ codeList[i]["p"][3]["messageText"] = translatedText
### Choices
- jaString = codeList[i]['p'][3]['choices']
+ jaString = codeList[i]["p"][3]["choices"]
matchList = re.findall(r'"label[\\]*":[\\]*"(.*?)[\\]', jaString)
if matchList != None:
# Translate
- question = codeList[i]['p'][3]['messageText']
- response = translateGPT(matchList, f'Previous text for context: {question}\n\nThis will be a dialogue option', True)
+ question = codeList[i]["p"][3]["messageText"]
+ response = translateGPT(
+ matchList,
+ f"Previous text for context: {question}\n\nThis will be a dialogue option",
+ True,
+ )
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
translatedText = jaString
# Replace Strings
for j in range(len(matchList)):
- translatedText = translatedText.replace(matchList[j], response[0][j])
+ translatedText = translatedText.replace(
+ matchList[j], response[0][j]
+ )
# Set Data
- codeList[i]['p'][3]['choices'] = translatedText
+ codeList[i]["p"][3]["choices"] = translatedText
- if 'SoR_GabWindow' in headerString:
- argVar = 'arg1'
+ if "SoR_GabWindow" in headerString:
+ argVar = "arg1"
### Message Text First
- if argVar in codeList[i]['p'][3]:
- jaString = codeList[i]['p'][3][argVar]
+ if argVar in codeList[i]["p"][3]:
+ jaString = codeList[i]["p"][3][argVar]
# If there isn't any Japanese in the text just skip
- if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
+ if not re.search(r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+", jaString):
i += 1
continue
# Remove any textwrap & TL
- jaString = re.sub(r'\n', ' ', jaString)
- response = translateGPT(jaString, '', False)
+ jaString = re.sub(r"\n", " ", jaString)
+ response = translateGPT(jaString, "", False)
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Textwrap & Set
translatedText = textwrap.fill(translatedText, width=WIDTH)
- codeList[i]['p'][3][argVar] = translatedText
+ codeList[i]["p"][3][argVar] = translatedText
pbar.update(1)
- if 'TorigoyaMZ_NotifyMessage' in headerString:
- argVar = 'message'
+ if "TorigoyaMZ_NotifyMessage" in headerString:
+ argVar = "message"
### Message Text First
- if argVar in codeList[i]['p'][3]:
- jaString = codeList[i]['p'][3][argVar]
+ if argVar in codeList[i]["p"][3]:
+ jaString = codeList[i]["p"][3][argVar]
# If there isn't any Japanese in the text just skip
- if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
+ if not re.search(r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+", jaString):
i += 1
continue
# Remove any textwrap & TL
- jaString = re.sub(r'\n', ' ', jaString)
- response = translateGPT(jaString, '', False)
+ jaString = re.sub(r"\n", " ", jaString)
+ response = translateGPT(jaString, "", False)
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Textwrap & Set
translatedText = textwrap.fill(translatedText, width=WIDTH)
- codeList[i]['p'][3][argVar] = translatedText
+ codeList[i]["p"][3][argVar] = translatedText
pbar.update(1)
- if '_TMLogWindowMZ' in headerString:
- argVar = 'text'
+ if "_TMLogWindowMZ" in headerString:
+ argVar = "text"
### Message Text First
- if argVar in codeList[i]['p'][3]:
- jaString = codeList[i]['p'][3][argVar]
+ if argVar in codeList[i]["p"][3]:
+ jaString = codeList[i]["p"][3][argVar]
# If there isn't any Japanese in the text just skip
# if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
@@ -1229,22 +1379,22 @@ def searchCodes(page, pbar, jobList, filename):
# continue
# Remove any textwrap & TL
- jaString = re.sub(r'\n', ' ', jaString)
- response = translateGPT(jaString, '', False)
+ jaString = re.sub(r"\n", " ", jaString)
+ response = translateGPT(jaString, "", False)
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Textwrap & Set
translatedText = textwrap.fill(translatedText, width=WIDTH)
- codeList[i]['p'][3][argVar] = translatedText
+ codeList[i]["p"][3][argVar] = translatedText
pbar.update(1)
- if 'DestinationWindow' in headerString:
- argVar = 'destination'
+ if "DestinationWindow" in headerString:
+ argVar = "destination"
### Message Text First
- if argVar in codeList[i]['p'][3]:
- jaString = codeList[i]['p'][3][argVar]
+ if argVar in codeList[i]["p"][3]:
+ jaString = codeList[i]["p"][3][argVar]
# If there isn't any Japanese in the text just skip
# if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
@@ -1252,22 +1402,22 @@ def searchCodes(page, pbar, jobList, filename):
# continue
# Remove any textwrap & TL
- jaString = re.sub(r'\n', ' ', jaString)
- response = translateGPT(jaString, '', False)
+ jaString = re.sub(r"\n", " ", jaString)
+ response = translateGPT(jaString, "", False)
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Textwrap & Set
translatedText = textwrap.fill(translatedText, width=WIDTH)
- codeList[i]['p'][3][argVar] = translatedText
+ codeList[i]["p"][3][argVar] = translatedText
pbar.update(1)
- if 'MNKR_CommonPopupCoreMZ' in headerString:
- argVar = 'text'
+ if "MNKR_CommonPopupCoreMZ" in headerString:
+ argVar = "text"
### Message Text First
- if argVar in codeList[i]['p'][3]:
- jaString = codeList[i]['p'][3][argVar]
+ if argVar in codeList[i]["p"][3]:
+ jaString = codeList[i]["p"][3][argVar]
# If there isn't any Japanese in the text just skip
# if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
@@ -1275,142 +1425,164 @@ def searchCodes(page, pbar, jobList, filename):
# continue
# Remove any textwrap & TL
- jaString = re.sub(r'\n', ' ', jaString)
- response = translateGPT(jaString, '', False)
+ jaString = re.sub(r"\n", " ", jaString)
+ response = translateGPT(jaString, "", False)
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Textwrap & Set
translatedText = textwrap.fill(translatedText, width=WIDTH)
- codeList[i]['p'][3][argVar] = translatedText
+ codeList[i]["p"][3][argVar] = translatedText
pbar.update(1)
-
+
## Event Code: 657 [Picture Text] [Optional]
- if 'c' in codeList[i] and codeList[i]['c'] == 657 and CODE657 is True:
- if 'text' in codeList[i]['p'][0]:
- jaString = codeList[i]['p'][0]
+ if "c" in codeList[i] and codeList[i]["c"] == 657 and CODE657 is True:
+ if "text" in codeList[i]["p"][0]:
+ jaString = codeList[i]["p"][0]
if not isinstance(jaString, str):
i += 1
continue
-
+
# Definitely don't want to mess with files
- if '_' in jaString:
+ if "_" in jaString:
i += 1
continue
# If there isn't any Japanese in the text just skip
- if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
+ if not re.search(r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+", jaString):
i += 1
continue
# Remove outside text
- startString = re.search(r'^[^一-龠ぁ-ゔァ-ヴー\<\>【】\\]+', jaString)
- jaString = re.sub(r'^[^一-龠ぁ-ゔァ-ヴー\<\>【】\\]+', '', jaString)
- endString = re.search(r'[^一-龠ぁ-ゔァ-ヴー\<\>【】。!?\\]+$', jaString)
- jaString = re.sub(r'[^一-龠ぁ-ゔァ-ヴー\<\>【】。!?\\]+$', '', jaString)
+ startString = re.search(
+ r"^[^一-龠ぁ-ゔァ-ヴー\<\>【】\\]+", jaString
+ )
+ jaString = re.sub(r"^[^一-龠ぁ-ゔァ-ヴー\<\>【】\\]+", "", jaString)
+ endString = re.search(
+ r"[^一-龠ぁ-ゔァ-ヴー\<\>【】。!?\\]+$", jaString
+ )
+ jaString = re.sub(
+ r"[^一-龠ぁ-ゔァ-ヴー\<\>【】。!?\\]+$", "", jaString
+ )
if startString is None:
- startString = ''
+ startString = ""
else:
startString = startString.group()
if endString is None:
- endString = ''
+ endString = ""
else:
endString = endString.group()
# Remove any textwrap
- jaString = re.sub(r'\n', ' ', jaString)
+ jaString = re.sub(r"\n", " ", jaString)
# Translate
- response = translateGPT(jaString, '', True)
+ response = translateGPT(jaString, "", True)
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
translatedText = response[0]
# Remove characters that may break scripts
- charList = ['.', '\"', "'"]
+ charList = [".", '"', "'"]
for char in charList:
- translatedText = translatedText.replace(char, '')
+ translatedText = translatedText.replace(char, "")
# Textwrap
translatedText = textwrap.fill(translatedText, width=WIDTH)
translatedText = startString + translatedText + endString
# Set Data
- codeList[i]['p'][0] = translatedText
+ codeList[i]["p"][0] = translatedText
- ## Event Code: 101 [Name] [Optional]
- if 'c' in codeList[i] and codeList[i]['c'] == 101 and CODE101 is True:
+ ## Event Code: 101 [Name] [Optional]
+ if "c" in codeList[i] and codeList[i]["c"] == 101 and CODE101 is True:
# Check Window Type (Certain games switch between 1st line speakers and none)
if FIRSTLINESPEAKERS:
- if codeList[i]['p'][2] == 0:
+ if codeList[i]["p"][2] == 0:
speakerWindow = True
else:
speakerWindow = False
else:
isVar = False
-
+
# Grab String
- jaString = ''
- if len(codeList[i]['p']) > 4:
- jaString = codeList[i]['p'][4]
+ jaString = ""
+ if len(codeList[i]["p"]) > 4:
+ jaString = codeList[i]["p"][4]
# Check for Var
- elif len(codeList[i]['p']) > 0:
- jaString = codeList[i]['p'][0]
+ elif len(codeList[i]["p"]) > 0:
+ jaString = codeList[i]["p"][0]
isVar = True
if not isinstance(jaString, str):
i += 1
continue
# Force Speaker using var
- if '\\ap[1左]' in jaString.lower() or '\\ap[1右]' in jaString.lower():
- speaker = 'Cecily'
+ if (
+ "\\ap[1左]" in jaString.lower()
+ or "\\ap[1右]" in jaString.lower()
+ ):
+ speaker = "Cecily"
i += 1
continue
- elif '\\ap[2左]' in jaString.lower() or '\\ap[2右]' in jaString.lower():
- speaker = 'Amelia'
+ elif (
+ "\\ap[2左]" in jaString.lower()
+ or "\\ap[2右]" in jaString.lower()
+ ):
+ speaker = "Amelia"
i += 1
continue
- elif '\\ap[3左]' in jaString.lower() or '\\ap[3右]' in jaString.lower():
- speaker = 'Henry'
+ elif (
+ "\\ap[3左]" in jaString.lower()
+ or "\\ap[3右]" in jaString.lower()
+ ):
+ speaker = "Henry"
i += 1
continue
- elif '\\ap[4左]' in jaString.lower() or '\\ap[4右]' in jaString.lower():
- speaker = 'Oswald'
+ elif (
+ "\\ap[4左]" in jaString.lower()
+ or "\\ap[4右]" in jaString.lower()
+ ):
+ speaker = "Oswald"
i += 1
continue
- elif '\\ap' in jaString:
- speaker = re.search(r'[\\]+AP\[(.*?)\]', jaString).group(1)
+ elif "\\ap" in jaString:
+ speaker = re.search(r"[\\]+AP\[(.*?)\]", jaString).group(1)
i += 1
- continue
+ continue
# Get Speaker
- if '\\' not in jaString:
+ if "\\" not in jaString:
response = getSpeaker(jaString)
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
speaker = response[0]
-
+
# Validate Speaker is not empty
if len(speaker) > 0:
if isVar == False:
- codeList[i]['p'][4] = speaker
+ codeList[i]["p"][4] = speaker
i += 1
continue
else:
- codeList[i]['p'][0] = speaker
+ codeList[i]["p"][0] = speaker
isVar = False
i += 1
continue
else:
- speaker = ''
+ speaker = ""
## Event Code: 355 or 655 Scripts [Optional]
- if 'c' in codeList[i] and (codeList[i]['c'] == 355 or codeList[i]['c'] == 655) and CODE355655 is True:
- jaString = codeList[i]['p'][0]
- regex = r'memory\._eventTitle\s=\s\"(.*)\"'
-
+ if (
+ "c" in codeList[i]
+ and (codeList[i]["c"] == 355 or codeList[i]["c"] == 655)
+ and CODE355655 is True
+ ):
+ jaString = codeList[i]["p"][0]
+ regex = r"memory\._eventTitle\s=\s\"(.*)\""
+
# Var Text
match = re.search(regex, jaString)
if re.search(regex, jaString):
@@ -1420,37 +1592,45 @@ def searchCodes(page, pbar, jobList, filename):
list355655.append(finalJAString)
# Pass 2
- else:
+ else:
# Grab and Replace
translatedText = list355655[0]
# Set
- codeList[i]['p'][0] = codeList[i]['p'][0].replace(finalJAString, translatedText)
- list355655.pop(0)
+ codeList[i]["p"][0] = codeList[i]["p"][0].replace(
+ finalJAString, translatedText
+ )
+ list355655.pop(0)
## Event Code: 408 (Script)
- if 'c' in codeList[i] and (codeList[i]['c'] == 408) and CODE408 is True:
- jaString = codeList[i]['p'][0]
+ if "c" in codeList[i] and (codeList[i]["c"] == 408) and CODE408 is True:
+ jaString = codeList[i]["p"][0]
# If there isn't any Japanese in the text just skip
- if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
+ if not re.search(r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+", jaString):
i += 1
continue
- if 'secretText' in jaString:
- regex = r'secretText:\s?(.+)'
- elif 'title' in jaString:
- regex = r'title:\s?(.+)'
+ if "secretText" in jaString:
+ regex = r"secretText:\s?(.+)"
+ elif "title" in jaString:
+ regex = r"title:\s?(.+)"
else:
- regex = r'(.+)'
+ regex = r"(.+)"
# Need to remove outside code and put it back later
matchList = re.findall(regex, jaString)
-
+
for match in matchList:
# Remove Textwrap
- match = match.replace('\n', ' ')
- response = translateGPT(match, 'Reply with the '+ LANGUAGE +' translation of the achievement title.', False)
+ match = match.replace("\n", " ")
+ response = translateGPT(
+ match,
+ "Reply with the "
+ + LANGUAGE
+ + " translation of the achievement title.",
+ False,
+ )
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
@@ -1459,32 +1639,32 @@ def searchCodes(page, pbar, jobList, filename):
translatedText = jaString.replace(match, translatedText)
# Remove characters that may break scripts
- charList = ['.', '\"', '\\n']
+ charList = [".", '"', "\\n"]
for char in charList:
- translatedText = translatedText.replace(char, '')
+ translatedText = translatedText.replace(char, "")
# Textwrap
translatedText = textwrap.fill(translatedText, width=WIDTH)
# Set Data
- codeList[i]['p'][0] = translatedText
+ codeList[i]["p"][0] = translatedText
## Event Code: 108 (Script)
- if 'c' in codeList[i] and (codeList[i]['c'] == 108) and CODE108 is True:
- jaString = codeList[i]['p'][0]
+ if "c" in codeList[i] and (codeList[i]["c"] == 108) and CODE108 is True:
+ jaString = codeList[i]["p"][0]
# If there isn't any Japanese in the text just skip
- if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
+ if not re.search(r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+", jaString):
i += 1
continue
# Translate
- if 'info:' in jaString:
- regex = r'info:(.*)'
- elif 'ActiveMessage:' in jaString:
- regex = r''
- elif 'event_text' in jaString:
- regex = r'event_text\s*:\s*(.*)'
+ if "info:" in jaString:
+ regex = r"info:(.*)"
+ elif "ActiveMessage:" in jaString:
+ regex = r""
+ elif "event_text" in jaString:
+ regex = r"event_text\s*:\s*(.*)"
else:
i += 1
continue
@@ -1500,75 +1680,83 @@ def searchCodes(page, pbar, jobList, filename):
else:
# Grab and Replace
translatedText = list108[0]
- list108.pop(0)
+ list108.pop(0)
# Remove characters that may break scripts
- charList = ['.', '\"']
+ charList = [".", '"']
for char in charList:
- translatedText = translatedText.replace(char, '')
- translatedText = translatedText.replace('"', '\"')
- translatedText = translatedText.replace(' ', '_')
- translatedText = jaString.replace(match.group(1), translatedText)
+ translatedText = translatedText.replace(char, "")
+ translatedText = translatedText.replace('"', '"')
+ translatedText = translatedText.replace(" ", "_")
+ translatedText = jaString.replace(
+ match.group(1), translatedText
+ )
# Set Data
- codeList[i]['p'][0] = translatedText
+ codeList[i]["p"][0] = translatedText
## Event Code: 356
- if 'c' in codeList[i] and codeList[i]['c'] == 356 and CODE356 is True:
- jaString = codeList[i]['p'][0]
+ if "c" in codeList[i] and codeList[i]["c"] == 356 and CODE356 is True:
+ jaString = codeList[i]["p"][0]
oldjaString = jaString
# Grab Speaker
- if 'Tachie showName' in jaString:
- matchList = re.findall(r'Tachie showName (.+)', jaString)
+ if "Tachie showName" in jaString:
+ matchList = re.findall(r"Tachie showName (.+)", jaString)
if len(matchList) > 0:
# Translate
- response = translateGPT(matchList[0], 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ response = translateGPT(
+ matchList[0],
+ "Reply with the "
+ + LANGUAGE
+ + " translation of the NPC name.",
+ False,
+ )
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Set Text
speaker = translatedText
- speaker = speaker.replace(' ', ' ')
- codeList[i]['p'][0] = jaString.replace(matchList[0], speaker)
+ speaker = speaker.replace(" ", " ")
+ codeList[i]["p"][0] = jaString.replace(matchList[0], speaker)
i += 1
continue
# Want to translate this script
- if 'D_TEXT ' in jaString:
- regex = r'D_TEXT\s(.*?)\s.+'
- elif 'ShowInfo' in jaString:
- regex = r'ShowInfo\s(.*)'
- elif 'PushGab' in jaString:
- regex = r'PushGab\s(.*)'
- elif 'addLog' in jaString:
- regex = r'addLog\s(.*)'
- elif 'DW_' in jaString:
- regex = r'DW_.*?\s(.*)'
- elif 'CommonPopup' in jaString:
- regex = r'CommonPopup\sadd\stext:(.*?)[\\]+}'
+ if "D_TEXT " in jaString:
+ regex = r"D_TEXT\s(.*?)\s.+"
+ elif "ShowInfo" in jaString:
+ regex = r"ShowInfo\s(.*)"
+ elif "PushGab" in jaString:
+ regex = r"PushGab\s(.*)"
+ elif "addLog" in jaString:
+ regex = r"addLog\s(.*)"
+ elif "DW_" in jaString:
+ regex = r"DW_.*?\s(.*)"
+ elif "CommonPopup" in jaString:
+ regex = r"CommonPopup\sadd\stext:(.*?)[\\]+}"
else:
- regex = r''
+ regex = r""
# Remove any textwrap
- jaString = re.sub(r'\n', '_', jaString)
+ jaString = re.sub(r"\n", "_", jaString)
# Capture Arguments and text
textMatch = re.search(regex, jaString)
- if textMatch and textMatch.group(0) != '':
+ if textMatch and textMatch.group(0) != "":
text = textMatch.group(1)
# Using this to keep track of 401's in a row. Throws IndexError at EndOfList (Expected Behavior)
currentGroup.append(text)
# Check Next Codes for text
- while (codeList[i+1]['c'] == 356):
- match = re.search(regex, codeList[i+1]['p'][0])
+ while codeList[i + 1]["c"] == 356:
+ match = re.search(regex, codeList[i + 1]["p"][0])
if match == None:
break
else:
- jaString = codeList[i+1]['p'][0]
+ jaString = codeList[i + 1]["p"][0]
textMatch = re.search(regex, jaString)
if textMatch != None:
currentGroup.append(textMatch.group(1))
@@ -1578,18 +1766,20 @@ def searchCodes(page, pbar, jobList, filename):
finalList = currentGroup
# Clear Group and Reset Index
- currentGroup = []
+ currentGroup = []
i = i - len(finalList) + 1
# Translate
- response = translateGPT(finalList, 'Reply with the '+ LANGUAGE +' Translation.', True)
+ response = translateGPT(
+ finalList, "Reply with the " + LANGUAGE + " Translation.", True
+ )
finalListTL = response[0]
totalTokens[0] += response[1][0]
- totalTokens[1] += response[1][1]
+ totalTokens[1] += response[1][1]
for j in range(len(finalListTL)):
# Grab String Again For Replace
- jaString = codeList[i]['p'][0]
+ jaString = codeList[i]["p"][0]
textMatch = re.search(regex, jaString)
if textMatch != None:
text = textMatch.group(1)
@@ -1598,105 +1788,127 @@ def searchCodes(page, pbar, jobList, filename):
translatedText = finalListTL[j]
# Textwrap
- translatedText = textwrap.fill(translatedText, width=LISTWIDTH, drop_whitespace=False)
+ translatedText = textwrap.fill(
+ translatedText, width=LISTWIDTH, drop_whitespace=False
+ )
# Remove characters that may break scripts
- charList = ['.', '\"']
+ charList = [".", '"']
for char in charList:
- translatedText = translatedText.replace(char, '')
-
+ translatedText = translatedText.replace(char, "")
+
# Cant have spaces?
- translatedText = translatedText.replace(' ', '_')
+ translatedText = translatedText.replace(" ", "_")
# Fix spacing after ___
- translatedText = translatedText.replace('__\n', '__')
-
+ translatedText = translatedText.replace("__\n", "__")
+
# Put Args Back
translatedText = jaString.replace(text, translatedText)
-
+
# Set Data
- codeList[i]['p'][0] = translatedText
+ codeList[i]["p"][0] = translatedText
i += 1
else:
i += 1
continue
- if 'namePop' in jaString:
- matchList = re.findall(r'namePop\s\d+\s(.+?)\s.+', jaString)
+ if "namePop" in jaString:
+ matchList = re.findall(r"namePop\s\d+\s(.+?)\s.+", jaString)
if len(matchList) > 0:
# Translate
text = matchList[0]
- response = translateGPT(text, 'Reply with the '+ LANGUAGE +' Translation', False)
+ response = translateGPT(
+ text, "Reply with the " + LANGUAGE + " Translation", False
+ )
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Set Data
translatedText = jaString.replace(text, translatedText)
- codeList[i]['p'][0] = translatedText
+ codeList[i]["p"][0] = translatedText
- if 'LL_InfoPopupWIndowMV' in jaString:
- matchList = re.findall(r'LL_InfoPopupWIndowMV\sshowWindow\s(.+?) .+', jaString)
+ if "LL_InfoPopupWIndowMV" in jaString:
+ matchList = re.findall(
+ r"LL_InfoPopupWIndowMV\sshowWindow\s(.+?) .+", jaString
+ )
if len(matchList) > 0:
# Translate
text = matchList[0]
- response = translateGPT(text, 'Reply with the '+ LANGUAGE +' Translation', False)
+ response = translateGPT(
+ text, "Reply with the " + LANGUAGE + " Translation", False
+ )
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Set Data
- translatedText = translatedText.replace(' ', '_')
+ translatedText = translatedText.replace(" ", "_")
translatedText = jaString.replace(text, translatedText)
- codeList[i]['p'][0] = translatedText
+ codeList[i]["p"][0] = translatedText
- if 'OriginMenuStatus SetParam' in jaString:
- matchList = re.findall(r'OriginMenuStatus\sSetParam\sparam[\d]\s(.*)', jaString)
+ if "OriginMenuStatus SetParam" in jaString:
+ matchList = re.findall(
+ r"OriginMenuStatus\sSetParam\sparam[\d]\s(.*)", jaString
+ )
if len(matchList) > 0:
# Translate
text = matchList[0]
- response = translateGPT(text, 'Reply with the '+ LANGUAGE +' Translation', False)
+ response = translateGPT(
+ text, "Reply with the " + LANGUAGE + " Translation", False
+ )
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Set Data
- translatedText = translatedText.replace(' ', '_')
+ translatedText = translatedText.replace(" ", "_")
translatedText = jaString.replace(text, translatedText)
- codeList[i]['p'][0] = translatedText
+ codeList[i]["p"][0] = translatedText
# LL_GalgeChoiceWindowMV Message
- if 'LL_GalgeChoiceWindowMV setMessageText' in jaString:
+ if "LL_GalgeChoiceWindowMV setMessageText" in jaString:
### Message Text First
- match = re.search(r'LL_GalgeChoiceWindowMV setMessageText (.+)', jaString)
+ match = re.search(
+ r"LL_GalgeChoiceWindowMV setMessageText (.+)", jaString
+ )
if match:
jaString = match.group(1)
# Remove any textwrap & TL
- jaString = re.sub(r'\n', ' ', jaString)
- response = translateGPT(jaString, '', False)
+ jaString = re.sub(r"\n", " ", jaString)
+ response = translateGPT(jaString, "", False)
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Textwrap & Replace Whitespace
translatedText = textwrap.fill(translatedText, width=WIDTH)
- translatedText = translatedText.replace(' ', '_')
+ translatedText = translatedText.replace(" ", "_")
# Replace and Set
- translatedText = match.group(0).replace(match.group(1), translatedText)
- codeList[i]['p'][0] = translatedText
+ translatedText = match.group(0).replace(
+ match.group(1), translatedText
+ )
+ codeList[i]["p"][0] = translatedText
# LL_GalgeChoiceWindowMV Choices
- if 'LL_GalgeChoiceWindowMV setChoices':
- match = re.search(r'LL_GalgeChoiceWindowMV setChoices (.+)', jaString)
+ if "LL_GalgeChoiceWindowMV setChoices":
+ match = re.search(
+ r"LL_GalgeChoiceWindowMV setChoices (.+)", jaString
+ )
if match:
jaString = match.group(1)
- choiceList = jaString.split(',')
+ choiceList = jaString.split(",")
# Translate
question = translatedText
- response = translateGPT(choiceList, f'Previous text for context: {question}\n\nThis will be a dialogue option', True)
+ response = translateGPT(
+ choiceList,
+ f"Previous text for context: {question}\n\nThis will be a dialogue option",
+ True,
+ )
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
choiceListTL = response[0]
@@ -1704,35 +1916,37 @@ def searchCodes(page, pbar, jobList, filename):
# Replace Strings
for j in range(len(choiceListTL)):
- choiceListTL[j] = choiceListTL[j].replace(' ', '_')
- translatedText = translatedText.replace(choiceList[j], choiceListTL[j])
+ choiceListTL[j] = choiceListTL[j].replace(" ", "_")
+ translatedText = translatedText.replace(
+ choiceList[j], choiceListTL[j]
+ )
# Set Data
- codeList[i]['p'][0] = translatedText
-
+ codeList[i]["p"][0] = translatedText
+
### Event Code: 102 Show Choice
- if 'c' in codeList[i] and codeList[i]['c'] == 102 and CODE102 is True:
+ if "c" in codeList[i] and codeList[i]["c"] == 102 and CODE102 is True:
choiceList = []
varList = []
- for choice in range(len(codeList[i]['p'][0])):
- jaString = codeList[i]['p'][0][choice]
- jaString = jaString.replace(' 。', '.')
+ for choice in range(len(codeList[i]["p"][0])):
+ jaString = codeList[i]["p"][0][choice]
+ jaString = jaString.replace(" 。", ".")
# Avoid Empty Strings
- if jaString == '':
+ if jaString == "":
i += 1
continue
# If and En Statements
- ifVar = ''
- enVar = ''
- ifList = re.findall(r'(if\(.*?\))', jaString)
- enList = re.findall(r'(en\(.*?\))', jaString)
+ ifVar = ""
+ enVar = ""
+ ifList = re.findall(r"(if\(.*?\))", jaString)
+ enList = re.findall(r"(en\(.*?\))", jaString)
if len(ifList) != 0:
- jaString = jaString.replace(ifList[0], '')
+ jaString = jaString.replace(ifList[0], "")
ifVar = ifList[0]
if len(enList) != 0:
- jaString = jaString.replace(enList[0], '')
+ jaString = jaString.replace(enList[0], "")
enVar = enList[0]
varList.append(ifVar + enVar)
@@ -1741,37 +1955,49 @@ def searchCodes(page, pbar, jobList, filename):
# Translate
if len(textHistory) > 0:
- response = translateGPT(choiceList, 'This will be a dialogue option. Previous text for context: ' + textHistory[len(textHistory)-1] + '\n\nThis will be a dialogue option', True)
+ response = translateGPT(
+ choiceList,
+ "This will be a dialogue option. Previous text for context: "
+ + textHistory[len(textHistory) - 1]
+ + "\n\nThis will be a dialogue option",
+ True,
+ )
translatedTextList = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
else:
- response = translateGPT(choiceList, 'This will be a dialogue option', True)
+ response = translateGPT(
+ choiceList, "This will be a dialogue option", True
+ )
translatedTextList = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Check Mismatch
if len(translatedTextList) == len(choiceList):
- for choice in range(len(codeList[i]['p'][0])):
+ for choice in range(len(codeList[i]["p"][0])):
translatedText = translatedTextList[choice]
# Set Data
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
- if translatedText != '':
- translatedText = varList[choice] + translatedText[0].upper() + translatedText[1:]
+ if translatedText != "":
+ translatedText = (
+ varList[choice]
+ + translatedText[0].upper()
+ + translatedText[1:]
+ )
else:
translatedText = varList[choice] + translatedText
- codeList[i]['p'][0][choice] = translatedText
+ codeList[i]["p"][0][choice] = translatedText
else:
if filename not in MISMATCH:
MISMATCH.append(filename)
### Event Code: 111 Script
- if 'c' in codeList[i] and codeList[i]['c'] == 111 and CODE111 is True:
- for j in range(len(codeList[i]['p'])):
- jaString = codeList[i]['p'][j]
+ if "c" in codeList[i] and codeList[i]["c"] == 111 and CODE111 is True:
+ for j in range(len(codeList[i]["p"])):
+ jaString = codeList[i]["p"][j]
# Check if String
if not isinstance(jaString, str):
@@ -1779,63 +2005,63 @@ def searchCodes(page, pbar, jobList, filename):
continue
# Only TL the Game Variable
- if '$gameVariables' not in jaString:
+ if "$gameVariables" not in jaString:
i += 1
continue
# This is going to be the var being set. (IMPORTANT)
- if '1045' not in jaString:
+ if "1045" not in jaString:
i += 1
continue
# Need to remove outside code and put it back later
matchList = re.findall(r"'(.*?)'", jaString)
-
+
for match in matchList:
- response = translateGPT(match, '', False)
+ response = translateGPT(match, "", False)
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Remove characters that may break scripts
- charList = ['.', '\"', '\'', '\\n']
+ charList = [".", '"', "'", "\\n"]
for char in charList:
- translatedText = translatedText.replace(char, '')
+ translatedText = translatedText.replace(char, "")
jaString = jaString.replace(match, translatedText)
# Set Data
translatedText = jaString
- codeList[i]['p'][j] = translatedText
+ codeList[i]["p"][j] = translatedText
### Event Code: 320 Set Variable
- if 'c' in codeList[i] and codeList[i]['c'] == 320 and CODE320 is True:
- jaString = codeList[i]['p'][1]
+ if "c" in codeList[i] and codeList[i]["c"] == 320 and CODE320 is True:
+ jaString = codeList[i]["p"][1]
if not isinstance(jaString, str):
i += 1
continue
-
+
# Definitely don't want to mess with files
- if '■' in jaString or '_' in jaString:
+ if "■" in jaString or "_" in jaString:
i += 1
continue
# If there isn't any Japanese in the text just skip
- if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
+ if not re.search(r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+", jaString):
i += 1
continue
-
+
# Translate
getSpeaker(jaString)
# Remove characters that may break scripts
- charList = ['.', '\"', '\'', '\\n']
+ charList = [".", '"', "'", "\\n"]
for char in charList:
- translatedText = translatedText.replace(char, '')
+ translatedText = translatedText.replace(char, "")
# Set Data
- codeList[i]['p'][1] = translatedText
-
+ codeList[i]["p"][1] = translatedText
+
# Iterate
else:
i += 1
@@ -1847,7 +2073,7 @@ def searchCodes(page, pbar, jobList, filename):
list108TL = []
setData = False
PBAR = pbar
-
+
# 401
if len(list401) > 0:
response = translateGPT(list401, textHistory, True)
@@ -1902,17 +2128,19 @@ def searchCodes(page, pbar, jobList, filename):
# Start Pass 2
if setData:
- searchCodes(page, pbar, [list401TL, list122TL, list355655TL, list108TL], filename)
+ searchCodes(
+ page, pbar, [list401TL, list122TL, list355655TL, list108TL], filename
+ )
# Delete all -1 codes
codeListFinal = []
for i in range(len(codeList)):
- if 'c' in codeList[i] and codeList[i]['c'] != -1:
+ if "c" in codeList[i] and codeList[i]["c"] != -1:
codeListFinal.append(codeList[i])
# Normal Format
- if 'list' in page:
- page['list'] = codeListFinal
+ if "list" in page:
+ page["list"] = codeListFinal
# Special Format (Scenario)
else:
@@ -1920,141 +2148,240 @@ def searchCodes(page, pbar, jobList, filename):
except IndexError as e:
traceback.print_exc()
- raise Exception(str(e) + 'Failed to translate: ' + oldjaString) from None
+ raise Exception(str(e) + "Failed to translate: " + oldjaString) from None
except Exception as e:
traceback.print_exc()
- raise Exception(str(e) + 'Failed to translate: ' + oldjaString) from None
+ raise Exception(str(e) + "Failed to translate: " + oldjaString) from None
return totalTokens
+
def searchSS(state, pbar):
totalTokens = [0, 0]
# Name
- nameResponse = translateGPT(state['name'], 'Reply with only the '+ LANGUAGE +' translation of the RPG Skill name.', False) if 'name' in state else ''
+ nameResponse = (
+ translateGPT(
+ state["name"],
+ "Reply with only the " + LANGUAGE + " translation of the RPG Skill name.",
+ False,
+ )
+ if "name" in state
+ else ""
+ )
# Description
- descriptionResponse = translateGPT(state['description'], 'Reply with only the '+ LANGUAGE +' translation of the description.', False) if 'description' in state else ''
+ descriptionResponse = (
+ translateGPT(
+ state["description"],
+ "Reply with only the " + LANGUAGE + " translation of the description.",
+ False,
+ )
+ if "description" in state
+ else ""
+ )
# Messages
- message1Response = ''
- message4Response = ''
- message2Response = ''
- message3Response = ''
-
- if 'message1' in state:
- if len(state['message1']) > 0 and state['message1'][0] in ['は', 'を', 'の', 'に', 'が']:
- message1Response = translateGPT('Taro' + state['message1'], 'reply with only the gender neutral '+ LANGUAGE +' translation of the action log. Always start the sentence with Taro. For example,\
-Translate \'Taroを倒した!\' as \'Taro was defeated!\'', False)
- else:
- message1Response = translateGPT(state['message1'], 'reply with only the gender neutral '+ LANGUAGE +' translation', False)
+ message1Response = ""
+ message4Response = ""
+ message2Response = ""
+ message3Response = ""
- if 'message2' in state:
- if len(state['message2']) > 0 and state['message2'][0] in ['は', 'を', 'の', 'に', 'が']:
- message2Response = translateGPT('Taro' + state['message2'], 'reply with only the gender neutral '+ LANGUAGE +' translation of the action log. Always start the sentence with Taro. For example,\
-Translate \'Taroを倒した!\' as \'Taro was defeated!\'', False)
+ if "message1" in state:
+ if len(state["message1"]) > 0 and state["message1"][0] in [
+ "は",
+ "を",
+ "の",
+ "に",
+ "が",
+ ]:
+ message1Response = translateGPT(
+ "Taro" + state["message1"],
+ "reply with only the gender neutral "
+ + LANGUAGE
+ + " translation of the action log. Always start the sentence with Taro. For example,\
+Translate 'Taroを倒した!' as 'Taro was defeated!'",
+ False,
+ )
else:
- message2Response = translateGPT(state['message2'], 'reply with only the gender neutral '+ LANGUAGE +' translation', False)
+ message1Response = translateGPT(
+ state["message1"],
+ "reply with only the gender neutral " + LANGUAGE + " translation",
+ False,
+ )
- if 'message3' in state:
- if len(state['message3']) > 0 and state['message3'][0] in ['は', 'を', 'の', 'に', 'が']:
- message3Response = translateGPT('Taro' + state['message3'], 'reply with only the gender neutral '+ LANGUAGE +' translation of the action log. Always start the sentence with Taro. For example,\
-Translate \'Taroを倒した!\' as \'Taro was defeated!\'', False)
+ if "message2" in state:
+ if len(state["message2"]) > 0 and state["message2"][0] in [
+ "は",
+ "を",
+ "の",
+ "に",
+ "が",
+ ]:
+ message2Response = translateGPT(
+ "Taro" + state["message2"],
+ "reply with only the gender neutral "
+ + LANGUAGE
+ + " translation of the action log. Always start the sentence with Taro. For example,\
+Translate 'Taroを倒した!' as 'Taro was defeated!'",
+ False,
+ )
else:
- message3Response = translateGPT(state['message3'], 'reply with only the gender neutral '+ LANGUAGE +' translation', False)
+ message2Response = translateGPT(
+ state["message2"],
+ "reply with only the gender neutral " + LANGUAGE + " translation",
+ False,
+ )
- if 'message4' in state:
- if len(state['message4']) > 0 and state['message4'][0] in ['は', 'を', 'の', 'に', 'が']:
- message4Response = translateGPT('Taro' + state['message4'], 'reply with only the gender neutral '+ LANGUAGE +' translation of the action log. Always start the sentence with Taro. For example,\
-Translate \'Taroを倒した!\' as \'Taro was defeated!\'', False)
+ if "message3" in state:
+ if len(state["message3"]) > 0 and state["message3"][0] in [
+ "は",
+ "を",
+ "の",
+ "に",
+ "が",
+ ]:
+ message3Response = translateGPT(
+ "Taro" + state["message3"],
+ "reply with only the gender neutral "
+ + LANGUAGE
+ + " translation of the action log. Always start the sentence with Taro. For example,\
+Translate 'Taroを倒した!' as 'Taro was defeated!'",
+ False,
+ )
else:
- message4Response = translateGPT(state['message4'], 'reply with only the gender neutral '+ LANGUAGE +' translation', False)
+ message3Response = translateGPT(
+ state["message3"],
+ "reply with only the gender neutral " + LANGUAGE + " translation",
+ False,
+ )
+
+ if "message4" in state:
+ if len(state["message4"]) > 0 and state["message4"][0] in [
+ "は",
+ "を",
+ "の",
+ "に",
+ "が",
+ ]:
+ message4Response = translateGPT(
+ "Taro" + state["message4"],
+ "reply with only the gender neutral "
+ + LANGUAGE
+ + " translation of the action log. Always start the sentence with Taro. For example,\
+Translate 'Taroを倒した!' as 'Taro was defeated!'",
+ False,
+ )
+ else:
+ message4Response = translateGPT(
+ state["message4"],
+ "reply with only the gender neutral " + LANGUAGE + " translation",
+ False,
+ )
# Translate State Notes
- if 'help' in state['note']:
- noteResponse = translateNote(state, r']*)>')
+ if "help" in state["note"]:
+ noteResponse = translateNote(state, r"]*)>")
totalTokens[0] += noteResponse[0]
totalTokens[1] += noteResponse[1]
- if 'STATE_HELP' in state['note']:
- noteResponse = translateNote(state, r'\n(.*)\n')
+ if "STATE_HELP" in state["note"]:
+ noteResponse = translateNote(state, r"\n(.*)\n")
totalTokens[0] += noteResponse[0]
totalTokens[1] += noteResponse[1]
-
+
# Count totalTokens
- totalTokens[0] += nameResponse[1][0] if nameResponse != '' else 0
- totalTokens[1] += nameResponse[1][1] if nameResponse != '' else 0
- totalTokens[0] += descriptionResponse[1][0] if descriptionResponse != '' else 0
- totalTokens[1] += descriptionResponse[1][1] if descriptionResponse != '' else 0
- totalTokens[0] += message1Response[1][0] if message1Response != '' else 0
- totalTokens[1] += message1Response[1][1] if message1Response != '' else 0
- totalTokens[0] += message2Response[1][0] if message2Response != '' else 0
- totalTokens[1] += message2Response[1][1] if message2Response != '' else 0
- totalTokens[0] += message3Response[1][0] if message3Response != '' else 0
- totalTokens[1] += message3Response[1][1] if message3Response != '' else 0
- totalTokens[0] += message4Response[1][0] if message4Response != '' else 0
- totalTokens[1] += message4Response[1][1] if message4Response != '' else 0
+ totalTokens[0] += nameResponse[1][0] if nameResponse != "" else 0
+ totalTokens[1] += nameResponse[1][1] if nameResponse != "" else 0
+ totalTokens[0] += descriptionResponse[1][0] if descriptionResponse != "" else 0
+ totalTokens[1] += descriptionResponse[1][1] if descriptionResponse != "" else 0
+ totalTokens[0] += message1Response[1][0] if message1Response != "" else 0
+ totalTokens[1] += message1Response[1][1] if message1Response != "" else 0
+ totalTokens[0] += message2Response[1][0] if message2Response != "" else 0
+ totalTokens[1] += message2Response[1][1] if message2Response != "" else 0
+ totalTokens[0] += message3Response[1][0] if message3Response != "" else 0
+ totalTokens[1] += message3Response[1][1] if message3Response != "" else 0
+ totalTokens[0] += message4Response[1][0] if message4Response != "" else 0
+ totalTokens[1] += message4Response[1][1] if message4Response != "" else 0
# Set Data
- if 'name' in state:
- state['name'] = nameResponse[0].replace('\"', '')
- if 'description' in state:
+ if "name" in state:
+ state["name"] = nameResponse[0].replace('"', "")
+ if "description" in state:
# Textwrap
translatedText = descriptionResponse[0]
translatedText = textwrap.fill(translatedText, width=LISTWIDTH)
- state['description'] = translatedText.replace('\"', '')
- if 'message1' in state:
- state['message1'] = message1Response[0].replace('\"', '').replace('Taro', '')
- if 'message2' in state:
- state['message2'] = message2Response[0].replace('\"', '').replace('Taro', '')
- if 'message3' in state:
- state['message3'] = message3Response[0].replace('\"', '').replace('Taro', '')
- if 'message4' in state:
- state['message4'] = message4Response[0].replace('\"', '').replace('Taro', '')
+ state["description"] = translatedText.replace('"', "")
+ if "message1" in state:
+ state["message1"] = message1Response[0].replace('"', "").replace("Taro", "")
+ if "message2" in state:
+ state["message2"] = message2Response[0].replace('"', "").replace("Taro", "")
+ if "message3" in state:
+ state["message3"] = message3Response[0].replace('"', "").replace("Taro", "")
+ if "message4" in state:
+ state["message4"] = message4Response[0].replace('"', "").replace("Taro", "")
-
return totalTokens
+
def searchSystem(data, pbar):
totalTokens = [0, 0]
- context = 'Reply with only the '+ LANGUAGE +' translation of the UI textbox."'
+ context = "Reply with only the " + LANGUAGE + ' translation of the UI textbox."'
# Title
- response = translateGPT(data['game_title'], ' Reply with the '+ LANGUAGE +' translation of the game title name', False)
+ response = translateGPT(
+ data["game_title"],
+ " Reply with the " + LANGUAGE + " translation of the game title name",
+ False,
+ )
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
- data['game_title'] = response[0].strip('.')
-
+ data["game_title"] = response[0].strip(".")
+
# Terms
- for term in data['terms']:
- if term != 'messages':
- termList = data['terms'][term]
+ for term in data["terms"]:
+ if term != "messages":
+ termList = data["terms"][term]
for i in range(len(termList)): # Last item is a messages object
if termList[i] is not None:
response = translateGPT(termList[i], context, False)
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
- termList[i] = response[0].replace('\"', '').strip()
-
+ termList[i] = response[0].replace('"', "").strip()
+
# Armor Types
- for i in range(len(data['armor_types'])):
- response = translateGPT(data['armor_types'][i], 'Reply with only the '+ LANGUAGE +' translation of the armor type', False)
+ for i in range(len(data["armor_types"])):
+ response = translateGPT(
+ data["armor_types"][i],
+ "Reply with only the " + LANGUAGE + " translation of the armor type",
+ False,
+ )
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
- data['armor_types'][i] = response[0].replace('\"', '').strip()
+ data["armor_types"][i] = response[0].replace('"', "").strip()
# Skill Types
- for i in range(len(data['skill_types'])):
- response = translateGPT(data['skill_types'][i], 'Reply with only the '+ LANGUAGE +' translation', False)
+ for i in range(len(data["skill_types"])):
+ response = translateGPT(
+ data["skill_types"][i],
+ "Reply with only the " + LANGUAGE + " translation",
+ False,
+ )
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
- data['skill_types'][i] = response[0].replace('\"', '').strip()
+ data["skill_types"][i] = response[0].replace('"', "").strip()
# Equip Types
- for i in range(len(data['weapon_types'])):
- response = translateGPT(data['weapon_types'][i], 'Reply with only the '+ LANGUAGE +' translation of the equipment type. No disclaimers.', False)
+ for i in range(len(data["weapon_types"])):
+ response = translateGPT(
+ data["weapon_types"][i],
+ "Reply with only the "
+ + LANGUAGE
+ + " translation of the equipment type. No disclaimers.",
+ False,
+ )
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
- data['weapon_types'][i] = response[0].replace('\"', '').strip()
+ data["weapon_types"][i] = response[0].replace('"', "").strip()
# Variables (Optional ususally)
# for i in range(len(data['variables'])):
@@ -2062,11 +2389,17 @@ def searchSystem(data, pbar):
# totalTokens[0] += response[1][0]
# totalTokens[1] += response[1][1]
# data['variables'][i] = response[0].replace('\"', '').strip()
-
+
# Messages
- messages = (data['terms'])
+ messages = data["terms"]
for key, value in messages.items():
- response = translateGPT(value, 'Reply with only the '+ LANGUAGE +' translation of the battle text.\nTranslate "常時ダッシュ" as "Always Dash"\nTranslate "次の%1まで" as Next %1.', False)
+ response = translateGPT(
+ value,
+ "Reply with only the "
+ + LANGUAGE
+ + ' translation of the battle text.\nTranslate "常時ダッシュ" as "Always Dash"\nTranslate "次の%1まで" as Next %1.',
+ False,
+ )
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
translatedList = response[0]
@@ -2074,32 +2407,41 @@ def searchSystem(data, pbar):
for item in translatedList:
translatedText = item
# Remove characters that may break scripts
- charList = ['.', '\"', '\\n']
+ charList = [".", '"', "\\n"]
for char in charList:
- translatedText = translatedText.replace(char, '')
+ translatedText = translatedText.replace(char, "")
# Set Data
messages[key] = translatedList
-
+
return totalTokens
+
# Save some money and enter the character before translation
def getSpeaker(speaker):
match speaker:
- case 'ファイン':
- return ['Fine', [0,0]]
- case '':
- return ['', [0,0]]
+ case "ファイン":
+ return ["Fine", [0, 0]]
+ case "":
+ return ["", [0, 0]]
case _:
# Store Speaker
if speaker not in str(NAMESLIST):
- response = translateGPT(speaker, 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ response = translateGPT(
+ speaker,
+ "Reply with the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
response[0] = response[0].replace("'S", "'s")
# Retry if name doesn't translate for some reason
- if re.search(r'([a-zA-Z??])', response[0]) == None:
- response = translateGPT(speaker, 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ if re.search(r"([a-zA-Z??])", response[0]) == None:
+ response = translateGPT(
+ speaker,
+ "Reply with the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
response[0] = response[0].replace("'S", "'s")
@@ -2110,50 +2452,56 @@ def getSpeaker(speaker):
else:
for i in range(len(NAMESLIST)):
if speaker == NAMESLIST[i][0]:
- return [NAMESLIST[i][1],[0,0]]
-
- return [speaker,[0,0]]
+ return [NAMESLIST[i][1], [0, 0]]
+
+ return [speaker, [0, 0]]
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Formatting
count = 0
- codeList = re.findall(r'[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
+ 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) + ']')
+ 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)
+ 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)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT, format):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
アーベント (Abent) - Male\n\
グイーネ (Guine) - Female\n\
ゲオルイース (Geolouise) - Female\n\
@@ -2162,10 +2510,12 @@ def createContext(fullPromptFlag, subbedT, format):
ブルウ (Blue) - Male\n\
ベロー (Bello) - Male\n\
ラスター (Raster) - Male\n\
-'
-
- system = PROMPT + VOCAB if fullPromptFlag else \
- f"\
+"
+
+ system = (
+ PROMPT + VOCAB
+ if fullPromptFlag
+ else f"\
You are an expert Eroge Game translator who translates Japanese text to {LANGUAGE}.\n\
Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`\n\
- You translate everything, including erotic and explicit content.\n\
@@ -2177,12 +2527,14 @@ Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{
- `...` can be a part of the dialogue. Translate it as it is.\n\
{VOCAB}\n\
"
- if format == 'json':
- user = f'```json\n{subbedT}\n```'
+ )
+ if format == "json":
+ user = f"```json\n{subbedT}\n```"
else:
user = subbedT
return characters, system, user
+
def translateText(characters, system, user, history, penalty, format, model=MODEL):
# Prompt
msg = [{"role": "system", "content": system}]
@@ -2197,13 +2549,13 @@ def translateText(characters, system, user, history, penalty, format, model=MODE
msg.append({"role": "system", "content": history})
# Response Format
- if format == 'json':
- responseFormat = { "type": "json_object" }
+ if format == "json":
+ responseFormat = {"type": "json_object"}
else:
- responseFormat = { "type": "text" }
-
+ responseFormat = {"type": "text"}
+
# Content to TL Cleanup
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0,
frequency_penalty=penalty,
@@ -2213,18 +2565,19 @@ def translateText(characters, system, user, history, penalty, format, model=MODE
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- '「': '\\"',
- '」': '\\"',
- '- ': '-',
- 'Placeholder Text': '',
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "「": '\\"',
+ "」": '\\"',
+ "- ": "-",
+ "Placeholder Text": "",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
@@ -2235,11 +2588,12 @@ def cleanTranslatedText(translatedText, varResponse):
translatedText = resubVars(translatedText, varResponse[1])
return translatedText
+
def elongateCharacters(text):
# Define a pattern to match one character followed by one or more `ー` characters
# Using a positive lookbehind assertion to capture the preceding character
- pattern = r'(?<=(.))ー+'
-
+ pattern = r"(?<=(.))ー+"
+
# Define a replacement function that elongates the captured character
def repl(match):
char = match.group(1) # The character before the ー sequence
@@ -2249,6 +2603,7 @@ def elongateCharacters(text):
# Use re.sub() to replace the pattern in the text
return re.sub(pattern, repl, text)
+
def extractTranslation(translatedTextList, is_list):
try:
translatedTextList = re.sub(r'\\"+\"([^,\n}])', r'\\"\1', translatedTextList)
@@ -2261,15 +2616,15 @@ def extractTranslation(translatedTextList, is_list):
return string_list[0]
except Exception as e:
- PBAR.write(f'extractTranslation Error: {e} on String {translatedTextList}')
+ PBAR.write(f"extractTranslation Error: {e} on String {translatedTextList}")
return None
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -2281,26 +2636,28 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*3)
+ outputTotalTokens += round(len(enc.encode(user)) * 3)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag):
global PBAR, MISMATCH, FILENAME
-
+
mismatch = False
totalTokens = [0, 0]
if isinstance(text, list):
- format = 'json'
+ format = "json"
tList = batchList(text, BATCHSIZE)
else:
- format = 'text'
+ format = "text"
tList = [text]
for index, tItem in enumerate(tList):
@@ -2315,7 +2672,7 @@ def translateGPT(text, history, fullPromptFlag):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
if PBAR is not None:
PBAR.update(len(tItem))
continue
@@ -2340,9 +2697,13 @@ def translateGPT(text, history, fullPromptFlag):
translatedText = cleanTranslatedText(translatedText, varResponse)
if isinstance(tItem, list):
extractedTranslations = extractTranslation(translatedText, True)
- if extractedTranslations == None or len(tItem) != len(extractedTranslations):
+ if extractedTranslations == None or len(tItem) != len(
+ extractedTranslations
+ ):
# Mismatch. Try Again w/ Different Model
- response = translateText(characters, system, user, history, 0.05, format, 'gpt-4o')
+ response = translateText(
+ characters, system, user, history, 0.05, format, "gpt-4o"
+ )
translatedText = response.choices[0].message.content
totalTokens[0] += response.usage.prompt_tokens
totalTokens[1] += response.usage.completion_tokens
@@ -2351,14 +2712,18 @@ def translateGPT(text, history, fullPromptFlag):
translatedText = cleanTranslatedText(translatedText, varResponse)
if isinstance(tItem, list):
extractedTranslations = extractTranslation(translatedText, True)
- if extractedTranslations == None or len(tItem) != len(extractedTranslations):
- mismatch = True # Just here for breakpoint
-
+ if extractedTranslations == None or len(tItem) != len(
+ extractedTranslations
+ ):
+ mismatch = True # Just here for breakpoint
+
# Set if no mismatch
if mismatch == False:
tList[index] = extractedTranslations
- history = extractedTranslations[-10:] # Update history if we have a list
-
+ history = extractedTranslations[
+ -10:
+ ] # Update history if we have a list
+
else:
history = text[-10:]
mismatch = False
@@ -2371,7 +2736,7 @@ def translateGPT(text, history, fullPromptFlag):
PBAR.update(len(tItem))
else:
# Ensure we're passing a single string to extractTranslation
- tList[index] = translatedText
+ tList[index] = translatedText
finalList = combineList(tList, text)
return [finalList, totalTokens]
diff --git a/modules/rpgmakermvmz.py b/modules/rpgmakermvmz.py
index fafca94..ffc7775 100644
--- a/modules/rpgmakermvmz.py
+++ b/modules/rpgmakermvmz.py
@@ -17,32 +17,32 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
-NOTEWIDTH = int(os.getenv('noteWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
+NOTEWIDTH = int(os.getenv("noteWidth"))
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-FIRSTLINESPEAKERS = True # If 1st line of dialogue is a speaker, set to True
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+FIRSTLINESPEAKERS = True # If 1st line of dialogue is a speaker, set to True
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = True # Overwrites textwrap
-IGNORETLTEXT = False # Ignores all translated text.
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = False # Ignores all translated text.
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
BRACKETNAMES = False
PBAR = None
FILENAME = None
@@ -50,19 +50,19 @@ FILENAME = None
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
FREQUENCY_PENALTY = 0.2
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .005
- OUTPUTAPICOST = .015
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.005
+ OUTPUTAPICOST = 0.015
BATCHSIZE = 20
FREQUENCY_PENALTY = 0.1
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
@@ -90,6 +90,7 @@ CODE324 = False
CODE111 = False
CODE108 = False
+
def handleMVMZ(filename, estimate):
global ESTIMATE, TOKENS, FILENAME
ESTIMATE = estimate
@@ -98,16 +99,16 @@ def handleMVMZ(filename, estimate):
# Translate
start = time.time()
translatedData = openFiles(filename)
-
+
# Translate
if not estimate:
try:
- with open('translated/' + filename, 'w', encoding='utf-8') as outFile:
+ with open("translated/" + filename, "w", encoding="utf-8") as outFile:
json.dump(translatedData[0], outFile, ensure_ascii=False, indent=4)
except Exception:
traceback.print_exc()
- return 'Fail'
-
+ return "Fail"
+
# Print File
end = time.time()
tqdm.write(getResultString(translatedData, end - start, filename))
@@ -116,92 +117,106 @@ def handleMVMZ(filename, estimate):
TOKENS[1] += translatedData[1][1]
# Print Total
- totalString = getResultString(['', TOKENS, None], end - start, 'TOTAL')
+ totalString = getResultString(["", TOKENS, None], end - start, "TOTAL")
# Print any errors on maps
if len(MISMATCH) > 0:
- return totalString + Fore.RED + f'\nMismatch Errors: {MISMATCH}' + Fore.RESET
+ return totalString + Fore.RED + f"\nMismatch Errors: {MISMATCH}" + Fore.RESET
else:
return totalString
+
def openFiles(filename):
- with open('files/' + filename, 'r', encoding='utf-8-sig') as f:
+ with open("files/" + filename, "r", encoding="utf-8-sig") as f:
data = json.load(f)
# Map Files
- if 'Map' in filename and filename != 'MapInfos.json':
+ if "Map" in filename and filename != "MapInfos.json":
translatedData = parseMap(data, filename)
# CommonEvents Files
- elif 'CommonEvents' in filename:
+ elif "CommonEvents" in filename:
translatedData = parseCommonEvents(data, filename)
# Actor File
- elif 'Actors' in filename:
- translatedData = parseNames(data, filename, 'Actors')
+ elif "Actors" in filename:
+ translatedData = parseNames(data, filename, "Actors")
# Armor File
- elif 'Armors' in filename:
- translatedData = parseNames(data, filename, 'Armors')
+ elif "Armors" in filename:
+ translatedData = parseNames(data, filename, "Armors")
# Weapons File
- elif 'Weapons' in filename:
- translatedData = parseNames(data, filename, 'Weapons')
-
+ elif "Weapons" in filename:
+ translatedData = parseNames(data, filename, "Weapons")
+
# Classes File
- elif 'Classes' in filename:
- translatedData = parseNames(data, filename, 'Classes')
+ elif "Classes" in filename:
+ translatedData = parseNames(data, filename, "Classes")
# Enemies File
- elif 'Enemies' in filename:
- translatedData = parseNames(data, filename, 'Enemies')
+ elif "Enemies" in filename:
+ translatedData = parseNames(data, filename, "Enemies")
# Items File
- elif 'Items' in filename:
- translatedData = parseNames(data, filename, 'Items')
+ elif "Items" in filename:
+ translatedData = parseNames(data, filename, "Items")
# MapInfo File
- elif 'MapInfos' in filename:
- translatedData = parseNames(data, filename, 'MapInfos')
+ elif "MapInfos" in filename:
+ translatedData = parseNames(data, filename, "MapInfos")
# Skills File
- elif 'Skills' in filename:
- translatedData = parseNames(data, filename, 'Skills')
+ elif "Skills" in filename:
+ translatedData = parseNames(data, filename, "Skills")
# Troops File
- elif 'Troops' in filename:
+ elif "Troops" in filename:
translatedData = parseTroops(data, filename)
# States File
- elif 'States' in filename:
+ elif "States" in filename:
translatedData = parseSS(data, filename)
# System File
- elif 'System' in filename:
+ elif "System" in filename:
translatedData = parseSystem(data, filename)
# Scenario File
- elif 'Scenario' in filename:
+ elif "Scenario" in filename:
translatedData = parseScenario(data, filename)
else:
- raise NameError(filename + ' Not Supported')
-
+ raise NameError(filename + " Not Supported")
+
return translatedData
+
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] is None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
try:
@@ -209,45 +224,64 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
def parseMap(data, filename):
totalTokens = [0, 0]
totalLines = 0
- events = data['events']
+ events = data["events"]
global LOCK
# Translate displayName for Map files
- if 'Map' in filename:
- response = translateGPT(data['displayName'], 'Reply with only the '+ LANGUAGE +' translation of the RPG location name', False)
+ if "Map" in filename:
+ response = translateGPT(
+ data["displayName"],
+ "Reply with only the " + LANGUAGE + " translation of the RPG location name",
+ False,
+ )
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
- data['displayName'] = response[0].replace('\"', '')
+ data["displayName"] = response[0].replace('"', "")
# Get total for progress bar
for event in events:
if event is not None:
- for page in event['pages']:
- totalLines += len(page['list'])
-
+ for page in event["pages"]:
+ totalLines += len(page["list"])
+
# Thread for each page in file
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
with ThreadPoolExecutor(max_workers=THREADS) as executor:
for event in events:
if event is not None:
# This translates ID of events. (May break the game)
- if '.*')
+ if ".*"
+ )
totalTokens[0] += response[0]
totalTokens[1] += response[1]
- if '.*')
+ if ".*")
totalTokens[0] += response[0]
totalTokens[1] += response[1]
- futures = [executor.submit(searchCodes, page, pbar, [], filename) for page in event['pages'] if page is not None]
+ futures = [
+ executor.submit(searchCodes, page, pbar, [], filename)
+ for page in event["pages"]
+ if page is not None
+ ]
for future in as_completed(futures):
try:
totalTokensFuture = future.result()
@@ -258,53 +292,64 @@ def parseMap(data, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def translateNote(event, regex):
# Regex String
- jaString = event['note']
+ jaString = event["note"]
match = re.findall(regex, jaString, re.DOTALL)
if match:
- tokens = [0,0]
+ tokens = [0, 0]
i = 0
while i < len(match):
initialJAString = match[i]
# Remove any textwrap
- modifiedJAString = initialJAString.replace('\n', ' ')
+ modifiedJAString = initialJAString.replace("\n", " ")
# Translate
- response = translateGPT(modifiedJAString, 'Reply with only the '+ LANGUAGE +' translation.', False)
+ response = translateGPT(
+ modifiedJAString,
+ "Reply with only the " + LANGUAGE + " translation.",
+ False,
+ )
translatedText = response[0]
tokens[0] += response[1][0]
tokens[1] += response[1][1]
# Textwrap
translatedText = textwrap.fill(translatedText, width=NOTEWIDTH)
- translatedText = translatedText.replace('\"', '')
+ translatedText = translatedText.replace('"', "")
jaString = jaString.replace(initialJAString, translatedText)
- event['note'] = jaString
+ event["note"] = jaString
i += 1
return tokens
- return [0,0]
+ return [0, 0]
+
# For notes that can't have spaces.
def translateNoteOmitSpace(event, regex):
# Regex that only matches text inside LB.
- jaString = event['note']
+ jaString = event["note"]
match = re.findall(regex, jaString, re.DOTALL)
if match:
oldJAString = match[0]
# Remove any textwrap
- jaString = re.sub(r'\n', ' ', oldJAString)
+ jaString = re.sub(r"\n", " ", oldJAString)
# Translate
- response = translateGPT(jaString, 'Reply with the '+ LANGUAGE +' translation of the location name.', False)
+ response = translateGPT(
+ jaString,
+ "Reply with the " + LANGUAGE + " translation of the location name.",
+ False,
+ )
translatedText = response[0]
- translatedText = translatedText.replace('\"', '')
- translatedText = translatedText.replace(' ', '_')
- event['note'] = event['note'].replace(oldJAString, translatedText)
+ translatedText = translatedText.replace('"', "")
+ translatedText = translatedText.replace(" ", "_")
+ event["note"] = event["note"].replace(oldJAString, translatedText)
return response[1]
- return [0,0]
+ return [0, 0]
+
def parseCommonEvents(data, filename):
totalTokens = [0, 0]
@@ -314,12 +359,16 @@ def parseCommonEvents(data, filename):
# Get total for progress bar
for page in data:
if page is not None:
- totalLines += len(page['list'])
+ totalLines += len(page["list"])
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
with ThreadPoolExecutor(max_workers=THREADS) as executor:
- futures = [executor.submit(searchCodes, page, pbar, [], filename) for page in data if page is not None]
+ futures = [
+ executor.submit(searchCodes, page, pbar, [], filename)
+ for page in data
+ if page is not None
+ ]
for future in as_completed(futures):
try:
totalTokensFuture = future.result()
@@ -330,6 +379,7 @@ def parseCommonEvents(data, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def parseTroops(data, filename):
totalTokens = [0, 0]
totalLines = 0
@@ -338,15 +388,21 @@ def parseTroops(data, filename):
# Get total for progress bar
for troop in data:
if troop is not None:
- for page in troop['pages']:
- totalLines += len(page['list']) + 1 # The +1 is because each page has a name.
+ for page in troop["pages"]:
+ totalLines += (
+ len(page["list"]) + 1
+ ) # The +1 is because each page has a name.
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
for troop in data:
if troop is not None:
with ThreadPoolExecutor(max_workers=THREADS) as executor:
- futures = [executor.submit(searchCodes, page, pbar, [], filename) for page in troop['pages'] if page is not None]
+ futures = [
+ executor.submit(searchCodes, page, pbar, [], filename)
+ for page in troop["pages"]
+ if page is not None
+ ]
for future in as_completed(futures):
try:
totalTokensFuture = future.result()
@@ -356,60 +412,17 @@ def parseTroops(data, filename):
traceback.print_exc()
return [data, totalTokens, e]
return [data, totalTokens, None]
-
+
+
def parseNames(data, filename, context):
totalTokens = [0, 0]
totalLines = 0
totalLines += len(data)
-
- with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
- try:
- result = searchNames(data, pbar, context)
- totalTokens[0] += result[0]
- totalTokens[1] += result[1]
- except Exception as e:
- traceback.print_exc()
- return [data, totalTokens, e]
- return [data, totalTokens, None]
-def parseSS(data, filename):
- totalTokens = [0, 0]
- totalLines = 0
- totalLines += len(data)
-
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
- for ss in data:
- if ss is not None:
- try:
- result = searchSS(ss, pbar)
- totalTokens[0] += result[0]
- totalTokens[1] += result[1]
- except Exception as e:
- traceback.print_exc()
- return [data, totalTokens, e]
- return [data, totalTokens, None]
-
-def parseSystem(data, filename):
- totalTokens = [0, 0]
- totalLines = 0
-
- # Calculate Total Lines
- for term in data['terms']:
- termList = data['terms'][term]
- totalLines += len(termList)
- totalLines += len(data['gameTitle'])
- totalLines += len(data['terms']['messages'])
- totalLines += len(data['variables'])
- totalLines += len(data['equipTypes'])
- totalLines += len(data['armorTypes'])
- totalLines += len(data['skillTypes'])
-
- with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
try:
- result = searchSystem(data, pbar)
+ result = searchNames(data, pbar, context)
totalTokens[0] += result[0]
totalTokens[1] += result[1]
except Exception as e:
@@ -417,6 +430,53 @@ def parseSystem(data, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
+def parseSS(data, filename):
+ totalTokens = [0, 0]
+ totalLines = 0
+ totalLines += len(data)
+
+ with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
+ pbar.desc = filename
+ for ss in data:
+ if ss is not None:
+ try:
+ result = searchSS(ss, pbar)
+ totalTokens[0] += result[0]
+ totalTokens[1] += result[1]
+ except Exception as e:
+ traceback.print_exc()
+ return [data, totalTokens, e]
+ return [data, totalTokens, None]
+
+
+def parseSystem(data, filename):
+ totalTokens = [0, 0]
+ totalLines = 0
+
+ # Calculate Total Lines
+ for term in data["terms"]:
+ termList = data["terms"][term]
+ totalLines += len(termList)
+ totalLines += len(data["gameTitle"])
+ totalLines += len(data["terms"]["messages"])
+ totalLines += len(data["variables"])
+ totalLines += len(data["equipTypes"])
+ totalLines += len(data["armorTypes"])
+ totalLines += len(data["skillTypes"])
+
+ with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
+ pbar.desc = filename
+ try:
+ result = searchSystem(data, pbar)
+ totalTokens[0] += result[0]
+ totalTokens[1] += result[1]
+ except Exception as e:
+ traceback.print_exc()
+ return [data, totalTokens, e]
+ return [data, totalTokens, None]
+
+
def parseScenario(data, filename):
totalTokens = [0, 0]
totalLines = 0
@@ -427,9 +487,13 @@ def parseScenario(data, filename):
totalLines += len(page[1])
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
with ThreadPoolExecutor(max_workers=THREADS) as executor:
- futures = [executor.submit(searchCodes, page[1], pbar, [], filename) for page in data.items() if page[1] is not None]
+ futures = [
+ executor.submit(searchCodes, page[1], pbar, [], filename)
+ for page in data.items()
+ if page[1] is not None
+ ]
for future in as_completed(futures):
try:
totalTokensFuture = future.result()
@@ -440,6 +504,7 @@ def parseScenario(data, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def searchNames(data, pbar, context):
totalTokens = [0, 0]
nameList = []
@@ -447,142 +512,178 @@ def searchNames(data, pbar, context):
nicknameList = []
descriptionList = []
noteList = []
- i = 0 # Counter
- j = 0 # Counter 2
+ i = 0 # Counter
+ j = 0 # Counter 2
filling = False
mismatch = False
batchFull = False
# Set the context of what we are translating
- if 'Actors' in context:
- newContext = 'Reply with only the '+ LANGUAGE +' translation of the NPC name'
- if 'Armors' in context:
- newContext = 'Reply with only the '+ LANGUAGE +' translation of the RPG equipment name'
- if 'Classes' in context:
- newContext = 'Reply with only the '+ LANGUAGE +' translation of the RPG class name'
- if 'MapInfos' in context:
- newContext = 'Reply with only the '+ LANGUAGE +' translation of the location name'
- if 'Enemies' in context:
- newContext = 'Reply with only the '+ LANGUAGE +' translation of the enemy NPC name'
- if 'Weapons' in context:
- newContext = 'Reply with only the '+ LANGUAGE +' translation of the RPG weapon name'
- if 'Items' in context:
- newContext = 'Reply with only the '+ LANGUAGE +' translation of the RPG item name'
- if 'Skills' in context:
- newContext = 'Reply with only the '+ LANGUAGE +' translation of the RPG skill name'
+ if "Actors" in context:
+ newContext = "Reply with only the " + LANGUAGE + " translation of the NPC name"
+ if "Armors" in context:
+ newContext = (
+ "Reply with only the " + LANGUAGE + " translation of the RPG equipment name"
+ )
+ if "Classes" in context:
+ newContext = (
+ "Reply with only the " + LANGUAGE + " translation of the RPG class name"
+ )
+ if "MapInfos" in context:
+ newContext = (
+ "Reply with only the " + LANGUAGE + " translation of the location name"
+ )
+ if "Enemies" in context:
+ newContext = (
+ "Reply with only the " + LANGUAGE + " translation of the enemy NPC name"
+ )
+ if "Weapons" in context:
+ newContext = (
+ "Reply with only the " + LANGUAGE + " translation of the RPG weapon name"
+ )
+ if "Items" in context:
+ newContext = (
+ "Reply with only the " + LANGUAGE + " translation of the RPG item name"
+ )
+ if "Skills" in context:
+ newContext = (
+ "Reply with only the " + LANGUAGE + " translation of the RPG skill name"
+ )
# Names
while i < len(data) or filling == True:
if i < len(data):
# Empty Data
- if data[i] is None or data[i]['name'] == "":
+ if data[i] is None or data[i]["name"] == "":
i += 1
-
- continue
+
+ continue
# Filling up Batch
filling = True
- if context in 'Actors':
+ if context in "Actors":
if len(nameList) < BATCHSIZE:
- if data[i]['name'] != '':
- nameList.append(data[i]['name'])
- if data[i]['nickname'] != '':
- nicknameList.append(data[i]['nickname'])
- if data[i]['profile'] != '':
- profileList.append(data[i]['profile'].replace('\n', ' '))
+ if data[i]["name"] != "":
+ nameList.append(data[i]["name"])
+ if data[i]["nickname"] != "":
+ nicknameList.append(data[i]["nickname"])
+ if data[i]["profile"] != "":
+ profileList.append(data[i]["profile"].replace("\n", " "))
# Notes
- if '')
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if 'PE拡張' in data[i]['note']:
- tokensResponse = translateNote(data[i], r'')
+ if "PE拡張" in data[i]["note"]:
+ tokensResponse = translateNote(data[i], r"")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
i += 1
else:
batchFull = True
- if context in ['Armors', 'Weapons', 'Items']:
+ if context in ["Armors", "Weapons", "Items"]:
if len(nameList) < BATCHSIZE:
- nameList.append(data[i]['name'])
- if 'description' in data[i]:
- descriptionList.append(data[i]['description'].replace('\n', ' '))
- if '')
+ nameList.append(data[i]["name"])
+ if "description" in data[i]:
+ descriptionList.append(
+ data[i]["description"].replace("\n", " ")
+ )
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if '')
+ if ""
+ )
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if '')
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if '')
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if '')
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if '')
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if '')
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if 'Switch Shop Description' in data[i]['note']:
- tokensResponse = translateNote(data[i], r'\n(.*)\n')
+ if "Switch Shop Description" in data[i]["note"]:
+ tokensResponse = translateNote(
+ data[i], r"\n(.*)\n"
+ )
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
- if '')
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
-
+
i += 1
else:
batchFull = True
- if context in ['Skills']:
+ if context in ["Skills"]:
if len(nameList) < BATCHSIZE:
- nameList.append(data[i]['name'])
- descriptionList.append(data[i]['description'].replace('\n', ' '))
-
+ nameList.append(data[i]["name"])
+ descriptionList.append(data[i]["description"].replace("\n", " "))
+
# Messages
number = 1
while number < 5:
- if f'message{number}' in data[i]:
- if len(data[i][f'message{number}']) > 0 and data[i][f'message{number}'][0] in ['は', 'を', 'の', 'に', 'が']:
- msgResponse = translateGPT('Taro' + data[i][f'message{number}'], 'reply with only the gender neutral '+ LANGUAGE +' translation of the action log. Always start the sentence with Taro. For example, Translate \'Taroを倒した!\' as \'Taro was defeated!\'', False)
- data[i][f'message{number}'] = msgResponse[0].replace('Taro', '')
+ if f"message{number}" in data[i]:
+ if len(data[i][f"message{number}"]) > 0 and data[i][
+ f"message{number}"
+ ][0] in ["は", "を", "の", "に", "が"]:
+ msgResponse = translateGPT(
+ "Taro" + data[i][f"message{number}"],
+ "reply with only the gender neutral "
+ + LANGUAGE
+ + " translation of the action log. Always start the sentence with Taro. For example, Translate 'Taroを倒した!' as 'Taro was defeated!'",
+ False,
+ )
+ data[i][f"message{number}"] = msgResponse[0].replace(
+ "Taro", ""
+ )
totalTokens[0] += msgResponse[1][0]
totalTokens[1] += msgResponse[1][1]
number += 1
else:
- msgResponse = translateGPT(data[i][f'message{number}'], 'reply with only the gender neutral '+ LANGUAGE +' translation', False)
- data[i][f'message{number}'] = msgResponse[0]
+ msgResponse = translateGPT(
+ data[i][f"message{number}"],
+ "reply with only the gender neutral "
+ + LANGUAGE
+ + " translation",
+ False,
+ )
+ data[i][f"message{number}"] = msgResponse[0]
totalTokens[0] += msgResponse[1][0]
totalTokens[1] += msgResponse[1][1]
number += 1
else:
number += 1
-
+
i += 1
else:
batchFull = True
- if context in ['Enemies', 'Classes', 'MapInfos']:
+ if context in ["Enemies", "Classes", "MapInfos"]:
if len(nameList) < BATCHSIZE:
- nameList.append(data[i]['name'])
+ nameList.append(data[i]["name"])
# Notes
- if '')
+ if "")
totalTokens[0] += tokensResponse[0]
totalTokens[1] += tokensResponse[1]
i += 1
@@ -591,8 +692,8 @@ def searchNames(data, pbar, context):
# Batch Full
if batchFull == True or i >= len(data):
- k = j # Original Index
- if context in 'Actors':
+ k = j # Original Index
+ if context in "Actors":
# Name
response = translateGPT(nameList, newContext, True)
translatedNameBatch = response[0]
@@ -606,7 +707,7 @@ def searchNames(data, pbar, context):
totalTokens[1] += response[1][1]
# Profile
- response = translateGPT(profileList, '', True)
+ response = translateGPT(profileList, "", True)
translatedProfileBatch = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
@@ -616,21 +717,27 @@ def searchNames(data, pbar, context):
j = k
while j < i:
# Empty Data
- if data[j] is None or data[j]['name'] == "":
+ if data[j] is None or data[j]["name"] == "":
j += 1
- continue
+ continue
else:
# Get Text
- if data[j]['name'] != '':
- with open('translations.txt', 'a', encoding='utf-8') as file:
- file.write(f'{data[j]['name']} ({translatedNameBatch[0]})\n')
- data[j]['name'] = translatedNameBatch[0]
+ if data[j]["name"] != "":
+ with open(
+ "translations.txt", "a", encoding="utf-8"
+ ) as file:
+ file.write(
+ f'{data[j]['name']} ({translatedNameBatch[0]})\n'
+ )
+ data[j]["name"] = translatedNameBatch[0]
translatedNameBatch.pop(0)
- if data[j]['nickname'] != '':
- data[j]['nickname'] = translatedNicknameBatch[0]
+ if data[j]["nickname"] != "":
+ data[j]["nickname"] = translatedNicknameBatch[0]
translatedNicknameBatch.pop(0)
- if data[j]['profile'] != '':
- data[j]['profile'] = textwrap.fill(translatedProfileBatch[0], LISTWIDTH)
+ if data[j]["profile"] != "":
+ data[j]["profile"] = textwrap.fill(
+ translatedProfileBatch[0], LISTWIDTH
+ )
translatedProfileBatch.pop(0)
# If Batch is empty. Move on.
@@ -641,7 +748,7 @@ def searchNames(data, pbar, context):
else:
mismatch = True
- if context in ['Armors', 'Weapons', 'Items', 'Skills']:
+ if context in ["Armors", "Weapons", "Items", "Skills"]:
# Name
response = translateGPT(nameList, newContext, True)
translatedNameBatch = response[0]
@@ -649,7 +756,11 @@ def searchNames(data, pbar, context):
totalTokens[1] += response[1][1]
# Description
- response = translateGPT(descriptionList, f'Reply with only the {LANGUAGE} translation of the text.', True)
+ response = translateGPT(
+ descriptionList,
+ f"Reply with only the {LANGUAGE} translation of the text.",
+ True,
+ )
translatedDescriptionBatch = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
@@ -657,19 +768,23 @@ def searchNames(data, pbar, context):
# Set Data
if len(nameList) == len(translatedNameBatch):
j = k
- with open('translations.txt', 'a', encoding='utf-8') as file:
- file.write('# Items\n')
+ with open("translations.txt", "a", encoding="utf-8") as file:
+ file.write("# Items\n")
while j < i:
# Empty Data
- if data[j] is None or data[j]['name'] == "":
+ if data[j] is None or data[j]["name"] == "":
j += 1
- continue
+ continue
else:
# Get Text
- file.write(f'{data[j]['name']} ({translatedNameBatch[0]})\n')
- data[j]['name'] = translatedNameBatch[0]
- if 'description' in data[j]:
- data[j]['description'] = textwrap.fill(translatedDescriptionBatch[0], LISTWIDTH)
+ file.write(
+ f'{data[j]['name']} ({translatedNameBatch[0]})\n'
+ )
+ data[j]["name"] = translatedNameBatch[0]
+ if "description" in data[j]:
+ data[j]["description"] = textwrap.fill(
+ translatedDescriptionBatch[0], LISTWIDTH
+ )
translatedNameBatch.pop(0)
translatedDescriptionBatch.pop(0)
@@ -682,7 +797,7 @@ def searchNames(data, pbar, context):
j += 1
else:
mismatch = True
- if context in ['Enemies', 'Classes', 'MapInfos']:
+ if context in ["Enemies", "Classes", "MapInfos"]:
response = translateGPT(nameList, newContext, True)
translatedNameBatch = response[0]
totalTokens[0] += response[1][0]
@@ -693,12 +808,12 @@ def searchNames(data, pbar, context):
j = k
while j < i:
# Empty Data
- if data[j] is None or data[j]['name'] == "":
+ if data[j] is None or data[j]["name"] == "":
j += 1
- continue
+ continue
else:
# Get Text
- data[j]['name'] = translatedNameBatch[0]
+ data[j]["name"] = translatedNameBatch[0]
translatedNameBatch.pop(0)
# If Batch is empty. Move on.
@@ -718,11 +833,12 @@ def searchNames(data, pbar, context):
descriptionList.clear()
filling = False
mismatch = False
-
+
i += 1
return totalTokens
+
def searchCodes(page, pbar, jobList, filename):
if len(jobList) > 0:
list401 = jobList[0]
@@ -739,8 +855,8 @@ def searchCodes(page, pbar, jobList, filename):
textHistory = []
match = []
totalTokens = [0, 0]
- translatedText = ''
- speaker = ''
+ translatedText = ""
+ speaker = ""
speakerID = None
syncIndex = 0
CLFlag = False
@@ -754,12 +870,11 @@ def searchCodes(page, pbar, jobList, filename):
with LOCK:
PBAR = pbar
-
# Begin Parsing File
try:
# Normal Format
- if 'list' in page:
- codeList = page['list']
+ if "list" in page:
+ codeList = page["list"]
# Special Format (Scenario)
else:
@@ -768,7 +883,7 @@ def searchCodes(page, pbar, jobList, filename):
# Iterate through page
i = 0
while i < len(codeList):
- with LOCK:
+ with LOCK:
# syncIndex will keep i in sync when it gets modified
if syncIndex > i:
i = syncIndex
@@ -777,21 +892,25 @@ def searchCodes(page, pbar, jobList, filename):
# Declare Varss
currentGroup = []
- nametag = ''
+ nametag = ""
## Event Code: 401 Show Text
- if 'code' in codeList[i] and codeList[i]['code'] in [401, 405, -1] and (CODE401 or CODE405):
+ if (
+ "code" in codeList[i]
+ and codeList[i]["code"] in [401, 405, -1]
+ and (CODE401 or CODE405)
+ ):
# Save Code and starting index (j)
- code = codeList[i]['code']
+ code = codeList[i]["code"]
j = i
- endtag = ''
+ endtag = ""
# Grab String
- if len(codeList[i]['parameters']) > 0:
- jaString = codeList[i]['parameters'][0]
+ if len(codeList[i]["parameters"]) > 0:
+ jaString = codeList[i]["parameters"][0]
oldjaString = jaString
else:
- codeList[i]['code'] = -1
+ codeList[i]["code"] = -1
i += 1
continue
@@ -814,95 +933,114 @@ def searchCodes(page, pbar, jobList, filename):
speakerList = []
# m and z Codes
- match = re.search(r'(.*?)[\\]+m\[\d+?\][\\]+z\[\d+?\]', jaString)
+ match = re.search(r"(.*?)[\\]+m\[\d+?\][\\]+z\[\d+?\]", jaString)
if match:
speakerList.append(match.group(1))
- if '\\c' in speakerList[0]:
- speakerList = re.findall(r'^[\\]+[cC]\[[\d]+\](.+?)[\\]+[Cc]\[[\d]\]\\?\\?$', speakerList[0])
+ if "\\c" in speakerList[0]:
+ speakerList = re.findall(
+ r"^[\\]+[cC]\[[\d]+\](.+?)[\\]+[Cc]\[[\d]\]\\?\\?$",
+ speakerList[0],
+ )
# Brackets
if len(speakerList) == 0:
- speakerList = re.findall(r'^【(.*?)】$', jaString)
+ speakerList = re.findall(r"^【(.*?)】$", jaString)
# Colors
if len(speakerList) == 0:
- speakerList = re.findall(r'^[\\]+[cC]\[[\d]+\](.+?)[\\]+[Cc]\[[\d]\]\\?\\?$', jaString)
+ speakerList = re.findall(
+ r"^[\\]+[cC]\[[\d]+\](.+?)[\\]+[Cc]\[[\d]\]\\?\\?$", jaString
+ )
# First Line Speakers
if len(speakerList) == 0 and FIRSTLINESPEAKERS is True:
# Remove any RPGMaker Code at start
- ffMatch = re.search(r'^(\s*[\\]+[aAbBdDeEfFgGhHiIjJlLmMoOpPqQrRsStTuUvVwWxXyYzZ]+\[[\w\d\[\]\\]+\])', jaString)
+ ffMatch = re.search(
+ r"^(\s*[\\]+[aAbBdDeEfFgGhHiIjJlLmMoOpPqQrRsStTuUvVwWxXyYzZ]+\[[\w\d\[\]\\]+\])",
+ jaString,
+ )
if ffMatch != None:
- jaString = jaString.replace(ffMatch.group(0), '')
+ jaString = jaString.replace(ffMatch.group(0), "")
nametag += ffMatch.group(0)
-
- # Test Speaker
- if len(jaString) < 40 \
- and 'code' in codeList[i+1] \
- and codeList[i+1]['code'] in [401, 405, -1] \
- and len(codeList[i+1]['parameters']) > 0 \
- and len(codeList[i+1]['parameters'][0]) > 0:
- if codeList[i+1]['parameters'][0].strip()[0] in ['「', '"', '(', '(', '*', '[']:
- speakerList = re.findall(r'.+', jaString)
- if len(speakerList) != 0 and codeList[i+1]['code'] in [401, 405, -1]:
+ # Test Speaker
+ if (
+ len(jaString) < 40
+ and "code" in codeList[i + 1]
+ and codeList[i + 1]["code"] in [401, 405, -1]
+ and len(codeList[i + 1]["parameters"]) > 0
+ and len(codeList[i + 1]["parameters"][0]) > 0
+ ):
+ if codeList[i + 1]["parameters"][0].strip()[0] in [
+ "「",
+ '"',
+ "(",
+ "(",
+ "*",
+ "[",
+ ]:
+ speakerList = re.findall(r".+", jaString)
+
+ if len(speakerList) != 0 and codeList[i + 1]["code"] in [401, 405, -1]:
# Get Speaker
response = getSpeaker(speakerList[0])
speaker = response[0]
totalTokens[0] += response[1][0]
- totalTokens[1] += response[1][1]
+ totalTokens[1] += response[1][1]
# Set Data
- codeList[i]['parameters'][0] = nametag + jaString.replace(speakerList[0], speaker)
- nametag = ''
+ codeList[i]["parameters"][0] = nametag + jaString.replace(
+ speakerList[0], speaker
+ )
+ nametag = ""
# Iterate to next string
i += 1
j = i
- while codeList[i]['code'] in [-1]:
+ while codeList[i]["code"] in [-1]:
i += 1
j = i
- jaString = codeList[i]['parameters'][0]
+ jaString = codeList[i]["parameters"][0]
# Using this to keep track of 401's in a row.
currentGroup.append(jaString)
# Join Up 401's into single string
- if len(codeList) > i+1:
- while codeList[i+1]['code'] in [401, 405, -1]:
+ if len(codeList) > i + 1:
+ while codeList[i + 1]["code"] in [401, 405, -1]:
if setData == True:
- codeList[i]['parameters'] = []
- codeList[i]['code'] = -1
+ codeList[i]["parameters"] = []
+ codeList[i]["code"] = -1
i += 1
j = i
# Only add if not empty
- if len(codeList[i]['parameters']) > 0:
- jaString = codeList[i]['parameters'][0]
+ if len(codeList[i]["parameters"]) > 0:
+ jaString = codeList[i]["parameters"][0]
currentGroup.append(jaString)
# Make sure not the end of the list.
- if len(codeList) <= i+1:
+ if len(codeList) <= i + 1:
break
# Format String
if len(currentGroup) > 0:
- finalJAString = ''
- finalJAString = ''.join(currentGroup).replace('?', '?')
+ finalJAString = ""
+ finalJAString = "".join(currentGroup).replace("?", "?")
oldjaString = finalJAString
# Check if Empty
- if finalJAString == '':
+ if finalJAString == "":
i += 1
continue
# Set Back
if setData == True:
- codeList[i]['parameters'] = [finalJAString]
+ codeList[i]["parameters"] = [finalJAString]
### \\n
nCase = None
- regex = r'([\\]+[kKnN][wWcCrRrEe]?[\[<](.*?)[>\]])'
+ regex = r"([\\]+[kKnN][wWcCrRrEe]?[\[<](.*?)[>\]])"
match = re.search(regex, finalJAString)
# Set Name
@@ -910,20 +1048,20 @@ def searchCodes(page, pbar, jobList, filename):
nametag = match.group(1)
speaker = match.group(2)
- # Translate Speaker
+ # Translate Speaker
response = getSpeaker(speaker)
tledSpeaker = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Set Nametag and Remove from Final String
- finalJAString = finalJAString.replace(nametag, '')
+ finalJAString = finalJAString.replace(nametag, "")
nametag = nametag.replace(speaker, tledSpeaker)
speaker = tledSpeaker
-
+
# Bracket Names
if BRACKETNAMES is True and len(matchList) != 0:
- if matchList[0][0] != '':
+ if matchList[0][0] != "":
match0 = matchList[0][0]
match1 = matchList[0][1]
else:
@@ -939,128 +1077,148 @@ def searchCodes(page, pbar, jobList, filename):
# Set Nametag and Remove from Final String
fullSpeaker = match0.replace(match1, speaker)
- finalJAString = finalJAString.replace(match0, '')
+ finalJAString = finalJAString.replace(match0, "")
# Set next item as dialogue
- if codeList[j + 1]['code'] == 401 or codeList[j + 1]['code'] == -1:
+ if (
+ codeList[j + 1]["code"] == 401
+ or codeList[j + 1]["code"] == -1
+ ):
# Set name var to top of list
- codeList[j]['parameters'] = [fullSpeaker]
- codeList[j]['code'] = code
+ codeList[j]["parameters"] = [fullSpeaker]
+ codeList[j]["code"] = code
j += 1
- codeList[j]['parameters'] = [finalJAString]
- codeList[j]['code'] = code
+ codeList[j]["parameters"] = [finalJAString]
+ codeList[j]["code"] = code
else:
# Set nametag in string
- codeList[j]['parameters'] = [fullSpeaker + finalJAString]
- codeList[j]['code'] = code
+ codeList[j]["parameters"] = [fullSpeaker + finalJAString]
+ codeList[j]["code"] = code
# Remove any textwrap
if FIXTEXTWRAP is True:
- finalJAString = re.sub(r'\n', ' ', finalJAString)
- finalJAString = finalJAString.replace('
', ' ')
+ finalJAString = re.sub(r"\n", " ", finalJAString)
+ finalJAString = finalJAString.replace("
", " ")
# Remove Extra Stuff bad for translation.
- finalJAString = finalJAString.replace('゙', '')
- finalJAString = finalJAString.replace('―', '-')
- finalJAString = finalJAString.replace('…', '...')
- finalJAString = finalJAString.replace('。', '.')
- finalJAString = re.sub(r'(\.{3}\.+)', '...', finalJAString)
- finalJAString = finalJAString.replace(' ', '')
- finalJAString = finalJAString.replace('「', '\"')
- finalJAString = finalJAString.replace('」', '\"')
+ finalJAString = finalJAString.replace("゙", "")
+ finalJAString = finalJAString.replace("―", "-")
+ finalJAString = finalJAString.replace("…", "...")
+ finalJAString = finalJAString.replace("。", ".")
+ finalJAString = re.sub(r"(\.{3}\.+)", "...", finalJAString)
+ finalJAString = finalJAString.replace(" ", "")
+ finalJAString = finalJAString.replace("「", '"')
+ finalJAString = finalJAString.replace("」", '"')
### Remove format codes
# Furigana
- rcodeMatch = re.findall(r'([\\]+[r][b]?\[.*?,(.*?)\])', finalJAString)
+ rcodeMatch = re.findall(
+ r"([\\]+[r][b]?\[.*?,(.*?)\])", finalJAString
+ )
if len(rcodeMatch) > 0:
for match in rcodeMatch:
- finalJAString = finalJAString.replace(match[0],match[1])
+ finalJAString = finalJAString.replace(match[0], match[1])
# Formatting
- formatMatch = re.findall(r'[\\]+[!><.|#^{}]', finalJAString)
+ formatMatch = re.findall(r"[\\]+[!><.|#^{}]", finalJAString)
if len(formatMatch) > 0:
for match in formatMatch:
- finalJAString = finalJAString.replace(match, '')
+ finalJAString = finalJAString.replace(match, "")
# Remove any RPGMaker Code at start
- ffMatch = re.search(r'^(\s*[\\]+[aAbBdDeEfFgGhHiIjJlLmMoOpPqQrRsStTuUvVwWxXyYzZ]+\[[\w\d\[\]\\]+\])', finalJAString)
+ ffMatch = re.search(
+ r"^(\s*[\\]+[aAbBdDeEfFgGhHiIjJlLmMoOpPqQrRsStTuUvVwWxXyYzZ]+\[[\w\d\[\]\\]+\])",
+ finalJAString,
+ )
if ffMatch != None:
- finalJAString = finalJAString.replace(ffMatch.group(0), '')
+ finalJAString = finalJAString.replace(ffMatch.group(0), "")
nametag += ffMatch.group(0)
# Remove _ABL Codes
- ffMatch = re.search(r'^(_ABL).*', finalJAString)
+ ffMatch = re.search(r"^(_ABL).*", finalJAString)
if ffMatch != None:
- finalJAString = finalJAString.replace(ffMatch.group(1), '')
+ finalJAString = finalJAString.replace(ffMatch.group(1), "")
nametag += ffMatch.group(1)
# Center Lines
- if '\\CL' in finalJAString or '\\ac' in finalJAString:
- finalJAString = finalJAString.replace('\\CL ', '')
- finalJAString = finalJAString.replace('\\CL', '')
- finalJAString = finalJAString.replace('\\ac ', '')
- finalJAString = finalJAString.replace('\\ac', '')
+ if "\\CL" in finalJAString or "\\ac" in finalJAString:
+ finalJAString = finalJAString.replace("\\CL ", "")
+ finalJAString = finalJAString.replace("\\CL", "")
+ finalJAString = finalJAString.replace("\\ac ", "")
+ finalJAString = finalJAString.replace("\\ac", "")
CLFlag = True
# If there isn't any Japanese in the text just skip
if IGNORETLTEXT is True:
- if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', finalJAString):
+ if not re.search(
+ r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+", finalJAString
+ ):
# Keep textHistory list at length maxHistory
- textHistory.append('\"' + finalJAString + '\"')
+ textHistory.append('"' + finalJAString + '"')
if len(textHistory) > maxHistory:
textHistory.pop(0)
- currentGroup = []
+ currentGroup = []
i += 1
continue
# 1st Passthrough (Grabbing Data)
if setData == False:
- if finalJAString != '':
- if speaker == '' and finalJAString != '':
+ if finalJAString != "":
+ if speaker == "" and finalJAString != "":
list401.append(finalJAString)
- elif finalJAString != '':
- list401.append(f'[{speaker}]: {finalJAString}')
+ elif finalJAString != "":
+ list401.append(f"[{speaker}]: {finalJAString}")
else:
list401.append(speaker)
- speaker = ''
+ speaker = ""
match = []
- nametag = ''
+ nametag = ""
currentGroup = []
- syncIndex = i + 1
+ syncIndex = i + 1
- # 2nd Passthrough (Setting Data)
+ # 2nd Passthrough (Setting Data)
else:
# Grab Translated String
if len(list401) > 0:
translatedText = list401[0]
-
+
# Remove speaker
- if speaker != '':
- matchSpeakerList = re.findall(r'^\[?(.+?)\]?\s?[|:]\s?', translatedText)
+ if speaker != "":
+ matchSpeakerList = re.findall(
+ r"^\[?(.+?)\]?\s?[|:]\s?", translatedText
+ )
if len(matchSpeakerList) > 0:
newSpeaker = matchSpeakerList[0]
nametag = nametag.replace(speaker, newSpeaker)
- translatedText = re.sub(r'^\[?(.+?)\]?\s?[|:]\s?', '', translatedText)
+ translatedText = re.sub(
+ r"^\[?(.+?)\]?\s?[|:]\s?", "", translatedText
+ )
# Fix '- '
- translatedText = translatedText.replace('- ', '-')
+ translatedText = translatedText.replace("- ", "-")
# Textwrap
- if FIXTEXTWRAP is True and '_ABL' in nametag:
- translatedText = textwrap.fill(translatedText, width=100)
+ if FIXTEXTWRAP is True and "_ABL" in nametag:
+ translatedText = textwrap.fill(
+ translatedText, width=100
+ )
elif FIXTEXTWRAP is True:
- translatedText = textwrap.fill(translatedText, width=WIDTH)
-
+ translatedText = textwrap.fill(
+ translatedText, width=WIDTH
+ )
+
# BR Flag
if BRFLAG is True:
- translatedText = translatedText.replace('\n', '
')
+ translatedText = translatedText.replace("\n", "
")
### Add Var Strings
# CL Flag
if CLFlag:
- translatedText = '\\ac ' + translatedText
- translatedText = translatedText.replace('\n', '\n\\ac ')
- translatedText = re.sub(r'[\\]+?ac\s+', r'\\ac ', translatedText)
+ translatedText = "\\ac " + translatedText
+ translatedText = translatedText.replace("\n", "\n\\ac ")
+ translatedText = re.sub(
+ r"[\\]+?ac\s+", r"\\ac ", translatedText
+ )
CLFlag = False
# Nametag
@@ -1068,38 +1226,38 @@ def searchCodes(page, pbar, jobList, filename):
translatedText = translatedText + nametag
else:
translatedText = nametag + translatedText
- nametag = ''
+ nametag = ""
# Endtag
- if endtag != '':
+ if endtag != "":
translatedText = translatedText + endtag
- endtag = ''
+ endtag = ""
# Set Data
if speakerID != None:
- codeList[speakerID]['parameters'] = [fullSpeaker]
- codeList[j]['parameters'] = [translatedText]
- codeList[j]['code'] = code
- speaker = ''
+ codeList[speakerID]["parameters"] = [fullSpeaker]
+ codeList[j]["parameters"] = [translatedText]
+ codeList[j]["code"] = code
+ speaker = ""
match = []
currentGroup = []
syncIndex = i + 1
- list401.pop(0)
+ list401.pop(0)
## Event Code: 122 [Set Variables]
- if 'code' in codeList[i] and codeList[i]['code'] == 122 and CODE122 is True:
+ 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(150, 180)):
+ if codeList[i]["parameters"][0] not in list(range(150, 180)):
i += 1
continue
-
- jaString = codeList[i]['parameters'][4]
+
+ jaString = codeList[i]["parameters"][4]
# # For Retarded Devs
# VNameValue = jaString
# i += 1
# continue
-
+
# Definitely don't want to mess with files
# if 'gameV' in jaString or '_' in jaString:
# i += 1
@@ -1109,7 +1267,7 @@ def searchCodes(page, pbar, jobList, filename):
if not isinstance(jaString, str):
i += 1
continue
-
+
# Set String
matchedText = None
if len(re.findall(r"([\'\"])", jaString)) == 2:
@@ -1120,121 +1278,129 @@ def searchCodes(page, pbar, jobList, filename):
# Last Check
if matchedText != None:
# Remove Textwrap
- finalJAString = matchedText.group(1).replace('\\n', ' ')
+ finalJAString = matchedText.group(1).replace("\\n", " ")
# Pass 1
if setData == False:
- if finalJAString != '':
+ if finalJAString != "":
list122.append(finalJAString)
# Pass 2
- else:
- if len(list122) > 0:
+ else:
+ if len(list122) > 0:
# Grab and Replace
translatedText = list122[0]
translatedText = jaString.replace(jaString, translatedText)
# Remove characters that may break scripts
- charList = ['\"', '\\n']
+ charList = ['"', "\\n"]
for char in charList:
- translatedText = translatedText.replace(char, '')
-
+ translatedText = translatedText.replace(char, "")
+
# Textwrap
translatedText = textwrap.fill(translatedText, width=80)
- translatedText = translatedText.replace('\n', '\\n')
+ translatedText = translatedText.replace("\n", "\\n")
# Set
- codeList[i]['parameters'][4] = jaString.replace(finalJAString, translatedText)
+ codeList[i]["parameters"][4] = jaString.replace(
+ finalJAString, translatedText
+ )
list122.pop(0)
## Event Code: 357 [Picture Text] [Optional]
- if 'code' in codeList[i] and codeList[i]['code'] == 357 and CODE357 is True:
- headerString = codeList[i]['parameters'][0]
+ if "code" in codeList[i] and codeList[i]["code"] == 357 and CODE357 is True:
+ headerString = codeList[i]["parameters"][0]
- if headerString == 'LL_GalgeChoiceWindow':
+ if headerString == "LL_GalgeChoiceWindow":
### Message Text First
- jaString = codeList[i]['parameters'][3]['messageText']
+ jaString = codeList[i]["parameters"][3]["messageText"]
# Remove any textwrap & TL
- jaString = re.sub(r'\n', ' ', jaString)
- response = translateGPT(jaString, '', False)
+ jaString = re.sub(r"\n", " ", jaString)
+ response = translateGPT(jaString, "", False)
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Textwrap & Set
translatedText = textwrap.fill(translatedText, width=WIDTH)
- codeList[i]['parameters'][3]['messageText'] = translatedText
+ codeList[i]["parameters"][3]["messageText"] = translatedText
### Choices
- jaString = codeList[i]['parameters'][3]['choices']
+ jaString = codeList[i]["parameters"][3]["choices"]
matchList = re.findall(r'"label[\\]*":[\\]*"(.*?)[\\]', jaString)
if matchList != None:
# Translate
- question = codeList[i]['parameters'][3]['messageText']
- response = translateGPT(matchList, f'Previous text for context: {question}\n\nThis will be a dialogue option', True)
+ question = codeList[i]["parameters"][3]["messageText"]
+ response = translateGPT(
+ matchList,
+ f"Previous text for context: {question}\n\nThis will be a dialogue option",
+ True,
+ )
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
translatedText = jaString
# Replace Strings
for j in range(len(matchList)):
- translatedText = translatedText.replace(matchList[j], response[0][j])
+ translatedText = translatedText.replace(
+ matchList[j], response[0][j]
+ )
# Set Data
- codeList[i]['parameters'][3]['choices'] = translatedText
+ codeList[i]["parameters"][3]["choices"] = translatedText
- if 'SoR_GabWindow' in headerString:
- argVar = 'arg1'
+ if "SoR_GabWindow" in headerString:
+ argVar = "arg1"
### Message Text First
- if argVar in codeList[i]['parameters'][3]:
- jaString = codeList[i]['parameters'][3][argVar]
+ if argVar in codeList[i]["parameters"][3]:
+ jaString = codeList[i]["parameters"][3][argVar]
# If there isn't any Japanese in the text just skip
- if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
+ if not re.search(r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+", jaString):
i += 1
continue
# Remove any textwrap & TL
- jaString = re.sub(r'\n', ' ', jaString)
- response = translateGPT(jaString, '', False)
+ jaString = re.sub(r"\n", " ", jaString)
+ response = translateGPT(jaString, "", False)
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Textwrap & Set
translatedText = textwrap.fill(translatedText, width=WIDTH)
- codeList[i]['parameters'][3][argVar] = translatedText
+ codeList[i]["parameters"][3][argVar] = translatedText
pbar.update(1)
- if 'TorigoyaMZ_NotifyMessage' in headerString:
- argVar = 'message'
+ if "TorigoyaMZ_NotifyMessage" in headerString:
+ argVar = "message"
### Message Text First
- if argVar in codeList[i]['parameters'][3]:
- jaString = codeList[i]['parameters'][3][argVar]
+ if argVar in codeList[i]["parameters"][3]:
+ jaString = codeList[i]["parameters"][3][argVar]
# If there isn't any Japanese in the text just skip
- if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
+ if not re.search(r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+", jaString):
i += 1
continue
# Remove any textwrap & TL
- jaString = re.sub(r'\n', ' ', jaString)
- response = translateGPT(jaString, '', False)
+ jaString = re.sub(r"\n", " ", jaString)
+ response = translateGPT(jaString, "", False)
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Textwrap & Set
translatedText = textwrap.fill(translatedText, width=WIDTH)
- codeList[i]['parameters'][3][argVar] = translatedText
+ codeList[i]["parameters"][3][argVar] = translatedText
pbar.update(1)
- if '_TMLogWindowMZ' in headerString:
- argVar = 'text'
+ if "_TMLogWindowMZ" in headerString:
+ argVar = "text"
### Message Text First
- if argVar in codeList[i]['parameters'][3]:
- jaString = codeList[i]['parameters'][3][argVar]
+ if argVar in codeList[i]["parameters"][3]:
+ jaString = codeList[i]["parameters"][3][argVar]
# If there isn't any Japanese in the text just skip
# if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
@@ -1242,22 +1408,22 @@ def searchCodes(page, pbar, jobList, filename):
# continue
# Remove any textwrap & TL
- jaString = re.sub(r'\n', ' ', jaString)
- response = translateGPT(jaString, '', False)
+ jaString = re.sub(r"\n", " ", jaString)
+ response = translateGPT(jaString, "", False)
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Textwrap & Set
translatedText = textwrap.fill(translatedText, width=WIDTH)
- codeList[i]['parameters'][3][argVar] = translatedText
+ codeList[i]["parameters"][3][argVar] = translatedText
pbar.update(1)
- if 'DestinationWindow' in headerString:
- argVar = 'destination'
+ if "DestinationWindow" in headerString:
+ argVar = "destination"
### Message Text First
- if argVar in codeList[i]['parameters'][3]:
- jaString = codeList[i]['parameters'][3][argVar]
+ if argVar in codeList[i]["parameters"][3]:
+ jaString = codeList[i]["parameters"][3][argVar]
# If there isn't any Japanese in the text just skip
# if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
@@ -1265,22 +1431,22 @@ def searchCodes(page, pbar, jobList, filename):
# continue
# Remove any textwrap & TL
- jaString = re.sub(r'\n', ' ', jaString)
- response = translateGPT(jaString, '', False)
+ jaString = re.sub(r"\n", " ", jaString)
+ response = translateGPT(jaString, "", False)
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Textwrap & Set
translatedText = textwrap.fill(translatedText, width=WIDTH)
- codeList[i]['parameters'][3][argVar] = translatedText
+ codeList[i]["parameters"][3][argVar] = translatedText
pbar.update(1)
- if 'MNKR_CommonPopupCoreMZ' in headerString:
- argVar = 'text'
+ if "MNKR_CommonPopupCoreMZ" in headerString:
+ argVar = "text"
### Message Text First
- if argVar in codeList[i]['parameters'][3]:
- jaString = codeList[i]['parameters'][3][argVar]
+ if argVar in codeList[i]["parameters"][3]:
+ jaString = codeList[i]["parameters"][3][argVar]
# If there isn't any Japanese in the text just skip
# if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
@@ -1288,142 +1454,164 @@ def searchCodes(page, pbar, jobList, filename):
# continue
# Remove any textwrap & TL
- jaString = re.sub(r'\n', ' ', jaString)
- response = translateGPT(jaString, '', False)
+ jaString = re.sub(r"\n", " ", jaString)
+ response = translateGPT(jaString, "", False)
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Textwrap & Set
translatedText = textwrap.fill(translatedText, width=WIDTH)
- codeList[i]['parameters'][3][argVar] = translatedText
+ codeList[i]["parameters"][3][argVar] = translatedText
pbar.update(1)
-
+
## Event Code: 657 [Picture Text] [Optional]
- if 'code' in codeList[i] and codeList[i]['code'] == 657 and CODE657 is True:
- if 'text' in codeList[i]['parameters'][0]:
- jaString = codeList[i]['parameters'][0]
+ if "code" in codeList[i] and codeList[i]["code"] == 657 and CODE657 is True:
+ if "text" in codeList[i]["parameters"][0]:
+ jaString = codeList[i]["parameters"][0]
if not isinstance(jaString, str):
i += 1
continue
-
+
# Definitely don't want to mess with files
- if '_' in jaString:
+ if "_" in jaString:
i += 1
continue
# If there isn't any Japanese in the text just skip
- if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
+ if not re.search(r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+", jaString):
i += 1
continue
# Remove outside text
- startString = re.search(r'^[^一-龠ぁ-ゔァ-ヴー\<\>【】\\]+', jaString)
- jaString = re.sub(r'^[^一-龠ぁ-ゔァ-ヴー\<\>【】\\]+', '', jaString)
- endString = re.search(r'[^一-龠ぁ-ゔァ-ヴー\<\>【】。!?\\]+$', jaString)
- jaString = re.sub(r'[^一-龠ぁ-ゔァ-ヴー\<\>【】。!?\\]+$', '', jaString)
+ startString = re.search(
+ r"^[^一-龠ぁ-ゔァ-ヴー\<\>【】\\]+", jaString
+ )
+ jaString = re.sub(r"^[^一-龠ぁ-ゔァ-ヴー\<\>【】\\]+", "", jaString)
+ endString = re.search(
+ r"[^一-龠ぁ-ゔァ-ヴー\<\>【】。!?\\]+$", jaString
+ )
+ jaString = re.sub(
+ r"[^一-龠ぁ-ゔァ-ヴー\<\>【】。!?\\]+$", "", jaString
+ )
if startString is None:
- startString = ''
+ startString = ""
else:
startString = startString.group()
if endString is None:
- endString = ''
+ endString = ""
else:
endString = endString.group()
# Remove any textwrap
- jaString = re.sub(r'\n', ' ', jaString)
+ jaString = re.sub(r"\n", " ", jaString)
# Translate
- response = translateGPT(jaString, '', True)
+ response = translateGPT(jaString, "", True)
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
translatedText = response[0]
# Remove characters that may break scripts
- charList = ['.', '\"', "'"]
+ charList = [".", '"', "'"]
for char in charList:
- translatedText = translatedText.replace(char, '')
+ translatedText = translatedText.replace(char, "")
# Textwrap
translatedText = textwrap.fill(translatedText, width=WIDTH)
translatedText = startString + translatedText + endString
# Set Data
- codeList[i]['parameters'][0] = translatedText
+ codeList[i]["parameters"][0] = translatedText
- ## Event Code: 101 [Name] [Optional]
- if 'code' in codeList[i] and codeList[i]['code'] == 101 and CODE101 is True:
+ ## Event Code: 101 [Name] [Optional]
+ if "code" in codeList[i] and codeList[i]["code"] == 101 and CODE101 is True:
# Check Window Type (Certain games switch between 1st line speakers and none)
if FIRSTLINESPEAKERS:
- if codeList[i]['parameters'][2] == 0:
+ if codeList[i]["parameters"][2] == 0:
speakerWindow = True
else:
speakerWindow = False
else:
isVar = False
-
+
# Grab String
- jaString = ''
- if len(codeList[i]['parameters']) > 4:
- jaString = codeList[i]['parameters'][4]
+ jaString = ""
+ if len(codeList[i]["parameters"]) > 4:
+ jaString = codeList[i]["parameters"][4]
# Check for Var
- elif len(codeList[i]['parameters']) > 0:
- jaString = codeList[i]['parameters'][0]
+ elif len(codeList[i]["parameters"]) > 0:
+ jaString = codeList[i]["parameters"][0]
isVar = True
if not isinstance(jaString, str):
i += 1
continue
# Force Speaker using var
- if '\\ap[1左]' in jaString.lower() or '\\ap[1右]' in jaString.lower():
- speaker = 'Cecily'
+ if (
+ "\\ap[1左]" in jaString.lower()
+ or "\\ap[1右]" in jaString.lower()
+ ):
+ speaker = "Cecily"
i += 1
continue
- elif '\\ap[2左]' in jaString.lower() or '\\ap[2右]' in jaString.lower():
- speaker = 'Amelia'
+ elif (
+ "\\ap[2左]" in jaString.lower()
+ or "\\ap[2右]" in jaString.lower()
+ ):
+ speaker = "Amelia"
i += 1
continue
- elif '\\ap[3左]' in jaString.lower() or '\\ap[3右]' in jaString.lower():
- speaker = 'Henry'
+ elif (
+ "\\ap[3左]" in jaString.lower()
+ or "\\ap[3右]" in jaString.lower()
+ ):
+ speaker = "Henry"
i += 1
continue
- elif '\\ap[4左]' in jaString.lower() or '\\ap[4右]' in jaString.lower():
- speaker = 'Oswald'
+ elif (
+ "\\ap[4左]" in jaString.lower()
+ or "\\ap[4右]" in jaString.lower()
+ ):
+ speaker = "Oswald"
i += 1
continue
- elif '\\ap' in jaString:
- speaker = re.search(r'[\\]+AP\[(.*?)\]', jaString).group(1)
+ elif "\\ap" in jaString:
+ speaker = re.search(r"[\\]+AP\[(.*?)\]", jaString).group(1)
i += 1
- continue
+ continue
# Get Speaker
- if '\\' not in jaString:
+ if "\\" not in jaString:
response = getSpeaker(jaString)
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
speaker = response[0]
-
+
# Validate Speaker is not empty
if len(speaker) > 0:
if isVar == False:
- codeList[i]['parameters'][4] = speaker
+ codeList[i]["parameters"][4] = speaker
i += 1
continue
else:
- codeList[i]['parameters'][0] = speaker
+ codeList[i]["parameters"][0] = speaker
isVar = False
i += 1
continue
else:
- speaker = ''
+ speaker = ""
## Event Code: 355 or 655 Scripts [Optional]
- if 'code' in codeList[i] and (codeList[i]['code'] == 355 or codeList[i]['code'] == 655) and CODE355655 is True:
- jaString = codeList[i]['parameters'][0]
- regex = r'memory\._eventTitle\s=\s\"(.*)\"'
-
+ if (
+ "code" in codeList[i]
+ and (codeList[i]["code"] == 355 or codeList[i]["code"] == 655)
+ and CODE355655 is True
+ ):
+ jaString = codeList[i]["parameters"][0]
+ regex = r"memory\._eventTitle\s=\s\"(.*)\""
+
# Var Text
match = re.search(regex, jaString)
if re.search(regex, jaString):
@@ -1433,37 +1621,49 @@ def searchCodes(page, pbar, jobList, filename):
list355655.append(finalJAString)
# Pass 2
- else:
+ else:
# Grab and Replace
translatedText = list355655[0]
# Set
- codeList[i]['parameters'][0] = codeList[i]['parameters'][0].replace(finalJAString, translatedText)
- list355655.pop(0)
+ codeList[i]["parameters"][0] = codeList[i]["parameters"][
+ 0
+ ].replace(finalJAString, translatedText)
+ list355655.pop(0)
## Event Code: 408 (Script)
- if 'code' in codeList[i] and (codeList[i]['code'] == 408) and CODE408 is True:
- jaString = codeList[i]['parameters'][0]
+ if (
+ "code" in codeList[i]
+ and (codeList[i]["code"] == 408)
+ and CODE408 is True
+ ):
+ jaString = codeList[i]["parameters"][0]
# If there isn't any Japanese in the text just skip
- if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
+ if not re.search(r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+", jaString):
i += 1
continue
- if 'secretText' in jaString:
- regex = r'secretText:\s?(.+)'
- elif 'title' in jaString:
- regex = r'title:\s?(.+)'
+ if "secretText" in jaString:
+ regex = r"secretText:\s?(.+)"
+ elif "title" in jaString:
+ regex = r"title:\s?(.+)"
else:
- regex = r'(.+)'
+ regex = r"(.+)"
# Need to remove outside code and put it back later
matchList = re.findall(regex, jaString)
-
+
for match in matchList:
# Remove Textwrap
- match = match.replace('\n', ' ')
- response = translateGPT(match, 'Reply with the '+ LANGUAGE +' translation of the achievement title.', False)
+ match = match.replace("\n", " ")
+ response = translateGPT(
+ match,
+ "Reply with the "
+ + LANGUAGE
+ + " translation of the achievement title.",
+ False,
+ )
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
@@ -1472,32 +1672,36 @@ def searchCodes(page, pbar, jobList, filename):
translatedText = jaString.replace(match, translatedText)
# Remove characters that may break scripts
- charList = ['.', '\"', '\\n']
+ charList = [".", '"', "\\n"]
for char in charList:
- translatedText = translatedText.replace(char, '')
+ translatedText = translatedText.replace(char, "")
# Textwrap
translatedText = textwrap.fill(translatedText, width=WIDTH)
# Set Data
- codeList[i]['parameters'][0] = translatedText
+ codeList[i]["parameters"][0] = translatedText
## Event Code: 108 (Script)
- if 'code' in codeList[i] and (codeList[i]['code'] == 108) and CODE108 is True:
- jaString = codeList[i]['parameters'][0]
+ if (
+ "code" in codeList[i]
+ and (codeList[i]["code"] == 108)
+ and CODE108 is True
+ ):
+ jaString = codeList[i]["parameters"][0]
# If there isn't any Japanese in the text just skip
- if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
+ if not re.search(r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+", jaString):
i += 1
continue
# Translate
- if 'info:' in jaString:
- regex = r'info:(.*)'
- elif 'ActiveMessage:' in jaString:
- regex = r''
- elif 'event_text' in jaString:
- regex = r'event_text\s*:\s*(.*)'
+ if "info:" in jaString:
+ regex = r"info:(.*)"
+ elif "ActiveMessage:" in jaString:
+ regex = r""
+ elif "event_text" in jaString:
+ regex = r"event_text\s*:\s*(.*)"
else:
i += 1
continue
@@ -1513,75 +1717,85 @@ def searchCodes(page, pbar, jobList, filename):
else:
# Grab and Replace
translatedText = list108[0]
- list108.pop(0)
+ list108.pop(0)
# Remove characters that may break scripts
- charList = ['.', '\"']
+ charList = [".", '"']
for char in charList:
- translatedText = translatedText.replace(char, '')
- translatedText = translatedText.replace('"', '\"')
- translatedText = translatedText.replace(' ', '_')
- translatedText = jaString.replace(match.group(1), translatedText)
+ translatedText = translatedText.replace(char, "")
+ translatedText = translatedText.replace('"', '"')
+ translatedText = translatedText.replace(" ", "_")
+ translatedText = jaString.replace(
+ match.group(1), translatedText
+ )
# Set Data
- codeList[i]['parameters'][0] = translatedText
+ codeList[i]["parameters"][0] = translatedText
## Event Code: 356
- if 'code' in codeList[i] and codeList[i]['code'] == 356 and CODE356 is True:
- jaString = codeList[i]['parameters'][0]
+ if "code" in codeList[i] and codeList[i]["code"] == 356 and CODE356 is True:
+ jaString = codeList[i]["parameters"][0]
oldjaString = jaString
# Grab Speaker
- if 'Tachie showName' in jaString:
- matchList = re.findall(r'Tachie showName (.+)', jaString)
+ if "Tachie showName" in jaString:
+ matchList = re.findall(r"Tachie showName (.+)", jaString)
if len(matchList) > 0:
# Translate
- response = translateGPT(matchList[0], 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ response = translateGPT(
+ matchList[0],
+ "Reply with the "
+ + LANGUAGE
+ + " translation of the NPC name.",
+ False,
+ )
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Set Text
speaker = translatedText
- speaker = speaker.replace(' ', ' ')
- codeList[i]['parameters'][0] = jaString.replace(matchList[0], speaker)
+ speaker = speaker.replace(" ", " ")
+ codeList[i]["parameters"][0] = jaString.replace(
+ matchList[0], speaker
+ )
i += 1
continue
# Want to translate this script
- if 'D_TEXT ' in jaString:
- regex = r'D_TEXT\s(.*?)\s.+'
- elif 'ShowInfo' in jaString:
- regex = r'ShowInfo\s(.*)'
- elif 'PushGab' in jaString:
- regex = r'PushGab\s(.*)'
- elif 'addLog' in jaString:
- regex = r'addLog\s(.*)'
- elif 'DW_' in jaString:
- regex = r'DW_.*?\s(.*)'
- elif 'CommonPopup' in jaString:
- regex = r'CommonPopup\sadd\stext:(.*?)[\\]+}'
+ if "D_TEXT " in jaString:
+ regex = r"D_TEXT\s(.*?)\s.+"
+ elif "ShowInfo" in jaString:
+ regex = r"ShowInfo\s(.*)"
+ elif "PushGab" in jaString:
+ regex = r"PushGab\s(.*)"
+ elif "addLog" in jaString:
+ regex = r"addLog\s(.*)"
+ elif "DW_" in jaString:
+ regex = r"DW_.*?\s(.*)"
+ elif "CommonPopup" in jaString:
+ regex = r"CommonPopup\sadd\stext:(.*?)[\\]+}"
else:
- regex = r''
+ regex = r""
# Remove any textwrap
- jaString = re.sub(r'\n', '_', jaString)
+ jaString = re.sub(r"\n", "_", jaString)
# Capture Arguments and text
textMatch = re.search(regex, jaString)
- if textMatch and textMatch.group(0) != '':
+ if textMatch and textMatch.group(0) != "":
text = textMatch.group(1)
# Using this to keep track of 401's in a row. Throws IndexError at EndOfList (Expected Behavior)
currentGroup.append(text)
# Check Next Codes for text
- while (codeList[i+1]['code'] == 356):
- match = re.search(regex, codeList[i+1]['parameters'][0])
+ while codeList[i + 1]["code"] == 356:
+ match = re.search(regex, codeList[i + 1]["parameters"][0])
if match == None:
break
else:
- jaString = codeList[i+1]['parameters'][0]
+ jaString = codeList[i + 1]["parameters"][0]
textMatch = re.search(regex, jaString)
if textMatch != None:
currentGroup.append(textMatch.group(1))
@@ -1591,18 +1805,20 @@ def searchCodes(page, pbar, jobList, filename):
finalList = currentGroup
# Clear Group and Reset Index
- currentGroup = []
+ currentGroup = []
i = i - len(finalList) + 1
# Translate
- response = translateGPT(finalList, 'Reply with the '+ LANGUAGE +' Translation.', True)
+ response = translateGPT(
+ finalList, "Reply with the " + LANGUAGE + " Translation.", True
+ )
finalListTL = response[0]
totalTokens[0] += response[1][0]
- totalTokens[1] += response[1][1]
+ totalTokens[1] += response[1][1]
for j in range(len(finalListTL)):
# Grab String Again For Replace
- jaString = codeList[i]['parameters'][0]
+ jaString = codeList[i]["parameters"][0]
textMatch = re.search(regex, jaString)
if textMatch != None:
text = textMatch.group(1)
@@ -1611,105 +1827,127 @@ def searchCodes(page, pbar, jobList, filename):
translatedText = finalListTL[j]
# Textwrap
- translatedText = textwrap.fill(translatedText, width=LISTWIDTH, drop_whitespace=False)
+ translatedText = textwrap.fill(
+ translatedText, width=LISTWIDTH, drop_whitespace=False
+ )
# Remove characters that may break scripts
- charList = ['.', '\"']
+ charList = [".", '"']
for char in charList:
- translatedText = translatedText.replace(char, '')
-
+ translatedText = translatedText.replace(char, "")
+
# Cant have spaces?
- translatedText = translatedText.replace(' ', '_')
+ translatedText = translatedText.replace(" ", "_")
# Fix spacing after ___
- translatedText = translatedText.replace('__\n', '__')
-
+ translatedText = translatedText.replace("__\n", "__")
+
# Put Args Back
translatedText = jaString.replace(text, translatedText)
-
+
# Set Data
- codeList[i]['parameters'][0] = translatedText
+ codeList[i]["parameters"][0] = translatedText
i += 1
else:
i += 1
continue
- if 'namePop' in jaString:
- matchList = re.findall(r'namePop\s\d+\s(.+?)\s.+', jaString)
+ if "namePop" in jaString:
+ matchList = re.findall(r"namePop\s\d+\s(.+?)\s.+", jaString)
if len(matchList) > 0:
# Translate
text = matchList[0]
- response = translateGPT(text, 'Reply with the '+ LANGUAGE +' Translation', False)
+ response = translateGPT(
+ text, "Reply with the " + LANGUAGE + " Translation", False
+ )
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Set Data
translatedText = jaString.replace(text, translatedText)
- codeList[i]['parameters'][0] = translatedText
+ codeList[i]["parameters"][0] = translatedText
- if 'LL_InfoPopupWIndowMV' in jaString:
- matchList = re.findall(r'LL_InfoPopupWIndowMV\sshowWindow\s(.+?) .+', jaString)
+ if "LL_InfoPopupWIndowMV" in jaString:
+ matchList = re.findall(
+ r"LL_InfoPopupWIndowMV\sshowWindow\s(.+?) .+", jaString
+ )
if len(matchList) > 0:
# Translate
text = matchList[0]
- response = translateGPT(text, 'Reply with the '+ LANGUAGE +' Translation', False)
+ response = translateGPT(
+ text, "Reply with the " + LANGUAGE + " Translation", False
+ )
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Set Data
- translatedText = translatedText.replace(' ', '_')
+ translatedText = translatedText.replace(" ", "_")
translatedText = jaString.replace(text, translatedText)
- codeList[i]['parameters'][0] = translatedText
+ codeList[i]["parameters"][0] = translatedText
- if 'OriginMenuStatus SetParam' in jaString:
- matchList = re.findall(r'OriginMenuStatus\sSetParam\sparam[\d]\s(.*)', jaString)
+ if "OriginMenuStatus SetParam" in jaString:
+ matchList = re.findall(
+ r"OriginMenuStatus\sSetParam\sparam[\d]\s(.*)", jaString
+ )
if len(matchList) > 0:
# Translate
text = matchList[0]
- response = translateGPT(text, 'Reply with the '+ LANGUAGE +' Translation', False)
+ response = translateGPT(
+ text, "Reply with the " + LANGUAGE + " Translation", False
+ )
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Set Data
- translatedText = translatedText.replace(' ', '_')
+ translatedText = translatedText.replace(" ", "_")
translatedText = jaString.replace(text, translatedText)
- codeList[i]['parameters'][0] = translatedText
+ codeList[i]["parameters"][0] = translatedText
# LL_GalgeChoiceWindowMV Message
- if 'LL_GalgeChoiceWindowMV setMessageText' in jaString:
+ if "LL_GalgeChoiceWindowMV setMessageText" in jaString:
### Message Text First
- match = re.search(r'LL_GalgeChoiceWindowMV setMessageText (.+)', jaString)
+ match = re.search(
+ r"LL_GalgeChoiceWindowMV setMessageText (.+)", jaString
+ )
if match:
jaString = match.group(1)
# Remove any textwrap & TL
- jaString = re.sub(r'\n', ' ', jaString)
- response = translateGPT(jaString, '', False)
+ jaString = re.sub(r"\n", " ", jaString)
+ response = translateGPT(jaString, "", False)
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Textwrap & Replace Whitespace
translatedText = textwrap.fill(translatedText, width=WIDTH)
- translatedText = translatedText.replace(' ', '_')
+ translatedText = translatedText.replace(" ", "_")
# Replace and Set
- translatedText = match.group(0).replace(match.group(1), translatedText)
- codeList[i]['parameters'][0] = translatedText
+ translatedText = match.group(0).replace(
+ match.group(1), translatedText
+ )
+ codeList[i]["parameters"][0] = translatedText
# LL_GalgeChoiceWindowMV Choices
- if 'LL_GalgeChoiceWindowMV setChoices':
- match = re.search(r'LL_GalgeChoiceWindowMV setChoices (.+)', jaString)
+ if "LL_GalgeChoiceWindowMV setChoices":
+ match = re.search(
+ r"LL_GalgeChoiceWindowMV setChoices (.+)", jaString
+ )
if match:
jaString = match.group(1)
- choiceList = jaString.split(',')
+ choiceList = jaString.split(",")
# Translate
question = translatedText
- response = translateGPT(choiceList, f'Previous text for context: {question}\n\nThis will be a dialogue option', True)
+ response = translateGPT(
+ choiceList,
+ f"Previous text for context: {question}\n\nThis will be a dialogue option",
+ True,
+ )
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
choiceListTL = response[0]
@@ -1717,35 +1955,37 @@ def searchCodes(page, pbar, jobList, filename):
# Replace Strings
for j in range(len(choiceListTL)):
- choiceListTL[j] = choiceListTL[j].replace(' ', '_')
- translatedText = translatedText.replace(choiceList[j], choiceListTL[j])
+ choiceListTL[j] = choiceListTL[j].replace(" ", "_")
+ translatedText = translatedText.replace(
+ choiceList[j], choiceListTL[j]
+ )
# Set Data
- codeList[i]['parameters'][0] = translatedText
-
+ codeList[i]["parameters"][0] = translatedText
+
### Event Code: 102 Show Choice
- if 'code' in codeList[i] and codeList[i]['code'] == 102 and CODE102 is True:
+ if "code" in codeList[i] and codeList[i]["code"] == 102 and CODE102 is True:
choiceList = []
varList = []
- for choice in range(len(codeList[i]['parameters'][0])):
- jaString = codeList[i]['parameters'][0][choice]
- jaString = jaString.replace(' 。', '.')
+ for choice in range(len(codeList[i]["parameters"][0])):
+ jaString = codeList[i]["parameters"][0][choice]
+ jaString = jaString.replace(" 。", ".")
# Avoid Empty Strings
- if jaString == '':
+ if jaString == "":
i += 1
continue
# If and En Statements
- ifVar = ''
- enVar = ''
- ifList = re.findall(r'(if\(.*?\))', jaString)
- enList = re.findall(r'(en\(.*?\))', jaString)
+ ifVar = ""
+ enVar = ""
+ ifList = re.findall(r"(if\(.*?\))", jaString)
+ enList = re.findall(r"(en\(.*?\))", jaString)
if len(ifList) != 0:
- jaString = jaString.replace(ifList[0], '')
+ jaString = jaString.replace(ifList[0], "")
ifVar = ifList[0]
if len(enList) != 0:
- jaString = jaString.replace(enList[0], '')
+ jaString = jaString.replace(enList[0], "")
enVar = enList[0]
varList.append(ifVar + enVar)
@@ -1754,37 +1994,49 @@ def searchCodes(page, pbar, jobList, filename):
# Translate
if len(textHistory) > 0:
- response = translateGPT(choiceList, 'This will be a dialogue option. Previous text for context: ' + textHistory[len(textHistory)-1] + '\n\nThis will be a dialogue option', True)
+ response = translateGPT(
+ choiceList,
+ "This will be a dialogue option. Previous text for context: "
+ + textHistory[len(textHistory) - 1]
+ + "\n\nThis will be a dialogue option",
+ True,
+ )
translatedTextList = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
else:
- response = translateGPT(choiceList, 'This will be a dialogue option', True)
+ response = translateGPT(
+ choiceList, "This will be a dialogue option", True
+ )
translatedTextList = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Check Mismatch
if len(translatedTextList) == len(choiceList):
- for choice in range(len(codeList[i]['parameters'][0])):
+ for choice in range(len(codeList[i]["parameters"][0])):
translatedText = translatedTextList[choice]
# Set Data
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
- if translatedText != '':
- translatedText = varList[choice] + translatedText[0].upper() + translatedText[1:]
+ if translatedText != "":
+ translatedText = (
+ varList[choice]
+ + translatedText[0].upper()
+ + translatedText[1:]
+ )
else:
translatedText = varList[choice] + translatedText
- codeList[i]['parameters'][0][choice] = translatedText
+ codeList[i]["parameters"][0][choice] = translatedText
else:
if filename not in MISMATCH:
MISMATCH.append(filename)
### Event Code: 111 Script
- if 'code' in codeList[i] and codeList[i]['code'] == 111 and CODE111 is True:
- for j in range(len(codeList[i]['parameters'])):
- jaString = codeList[i]['parameters'][j]
+ if "code" in codeList[i] and codeList[i]["code"] == 111 and CODE111 is True:
+ for j in range(len(codeList[i]["parameters"])):
+ jaString = codeList[i]["parameters"][j]
# Check if String
if not isinstance(jaString, str):
@@ -1792,63 +2044,63 @@ def searchCodes(page, pbar, jobList, filename):
continue
# Only TL the Game Variable
- if '$gameVariables' not in jaString:
+ if "$gameVariables" not in jaString:
i += 1
continue
# This is going to be the var being set. (IMPORTANT)
- if '1045' not in jaString:
+ if "1045" not in jaString:
i += 1
continue
# Need to remove outside code and put it back later
matchList = re.findall(r"'(.*?)'", jaString)
-
+
for match in matchList:
- response = translateGPT(match, '', False)
+ response = translateGPT(match, "", False)
translatedText = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Remove characters that may break scripts
- charList = ['.', '\"', '\'', '\\n']
+ charList = [".", '"', "'", "\\n"]
for char in charList:
- translatedText = translatedText.replace(char, '')
+ translatedText = translatedText.replace(char, "")
jaString = jaString.replace(match, translatedText)
# Set Data
translatedText = jaString
- codeList[i]['parameters'][j] = translatedText
+ codeList[i]["parameters"][j] = translatedText
### Event Code: 320 Set Variable
- if 'code' in codeList[i] and codeList[i]['code'] == 320 and CODE320 is True:
- jaString = codeList[i]['parameters'][1]
+ if "code" in codeList[i] and codeList[i]["code"] == 320 and CODE320 is True:
+ jaString = codeList[i]["parameters"][1]
if not isinstance(jaString, str):
i += 1
continue
-
+
# Definitely don't want to mess with files
- if '■' in jaString or '_' in jaString:
+ if "■" in jaString or "_" in jaString:
i += 1
continue
# If there isn't any Japanese in the text just skip
- if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', jaString):
+ if not re.search(r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+", jaString):
i += 1
continue
-
+
# Translate
getSpeaker(jaString)
# Remove characters that may break scripts
- charList = ['.', '\"', '\'', '\\n']
+ charList = [".", '"', "'", "\\n"]
for char in charList:
- translatedText = translatedText.replace(char, '')
+ translatedText = translatedText.replace(char, "")
# Set Data
- codeList[i]['parameters'][1] = translatedText
-
+ codeList[i]["parameters"][1] = translatedText
+
# Iterate
else:
i += 1
@@ -1860,7 +2112,7 @@ def searchCodes(page, pbar, jobList, filename):
list108TL = []
setData = False
PBAR = pbar
-
+
# 401
if len(list401) > 0:
response = translateGPT(list401, textHistory, True)
@@ -1915,17 +2167,19 @@ def searchCodes(page, pbar, jobList, filename):
# Start Pass 2
if setData:
- searchCodes(page, pbar, [list401TL, list122TL, list355655TL, list108TL], filename)
+ searchCodes(
+ page, pbar, [list401TL, list122TL, list355655TL, list108TL], filename
+ )
# Delete all -1 codes
codeListFinal = []
for i in range(len(codeList)):
- if 'code' in codeList[i] and codeList[i]['code'] != -1:
+ if "code" in codeList[i] and codeList[i]["code"] != -1:
codeListFinal.append(codeList[i])
# Normal Format
- if 'list' in page:
- page['list'] = codeListFinal
+ if "list" in page:
+ page["list"] = codeListFinal
# Special Format (Scenario)
else:
@@ -1933,141 +2187,240 @@ def searchCodes(page, pbar, jobList, filename):
except IndexError as e:
traceback.print_exc()
- raise Exception(str(e) + 'Failed to translate: ' + oldjaString) from None
+ raise Exception(str(e) + "Failed to translate: " + oldjaString) from None
except Exception as e:
traceback.print_exc()
- raise Exception(str(e) + 'Failed to translate: ' + oldjaString) from None
+ raise Exception(str(e) + "Failed to translate: " + oldjaString) from None
return totalTokens
+
def searchSS(state, pbar):
totalTokens = [0, 0]
# Name
- nameResponse = translateGPT(state['name'], 'Reply with only the '+ LANGUAGE +' translation of the RPG Skill name.', False) if 'name' in state else ''
+ nameResponse = (
+ translateGPT(
+ state["name"],
+ "Reply with only the " + LANGUAGE + " translation of the RPG Skill name.",
+ False,
+ )
+ if "name" in state
+ else ""
+ )
# Description
- descriptionResponse = translateGPT(state['description'], 'Reply with only the '+ LANGUAGE +' translation of the description.', False) if 'description' in state else ''
+ descriptionResponse = (
+ translateGPT(
+ state["description"],
+ "Reply with only the " + LANGUAGE + " translation of the description.",
+ False,
+ )
+ if "description" in state
+ else ""
+ )
# Messages
- message1Response = ''
- message4Response = ''
- message2Response = ''
- message3Response = ''
-
- if 'message1' in state:
- if len(state['message1']) > 0 and state['message1'][0] in ['は', 'を', 'の', 'に', 'が']:
- message1Response = translateGPT('Taro' + state['message1'], 'reply with only the gender neutral '+ LANGUAGE +' translation of the action log. Always start the sentence with Taro. For example,\
-Translate \'Taroを倒した!\' as \'Taro was defeated!\'', False)
- else:
- message1Response = translateGPT(state['message1'], 'reply with only the gender neutral '+ LANGUAGE +' translation', False)
+ message1Response = ""
+ message4Response = ""
+ message2Response = ""
+ message3Response = ""
- if 'message2' in state:
- if len(state['message2']) > 0 and state['message2'][0] in ['は', 'を', 'の', 'に', 'が']:
- message2Response = translateGPT('Taro' + state['message2'], 'reply with only the gender neutral '+ LANGUAGE +' translation of the action log. Always start the sentence with Taro. For example,\
-Translate \'Taroを倒した!\' as \'Taro was defeated!\'', False)
+ if "message1" in state:
+ if len(state["message1"]) > 0 and state["message1"][0] in [
+ "は",
+ "を",
+ "の",
+ "に",
+ "が",
+ ]:
+ message1Response = translateGPT(
+ "Taro" + state["message1"],
+ "reply with only the gender neutral "
+ + LANGUAGE
+ + " translation of the action log. Always start the sentence with Taro. For example,\
+Translate 'Taroを倒した!' as 'Taro was defeated!'",
+ False,
+ )
else:
- message2Response = translateGPT(state['message2'], 'reply with only the gender neutral '+ LANGUAGE +' translation', False)
+ message1Response = translateGPT(
+ state["message1"],
+ "reply with only the gender neutral " + LANGUAGE + " translation",
+ False,
+ )
- if 'message3' in state:
- if len(state['message3']) > 0 and state['message3'][0] in ['は', 'を', 'の', 'に', 'が']:
- message3Response = translateGPT('Taro' + state['message3'], 'reply with only the gender neutral '+ LANGUAGE +' translation of the action log. Always start the sentence with Taro. For example,\
-Translate \'Taroを倒した!\' as \'Taro was defeated!\'', False)
+ if "message2" in state:
+ if len(state["message2"]) > 0 and state["message2"][0] in [
+ "は",
+ "を",
+ "の",
+ "に",
+ "が",
+ ]:
+ message2Response = translateGPT(
+ "Taro" + state["message2"],
+ "reply with only the gender neutral "
+ + LANGUAGE
+ + " translation of the action log. Always start the sentence with Taro. For example,\
+Translate 'Taroを倒した!' as 'Taro was defeated!'",
+ False,
+ )
else:
- message3Response = translateGPT(state['message3'], 'reply with only the gender neutral '+ LANGUAGE +' translation', False)
+ message2Response = translateGPT(
+ state["message2"],
+ "reply with only the gender neutral " + LANGUAGE + " translation",
+ False,
+ )
- if 'message4' in state:
- if len(state['message4']) > 0 and state['message4'][0] in ['は', 'を', 'の', 'に', 'が']:
- message4Response = translateGPT('Taro' + state['message4'], 'reply with only the gender neutral '+ LANGUAGE +' translation of the action log. Always start the sentence with Taro. For example,\
-Translate \'Taroを倒した!\' as \'Taro was defeated!\'', False)
+ if "message3" in state:
+ if len(state["message3"]) > 0 and state["message3"][0] in [
+ "は",
+ "を",
+ "の",
+ "に",
+ "が",
+ ]:
+ message3Response = translateGPT(
+ "Taro" + state["message3"],
+ "reply with only the gender neutral "
+ + LANGUAGE
+ + " translation of the action log. Always start the sentence with Taro. For example,\
+Translate 'Taroを倒した!' as 'Taro was defeated!'",
+ False,
+ )
else:
- message4Response = translateGPT(state['message4'], 'reply with only the gender neutral '+ LANGUAGE +' translation', False)
+ message3Response = translateGPT(
+ state["message3"],
+ "reply with only the gender neutral " + LANGUAGE + " translation",
+ False,
+ )
+
+ if "message4" in state:
+ if len(state["message4"]) > 0 and state["message4"][0] in [
+ "は",
+ "を",
+ "の",
+ "に",
+ "が",
+ ]:
+ message4Response = translateGPT(
+ "Taro" + state["message4"],
+ "reply with only the gender neutral "
+ + LANGUAGE
+ + " translation of the action log. Always start the sentence with Taro. For example,\
+Translate 'Taroを倒した!' as 'Taro was defeated!'",
+ False,
+ )
+ else:
+ message4Response = translateGPT(
+ state["message4"],
+ "reply with only the gender neutral " + LANGUAGE + " translation",
+ False,
+ )
# Translate State Notes
- if 'help' in state['note']:
- noteResponse = translateNote(state, r']*)>')
+ if "help" in state["note"]:
+ noteResponse = translateNote(state, r"]*)>")
totalTokens[0] += noteResponse[0]
totalTokens[1] += noteResponse[1]
- if 'STATE_HELP' in state['note']:
- noteResponse = translateNote(state, r'\n(.*)\n')
+ if "STATE_HELP" in state["note"]:
+ noteResponse = translateNote(state, r"\n(.*)\n")
totalTokens[0] += noteResponse[0]
totalTokens[1] += noteResponse[1]
-
+
# Count totalTokens
- totalTokens[0] += nameResponse[1][0] if nameResponse != '' else 0
- totalTokens[1] += nameResponse[1][1] if nameResponse != '' else 0
- totalTokens[0] += descriptionResponse[1][0] if descriptionResponse != '' else 0
- totalTokens[1] += descriptionResponse[1][1] if descriptionResponse != '' else 0
- totalTokens[0] += message1Response[1][0] if message1Response != '' else 0
- totalTokens[1] += message1Response[1][1] if message1Response != '' else 0
- totalTokens[0] += message2Response[1][0] if message2Response != '' else 0
- totalTokens[1] += message2Response[1][1] if message2Response != '' else 0
- totalTokens[0] += message3Response[1][0] if message3Response != '' else 0
- totalTokens[1] += message3Response[1][1] if message3Response != '' else 0
- totalTokens[0] += message4Response[1][0] if message4Response != '' else 0
- totalTokens[1] += message4Response[1][1] if message4Response != '' else 0
+ totalTokens[0] += nameResponse[1][0] if nameResponse != "" else 0
+ totalTokens[1] += nameResponse[1][1] if nameResponse != "" else 0
+ totalTokens[0] += descriptionResponse[1][0] if descriptionResponse != "" else 0
+ totalTokens[1] += descriptionResponse[1][1] if descriptionResponse != "" else 0
+ totalTokens[0] += message1Response[1][0] if message1Response != "" else 0
+ totalTokens[1] += message1Response[1][1] if message1Response != "" else 0
+ totalTokens[0] += message2Response[1][0] if message2Response != "" else 0
+ totalTokens[1] += message2Response[1][1] if message2Response != "" else 0
+ totalTokens[0] += message3Response[1][0] if message3Response != "" else 0
+ totalTokens[1] += message3Response[1][1] if message3Response != "" else 0
+ totalTokens[0] += message4Response[1][0] if message4Response != "" else 0
+ totalTokens[1] += message4Response[1][1] if message4Response != "" else 0
# Set Data
- if 'name' in state:
- state['name'] = nameResponse[0].replace('\"', '')
- if 'description' in state:
+ if "name" in state:
+ state["name"] = nameResponse[0].replace('"', "")
+ if "description" in state:
# Textwrap
translatedText = descriptionResponse[0]
translatedText = textwrap.fill(translatedText, width=LISTWIDTH)
- state['description'] = translatedText.replace('\"', '')
- if 'message1' in state:
- state['message1'] = message1Response[0].replace('\"', '').replace('Taro', '')
- if 'message2' in state:
- state['message2'] = message2Response[0].replace('\"', '').replace('Taro', '')
- if 'message3' in state:
- state['message3'] = message3Response[0].replace('\"', '').replace('Taro', '')
- if 'message4' in state:
- state['message4'] = message4Response[0].replace('\"', '').replace('Taro', '')
+ state["description"] = translatedText.replace('"', "")
+ if "message1" in state:
+ state["message1"] = message1Response[0].replace('"', "").replace("Taro", "")
+ if "message2" in state:
+ state["message2"] = message2Response[0].replace('"', "").replace("Taro", "")
+ if "message3" in state:
+ state["message3"] = message3Response[0].replace('"', "").replace("Taro", "")
+ if "message4" in state:
+ state["message4"] = message4Response[0].replace('"', "").replace("Taro", "")
-
return totalTokens
+
def searchSystem(data, pbar):
totalTokens = [0, 0]
- context = 'Reply with only the '+ LANGUAGE +' translation of the UI textbox."'
+ context = "Reply with only the " + LANGUAGE + ' translation of the UI textbox."'
# Title
- response = translateGPT(data['gameTitle'], ' Reply with the '+ LANGUAGE +' translation of the game title name', False)
+ response = translateGPT(
+ data["gameTitle"],
+ " Reply with the " + LANGUAGE + " translation of the game title name",
+ False,
+ )
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
- data['gameTitle'] = response[0].strip('.')
-
+ data["gameTitle"] = response[0].strip(".")
+
# Terms
- for term in data['terms']:
- if term != 'messages':
- termList = data['terms'][term]
+ for term in data["terms"]:
+ if term != "messages":
+ termList = data["terms"][term]
for i in range(len(termList)): # Last item is a messages object
if termList[i] is not None:
response = translateGPT(termList[i], context, False)
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
- termList[i] = response[0].replace('\"', '').strip()
-
+ termList[i] = response[0].replace('"', "").strip()
+
# Armor Types
- for i in range(len(data['armorTypes'])):
- response = translateGPT(data['armorTypes'][i], 'Reply with only the '+ LANGUAGE +' translation of the armor type', False)
+ for i in range(len(data["armorTypes"])):
+ response = translateGPT(
+ data["armorTypes"][i],
+ "Reply with only the " + LANGUAGE + " translation of the armor type",
+ False,
+ )
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
- data['armorTypes'][i] = response[0].replace('\"', '').strip()
+ data["armorTypes"][i] = response[0].replace('"', "").strip()
# Skill Types
- for i in range(len(data['skillTypes'])):
- response = translateGPT(data['skillTypes'][i], 'Reply with only the '+ LANGUAGE +' translation', False)
+ for i in range(len(data["skillTypes"])):
+ response = translateGPT(
+ data["skillTypes"][i],
+ "Reply with only the " + LANGUAGE + " translation",
+ False,
+ )
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
- data['skillTypes'][i] = response[0].replace('\"', '').strip()
+ data["skillTypes"][i] = response[0].replace('"', "").strip()
# Equip Types
- for i in range(len(data['equipTypes'])):
- response = translateGPT(data['equipTypes'][i], 'Reply with only the '+ LANGUAGE +' translation of the equipment type. No disclaimers.', False)
+ for i in range(len(data["equipTypes"])):
+ response = translateGPT(
+ data["equipTypes"][i],
+ "Reply with only the "
+ + LANGUAGE
+ + " translation of the equipment type. No disclaimers.",
+ False,
+ )
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
- data['equipTypes'][i] = response[0].replace('\"', '').strip()
+ data["equipTypes"][i] = response[0].replace('"', "").strip()
# # Variables (Optional ususally)
# for i in range(len(data['variables'])):
@@ -2075,42 +2428,56 @@ def searchSystem(data, pbar):
# totalTokens[0] += response[1][0]
# totalTokens[1] += response[1][1]
# data['variables'][i] = response[0].replace('\"', '').strip()
-
# Messages
- messages = (data['terms']['messages'])
+ messages = data["terms"]["messages"]
for key, value in messages.items():
- response = translateGPT(value, 'Reply with only the '+ LANGUAGE +' translation of the battle text.\nTranslate "常時ダッシュ" as "Always Dash"\nTranslate "次の%1まで" as Next %1.', False)
+ response = translateGPT(
+ value,
+ "Reply with only the "
+ + LANGUAGE
+ + ' translation of the battle text.\nTranslate "常時ダッシュ" as "Always Dash"\nTranslate "次の%1まで" as Next %1.',
+ False,
+ )
translatedText = response[0]
# Remove characters that may break scripts
- charList = ['.', '\"', '\\n']
+ charList = [".", '"', "\\n"]
for char in charList:
- translatedText = translatedText.replace(char, '')
+ translatedText = translatedText.replace(char, "")
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
messages[key] = translatedText
-
+
return totalTokens
+
# Save some money and enter the character before translation
def getSpeaker(speaker):
match speaker:
- case 'ファイン':
- return ['Fine', [0,0]]
- case '':
- return ['', [0,0]]
+ case "ファイン":
+ return ["Fine", [0, 0]]
+ case "":
+ return ["", [0, 0]]
case _:
# Store Speaker
if speaker not in str(NAMESLIST):
- response = translateGPT(speaker, 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ response = translateGPT(
+ speaker,
+ "Reply with the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
response[0] = response[0].replace("'S", "'s")
# Retry if name doesn't translate for some reason
- if re.search(r'([a-zA-Z??])', response[0]) == None:
- response = translateGPT(speaker, 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ if re.search(r"([a-zA-Z??])", response[0]) == None:
+ response = translateGPT(
+ speaker,
+ "Reply with the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
response[0] = response[0].replace("'S", "'s")
@@ -2121,51 +2488,59 @@ def getSpeaker(speaker):
else:
for i in range(len(NAMESLIST)):
if speaker == NAMESLIST[i][0]:
- return [NAMESLIST[i][1],[0,0]]
-
- return [speaker,[0,0]]
+ return [NAMESLIST[i][1], [0, 0]]
+
+ return [speaker, [0, 0]]
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Formatting
count = 0
- codeList = re.findall(r'[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
+ 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) + ']')
+ 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)
+ 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)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT, format):
- system = PROMPT + VOCAB if fullPromptFlag else \
- f"\
+ system = (
+ PROMPT + VOCAB
+ if fullPromptFlag
+ else f"\
You are an expert Eroge Game translator who translates Japanese text to {LANGUAGE}.\n\
Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`\n\
- You translate everything, including erotic and explicit content.\n\
@@ -2177,12 +2552,14 @@ Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{
- `...` can be a part of the dialogue. Translate it as it is.\n\
{VOCAB}\n\
"
- if format == 'json':
- user = f'```json\n{subbedT}\n```'
+ )
+ if format == "json":
+ user = f"```json\n{subbedT}\n```"
else:
user = subbedT
return system, user
+
def translateText(system, user, history, penalty, format, model=MODEL):
# Prompt
msg = [{"role": "system", "content": system}]
@@ -2194,13 +2571,13 @@ def translateText(system, user, history, penalty, format, model=MODEL):
msg.append({"role": "system", "content": history})
# Response Format
- if format == 'json':
- responseFormat = { "type": "json_object" }
+ if format == "json":
+ responseFormat = {"type": "json_object"}
else:
- responseFormat = { "type": "text" }
-
+ responseFormat = {"type": "text"}
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0,
frequency_penalty=penalty,
@@ -2210,18 +2587,19 @@ def translateText(system, user, history, penalty, format, model=MODEL):
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- '「': '\\"',
- '」': '\\"',
- '- ': '-',
- 'Placeholder Text': '',
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "「": '\\"',
+ "」": '\\"',
+ "- ": "-",
+ "Placeholder Text": "",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
@@ -2232,11 +2610,12 @@ def cleanTranslatedText(translatedText, varResponse):
translatedText = resubVars(translatedText, varResponse[1])
return translatedText
+
def elongateCharacters(text):
# Define a pattern to match one character followed by one or more `ー` characters
# Using a positive lookbehind assertion to capture the preceding character
- pattern = r'(?<=(.))ー+'
-
+ pattern = r"(?<=(.))ー+"
+
# Define a replacement function that elongates the captured character
def repl(match):
char = match.group(1) # The character before the ー sequence
@@ -2246,6 +2625,7 @@ def elongateCharacters(text):
# Use re.sub() to replace the pattern in the text
return re.sub(pattern, repl, text)
+
def extractTranslation(translatedTextList, is_list):
try:
line_dict = json.loads(translatedTextList)
@@ -2257,15 +2637,15 @@ def extractTranslation(translatedTextList, is_list):
return string_list[0]
except Exception as e:
- print(f'extractTranslation Error: {e}')
+ print(f"extractTranslation Error: {e}")
return None
def countTokens(system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -2276,26 +2656,28 @@ def countTokens(system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*3)
+ outputTotalTokens += round(len(enc.encode(user)) * 3)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag):
global PBAR, MISMATCH, FILENAME
-
+
mismatch = False
totalTokens = [0, 0]
if isinstance(text, list):
- format = 'json'
+ format = "json"
tList = batchList(text, BATCHSIZE)
else:
- format = 'text'
+ format = "text"
tList = [text]
for index, tItem in enumerate(tList):
@@ -2310,7 +2692,7 @@ def translateGPT(text, history, fullPromptFlag):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
if PBAR is not None:
PBAR.update(len(tItem))
continue
@@ -2335,9 +2717,11 @@ def translateGPT(text, history, fullPromptFlag):
translatedText = cleanTranslatedText(translatedText, varResponse)
if isinstance(tItem, list):
extractedTranslations = extractTranslation(translatedText, True)
- if extractedTranslations == None or len(tItem) != len(extractedTranslations):
+ if extractedTranslations == None or len(tItem) != len(
+ extractedTranslations
+ ):
# Mismatch. Try Again
- response = translateText(system, user, history, 0.05, format, 'gpt-4o')
+ response = translateText(system, user, history, 0.05, format, "gpt-4o")
translatedText = response.choices[0].message.content
totalTokens[0] += response.usage.prompt_tokens
totalTokens[1] += response.usage.completion_tokens
@@ -2346,13 +2730,17 @@ def translateGPT(text, history, fullPromptFlag):
translatedText = cleanTranslatedText(translatedText, varResponse)
if isinstance(tItem, list):
extractedTranslations = extractTranslation(translatedText, True)
- if extractedTranslations == None or len(tItem) != len(extractedTranslations):
- mismatch = True # Just here for breakpoint
-
+ if extractedTranslations == None or len(tItem) != len(
+ extractedTranslations
+ ):
+ mismatch = True # Just here for breakpoint
+
# Set if no mismatch
if mismatch == False:
tList[index] = extractedTranslations
- history = extractedTranslations[-10:] # Update history if we have a list
+ history = extractedTranslations[
+ -10:
+ ] # Update history if we have a list
else:
history = text[-10:]
mismatch = False
@@ -2365,7 +2753,7 @@ def translateGPT(text, history, fullPromptFlag):
PBAR.update(len(tItem))
else:
# Ensure we're passing a single string to extractTranslation
- tList[index] = translatedText
+ tList[index] = translatedText
finalList = combineList(tList, text)
return [finalList, totalTokens]
diff --git a/modules/rpgmakerplugin.py b/modules/rpgmakerplugin.py
index ce4fb36..3d3b493 100644
--- a/modules/rpgmakerplugin.py
+++ b/modules/rpgmakerplugin.py
@@ -16,34 +16,34 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
NOTEWIDTH = 70
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = True # Overwrites textwrap
-IGNORETLTEXT = False # Ignores all translated text.
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = False # Ignores all translated text.
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
PBAR = None
@@ -51,15 +51,16 @@ PBAR = None
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .005
- OUTPUTAPICOST = .015
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.005
+ OUTPUTAPICOST = 0.015
BATCHSIZE = 40
+
def handlePlugin(filename, estimate):
global ESTIMATE, PBAR
ESTIMATE = estimate
@@ -76,17 +77,21 @@ def handlePlugin(filename, estimate):
TOKENS[1] += translatedData[1][1]
# Print Total
- totalString = getResultString(['', TOKENS, None], end - start, 'TOTAL')
+ totalString = getResultString(["", TOKENS, None], end - start, "TOTAL")
# Print any errors on maps
if len(MISMATCH) > 0:
- return totalString + Fore.RED + f'\nMismatch Errors: {MISMATCH}' + Fore.RESET
+ return (
+ totalString + Fore.RED + f"\nMismatch Errors: {MISMATCH}" + Fore.RESET
+ )
else:
return totalString
-
+
else:
try:
- with open('translated/' + filename, 'w', encoding='utf_8', errors='ignore') as outFile:
+ with open(
+ "translated/" + filename, "w", encoding="utf_8", errors="ignore"
+ ) as outFile:
start = time.time()
translatedData = openFiles(filename)
@@ -99,23 +104,36 @@ def handlePlugin(filename, estimate):
TOKENS[1] += translatedData[1][1]
except Exception:
traceback.print_exc()
- return 'Fail'
+ return "Fail"
+
+ return getResultString(["", TOKENS, None], end - start, "TOTAL")
- return getResultString(['', TOKENS, None], end - start, 'TOTAL')
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] == None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
@@ -124,31 +142,41 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
def openFiles(filename):
- with open('files/' + filename, 'r', encoding='utf_8') as readFile:
+ with open("files/" + filename, "r", encoding="utf_8") as readFile:
translatedData = parsePlugin(readFile, filename)
# Delete lines marked for deletion
finalData = []
for line in translatedData[0]:
- if line != '\\d\n':
+ if line != "\\d\n":
finalData.append(line)
translatedData[0] = finalData
-
+
return translatedData
+
def parsePlugin(readFile, filename):
- totalTokens = [0,0]
+ totalTokens = [0, 0]
# Read File into data
data = readFile.readlines()
# Create Progress Bar
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
try:
result = translatePlugin(data, pbar, filename, [])
@@ -159,19 +187,20 @@ def parsePlugin(readFile, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def translatePlugin(data, pbar, filename, translatedList):
stringList = []
currentGroup = []
- tokens = [0,0]
- speaker = ''
+ tokens = [0, 0]
+ speaker = ""
voice = False
global LOCK, ESTIMATE
i = 0
while i < len(data):
voice = False
- speaker = ''
- newline = r'\n'
+ speaker = ""
+ newline = r"\n"
"""
Plugin List
@@ -192,16 +221,16 @@ def translatePlugin(data, pbar, filename, translatedList):
for match in matchList:
# Save Original String
originalString = match
-
+
# Remove any textwrap
- match = match.replace(newline, ' ')
+ match = match.replace(newline, " ")
# Pass 1
- if translatedList == []:
+ if translatedList == []:
# Add String
- if match != '\\\\\\\\':
+ if match != "\\\\\\\\":
stringList.append(match.strip())
-
+
# Pass 2
else:
# Get Text
@@ -216,7 +245,7 @@ def translatePlugin(data, pbar, filename, translatedList):
# Textwrap
translatedText = textwrap.fill(translatedText, width=WIDTH)
- translatedText = translatedText.replace('\n', newline)
+ translatedText = translatedText.replace("\n", newline)
# Replace Single Quotes
translatedText = translatedText.replace("'", "\\'")
@@ -224,7 +253,7 @@ def translatePlugin(data, pbar, filename, translatedList):
# Set Data
data[i] = data[i].replace(originalString, translatedText)
- # Next Line
+ # Next Line
i += 1
# EOF
@@ -233,9 +262,9 @@ def translatePlugin(data, pbar, filename, translatedList):
pbar.total = len(stringList)
pbar.refresh()
PBAR = pbar
-
+
# Translate
- response = translateGPT(stringList, '', True)
+ response = translateGPT(stringList, "", True)
tokens[0] += response[1][0]
tokens[1] += response[1][1]
translatedList = response[0]
@@ -251,23 +280,32 @@ def translatePlugin(data, pbar, filename, translatedList):
MISMATCH.append(filename)
return tokens
+
# Save some money and enter the character before translation
def getSpeaker(speaker):
match speaker:
- case 'ファイン':
- return ['Fine', [0,0]]
- case '':
- return ['', [0,0]]
+ case "ファイン":
+ return ["Fine", [0, 0]]
+ case "":
+ return ["", [0, 0]]
case _:
# Store Speaker
if speaker not in str(NAMESLIST):
- response = translateGPT(speaker, 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ response = translateGPT(
+ speaker,
+ "Reply with the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
response[0] = response[0].replace("'S", "'s")
# Retry if name doesn't translate for some reason
- if re.search(r'([a-zA-Z??])', response[0]) == None:
- response = translateGPT(speaker, 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ if re.search(r"([a-zA-Z??])", response[0]) == None:
+ response = translateGPT(
+ speaker,
+ "Reply with the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
response[0] = response[0].replace("'S", "'s")
@@ -278,74 +316,76 @@ def getSpeaker(speaker):
else:
for i in range(len(NAMESLIST)):
if speaker == NAMESLIST[i][0]:
- return [NAMESLIST[i][1],[0,0]]
-
- return [speaker,[0,0]]
+ return [NAMESLIST[i][1], [0, 0]]
+
+ return [speaker, [0, 0]]
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Nested
count = 0
- nestedList = re.findall(r'[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]', jaString)
+ nestedList = re.findall(r"[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]", jaString)
nestedList = set(nestedList)
if len(nestedList) != 0:
for icon in nestedList:
- jaString = jaString.replace(icon, '[Nested_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Nested_" + str(count) + "]")
count += 1
# Icons
count = 0
- iconList = re.findall(r'[\\]+[iIkKwWaA]+\[[0-9]+\]', jaString)
+ iconList = re.findall(r"[\\]+[iIkKwWaA]+\[[0-9]+\]", jaString)
iconList = set(iconList)
if len(iconList) != 0:
for icon in iconList:
- jaString = jaString.replace(icon, '[Ascii_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Ascii_" + str(count) + "]")
count += 1
# Colors
count = 0
- colorList = re.findall(r'([\\]+c\[\d+\][\\]+c|[\\]+c\[\d+\])', jaString)
+ colorList = re.findall(r"([\\]+c\[\d+\][\\]+c|[\\]+c\[\d+\])", jaString)
colorList = set(colorList)
if len(colorList) != 0:
for color in colorList:
- jaString = jaString.replace(color, '[Color_' + str(count) + ']')
+ jaString = jaString.replace(color, "[Color_" + str(count) + "]")
count += 1
# Names
count = 0
- nameList = re.findall(r'[\\]+[nN]\[.+?\]+', jaString)
+ nameList = re.findall(r"[\\]+[nN]\[.+?\]+", jaString)
nameList = set(nameList)
if len(nameList) != 0:
for name in nameList:
- jaString = jaString.replace(name, '[Noun_' + str(count) + ']')
+ jaString = jaString.replace(name, "[Noun_" + str(count) + "]")
count += 1
# Variables
count = 0
- varList = re.findall(r'[\\]+[vV]\[[0-9]+\]', jaString)
+ varList = re.findall(r"[\\]+[vV]\[[0-9]+\]", jaString)
varList = set(varList)
if len(varList) != 0:
for var in varList:
- jaString = jaString.replace(var, '[Var_' + str(count) + ']')
+ jaString = jaString.replace(var, "[Var_" + str(count) + "]")
count += 1
# Formatting
count = 0
- formatList = re.findall(r'[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
+ formatList = re.findall(r"[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]", jaString)
formatList = set(formatList)
if len(formatList) != 0:
for var in formatList:
- jaString = jaString.replace(var, '[FCode_' + str(count) + ']')
+ jaString = jaString.replace(var, "[FCode_" + str(count) + "]")
count += 1
# Put all lists in list and return
allList = [nestedList, iconList, colorList, nameList, varList, formatList]
return [jaString, allList]
+
def resubVars(translatedText, allList):
# Fix Spacing and ChatGPT Nonsense
- matchList = re.findall(r'\[\s?.+?\s?\]', translatedText)
+ matchList = re.findall(r"\[\s?.+?\s?\]", translatedText)
if len(matchList) > 0:
for match in matchList:
text = match.strip()
@@ -355,54 +395,58 @@ def resubVars(translatedText, allList):
count = 0
if len(allList[0]) != 0:
for var in allList[0]:
- translatedText = translatedText.replace('[Nested_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Nested_" + str(count) + "]", var)
count += 1
# Icons
count = 0
if len(allList[1]) != 0:
for var in allList[1]:
- translatedText = translatedText.replace('[Ascii_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Ascii_" + str(count) + "]", var)
count += 1
# Colors
count = 0
if len(allList[2]) != 0:
for var in allList[2]:
- translatedText = translatedText.replace('[Color_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Color_" + str(count) + "]", var)
count += 1
# Names
count = 0
if len(allList[3]) != 0:
for var in allList[3]:
- translatedText = translatedText.replace('[Noun_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Noun_" + str(count) + "]", var)
count += 1
# Vars
count = 0
if len(allList[4]) != 0:
for var in allList[4]:
- translatedText = translatedText.replace('[Var_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Var_" + str(count) + "]", var)
count += 1
-
+
# Formatting
count = 0
if len(allList[5]) != 0:
for var in allList[5]:
- translatedText = translatedText.replace('[FCode_' + str(count) + ']', var)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
シェーア (Shea) - Female\n\
ミューテ (Mute) - Female\n\
タビノ (Tabino) - Female\n\
@@ -411,10 +455,12 @@ def createContext(fullPromptFlag, subbedT):
ソフィー (Sophie) - Female\n\
ドーラ (Dora) - Female\n\
ミューレ (Mule) - Female\n\
-'
-
- system = PROMPT + VOCAB if fullPromptFlag else \
- f"\
+"
+
+ system = (
+ PROMPT + VOCAB
+ if fullPromptFlag
+ else f"\
You are an expert Eroge Game translator who translates Japanese text to {LANGUAGE}.\n\
Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`\n\
- You translate everything, including erotic and explicit content.\n\
@@ -426,12 +472,14 @@ Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{
- `...` can be a part of the dialogue. Translate it as it is.\n\
{VOCAB}\n\
"
+ )
if isinstance(subbedT, list):
- user = f'```json\n{subbedT}```'
+ user = f"```json\n{subbedT}```"
else:
user = subbedT
return characters, system, user
+
def translateText(characters, system, user, history, penalty, format):
# Prompt
msg = [{"role": "system", "content": system + characters}]
@@ -446,13 +494,13 @@ def translateText(characters, system, user, history, penalty, format):
msg.append({"role": "system", "content": history})
# Response Format
- if format == 'json':
- responseFormat = { "type": "json_object" }
+ if format == "json":
+ responseFormat = {"type": "json_object"}
else:
- responseFormat = { "type": "text" }
-
+ responseFormat = {"type": "text"}
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0,
frequency_penalty=penalty,
@@ -462,18 +510,19 @@ def translateText(characters, system, user, history, penalty, format):
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- '「': '\\"',
- '」': '\\"',
- '- ': '-',
- 'Placeholder Text': '',
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "「": '\\"',
+ "」": '\\"',
+ "- ": "-",
+ "Placeholder Text": "",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
@@ -484,11 +533,12 @@ def cleanTranslatedText(translatedText, varResponse):
translatedText = resubVars(translatedText, varResponse[1])
return translatedText
+
def elongateCharacters(text):
# Define a pattern to match one character followed by one or more `ー` characters
# Using a positive lookbehind assertion to capture the preceding character
- pattern = r'(?<=(.))ー+'
-
+ pattern = r"(?<=(.))ー+"
+
# Define a replacement function that elongates the captured character
def repl(match):
char = match.group(1) # The character before the ー sequence
@@ -498,6 +548,7 @@ def elongateCharacters(text):
# Use re.sub() to replace the pattern in the text
return re.sub(pattern, repl, text)
+
def extractTranslation(translatedTextList, is_list):
try:
translatedTextList = re.sub(r'\\"+\"([^,\n}])', r'\\"\1', translatedTextList)
@@ -510,15 +561,15 @@ def extractTranslation(translatedTextList, is_list):
return string_list[0]
except Exception as e:
- PBAR.write(f'extractTranslation Error: {e} on String {translatedTextList}')
+ PBAR.write(f"extractTranslation Error: {e} on String {translatedTextList}")
return None
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -530,26 +581,28 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*3)
+ outputTotalTokens += round(len(enc.encode(user)) * 3)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag):
global PBAR
-
+
mismatch = False
totalTokens = [0, 0]
if isinstance(text, list):
- format = 'json'
+ format = "json"
tList = batchList(text, BATCHSIZE)
else:
- format = 'text'
+ format = "text"
tList = [text]
for index, tItem in enumerate(tList):
@@ -564,7 +617,7 @@ def translateGPT(text, history, fullPromptFlag):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
if PBAR is not None:
PBAR.update(len(tItem))
continue
@@ -589,9 +642,13 @@ def translateGPT(text, history, fullPromptFlag):
translatedText = cleanTranslatedText(translatedText, varResponse)
if isinstance(tItem, list):
extractedTranslations = extractTranslation(translatedText, True)
- if extractedTranslations == None or len(tItem) != len(extractedTranslations):
+ if extractedTranslations == None or len(tItem) != len(
+ extractedTranslations
+ ):
# Mismatch. Try Again
- response = translateText(characters, system, user, history, 0.05, format)
+ response = translateText(
+ characters, system, user, history, 0.05, format
+ )
translatedText = response.choices[0].message.content
totalTokens[0] += response.usage.prompt_tokens
totalTokens[1] += response.usage.completion_tokens
@@ -600,13 +657,17 @@ def translateGPT(text, history, fullPromptFlag):
translatedText = cleanTranslatedText(translatedText, varResponse)
if isinstance(tItem, list):
extractedTranslations = extractTranslation(translatedText, True)
- if extractedTranslations == None or len(tItem) != len(extractedTranslations):
- mismatch = True # Just here for breakpoint
-
+ if extractedTranslations == None or len(tItem) != len(
+ extractedTranslations
+ ):
+ mismatch = True # Just here for breakpoint
+
# Set if no mismatch
if mismatch == False:
tList[index] = extractedTranslations
- history = extractedTranslations[-10:] # Update history if we have a list
+ history = extractedTranslations[
+ -10:
+ ] # Update history if we have a list
else:
history = text[-10:]
mismatch = False
@@ -617,7 +678,7 @@ def translateGPT(text, history, fullPromptFlag):
PBAR.update(len(tItem))
else:
# Ensure we're passing a single string to extractTranslation
- tList[index] = translatedText
+ tList[index] = translatedText
finalList = combineList(tList, text)
return [finalList, totalTokens]
diff --git a/modules/sakuranbo.py b/modules/sakuranbo.py
index e45c177..b0e4c29 100644
--- a/modules/sakuranbo.py
+++ b/modules/sakuranbo.py
@@ -16,7 +16,7 @@ from tqdm import tqdm
# Open AI
load_dotenv()
if os.getenv("api").replace(" ", "") != "":
- openai.base_url = os.getenv('api')
+ openai.base_url = os.getenv("api")
openai.organization = os.getenv("org")
openai.api_key = os.getenv("key")
@@ -95,8 +95,9 @@ def getResultString(translatedData, translationTime, filename):
# File Print String
totalTokenstring = (
Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
- "[Output: " + str(translatedData[1][1]) + "]"
- "[Cost: ${:,.4f}".format(
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
(translatedData[1][0] * 0.001 * INPUTAPICOST)
+ (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
)
@@ -189,17 +190,17 @@ def translateTyrano(data, pbar):
if syncIndex > i:
i = syncIndex
- if '[▼]' in data[i]:
- data[i] = data[i].replace('[▼]'.strip(), '[page]\n')
+ if "[▼]" in data[i]:
+ data[i] = data[i].replace("[▼]".strip(), "[page]\n")
# If there isn't any Japanese in the text just skip
if IGNORETLTEXT is True:
- if not re.search(r'[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+', data[i]):
+ if not re.search(r"[一-龠]+|[ぁ-ゔ]+|[ァ-ヴー]+", data[i]):
# Keep textHistory list at length maxHistory
- textHistory.append('\"' + data[i] + '\"')
+ textHistory.append('"' + data[i] + '"')
if len(textHistory) > maxHistory:
textHistory.pop(0)
- currentGroup = []
+ currentGroup = []
continue
# Speaker
@@ -215,18 +216,16 @@ def translateTyrano(data, pbar):
speaker = "Narrator"
elif "マコ" in matchList[0]:
speaker = "Mako"
- elif '少年' in matchList[0]:
+ elif "少年" in matchList[0]:
speaker = "Boy"
- elif '友達' in matchList[0]:
+ elif "友達" in matchList[0]:
speaker = "Friend"
- elif '少女' in matchList[0]:
+ elif "少女" in matchList[0]:
speaker = "Girl"
else:
response = translateGPT(
matchList[0],
- "Reply with only the "
- + LANGUAGE
- + " translation of the NPC name",
+ "Reply with only the " + LANGUAGE + " translation of the NPC name",
True,
)
speaker = response[0]
@@ -263,13 +262,17 @@ def translateTyrano(data, pbar):
# Set Data
translatedText = data[i].replace(
- matchList[0], translatedText.replace(" ", "\u00A0")
+ matchList[0], translatedText.replace(" ", "\u00a0")
)
data[i] = translatedText
# Grab Lines
matchList = re.findall(r"^([^\n;@*\{\[].+[^;'{}\[]$)", data[i])
- if len(matchList) > 0 and (re.search(r'^\[(.+)\sstorage=.+\],', data[i-1]) or re.search(r'^\[(.+)\]$', data[i-1]) or re.search(r'^《(.+)》', data[i-1])):
+ if len(matchList) > 0 and (
+ re.search(r"^\[(.+)\sstorage=.+\],", data[i - 1])
+ or re.search(r"^\[(.+)\]$", data[i - 1])
+ or re.search(r"^《(.+)》", data[i - 1])
+ ):
currentGroup.append(matchList[0])
if len(data) > i + 1:
matchList = re.findall(r"^([^\n;@*\{\[].+[^;'{}\[]$)", data[i + 1])
@@ -323,10 +326,10 @@ def translateTyrano(data, pbar):
# Set
if delFlag is True:
- data.insert(i, translatedText.strip() + '\n')
+ data.insert(i, translatedText.strip() + "\n")
delFlag = False
else:
- data[i] = translatedText.strip() + '\n'
+ data[i] = translatedText.strip() + "\n"
# Keep textHistory list at length maxHistory
if len(textHistory) > maxHistory:
@@ -399,10 +402,10 @@ def translateTyrano(data, pbar):
# Set
if delFlag is True:
- data.insert(i, translatedText.strip() + '\n')
+ data.insert(i, translatedText.strip() + "\n")
delFlag = False
else:
- data[i] = translatedText.strip() + '\n'
+ data[i] = translatedText.strip() + "\n"
# Keep textHistory list at length maxHistory
if len(textHistory) > maxHistory:
@@ -418,6 +421,7 @@ def translateTyrano(data, pbar):
return tokens
+
def subVars(jaString):
jaString = jaString.replace("\u3000", " ")
@@ -551,7 +555,7 @@ def translateGPT(t, history, fullPromptFlag):
# If ESTIMATE is True just count this as an execution and return.
if ESTIMATE:
- enc = tiktoken.encoding_for_model('gpt-4')
+ enc = tiktoken.encoding_for_model("gpt-4")
historyRaw = ""
if isinstance(history, list):
for line in history:
diff --git a/modules/tyrano.py b/modules/tyrano.py
index b63a5d6..f52814f 100644
--- a/modules/tyrano.py
+++ b/modules/tyrano.py
@@ -15,35 +15,35 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
+# Globals
PBAR = None
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
NOTEWIDTH = 70
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = False # Overwrites textwrap
-IGNORETLTEXT = False # Ignores all translated text.
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = False # Ignores all translated text.
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
@@ -54,15 +54,16 @@ TEXTWRAPCHOICES = True
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .005
- OUTPUTAPICOST = .015
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.005
+ OUTPUTAPICOST = 0.015
BATCHSIZE = 40
+
def handleTyrano(filename, estimate):
global ESTIMATE
ESTIMATE = estimate
@@ -79,17 +80,21 @@ def handleTyrano(filename, estimate):
TOKENS[1] += translatedData[1][1]
# Print Total
- totalString = getResultString(['', TOKENS, None], end - start, 'TOTAL')
+ totalString = getResultString(["", TOKENS, None], end - start, "TOTAL")
# Print any errors on maps
if len(MISMATCH) > 0:
- return totalString + Fore.RED + f'\nMismatch Errors: {MISMATCH}' + Fore.RESET
+ return (
+ totalString + Fore.RED + f"\nMismatch Errors: {MISMATCH}" + Fore.RESET
+ )
else:
return totalString
-
+
else:
try:
- with open('translated/' + filename, 'w', encoding='utf8', errors='ignore') as outFile:
+ with open(
+ "translated/" + filename, "w", encoding="utf8", errors="ignore"
+ ) as outFile:
start = time.time()
translatedData = openFiles(filename)
@@ -102,23 +107,36 @@ def handleTyrano(filename, estimate):
TOKENS[1] += translatedData[1][1]
except Exception:
traceback.print_exc()
- return 'Fail'
+ return "Fail"
+
+ return getResultString(["", TOKENS, None], end - start, "TOTAL")
- return getResultString(['', TOKENS, None], end - start, 'TOTAL')
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] == None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
@@ -127,34 +145,46 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
def openFiles(filename):
- with open('files/' + filename, 'r', encoding='utf8') as readFile:
+ with open("files/" + filename, "r", encoding="utf8") as readFile:
translatedData = parseTyrano(readFile, filename)
# Delete lines marked for deletion
finalData = []
for line in translatedData[0]:
- if line != '\\d\n':
+ if line != "\\d\n":
finalData.append(line)
translatedData[0] = finalData
-
+
return translatedData
+
def parseTyrano(readFile, filename):
- totalTokens = [0,0]
+ totalTokens = [0, 0]
totalLines = 0
# Get total for progress bar
data = readFile.readlines()
- with tqdm(bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE) as pbar:
- pbar.desc=filename
+ with tqdm(
+ bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE
+ ) as pbar:
+ pbar.desc = filename
try:
- result = translateTyrano(data, pbar, filename, False, [[],[]])
+ result = translateTyrano(data, pbar, filename, False, [[], []])
totalTokens[0] += result[0]
totalTokens[1] += result[1]
except Exception as e:
@@ -162,58 +192,63 @@ def parseTyrano(readFile, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def translateTyrano(data, pbar, filename, setData, jobList):
textHistory = []
lineList = jobList[0]
- totalTokens = [0,0]
- speaker = ''
+ totalTokens = [0, 0]
+ speaker = ""
global LOCK, ESTIMATE
i = 0
# Set Progress Bar
- global PBAR
+ global PBAR
PBAR = pbar
while i < len(data):
# Choices
choiceList = []
- choiceRegex = r'[sS]tatus.+?\](.+)'
- if 'tatus' in data[i]:
+ choiceRegex = r"[sS]tatus.+?\](.+)"
+ if "tatus" in data[i]:
match = re.search(choiceRegex, data[i])
if match != None:
jaString = match.group(1)
# Remove Textwrap
if TEXTWRAPCHOICES is True:
- jaString = jaString.replace('[r]', ' ')
- data[i] = data[i].replace('[r]', ' ')
-
+ jaString = jaString.replace("[r]", " ")
+ data[i] = data[i].replace("[r]", " ")
+
# Add to list
choiceList.append(jaString)
i += 1
# Grab them all up for list
- while(i < len(data) and 'tatus' in data[i]):
+ while i < len(data) and "tatus" in data[i]:
match = re.search(choiceRegex, data[i])
if match != None:
jaString = match.group(1)
# Remove Textwrap
if TEXTWRAPCHOICES is True:
- jaString = jaString.replace('[r]', ' ')
- data[i] = data[i].replace('[r]', ' ')
+ jaString = jaString.replace("[r]", " ")
+ data[i] = data[i].replace("[r]", " ")
# Add to list
choiceList.append(jaString)
i += 1
-
+
# Translate
if len(choiceList) != 0:
- response = translateGPT(choiceList, 'Reply with the {LANGUAGE} translation of the text', True)
+ response = translateGPT(
+ choiceList,
+ "Reply with the {LANGUAGE} translation of the text",
+ True,
+ )
choiceListTL = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
-
+
# Set Data
if len(choiceList) == len(choiceListTL):
i = i - len(choiceListTL)
@@ -223,75 +258,83 @@ def translateTyrano(data, pbar, filename, setData, jobList):
# Textwrap
if TEXTWRAPCHOICES is True:
translatedText = textwrap.fill(translatedText, WIDTH)
- translatedText = translatedText.replace('\n', '[r]')
+ translatedText = translatedText.replace("\n", "[r]")
data[i] = data[i].replace(choiceList[j], translatedText)
i += 1
else:
with LOCK:
if filename not in MISMATCH:
MISMATCH.append(filename)
-
+
if DIALOGUEFLAG is True:
# Speaker
- if '[@]' in data[i]:
- if 'FACE' not in data[i]:
- matchList = re.findall(r'\[(.*?)\].+\[.*\]', data[i])
+ if "[@]" in data[i]:
+ if "FACE" not in data[i]:
+ matchList = re.findall(r"\[(.*?)\].+\[.*\]", data[i])
else:
- matchList = re.findall(r'face=.+?\]\[(.+?)\]', data[i])
- if len(matchList) != 0 and '=' not in matchList[0] and re.search(r'\[.+\]', matchList[0]) == None:
+ matchList = re.findall(r"face=.+?\]\[(.+?)\]", data[i])
+ if (
+ len(matchList) != 0
+ and "=" not in matchList[0]
+ and re.search(r"\[.+\]", matchList[0]) == None
+ ):
response = getSpeaker(matchList[0])
speaker = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# data[i] = data[i].replace(matchList[0], f'{speaker}')
else:
- speaker = ''
-
+ speaker = ""
+
# Lines
- if 'FACE' not in data[i]:
- matchList = re.findall(r'\[.+?\](.+)\[.+\]', data[i])
+ if "FACE" not in data[i]:
+ matchList = re.findall(r"\[.+?\](.+)\[.+\]", data[i])
else:
- matchList = re.findall(r'face=.+?\]\[.+?\](.+)\[.+\]', data[i])
- if len(matchList) > 0 and '=' not in matchList[0]:
+ matchList = re.findall(r"face=.+?\]\[.+?\](.+)\[.+\]", data[i])
+ if len(matchList) > 0 and "=" not in matchList[0]:
# No Japanese text
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', matchList[0]):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", matchList[0]):
i += 1
continue
# Remove [r] and [l]
oldjaString = matchList[0]
jaString = oldjaString
- jaString = jaString.replace('[r]', ' ')
- jaString = jaString.replace('[l]', '')
+ jaString = jaString.replace("[r]", " ")
+ jaString = jaString.replace("[l]", "")
# Join up 401 groups for better translation.
finalJAString = jaString
# Remove Extra Stuff bad for translation.
- finalJAString = finalJAString.replace('゙', '')
- finalJAString = finalJAString.replace('・', '.')
- finalJAString = finalJAString.replace('‶', '')
- finalJAString = finalJAString.replace('”', '')
- finalJAString = finalJAString.replace('―', '-')
- finalJAString = finalJAString.replace('…', '...')
- finalJAString = re.sub(r'(\.{3}\.+)', '...', finalJAString)
- finalJAString = finalJAString.replace(' ', ' ')
- finalJAString = finalJAString.replace('】', ')')
- finalJAString = finalJAString.replace('【 ', '(')
+ finalJAString = finalJAString.replace("゙", "")
+ finalJAString = finalJAString.replace("・", ".")
+ finalJAString = finalJAString.replace("‶", "")
+ finalJAString = finalJAString.replace("”", "")
+ finalJAString = finalJAString.replace("―", "-")
+ finalJAString = finalJAString.replace("…", "...")
+ finalJAString = re.sub(r"(\.{3}\.+)", "...", finalJAString)
+ finalJAString = finalJAString.replace(" ", " ")
+ finalJAString = finalJAString.replace("】", ")")
+ finalJAString = finalJAString.replace("【 ", "(")
# Furigana Removal
- matchList = re.findall(r'(\[ruby\stext=.+text=\"(.+)\"\])', finalJAString)
+ matchList = re.findall(
+ r"(\[ruby\stext=.+text=\"(.+)\"\])", finalJAString
+ )
if len(matchList) > 0:
- finalJAString = finalJAString.replace(matchList[0][0], matchList[0][1])
+ finalJAString = finalJAString.replace(
+ matchList[0][0], matchList[0][1]
+ )
# Add Speaker (If there is one)
- if speaker != '':
- finalJAString = f'{speaker}: {finalJAString}'
+ if speaker != "":
+ finalJAString = f"{speaker}: {finalJAString}"
# [Passthrough 1] Append To List
if setData is False:
lineList.append(finalJAString)
-
+
# [Passthrough 2] Set Data
else:
# Grab and Pop
@@ -299,22 +342,24 @@ def translateTyrano(data, pbar, filename, setData, jobList):
lineList.pop(0)
# Remove speaker
- translatedText = re.sub(r'^\[?(.+?)\]?\s?[|:]\s?', '', translatedText)
+ translatedText = re.sub(
+ r"^\[?(.+?)\]?\s?[|:]\s?", "", translatedText
+ )
# Textwrap
translatedText = textwrap.fill(translatedText, WIDTH)
- translatedText = translatedText.replace('\n', '[r]')
+ translatedText = translatedText.replace("\n", "[r]")
# Set Data
data[i] = data[i].replace(oldjaString, translatedText)
# Next Line
i += 1
-
+
# Translate Data
lineListTL = []
setData = False
-
+
# Line List
if len(lineList) > 0:
pbar.total = len(lineList)
@@ -335,17 +380,23 @@ def translateTyrano(data, pbar, filename, setData, jobList):
translateTyrano(data, pbar, filename, True, [lineListTL])
return totalTokens
+
+
# Save some money and enter the character before translation
def getSpeaker(speaker):
match speaker:
- case 'ファイン':
- return ['Fine', [0,0]]
- case '':
- return ['', [0,0]]
+ case "ファイン":
+ return ["Fine", [0, 0]]
+ case "":
+ return ["", [0, 0]]
case _:
# Store Speaker
if speaker not in str(NAMESLIST):
- response = translateGPT(speaker, 'Reply with only the '+ LANGUAGE +' translation of the NPC name.', False)
+ response = translateGPT(
+ speaker,
+ "Reply with only the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
speakerList = [speaker, response[0]]
NAMESLIST.append(speakerList)
@@ -354,74 +405,76 @@ def getSpeaker(speaker):
else:
for i in range(len(NAMESLIST)):
if speaker == NAMESLIST[i][0]:
- return [NAMESLIST[i][1],[0,0]]
-
- return [speaker,[0,0]]
+ return [NAMESLIST[i][1], [0, 0]]
+
+ return [speaker, [0, 0]]
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Nested
count = 0
- nestedList = re.findall(r'[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]', jaString)
+ nestedList = re.findall(r"[\\]+[\w]+\[[\\]+[\w]+\[[0-9]+\]\]", jaString)
nestedList = set(nestedList)
if len(nestedList) != 0:
for icon in nestedList:
- jaString = jaString.replace(icon, '[Nested_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Nested_" + str(count) + "]")
count += 1
# Icons
count = 0
- iconList = re.findall(r'[\\]+[iIkKwWaA]+\[[0-9]+\]', jaString)
+ iconList = re.findall(r"[\\]+[iIkKwWaA]+\[[0-9]+\]", jaString)
iconList = set(iconList)
if len(iconList) != 0:
for icon in iconList:
- jaString = jaString.replace(icon, '[Ascii_' + str(count) + ']')
+ jaString = jaString.replace(icon, "[Ascii_" + str(count) + "]")
count += 1
# Colors
count = 0
- colorList = re.findall(r'[\\]+[cC]\[[0-9]+\]', jaString)
+ colorList = re.findall(r"[\\]+[cC]\[[0-9]+\]", jaString)
colorList = set(colorList)
if len(colorList) != 0:
for color in colorList:
- jaString = jaString.replace(color, '[Color_' + str(count) + ']')
+ jaString = jaString.replace(color, "[Color_" + str(count) + "]")
count += 1
# Names
count = 0
- nameList = re.findall(r'[\\]+[nN]\[.+?\]+', jaString)
+ nameList = re.findall(r"[\\]+[nN]\[.+?\]+", jaString)
nameList = set(nameList)
if len(nameList) != 0:
for name in nameList:
- jaString = jaString.replace(name, '[Noun_' + str(count) + ']')
+ jaString = jaString.replace(name, "[Noun_" + str(count) + "]")
count += 1
# Variables
count = 0
- varList = re.findall(r'[\\]+[vV]\[[0-9]+\]', jaString)
+ varList = re.findall(r"[\\]+[vV]\[[0-9]+\]", jaString)
varList = set(varList)
if len(varList) != 0:
for var in varList:
- jaString = jaString.replace(var, '[Var_' + str(count) + ']')
+ jaString = jaString.replace(var, "[Var_" + str(count) + "]")
count += 1
# Formatting
count = 0
- formatList = re.findall(r'[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
+ formatList = re.findall(r"[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]", jaString)
formatList = set(formatList)
if len(formatList) != 0:
for var in formatList:
- jaString = jaString.replace(var, '[FCode_' + str(count) + ']')
+ jaString = jaString.replace(var, "[FCode_" + str(count) + "]")
count += 1
# Put all lists in list and return
allList = [nestedList, iconList, colorList, nameList, varList, formatList]
return [jaString, allList]
+
def resubVars(translatedText, allList):
# Fix Spacing and ChatGPT Nonsense
- matchList = re.findall(r'\[\s?.+?\s?\]', translatedText)
+ matchList = re.findall(r"\[\s?.+?\s?\]", translatedText)
if len(matchList) > 0:
for match in matchList:
text = match.strip()
@@ -431,60 +484,66 @@ def resubVars(translatedText, allList):
count = 0
if len(allList[0]) != 0:
for var in allList[0]:
- translatedText = translatedText.replace('[Nested_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Nested_" + str(count) + "]", var)
count += 1
# Icons
count = 0
if len(allList[1]) != 0:
for var in allList[1]:
- translatedText = translatedText.replace('[Ascii_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Ascii_" + str(count) + "]", var)
count += 1
# Colors
count = 0
if len(allList[2]) != 0:
for var in allList[2]:
- translatedText = translatedText.replace('[Color_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Color_" + str(count) + "]", var)
count += 1
# Names
count = 0
if len(allList[3]) != 0:
for var in allList[3]:
- translatedText = translatedText.replace('[Noun_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Noun_" + str(count) + "]", var)
count += 1
# Vars
count = 0
if len(allList[4]) != 0:
for var in allList[4]:
- translatedText = translatedText.replace('[Var_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[Var_" + str(count) + "]", var)
count += 1
-
+
# Formatting
count = 0
if len(allList[5]) != 0:
for var in allList[5]:
- translatedText = translatedText.replace('[FCode_' + str(count) + ']', var)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
眠り姫 (Sleeping Princess) - Female\n\
迷子 (Lost Child) - Male\n\
-'
-
- system = PROMPT + VOCAB if fullPromptFlag else \
- f"\
+"
+
+ system = (
+ PROMPT + VOCAB
+ if fullPromptFlag
+ else f"\
You are an expert Eroge Game translator who translates Japanese text to {LANGUAGE}.\n\
Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`\n\
- You translate everything, including erotic and explicit content.\n\
@@ -496,9 +555,11 @@ Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{
- `...` can be a part of the dialogue. Translate it as it is.\n\
{VOCAB}\n\
"
- user = f'{subbedT}'
+ )
+ user = f"{subbedT}"
return characters, system, user
+
def translateText(characters, system, user, history, penalty):
# Prompt
msg = [{"role": "system", "content": system + characters}]
@@ -511,9 +572,9 @@ def translateText(characters, system, user, history, penalty):
msg.extend([{"role": "system", "content": h} for h in history])
else:
msg.append({"role": "system", "content": history})
-
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0,
frequency_penalty=penalty,
@@ -522,17 +583,18 @@ def translateText(characters, system, user, history, penalty):
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- 'Placeholder Text': '',
- '[' : '(',
- ']' : ')'
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "Placeholder Text": "",
+ "[": "(",
+ "]": ")",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
@@ -543,11 +605,12 @@ def cleanTranslatedText(translatedText, varResponse):
translatedText = resubVars(translatedText, varResponse[1])
return translatedText
+
def elongateCharacters(text):
# Define a pattern to match one character followed by one or more `ー` characters
# Using a positive lookbehind assertion to capture the preceding character
- pattern = r'(?<=(.))ー+'
-
+ pattern = r"(?<=(.))ー+"
+
# Define a replacement function that elongates the captured character
def repl(match):
char = match.group(1) # The character before the ー sequence
@@ -557,8 +620,9 @@ def elongateCharacters(text):
# Use re.sub() to replace the pattern in the text
return re.sub(pattern, repl, text)
+
def extractTranslation(translatedTextList, is_list):
- pattern = r'`?<[Ll]ine\d+>([\\]*.*?[\\]*?)<\/?[Ll]ine\d+>`?'
+ pattern = r"`?<[Ll]ine\d+>([\\]*.*?[\\]*?)<\/?[Ll]ine\d+>`?"
# If it's a batch (i.e., list), extract with tags; otherwise, return the single item.
if is_list:
matchList = re.findall(pattern, translatedTextList)
@@ -567,11 +631,12 @@ def extractTranslation(translatedTextList, is_list):
matchList = re.findall(pattern, translatedTextList)
return matchList[0][0] if matchList else translatedTextList
+
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -583,15 +648,17 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*3)
+ outputTotalTokens += round(len(enc.encode(user)) * 3)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag):
global PBAR
@@ -605,8 +672,12 @@ def translateGPT(text, history, fullPromptFlag):
for index, tItem in enumerate(tList):
# Before sending to translation, if we have a list of items, add the formatting
if isinstance(tItem, list):
- payload = '\n'.join([f'`{item}`' for i, item in enumerate(tItem)])
- payload = re.sub(r'(<)(\/Line\d+>)', r'\1>Placeholder Text<\3', payload)
+ payload = "\n".join(
+ [f"`{item}`" for i, item in enumerate(tItem)]
+ )
+ payload = re.sub(
+ r"(<)(\/Line\d+>)", r"\1>Placeholder Text<\3", payload
+ )
varResponse = subVars(payload)
subbedT = varResponse[0]
else:
@@ -614,7 +685,7 @@ def translateGPT(text, history, fullPromptFlag):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
continue
# Create Message
@@ -651,11 +722,13 @@ def translateGPT(text, history, fullPromptFlag):
extractedTranslations = extractTranslation(translatedText, True)
tList[index] = extractedTranslations
if len(tItem) != len(extractedTranslations):
- mismatch = True # Just here for breakpoint
+ mismatch = True # Just here for breakpoint
# Create History
if not mismatch:
- history = extractedTranslations[-10:] # Update history if we have a list
+ history = extractedTranslations[
+ -10:
+ ] # Update history if we have a list
else:
history = text[-10:]
PBAR.update(len(tItem))
diff --git a/modules/wolf.py b/modules/wolf.py
index f302d8b..159b6e4 100644
--- a/modules/wolf.py
+++ b/modules/wolf.py
@@ -17,51 +17,51 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
-NOTEWIDTH = int(os.getenv('noteWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
+NOTEWIDTH = int(os.getenv("noteWidth"))
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
-NAMESLIST = [] # Keep list for consistency
-TERMSLIST = [] # Keep list for consistency
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+NAMESLIST = [] # Keep list for consistency
+TERMSLIST = [] # Keep list for consistency
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = True # Overwrites textwrap
-IGNORETLTEXT = False # Ignores all translated text.
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = False # Ignores all translated text.
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
FILENAME = None
BRACKETNAMES = False
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
FREQUENCY_PENALTY = 0.2
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .005
- OUTPUTAPICOST = .015
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.005
+ OUTPUTAPICOST = 0.015
BATCHSIZE = 20
FREQUENCY_PENALTY = 0.1
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
PBAR = None
@@ -86,6 +86,7 @@ ARMORFLAG = False
ENEMYFLAG = False
WEAPONFLAG = False
+
def handleWOLF(filename, estimate):
global ESTIMATE, TOKENS, FILENAME
ESTIMATE = estimate
@@ -94,16 +95,16 @@ def handleWOLF(filename, estimate):
# Translate
start = time.time()
translatedData = openFiles(filename)
-
+
# Translate
if not estimate:
try:
- with open('translated/' + filename, 'w', encoding='utf-8') as outFile:
+ with open("translated/" + filename, "w", encoding="utf-8") as outFile:
json.dump(translatedData[0], outFile, ensure_ascii=False, indent=4)
except Exception:
traceback.print_exc()
- return 'Fail'
-
+ return "Fail"
+
# Print File
end = time.time()
tqdm.write(getResultString(translatedData, end - start, filename))
@@ -112,24 +113,25 @@ def handleWOLF(filename, estimate):
TOKENS[1] += translatedData[1][1]
# Print Total
- totalString = getResultString(['', TOKENS, None], end - start, 'TOTAL')
+ totalString = getResultString(["", TOKENS, None], end - start, "TOTAL")
# Print any errors on maps
if len(MISMATCH) > 0:
- return totalString + Fore.RED + f'\nMismatch Errors: {MISMATCH}' + Fore.RESET
+ return totalString + Fore.RED + f"\nMismatch Errors: {MISMATCH}" + Fore.RESET
else:
return totalString
+
def openFiles(filename):
- with open('files/' + filename, 'r', encoding='utf-8-sig') as f:
+ with open("files/" + filename, "r", encoding="utf-8-sig") as f:
data = json.load(f)
# Map Files
if "'events':" in str(data):
- if len(data['events']) > 0:
+ if len(data["events"]) > 0:
translatedData = parseMap(data, filename)
else:
- return [data, [0,0], None]
+ return [data, [0, 0], None]
# Map Files
elif "'types':" in str(data):
@@ -138,25 +140,38 @@ def openFiles(filename):
# Other Files
elif "'commands':" in str(data):
translatedData = parseOther(data, filename)
-
+
else:
- raise NameError(filename + ' Not Supported')
-
+ raise NameError(filename + " Not Supported")
+
return translatedData
+
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] is None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
try:
@@ -164,19 +179,28 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
def parseOther(data, filename):
totalTokens = [0, 0]
totalLines = 0
- events = data['commands']
+ events = data["commands"]
global LOCK
-
+
# Thread for each page in file
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
- pbar.total=totalLines
+ pbar.desc = filename
+ pbar.total = totalLines
translationData = searchCodes(events, pbar, [], filename)
try:
totalTokens[0] += translationData[0]
@@ -185,16 +209,17 @@ def parseOther(data, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def parseDB(data, filename):
totalTokens = [0, 0]
totalLines = 0
- events = data['types']
+ events = data["types"]
global LOCK
-
+
# Thread for each page in file
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
- pbar.total=totalLines
+ pbar.desc = filename
+ pbar.total = totalLines
translationData = searchDB(events, pbar, [], filename)
try:
totalTokens[0] += translationData[0]
@@ -203,26 +228,33 @@ def parseDB(data, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def parseMap(data, filename):
totalTokens = [0, 0]
totalLines = 0
- events = data['events']
+ events = data["events"]
global LOCK
# Get total for progress bar
for event in events:
if event is not None:
- for page in event['pages']:
- totalLines += len(page['list'])
-
+ for page in event["pages"]:
+ totalLines += len(page["list"])
+
# Thread for each page in file
- with tqdm(bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE) as pbar:
- pbar.desc=filename
- pbar.total=totalLines
+ with tqdm(
+ bar_format=BAR_FORMAT, position=POSITION, total=totalLines, leave=LEAVE
+ ) as pbar:
+ pbar.desc = filename
+ pbar.total = totalLines
with ThreadPoolExecutor(max_workers=THREADS) as executor:
for event in events:
if event is not None:
- futures = [executor.submit(searchCodes, page['list'], pbar, None, filename) for page in event['pages'] if page is not None]
+ futures = [
+ executor.submit(searchCodes, page["list"], pbar, None, filename)
+ for page in event["pages"]
+ if page is not None
+ ]
for future in as_completed(futures):
try:
totalTokensFuture = future.result()
@@ -232,8 +264,9 @@ def parseMap(data, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def searchCodes(events, pbar, jobList, filename):
- #Lists
+ # Lists
if jobList:
stringList = jobList[0]
list300 = jobList[1]
@@ -247,79 +280,78 @@ def searchCodes(events, pbar, jobList, filename):
codeList = events
textHistory = []
totalTokens = [0, 0]
- translatedText = ''
- speaker = ''
- nametag = ''
- initialJAString = ''
- global LOCK, NAMESLIST, MISMATCH, PBAR , FILENAME
+ translatedText = ""
+ speaker = ""
+ nametag = ""
+ initialJAString = ""
+ global LOCK, NAMESLIST, MISMATCH, PBAR, FILENAME
FILENAME = filename
PBAR = pbar
# Calculate Total Length
- code_flags = {
- 102: CODE102,
- 122: CODE122,
- 300: CODE300,
- 250: CODE250
- }
+ code_flags = {102: CODE102, 122: CODE122, 300: CODE300, 250: CODE250}
totalList = 0
for code_item in codeList:
- if code_flags.get(code_item['code'], False):
+ if code_flags.get(code_item["code"], False):
totalList += 1
pbar.total = totalList
pbar.refresh()
-
+
# Begin Parsing File
try:
# Iterate through events
i = 0
while i < len(codeList):
### Event Code: 101 Message
- if codeList[i]['code'] == 101 and CODE101 == True:
+ if codeList[i]["code"] == 101 and CODE101 == True:
# Grab String
- jaString = codeList[i]['stringArgs'][0]
+ jaString = codeList[i]["stringArgs"][0]
initialJAString = jaString
# Catch Vars that may break the TL
- varString = ''
- matchList = re.findall(r'^[\\_]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
+ varString = ""
+ matchList = re.findall(
+ r"^[\\_]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]", jaString
+ )
if len(matchList) != 0:
varString = matchList[0]
- jaString = jaString.replace(matchList[0], '')
+ jaString = jaString.replace(matchList[0], "")
# Grab Speaker
- if ':\n' in jaString:
- nameList = re.findall(r'(.*):\n', jaString)
+ if ":\n" in jaString:
+ nameList = re.findall(r"(.*):\n", jaString)
if nameList is not None:
# TL Speaker
response = getSpeaker(nameList[0])
speaker = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
-
+
# Set nametag and remove from string
- nametag = f'{speaker}:\n'
- jaString = jaString.replace(f'{nameList[0]}:\n', '')
+ nametag = f"{speaker}:\n"
+ jaString = jaString.replace(f"{nameList[0]}:\n", "")
# Remove Textwrap
- jaString = jaString.replace('\n', ' ')
+ jaString = jaString.replace("\n", " ")
# 1st Pass (Save Text to List)
if not setData:
- if speaker == '':
+ if speaker == "":
stringList.append(jaString)
else:
- stringList.append(f'[{speaker}]: {jaString}')
+ stringList.append(f"[{speaker}]: {jaString}")
# 2nd Pass (Set Text)
else:
# Grab Translated String
translatedText = stringList[0]
-
+
# Remove speaker
- matchSpeakerList = re.findall(r'^(\[.+?\]\s?[|:]\s?)\s?', translatedText)
+ matchSpeakerList = re.findall(
+ r"^(\[.+?\]\s?[|:]\s?)\s?", translatedText
+ )
if len(matchSpeakerList) > 0:
- translatedText = translatedText.replace(matchSpeakerList[0], '')
+ translatedText = translatedText.replace(matchSpeakerList[0], "")
# Textwrap
if FIXTEXTWRAP is True:
@@ -327,35 +359,39 @@ def searchCodes(events, pbar, jobList, filename):
# Add back Nametag
translatedText = nametag + translatedText
- nametag = ''
+ nametag = ""
# Add back Potential Variables in String
translatedText = varString + translatedText
# Set Data
- codeList[i]['stringArgs'][0] = translatedText
+ codeList[i]["stringArgs"][0] = translatedText
# Reset Data and Pop Item
- speaker = ''
+ speaker = ""
stringList.pop(0)
### Event Code: 102 Choices
- if codeList[i]['code'] == 102 and CODE102 == True:
+ if codeList[i]["code"] == 102 and CODE102 == True:
# Grab Choice List
- choiceList = codeList[i]['stringArgs']
+ choiceList = codeList[i]["stringArgs"]
# Translate
- response = translateGPT(choiceList, f'Reply with the {LANGUAGE} translation of the dialogue choice', True)
+ response = translateGPT(
+ choiceList,
+ f"Reply with the {LANGUAGE} translation of the dialogue choice",
+ True,
+ )
translatedChoiceList = response[0]
totalTokens[0] = response[1][0]
totalTokens[1] = response[1][1]
# Validate and Set Data
if len(choiceList) == len(translatedChoiceList):
- codeList[i]['stringArgs'] = translatedChoiceList
+ codeList[i]["stringArgs"] = translatedChoiceList
### Event Code: 210 Common Event
- if codeList[i]['code'] == 210 and CODE210 == True:
+ if codeList[i]["code"] == 210 and CODE210 == True:
# if 'stringArgs' in codeList[i] and len(codeList[i]['stringArgs']) > 1:
# # Grab Event List
# jaString = codeList[i]['stringArgs'][1]
@@ -374,33 +410,49 @@ def searchCodes(events, pbar, jobList, filename):
# # Validate and Set Data
# codeList[i]['stringArgs'][1] = translatedText
- if 'stringArgs' in codeList[i] and len(codeList[i]['stringArgs']) > 1:
- cleanedList = formatDramon(codeList[i]['stringArgs'][1])
+ if "stringArgs" in codeList[i] and len(codeList[i]["stringArgs"]) > 1:
+ cleanedList = formatDramon(codeList[i]["stringArgs"][1])
fontSize = 24
- translatedText = ''
-
+ translatedText = ""
+
for str in cleanedList:
# Pass 1
if not setData:
- if all(x not in str for x in ['_', '@', '>', '/']) and str != '\r\n':
+ if (
+ all(x not in str for x in ["_", "@", ">", "/"])
+ and str != "\r\n"
+ ):
# Remove Textwrap and Font and Add to list
- str = str.replace('\r\n', ' ')
- str = str.replace(f'\\f[{fontSize}]', '')
+ str = str.replace("\r\n", " ")
+ str = str.replace(f"\\f[{fontSize}]", "")
list300.append(str)
# Pass 2
else:
- if all(x not in str for x in ['_', '@', '>', '/',]) and str != '\r\n':
+ if (
+ all(
+ x not in str
+ for x in [
+ "_",
+ "@",
+ ">",
+ "/",
+ ]
+ )
+ and str != "\r\n"
+ ):
# Decide Wrap
- if codeList[i]['stringArgs'][0] == '[移]サウンドノベル':
+ if codeList[i]["stringArgs"][0] == "[移]サウンドノベル":
width = 40
else:
width = WIDTH
# Add Textwrap and Font
list300[0] = textwrap.fill(list300[0], width)
- list300[0] = list300[0].replace('\n', f'\r\n\\f[{fontSize}]')
- list300[0] = f'\\f[{fontSize}]{list300[0]}\r\n'
+ list300[0] = list300[0].replace(
+ "\n", f"\r\n\\f[{fontSize}]"
+ )
+ list300[0] = f"\\f[{fontSize}]{list300[0]}\r\n"
translatedText += list300[0]
list300.pop(0)
else:
@@ -410,28 +462,31 @@ def searchCodes(events, pbar, jobList, filename):
if setData:
# Formatting Fixes
translatedText = translatedText.replace('*"', '* "')
- translatedText = translatedText.replace('\r\n\r\n', '\r\n')
- translatedText = re.sub(r'[^\S\r\n]+', ' ', translatedText)
- codeList[i]['stringArgs'][1] = translatedText
-
+ translatedText = translatedText.replace("\r\n\r\n", "\r\n")
+ translatedText = re.sub(r"[^\S\r\n]+", " ", translatedText)
+ codeList[i]["stringArgs"][1] = translatedText
### Event Code: 122 SetString
- if codeList[i]['code'] == 122 and CODE122 == True:
- if 'stringArgs' in codeList[i] and len(codeList[i]['stringArgs']) > 0:
+ if codeList[i]["code"] == 122 and CODE122 == True:
+ if "stringArgs" in codeList[i] and len(codeList[i]["stringArgs"]) > 0:
# Grab String
- jaString = codeList[i]['stringArgs'][0]
+ jaString = codeList[i]["stringArgs"][0]
# Translate Conversations
- if ':Nothing' in jaString:
+ if ":Nothing" in jaString:
# Separate into list
- list122 = jaString.split('\n\n')
+ list122 = jaString.split("\n\n")
# Remove Textwrap
for j in range(len(list122)):
- list122[j] = list122[j].replace('\n', ' ')
+ list122[j] = list122[j].replace("\n", " ")
# Translate
- response = translateGPT(list122, f'Reply with the {LANGUAGE} translation of the text', True)
+ response = translateGPT(
+ list122,
+ f"Reply with the {LANGUAGE} translation of the text",
+ True,
+ )
list122TL = response[0]
totalTokens[0] = response[1][0]
totalTokens[1] = response[1][1]
@@ -441,30 +496,40 @@ def searchCodes(events, pbar, jobList, filename):
# Adjust Speaker and Add Textwrap
for j in range(len(list122TL)):
list122TL[j] = textwrap.fill(list122TL[j], WIDTH)
- list122TL[j] = re.sub(r'^\[?(.+?)\]?:', r'\1:', list122TL[j])
- list122TL[j] = list122TL[j].replace(':', ':\n')
- list122TL[j] = list122TL[j].replace(':\n ', ':\n')
+ list122TL[j] = re.sub(
+ r"^\[?(.+?)\]?:", r"\1:", list122TL[j]
+ )
+ list122TL[j] = list122TL[j].replace(":", ":\n")
+ list122TL[j] = list122TL[j].replace(":\n ", ":\n")
# Join back into single string
- list122TL = '\n\n'.join(list122TL)
-
+ list122TL = "\n\n".join(list122TL)
+
# Set String
- codeList[i]['stringArgs'][0] = list122TL
-
+ codeList[i]["stringArgs"][0] = list122TL
+
# Translate Other Strings [Specific Files Only]
else:
- if not re.search(r'\.[\w]+$', jaString)\
- and jaString != ''\
- and '_' not in jaString\
- and '",' not in jaString\
- and '/' not in jaString:
+ if (
+ not re.search(r"\.[\w]+$", jaString)
+ and jaString != ""
+ and "_" not in jaString
+ and '",' not in jaString
+ and "/" not in jaString
+ ):
# Things to Check before starting translation
- if re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', jaString):
+ if re.search(
+ r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", jaString
+ ):
# Remove Textwrap
- jaString = jaString.replace('\n', ' ')
+ jaString = jaString.replace("\n", " ")
# Translate
- response = translateGPT(jaString, f'Reply with the {LANGUAGE} translation of the text', False)
+ response = translateGPT(
+ jaString,
+ f"Reply with the {LANGUAGE} translation of the text",
+ False,
+ )
translatedText = response[0]
totalTokens[0] = response[1][0]
totalTokens[1] = response[1][1]
@@ -473,15 +538,22 @@ def searchCodes(events, pbar, jobList, filename):
translatedText = textwrap.fill(translatedText, WIDTH)
# Set String
- codeList[i]['stringArgs'][0] = translatedText
+ codeList[i]["stringArgs"][0] = translatedText
### Event Code: 300 Common Events
- if codeList[i]['code'] == 300 and CODE300 == True and 'stringArgs' in codeList[i] and len(codeList[i]['stringArgs']) > 1:
+ if (
+ codeList[i]["code"] == 300
+ and CODE300 == True
+ and "stringArgs" in codeList[i]
+ and len(codeList[i]["stringArgs"]) > 1
+ ):
# Choices
- if codeList[i]['stringArgs'][0] == "[共]汎用ウィンドウ生成" \
- or codeList[i]['stringArgs'][0] == "[共]選択生成":
+ if (
+ codeList[i]["stringArgs"][0] == "[共]汎用ウィンドウ生成"
+ or codeList[i]["stringArgs"][0] == "[共]選択生成"
+ ):
# Grab String
- choiceList = codeList[i]['stringArgs'][1].split('\r\n')
+ choiceList = codeList[i]["stringArgs"][1].split("\r\n")
# # Translate Question
# question = codeList[i]['stringArgs'][2]
@@ -501,51 +573,80 @@ def searchCodes(events, pbar, jobList, filename):
# Replace Commas
for j in range(len(choiceListTL)):
- choiceListTL[j] = choiceListTL[j].replace(', ', '、')
+ choiceListTL[j] = choiceListTL[j].replace(", ", "、")
# Convert to String and Set
- translatedText = '\r\n'.join(choiceListTL)
- codeList[i]['stringArgs'][1] = translatedText
+ translatedText = "\r\n".join(choiceListTL)
+ codeList[i]["stringArgs"][1] = translatedText
# Dialogue
- elif codeList[i]['stringArgs'][0] == "Hメッセージ" \
- or codeList[i]['stringArgs'][0] == 'Hしらべる' \
- or codeList[i]['stringArgs'][0] == '[共]Hメッセージ+' \
- or codeList[i]['stringArgs'][0] == 'd[共]ポップアップ表示' \
- or codeList[i]['stringArgs'][0] == 'm_謎冒頭' \
- or (codeList[i]['codeStr'] == 'SetString' and ('「' in codeList[i]['stringArgs'][0] or '*' in codeList[i]['stringArgs'][0]))\
- or codeList[i]['stringArgs'][0] == '[移]サウンドノベル':
+ elif (
+ codeList[i]["stringArgs"][0] == "Hメッセージ"
+ or codeList[i]["stringArgs"][0] == "Hしらべる"
+ or codeList[i]["stringArgs"][0] == "[共]Hメッセージ+"
+ or codeList[i]["stringArgs"][0] == "d[共]ポップアップ表示"
+ or codeList[i]["stringArgs"][0] == "m_謎冒頭"
+ or (
+ codeList[i]["codeStr"] == "SetString"
+ and (
+ "「" in codeList[i]["stringArgs"][0]
+ or "*" in codeList[i]["stringArgs"][0]
+ )
+ )
+ or codeList[i]["stringArgs"][0] == "[移]サウンドノベル"
+ ):
cleanedList = None
- if len(codeList[i]['stringArgs']) > 1 and not re.search(r'^[\\]+cself\[\d+\]$', codeList[i]['stringArgs'][1]):
- cleanedList = formatDramon(codeList[i]['stringArgs'][1])
- elif codeList[i]['code'] == 122:
- cleanedList = formatDramon(codeList[i]['stringArgs'][0])
+ if len(codeList[i]["stringArgs"]) > 1 and not re.search(
+ r"^[\\]+cself\[\d+\]$", codeList[i]["stringArgs"][1]
+ ):
+ cleanedList = formatDramon(codeList[i]["stringArgs"][1])
+ elif codeList[i]["code"] == 122:
+ cleanedList = formatDramon(codeList[i]["stringArgs"][0])
if cleanedList:
fontSize = 24
- translatedText = ''
-
+ translatedText = ""
+
for str in cleanedList:
# Pass 1
if not setData:
- if all(x not in str for x in ['_', '@', '>', '/']) and str != '\r\n':
+ if (
+ all(x not in str for x in ["_", "@", ">", "/"])
+ and str != "\r\n"
+ ):
# Remove Textwrap and Font and Add to list
- str = str.replace('\r\n', ' ')
- str = str.replace(f'\\f[{fontSize}]', '')
+ str = str.replace("\r\n", " ")
+ str = str.replace(f"\\f[{fontSize}]", "")
list300.append(str)
# Pass 2
else:
- if all(x not in str for x in ['_', '@', '>', '/',]) and str != '\r\n':
+ if (
+ all(
+ x not in str
+ for x in [
+ "_",
+ "@",
+ ">",
+ "/",
+ ]
+ )
+ and str != "\r\n"
+ ):
# Decide Wrap
- if codeList[i]['stringArgs'][0] == '[移]サウンドノベル':
+ if (
+ codeList[i]["stringArgs"][0]
+ == "[移]サウンドノベル"
+ ):
width = 40
else:
width = WIDTH
# Add Textwrap and Font
list300[0] = textwrap.fill(list300[0], width)
- list300[0] = list300[0].replace('\n', f'\r\n\\f[{fontSize}]')
- list300[0] = f'\\f[{fontSize}]{list300[0]}\r\n'
+ list300[0] = list300[0].replace(
+ "\n", f"\r\n\\f[{fontSize}]"
+ )
+ list300[0] = f"\\f[{fontSize}]{list300[0]}\r\n"
translatedText += list300[0]
list300.pop(0)
else:
@@ -555,29 +656,34 @@ def searchCodes(events, pbar, jobList, filename):
if setData:
# Formatting Fixes
translatedText = translatedText.replace('*"', '* "')
- translatedText = translatedText.replace('\r\n\r\n', '\r\n')
- translatedText = re.sub(r'[^\S\r\n]+', ' ', translatedText)
- if len(codeList[i]['stringArgs']) > 1:
- codeList[i]['stringArgs'][1] = translatedText
+ translatedText = translatedText.replace("\r\n\r\n", "\r\n")
+ translatedText = re.sub(r"[^\S\r\n]+", " ", translatedText)
+ if len(codeList[i]["stringArgs"]) > 1:
+ codeList[i]["stringArgs"][1] = translatedText
else:
- codeList[i]['stringArgs'][0] = translatedText
+ codeList[i]["stringArgs"][0] = translatedText
### Event Code: 250 Common Events
- if codeList[i]['code'] == 250 and CODE250 == True:
+ if codeList[i]["code"] == 250 and CODE250 == True:
foundTerm = False
# Validate size
- if len(codeList[i]['stringArgs']) > 2:
- if codeList[i]['stringArgs'][1] == "┗所持防具個数" and codeList[i]['stringArgs'][2] != '':
+ if len(codeList[i]["stringArgs"]) > 2:
+ if (
+ codeList[i]["stringArgs"][1] == "┗所持防具個数"
+ and codeList[i]["stringArgs"][2] != ""
+ ):
# Grab String
- jaString = codeList[i]['stringArgs'][2]
+ jaString = codeList[i]["stringArgs"][2]
# Catch Vars that may break the TL
- varString = ''
- matchList = re.findall(r'^[\\_]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
+ varString = ""
+ matchList = re.findall(
+ r"^[\\_]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]", jaString
+ )
if len(matchList) != 0:
varString = matchList[0]
- jaString = jaString.replace(matchList[0], '')
+ jaString = jaString.replace(matchList[0], "")
# Check if term already translated
for j in range(len(TERMSLIST)):
@@ -587,7 +693,11 @@ def searchCodes(events, pbar, jobList, filename):
# Translate
if foundTerm == False:
- response = translateGPT(jaString, f'Reply with the {LANGUAGE} translation of the text.', False)
+ response = translateGPT(
+ jaString,
+ f"Reply with the {LANGUAGE} translation of the text.",
+ False,
+ )
translatedText = response[0]
totalTokens[0] = response[1][0]
totalTokens[1] = response[1][1]
@@ -597,11 +707,11 @@ def searchCodes(events, pbar, jobList, filename):
translatedText = varString + translatedText
# Set Data
- codeList[i]['stringArgs'][2] = translatedText
-
+ codeList[i]["stringArgs"][2] = translatedText
+
### Iterate
i += 1
-
+
# EOF
stringListTL = []
list300TL = []
@@ -621,7 +731,7 @@ def searchCodes(events, pbar, jobList, filename):
MISMATCH.append(filename)
else:
setData = True
-
+
# 300 List
if len(list300) > 0:
pbar.total = len(list300)
@@ -636,54 +746,70 @@ def searchCodes(events, pbar, jobList, filename):
MISMATCH.append(filename)
else:
setData = True
-
+
# Pass 2
if setData:
stringList = []
searchCodes(events, pbar, [stringListTL, list300TL], filename)
- else:
+ else:
# Set Data
events = codeList
except IndexError as e:
traceback.print_exc()
- raise Exception(str(e) + 'Failed to translate: ' + initialJAString) from None
+ raise Exception(str(e) + "Failed to translate: " + initialJAString) from None
except Exception as e:
traceback.print_exc()
- raise Exception(str(e) + 'Failed to translate: ' + initialJAString) from None
+ raise Exception(str(e) + "Failed to translate: " + initialJAString) from None
return totalTokens
-def formatDramon(jaString):
- imageRegex = r'(\r?\n?_[a-zA-Z_\d/.]+\r?\n?)|(@-?\d?\r\n)|(@-?\d?)([^\r]\d?-?\d?[^\r]+?)(\r\n|$)|(_PDC)|(>\r\n)|(^[#])|(\r\n@$)|(/)|(_SS_)|(\r\n[@/]\s?-?\d?\r\n)'
- jaString = jaString.replace('\u3000', ' ')
- jaString = jaString.replace('#', '')
- jaString = re.sub(r'([^\r])\n', r'\1\r\n', jaString)
+def formatDramon(jaString):
+ imageRegex = r"(\r?\n?_[a-zA-Z_\d/.]+\r?\n?)|(@-?\d?\r\n)|(@-?\d?)([^\r]\d?-?\d?[^\r]+?)(\r\n|$)|(_PDC)|(>\r\n)|(^[#])|(\r\n@$)|(/)|(_SS_)|(\r\n[@/]\s?-?\d?\r\n)"
+
+ jaString = jaString.replace("\u3000", " ")
+ jaString = jaString.replace("#", "")
+ jaString = re.sub(r"([^\r])\n", r"\1\r\n", jaString)
# Grab and Split
jaStringList = re.split(imageRegex, jaString)
# Clean List
- cleanedList = [x for x in jaStringList if x is not None and x != '' and x != '\r\n' and x != '_SS_']
+ cleanedList = [
+ x
+ for x in jaStringList
+ if x is not None and x != "" and x != "\r\n" and x != "_SS_"
+ ]
# Iterate Through List
j = 0
- translatedText = ''
+ translatedText = ""
while j < len(cleanedList):
- if ('@' in cleanedList[j] or '/' in cleanedList[j]) and j < len(cleanedList)-1 and re.search(r'([@/]-?\d?\r\n)', cleanedList[j]) is None and '.ogg' not in cleanedList[j]:
+ if (
+ ("@" in cleanedList[j] or "/" in cleanedList[j])
+ and j < len(cleanedList) - 1
+ and re.search(r"([@/]-?\d?\r\n)", cleanedList[j]) is None
+ and ".ogg" not in cleanedList[j]
+ ):
# Setup @
- if j > 0 and '@' not in cleanedList[j-1] and '/' not in cleanedList[j-1] and '_' not in cleanedList[j-1]:
- cleanedList[j-1] = cleanedList[j-1] + cleanedList[j+1]
+ if (
+ j > 0
+ and "@" not in cleanedList[j - 1]
+ and "/" not in cleanedList[j - 1]
+ and "_" not in cleanedList[j - 1]
+ ):
+ cleanedList[j - 1] = cleanedList[j - 1] + cleanedList[j + 1]
else:
- cleanedList.insert(j, cleanedList[j+1])
+ cleanedList.insert(j, cleanedList[j + 1])
j += 1
- cleanedList[j] = f'\r\n{cleanedList[j]}\r\n'
- cleanedList.pop(j+1)
+ cleanedList[j] = f"\r\n{cleanedList[j]}\r\n"
+ cleanedList.pop(j + 1)
j += 1
-
+
return cleanedList
+
# DatabaseDatabase
def searchDB(events, pbar, jobList, filename):
# Set Lists
@@ -697,187 +823,209 @@ def searchDB(events, pbar, jobList, filename):
weaponsList = jobList[6]
setData = True
else:
- scenarioList = [[],[],[]]
- NPCList = [[],[],[],[]]
- itemList = [[],[],[],[]]
- armorList = [[],[]]
- enemyList = [[],[]]
- weaponsList = [[],[],[],[]]
- collectionList = [[],[],[],[]]
+ scenarioList = [[], [], []]
+ NPCList = [[], [], [], []]
+ itemList = [[], [], [], []]
+ armorList = [[], []]
+ enemyList = [[], []]
+ weaponsList = [[], [], [], []]
+ collectionList = [[], [], [], []]
setData = False
-
+
# Vars/Globals
totalTokens = [0, 0]
- initialJAString = ''
+ initialJAString = ""
tableList = events
- font = ''
+ font = ""
global LOCK
global NAMESLIST
global MISMATCH
-
+
# Calculate Total
totalLines = 0
for table in tableList:
- if table['name'] == 'NPC' and NPCFLAG == True:
- for NPC in table['data']:
- totalLines += len(NPC['data'])
- if table['name'] == 'Hシナリオ' and SCENARIOFLAG == True:
- for hScenario in table['data']:
- totalLines += len(hScenario['data'])
+ if table["name"] == "NPC" and NPCFLAG == True:
+ for NPC in table["data"]:
+ totalLines += len(NPC["data"])
+ if table["name"] == "Hシナリオ" and SCENARIOFLAG == True:
+ for hScenario in table["data"]:
+ totalLines += len(hScenario["data"])
pbar.total = totalLines
pbar.refresh()
# Begin Parsing File
try:
for table in tableList:
-
# Translate NPC
- if table['name'] == 'キャラ会話' and NPCFLAG == True:
- for npc in table['data']:
- dataList = npc['data']
+ if table["name"] == "キャラ会話" and NPCFLAG == True:
+ for npc in table["data"]:
+ dataList = npc["data"]
# Parse
for j in range(len(dataList)):
# Name
- if 'キャラ名' in dataList[j].get('name'):
+ if "キャラ名" in dataList[j].get("name"):
# Pass 1 (Grab Data)
if setData == False:
- if dataList[j].get('value') != '':
- NPCList[0].append(dataList[j].get('value'))
+ if dataList[j].get("value") != "":
+ NPCList[0].append(dataList[j].get("value"))
# Pass 2 (Set Data)
else:
- if dataList[j].get('value') != '':
- dataList[j].update({'value': NPCList[0][0]})
+ if dataList[j].get("value") != "":
+ dataList[j].update({"value": NPCList[0][0]})
NPCList[0].pop(0)
-
+
# Description
- if '菊池' in dataList[j].get('name'):
+ if "菊池" in dataList[j].get("name"):
# Pass 1 (Grab Data)
if setData == False:
- if dataList[j].get('value') != '':
+ if dataList[j].get("value") != "":
# Remove Textwrap
- jaString = dataList[j].get('value')
- jaString = jaString.replace('\n', ' ')
- jaString = jaString.replace('\r', '')
- jaString = re.sub(r'[\\]+f\[\d+\]', '', jaString)
+ jaString = dataList[j].get("value")
+ jaString = jaString.replace("\n", " ")
+ jaString = jaString.replace("\r", "")
+ jaString = re.sub(r"[\\]+f\[\d+\]", "", jaString)
# Append Data
NPCList[1].append(jaString)
# Pass 2 (Set Data)
else:
- if dataList[j].get('value') != '':
+ if dataList[j].get("value") != "":
# Textwrap
translatedText = NPCList[1][0]
translatedText = textwrap.fill(translatedText, 30)
translatedText = font + translatedText
# Set Data
- dataList[j].update({'value': translatedText})
+ dataList[j].update({"value": translatedText})
NPCList[1].pop(0)
# Description
- if '篠宮' in dataList[j].get('name'):
+ if "篠宮" in dataList[j].get("name"):
# Pass 1 (Grab Data)
if setData == False:
- if dataList[j].get('value') != '':
+ if dataList[j].get("value") != "":
# Remove Textwrap
- jaString = dataList[j].get('value')
- jaString = jaString.replace('\n', ' ')
- jaString = jaString.replace('\r', '')
- jaString = re.sub(r'[\\]+f\[\d+\]', '', jaString)
+ jaString = dataList[j].get("value")
+ jaString = jaString.replace("\n", " ")
+ jaString = jaString.replace("\r", "")
+ jaString = re.sub(r"[\\]+f\[\d+\]", "", jaString)
# Append Data
NPCList[2].append(jaString)
# Pass 2 (Set Data)
else:
- if dataList[j].get('value') != '':
+ if dataList[j].get("value") != "":
# Textwrap
translatedText = NPCList[2][0]
- translatedText = textwrap.fill(translatedText, LISTWIDTH)
+ translatedText = textwrap.fill(
+ translatedText, LISTWIDTH
+ )
translatedText = font + translatedText
# Set Data
- dataList[j].update({'value': translatedText})
+ dataList[j].update({"value": translatedText})
NPCList[2].pop(0)
# Grab Scenarios
- if table['name'] == 'Hシナリオ' and SCENARIOFLAG == True:
- for hScenario in table['data']:
- dataList = hScenario['data']
+ if table["name"] == "Hシナリオ" and SCENARIOFLAG == True:
+ for hScenario in table["data"]:
+ dataList = hScenario["data"]
# Parse
# Pass 1 (Grab Data)
if setData == False:
- if dataList[1].get('value') != '':
- scenarioList[0].append(dataList[1].get('value'))
- if dataList[44].get('value') != '':
- scenarioList[1].append(dataList[44].get('value'))
- if dataList[45].get('value') != '':
- scenarioList[2].append(dataList[45].get('value'))
+ if dataList[1].get("value") != "":
+ scenarioList[0].append(dataList[1].get("value"))
+ if dataList[44].get("value") != "":
+ scenarioList[1].append(dataList[44].get("value"))
+ if dataList[45].get("value") != "":
+ scenarioList[2].append(dataList[45].get("value"))
# Pass 2 (Set Data)
else:
- if dataList[1].get('value') != '':
- dataList[1].update({'value': scenarioList[0][0]})
+ if dataList[1].get("value") != "":
+ dataList[1].update({"value": scenarioList[0][0]})
scenarioList[0].pop(0)
- if dataList[44].get('value') != '':
- dataList[44].update({'value': scenarioList[1][0]})
+ if dataList[44].get("value") != "":
+ dataList[44].update({"value": scenarioList[1][0]})
scenarioList[1].pop(0)
- if dataList[45].get('value') != '':
- dataList[45].update({'value': scenarioList[2][0]})
+ if dataList[45].get("value") != "":
+ dataList[45].update({"value": scenarioList[2][0]})
scenarioList[2].pop(0)
# Grab Items
- if table['name'] == 'オーブ' and ITEMFLAG == True:
- with open('translations.txt', 'a', encoding='utf-8') as file:
- for item in table['data']:
- dataList = item['data']
+ if table["name"] == "オーブ" and ITEMFLAG == True:
+ with open("translations.txt", "a", encoding="utf-8") as file:
+ for item in table["data"]:
+ dataList = item["data"]
# Parse #
for j in range(len(dataList)):
# Name
- if dataList[j].get('name') == 'オーブの名前':
+ if dataList[j].get("name") == "オーブの名前":
# Pass 1 (Grab Data)
if setData == False:
- if dataList[j].get('value') != '':
- itemList[0].append(dataList[j].get('value'))
+ if dataList[j].get("value") != "":
+ itemList[0].append(dataList[j].get("value"))
# Pass 2 (Set Data)
else:
- if dataList[j].get('value') != '':
- file.write(f'{dataList[j].get('value')} ({itemList[0][0]})\n')
- dataList[j].update({'value': itemList[0][0]})
+ if dataList[j].get("value") != "":
+ file.write(
+ f'{dataList[j].get('value')} ({itemList[0][0]})\n'
+ )
+ dataList[j].update({"value": itemList[0][0]})
itemList[0].pop(0)
-
+
# Description 1 (You are my specialz)
- if dataList[j].get('name') == 'オーブの説明':
+ if dataList[j].get("name") == "オーブの説明":
# Clean String
fontSize = 18
- translatedText = ''
- cleanedList = formatDramon(dataList[j].get('value'))
+ translatedText = ""
+ cleanedList = formatDramon(dataList[j].get("value"))
for str in cleanedList:
# Pass 1
if not setData:
- if all(x not in str for x in ['_', '@', '>', '/']) and str != '\r\n':
+ if (
+ all(
+ x not in str
+ for x in ["_", "@", ">", "/"]
+ )
+ and str != "\r\n"
+ ):
# Remove Textwrap and Font and Add to list
- str = str.replace('\r\n', ' ')
- str = str.replace(f'\\f[{fontSize}]', '')
+ str = str.replace("\r\n", " ")
+ str = str.replace(f"\\f[{fontSize}]", "")
itemList[1].append(str)
# Pass 2
else:
- if all(x not in str for x in ['_', '@', '>', '/',]) and str != '\r\n':
+ if (
+ all(
+ x not in str
+ for x in [
+ "_",
+ "@",
+ ">",
+ "/",
+ ]
+ )
+ and str != "\r\n"
+ ):
# Decide Wrap
width = WIDTH
# Add Textwrap and Font
tempText = itemList[1][0]
tempText = textwrap.fill(tempText, width)
- tempText = tempText.replace('\n', f'\r\n\\f[{fontSize}]')
- tempText = f'\\f[{fontSize}]{tempText}\r\n'
+ tempText = tempText.replace(
+ "\n", f"\r\n\\f[{fontSize}]"
+ )
+ tempText = f"\\f[{fontSize}]{tempText}\r\n"
translatedText += tempText
itemList[1].pop(0)
else:
@@ -887,36 +1035,59 @@ def searchDB(events, pbar, jobList, filename):
if setData:
# Formatting Fixes
translatedText = translatedText.replace('*"', '* "')
- translatedText = translatedText.replace('\r\n\r\n', '\r\n')
- translatedText = re.sub(r'[^\S\r\n]+', ' ', translatedText)
- dataList[j].update({'value': translatedText})
+ translatedText = translatedText.replace(
+ "\r\n\r\n", "\r\n"
+ )
+ translatedText = re.sub(
+ r"[^\S\r\n]+", " ", translatedText
+ )
+ dataList[j].update({"value": translatedText})
# Description 2 (You are my specialz)
- if dataList[j].get('name') == 'NULL':
+ if dataList[j].get("name") == "NULL":
# Clean String
fontSize = 24
- translatedText = ''
- cleanedList = formatDramon(dataList[j].get('value'))
+ translatedText = ""
+ cleanedList = formatDramon(dataList[j].get("value"))
for str in cleanedList:
# Pass 1
if not setData:
- if all(x not in str for x in ['_', '@', '>', '/']) and str != '\r\n':
+ if (
+ all(
+ x not in str
+ for x in ["_", "@", ">", "/"]
+ )
+ and str != "\r\n"
+ ):
# Remove Textwrap and Font and Add to list
- str = str.replace('\r\n', ' ')
- str = str.replace(f'\\f[{fontSize}]', '')
+ str = str.replace("\r\n", " ")
+ str = str.replace(f"\\f[{fontSize}]", "")
itemList[2].append(str)
# Pass 2
else:
- if all(x not in str for x in ['_', '@', '>', '/',]) and str != '\r\n':
+ if (
+ all(
+ x not in str
+ for x in [
+ "_",
+ "@",
+ ">",
+ "/",
+ ]
+ )
+ and str != "\r\n"
+ ):
# Decide Wrap
width = WIDTH
# Add Textwrap and Font
tempText = itemList[2][0]
tempText = textwrap.fill(tempText, width)
- tempText = tempText.replace('\n', f'\r\n\\f[{fontSize}]')
- tempText = f'\\f[{fontSize}]{tempText}\r\n'
+ tempText = tempText.replace(
+ "\n", f"\r\n\\f[{fontSize}]"
+ )
+ tempText = f"\\f[{fontSize}]{tempText}\r\n"
translatedText += tempText
itemList[2].pop(0)
else:
@@ -926,28 +1097,49 @@ def searchDB(events, pbar, jobList, filename):
if setData:
# Formatting Fixes
translatedText = translatedText.replace('*"', '* "')
- translatedText = translatedText.replace('\r\n\r\n', '\r\n')
- translatedText = re.sub(r'[^\S\r\n]+', ' ', translatedText)
- dataList[j].update({'value': translatedText})
+ translatedText = translatedText.replace(
+ "\r\n\r\n", "\r\n"
+ )
+ translatedText = re.sub(
+ r"[^\S\r\n]+", " ", translatedText
+ )
+ dataList[j].update({"value": translatedText})
# Description 3 (You are my specialz)
- if dataList[j].get('name') == 'NULL':
+ if dataList[j].get("name") == "NULL":
# Clean String
fontSize = 24
- translatedText = ''
- cleanedList = formatDramon(dataList[j].get('value'))
+ translatedText = ""
+ cleanedList = formatDramon(dataList[j].get("value"))
for str in cleanedList:
# Pass 1
if not setData:
- if all(x not in str for x in ['_', '@', '>', '/']) and str != '\r\n':
+ if (
+ all(
+ x not in str
+ for x in ["_", "@", ">", "/"]
+ )
+ and str != "\r\n"
+ ):
# Remove Textwrap and Font and Add to list
- str = str.replace('\r\n', ' ')
- str = str.replace(f'\\f[{fontSize}]', '')
+ str = str.replace("\r\n", " ")
+ str = str.replace(f"\\f[{fontSize}]", "")
itemList[3].append(str)
# Pass 2
else:
- if all(x not in str for x in ['_', '@', '>', '/',]) and str != '\r\n':
+ if (
+ all(
+ x not in str
+ for x in [
+ "_",
+ "@",
+ ">",
+ "/",
+ ]
+ )
+ and str != "\r\n"
+ ):
# Decide Wrap
width = WIDTH
@@ -965,180 +1157,190 @@ def searchDB(events, pbar, jobList, filename):
if setData:
# Formatting Fixes
translatedText = translatedText.replace('*"', '* "')
- translatedText = translatedText.replace('\r\n\r\n', '\r\n')
- translatedText = re.sub(r'[^\S\r\n]+', ' ', translatedText)
- dataList[j].update({'value': translatedText})
+ translatedText = translatedText.replace(
+ "\r\n\r\n", "\r\n"
+ )
+ translatedText = re.sub(
+ r"[^\S\r\n]+", " ", translatedText
+ )
+ dataList[j].update({"value": translatedText})
# Grab Armors
- if table['name'] == '防具' and ARMORFLAG == True:
- for armor in table['data']:
- dataList = armor['data']
+ if table["name"] == "防具" and ARMORFLAG == True:
+ for armor in table["data"]:
+ dataList = armor["data"]
# Parse
for j in range(len(dataList)):
# Name
- if '防具の名前' in dataList[j].get('name'):
+ if "防具の名前" in dataList[j].get("name"):
# Pass 1 (Grab Data)
if setData == False:
- if dataList[j].get('value') != '':
- armorList[0].append(dataList[j].get('value'))
+ if dataList[j].get("value") != "":
+ armorList[0].append(dataList[j].get("value"))
# Pass 2 (Set Data)
else:
- if dataList[j].get('value') != '':
- dataList[j].update({'value': armorList[0][0]})
+ if dataList[j].get("value") != "":
+ dataList[j].update({"value": armorList[0][0]})
armorList[0].pop(0)
-
+
# Description
- if '防具の説明' in dataList[j].get('name'):
+ if "防具の説明" in dataList[j].get("name"):
# Pass 1 (Grab Data)
if setData == False:
- if dataList[j].get('value') != '':
+ if dataList[j].get("value") != "":
# Remove Textwrap
- jaString = dataList[j].get('value')
- jaString = jaString.replace('\n', ' ')
- jaString = jaString.replace('\r', '')
- jaString = re.sub(r'[\\]+f\[\d+\]', '', jaString)
+ jaString = dataList[j].get("value")
+ jaString = jaString.replace("\n", " ")
+ jaString = jaString.replace("\r", "")
+ jaString = re.sub(r"[\\]+f\[\d+\]", "", jaString)
# Append Data
armorList[1].append(jaString)
# Pass 2 (Set Data)
else:
- if dataList[j].get('value') != '':
+ if dataList[j].get("value") != "":
# Textwrap
translatedText = armorList[1][0]
- translatedText = textwrap.fill(translatedText, LISTWIDTH)
+ translatedText = textwrap.fill(
+ translatedText, LISTWIDTH
+ )
translatedText = font + translatedText
# Set Data
- dataList[j].update({'value': translatedText})
+ dataList[j].update({"value": translatedText})
armorList[1].pop(0)
# Grab Enemies
- if table['name'] == '敵キャラ個体データ' and ENEMYFLAG == True:
- for enemy in table['data']:
- dataList = enemy['data']
+ if table["name"] == "敵キャラ個体データ" and ENEMYFLAG == True:
+ for enemy in table["data"]:
+ dataList = enemy["data"]
# Parse
for j in range(len(dataList)):
# Name
- if '敵キャラ名' in dataList[j].get('name'):
+ if "敵キャラ名" in dataList[j].get("name"):
# Pass 1 (Grab Data)
if setData == False:
- if dataList[j].get('value') != '':
- enemyList[0].append(dataList[j].get('value'))
+ if dataList[j].get("value") != "":
+ enemyList[0].append(dataList[j].get("value"))
# Pass 2 (Set Data)
else:
- if dataList[j].get('value') != '':
- dataList[j].update({'value': enemyList[0][0]})
+ if dataList[j].get("value") != "":
+ dataList[j].update({"value": enemyList[0][0]})
enemyList[0].pop(0)
-
+
# Description
- if 'NULL' in dataList[j].get('name'):
+ if "NULL" in dataList[j].get("name"):
# Pass 1 (Grab Data)
if setData == False:
- if dataList[j].get('value') != '':
+ if dataList[j].get("value") != "":
# Remove Textwrap
- jaString = dataList[j].get('value')
- jaString = jaString.replace('\n', ' ')
- jaString = jaString.replace('\r', '')
- jaString = re.sub(r'[\\]+f\[\d+\]', '', jaString)
+ jaString = dataList[j].get("value")
+ jaString = jaString.replace("\n", " ")
+ jaString = jaString.replace("\r", "")
+ jaString = re.sub(r"[\\]+f\[\d+\]", "", jaString)
# Append Data
enemyList[1].append(jaString)
# Pass 2 (Set Data)
else:
- if dataList[j].get('value') != '':
+ if dataList[j].get("value") != "":
# Textwrap
translatedText = enemyList[1][0]
- translatedText = textwrap.fill(translatedText, LISTWIDTH)
+ translatedText = textwrap.fill(
+ translatedText, LISTWIDTH
+ )
translatedText = font + translatedText
# Set Data
- dataList[j].update({'value': translatedText})
+ dataList[j].update({"value": translatedText})
enemyList[1].pop(0)
# Grab Weapons
- if table['name'] == '武器' and WEAPONFLAG == True:
- for weapon in table['data']:
- dataList = weapon['data']
+ if table["name"] == "武器" and WEAPONFLAG == True:
+ for weapon in table["data"]:
+ dataList = weapon["data"]
# Parse
for j in range(len(dataList)):
# Name
- if '武器の名前' in dataList[j].get('name'):
+ if "武器の名前" in dataList[j].get("name"):
# Pass 1 (Grab Data)
if setData == False:
- if dataList[j].get('value') != '':
- weaponsList[0].append(dataList[j].get('value'))
+ if dataList[j].get("value") != "":
+ weaponsList[0].append(dataList[j].get("value"))
# Pass 2 (Set Data)
else:
- if dataList[j].get('value') != '':
- dataList[j].update({'value': weaponsList[0][0]})
+ if dataList[j].get("value") != "":
+ dataList[j].update({"value": weaponsList[0][0]})
weaponsList[0].pop(0)
-
+
# Description
- if '武器の説明' in dataList[j].get('name'):
+ if "武器の説明" in dataList[j].get("name"):
# Pass 1 (Grab Data)
if setData == False:
- if dataList[j].get('value') != '':
+ if dataList[j].get("value") != "":
# Remove Textwrap
- jaString = dataList[j].get('value')
- jaString = jaString.replace('\n', ' ')
- jaString = jaString.replace('\r', '')
- jaString = re.sub(r'[\\]+f\[\d+\]', '', jaString)
+ jaString = dataList[j].get("value")
+ jaString = jaString.replace("\n", " ")
+ jaString = jaString.replace("\r", "")
+ jaString = re.sub(r"[\\]+f\[\d+\]", "", jaString)
# Append Data
weaponsList[1].append(jaString)
# Pass 2 (Set Data)
else:
- if dataList[j].get('value') != '':
+ if dataList[j].get("value") != "":
# Textwrap
translatedText = weaponsList[1][0]
- translatedText = textwrap.fill(translatedText, LISTWIDTH)
+ translatedText = textwrap.fill(
+ translatedText, LISTWIDTH
+ )
translatedText = font + translatedText
# Set Data
- dataList[j].update({'value': translatedText})
+ dataList[j].update({"value": translatedText})
weaponsList[1].pop(0)
# Grab Collection
- if table['name'] == '鍛冶師用DB' and COLLECTIONFLAG == True:
- for object in table['data']:
- dataList = object['data']
+ if table["name"] == "鍛冶師用DB" and COLLECTIONFLAG == True:
+ for object in table["data"]:
+ dataList = object["data"]
# Parse
for j in range(len(dataList)):
# Name
- if '作る装備' in dataList[j].get('name'):
+ if "作る装備" in dataList[j].get("name"):
# Pass 1 (Grab Data)
if setData == False:
- if dataList[j].get('value') != '':
+ if dataList[j].get("value") != "":
# Remove Textwrap
- jaString = dataList[j].get('value')
- jaString = jaString.replace('\n', ' ')
- jaString = jaString.replace('\r', '')
- jaString = re.sub(r'[\\]+f\[\d+\]', '', jaString)
+ jaString = dataList[j].get("value")
+ jaString = jaString.replace("\n", " ")
+ jaString = jaString.replace("\r", "")
+ jaString = re.sub(r"[\\]+f\[\d+\]", "", jaString)
collectionList[0].append(jaString)
# Pass 2 (Set Data)
else:
- if dataList[j].get('value') != '':
- dataList[j].update({'value': collectionList[0][0]})
+ if dataList[j].get("value") != "":
+ dataList[j].update({"value": collectionList[0][0]})
collectionList[0].pop(0)
- # Description
- if '品物の解説' in dataList[j].get('name'):
+ # Description
+ if "品物の解説" in dataList[j].get("name"):
# Pass 1 (Grab Data)
if setData == False:
- if dataList[j].get('value') != '':
+ if dataList[j].get("value") != "":
# Remove Textwrap
- jaString = dataList[j].get('value')
- jaString = jaString.replace('\n', ' ')
- jaString = jaString.replace('\r', '')
- jaString = re.sub(r'[\\]+f\[\d+\]', '', jaString)
+ jaString = dataList[j].get("value")
+ jaString = jaString.replace("\n", " ")
+ jaString = jaString.replace("\r", "")
+ jaString = re.sub(r"[\\]+f\[\d+\]", "", jaString)
# Skill Action (Optional)
# jaString = f'Taro{jaString}'
@@ -1147,30 +1349,32 @@ def searchDB(events, pbar, jobList, filename):
collectionList[1].append(jaString)
# Pass 2 (Set Data)
else:
- if dataList[j].get('value') != '':
+ if dataList[j].get("value") != "":
translatedText = collectionList[1][0]
# Remove Action (Optional)
# translatedText = translatedText.replace('Taro', '')
# Textwrap
- translatedText = textwrap.fill(translatedText, LISTWIDTH)
+ translatedText = textwrap.fill(
+ translatedText, LISTWIDTH
+ )
translatedText = font + translatedText
# Set Data
- dataList[j].update({'value': translatedText})
+ dataList[j].update({"value": translatedText})
collectionList[1].pop(0)
- # Description 2
- if 'NULL' in dataList[j].get('name'):
+ # Description 2
+ if "NULL" in dataList[j].get("name"):
# Pass 1 (Grab Data)
if setData == False:
- if dataList[j].get('value') != '':
+ if dataList[j].get("value") != "":
# Remove Textwrap
- jaString = dataList[j].get('value')
- jaString = jaString.replace('\n', ' ')
- jaString = jaString.replace('\r', '')
- jaString = re.sub(r'[\\]+f\[\d+\]', '', jaString)
+ jaString = dataList[j].get("value")
+ jaString = jaString.replace("\n", " ")
+ jaString = jaString.replace("\r", "")
+ jaString = re.sub(r"[\\]+f\[\d+\]", "", jaString)
# Skill Action (Optional)
# jaString = f'Taro{jaString}'
@@ -1179,28 +1383,30 @@ def searchDB(events, pbar, jobList, filename):
collectionList[2].append(jaString)
# Pass 2 (Set Data)
else:
- if dataList[j].get('value') != '':
+ if dataList[j].get("value") != "":
translatedText = collectionList[2][0]
# Remove Action (Optional)
# translatedText = translatedText.replace('Taro', '')
# Textwrap
- translatedText = textwrap.fill(translatedText, LISTWIDTH)
+ translatedText = textwrap.fill(
+ translatedText, LISTWIDTH
+ )
translatedText = font + translatedText
# Set Data
- dataList[j].update({'value': translatedText})
+ dataList[j].update({"value": translatedText})
collectionList[2].pop(0)
# Translation
- scenarioListTL = [[],[],[]]
- NPCListTL = [[],[],[],[]]
- itemListTL = [[],[],[],[]]
- collectionListTL = [[],[],[],[]]
- armorListTL = [[],[]]
- enemyListTL = [[],[]]
- weaponsListTL = [[],[],[]]
+ scenarioListTL = [[], [], []]
+ NPCListTL = [[], [], [], []]
+ itemListTL = [[], [], [], []]
+ collectionListTL = [[], [], [], []]
+ armorListTL = [[], []]
+ enemyListTL = [[], []]
+ weaponsListTL = [[], [], []]
translate = False
@@ -1214,37 +1420,51 @@ def searchDB(events, pbar, jobList, filename):
pbar.refresh()
# Name
- response = translateGPT(NPCList[0], 'Reply with only the '+ LANGUAGE +' translation of the RPG enemy name', True)
+ response = translateGPT(
+ NPCList[0],
+ "Reply with only the "
+ + LANGUAGE
+ + " translation of the RPG enemy name",
+ True,
+ )
nameListTL = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Desc 1
- response = translateGPT(NPCList[1], 'Reply with only the '+ LANGUAGE +' translation', True)
+ response = translateGPT(
+ NPCList[1], "Reply with only the " + LANGUAGE + " translation", True
+ )
descListTL1 = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Desc 2
- response = translateGPT(NPCList[2], 'Reply with only the '+ LANGUAGE +' translation', True)
+ response = translateGPT(
+ NPCList[2], "Reply with only the " + LANGUAGE + " translation", True
+ )
descListTL2 = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Desc 3
- response = translateGPT(NPCList[3], 'Reply with only the '+ LANGUAGE +' translation', True)
+ response = translateGPT(
+ NPCList[3], "Reply with only the " + LANGUAGE + " translation", True
+ )
descListTL3 = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Check Mismatch
- if len(nameListTL) != len(NPCList[0]) or\
- len(descListTL1) != len(NPCList[1]) or\
- len(descListTL2) != len(NPCList[2])or\
- len(descListTL3) != len(NPCList[3]):
+ if (
+ len(nameListTL) != len(NPCList[0])
+ or len(descListTL1) != len(NPCList[1])
+ or len(descListTL2) != len(NPCList[2])
+ or len(descListTL3) != len(NPCList[3])
+ ):
with LOCK:
if filename not in MISMATCH:
MISMATCH.append(filename)
else:
NPCListTL = [nameListTL, descListTL1, descListTL2, descListTL3]
- translate = True
+ translate = True
# SCENARIO
if len(scenarioList[0]) > 0:
@@ -1256,31 +1476,49 @@ def searchDB(events, pbar, jobList, filename):
pbar.refresh()
# Name
- response = translateGPT(scenarioList[0], 'Reply with only the '+ LANGUAGE +' translation', True)
+ response = translateGPT(
+ scenarioList[0],
+ "Reply with only the " + LANGUAGE + " translation",
+ True,
+ )
nameListTL = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Desc 1
- response = translateGPT(scenarioList[1], 'reply with only the gender neutral '+ LANGUAGE +' translation of the NPC name', True)
+ response = translateGPT(
+ scenarioList[1],
+ "reply with only the gender neutral "
+ + LANGUAGE
+ + " translation of the NPC name",
+ True,
+ )
descListTL1 = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Desc 2
- response = translateGPT(scenarioList[2], 'reply with only the gender neutral '+ LANGUAGE +' translation of the NPC name', True)
+ response = translateGPT(
+ scenarioList[2],
+ "reply with only the gender neutral "
+ + LANGUAGE
+ + " translation of the NPC name",
+ True,
+ )
descListTL2 = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Check Mismatch
- if len(nameListTL) != len(scenarioList[0]) or\
- len(descListTL1) != len(scenarioList[1]) or\
- len(descListTL2) != len(scenarioList[2]):
+ if (
+ len(nameListTL) != len(scenarioList[0])
+ or len(descListTL1) != len(scenarioList[1])
+ or len(descListTL2) != len(scenarioList[2])
+ ):
with LOCK:
if filename not in MISMATCH:
MISMATCH.append(filename)
else:
scenarioListTL = [nameListTL, descListTL1, descListTL2]
- translate = True
+ translate = True
# ITEMS
if len(itemList[0]) > 0 or len(itemList[1]) > 0:
@@ -1292,37 +1530,47 @@ def searchDB(events, pbar, jobList, filename):
pbar.refresh()
# Name
- response = translateGPT(itemList[0], 'Reply with only the '+ LANGUAGE +' translation', True)
+ response = translateGPT(
+ itemList[0], "Reply with only the " + LANGUAGE + " translation", True
+ )
nameListTL = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Desc 1
- response = translateGPT(itemList[1], 'Reply with only the '+ LANGUAGE +' translation', True)
+ response = translateGPT(
+ itemList[1], "Reply with only the " + LANGUAGE + " translation", True
+ )
descListTL1 = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Desc 2
- response = translateGPT(itemList[2], 'Reply with only the '+ LANGUAGE +' translation', True)
+ response = translateGPT(
+ itemList[2], "Reply with only the " + LANGUAGE + " translation", True
+ )
descListTL2 = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Desc 3
- response = translateGPT(itemList[3], 'Reply with only the '+ LANGUAGE +' translation', True)
+ response = translateGPT(
+ itemList[3], "Reply with only the " + LANGUAGE + " translation", True
+ )
descListTL3 = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Check Mismatch
- if len(nameListTL) != len(itemList[0]) or\
- len(descListTL1) != len(itemList[1]) or\
- len(descListTL2) != len(itemList[2])or\
- len(descListTL3) != len(itemList[3]):
+ if (
+ len(nameListTL) != len(itemList[0])
+ or len(descListTL1) != len(itemList[1])
+ or len(descListTL2) != len(itemList[2])
+ or len(descListTL3) != len(itemList[3])
+ ):
with LOCK:
if filename not in MISMATCH:
MISMATCH.append(filename)
else:
itemListTL = [nameListTL, descListTL1, descListTL2, descListTL3]
- translate = True
+ translate = True
# Armor
if len(armorList[0]) > 0:
@@ -1334,25 +1582,32 @@ def searchDB(events, pbar, jobList, filename):
pbar.refresh()
# Name
- response = translateGPT(armorList[0], 'Reply with only the '+ LANGUAGE +' translation of the NPC name', True)
+ response = translateGPT(
+ armorList[0],
+ "Reply with only the " + LANGUAGE + " translation of the NPC name",
+ True,
+ )
nameListTL = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Desc 1
- response = translateGPT(armorList[1], 'Reply with only the '+ LANGUAGE +' translation', True)
+ response = translateGPT(
+ armorList[1], "Reply with only the " + LANGUAGE + " translation", True
+ )
descListTL1 = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Check Mismatch
- if len(nameListTL) != len(armorList[0]) or\
- len(descListTL1) != len(armorList[1]):
+ if len(nameListTL) != len(armorList[0]) or len(descListTL1) != len(
+ armorList[1]
+ ):
with LOCK:
if filename not in MISMATCH:
MISMATCH.append(filename)
else:
armorListTL = [nameListTL, descListTL1]
- translate = True
+ translate = True
# Enemies
if len(enemyList[0]) > 0:
@@ -1364,25 +1619,32 @@ def searchDB(events, pbar, jobList, filename):
pbar.refresh()
# Name
- response = translateGPT(enemyList[0], 'Reply with only the '+ LANGUAGE +' translation of the RPG item name', True)
+ response = translateGPT(
+ enemyList[0],
+ "Reply with only the " + LANGUAGE + " translation of the RPG item name",
+ True,
+ )
nameListTL = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Desc 1
- response = translateGPT(enemyList[1], 'Reply with only the '+ LANGUAGE +' translation', True)
+ response = translateGPT(
+ enemyList[1], "Reply with only the " + LANGUAGE + " translation", True
+ )
descListTL1 = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Check Mismatch
- if len(nameListTL) != len(enemyList[0]) or\
- len(descListTL1) != len(enemyList[1]):
+ if len(nameListTL) != len(enemyList[0]) or len(descListTL1) != len(
+ enemyList[1]
+ ):
with LOCK:
if filename not in MISMATCH:
MISMATCH.append(filename)
else:
enemyListTL = [nameListTL, descListTL1]
- translate = True
+ translate = True
# Weapons
if len(weaponsList[0]) > 0:
@@ -1394,31 +1656,37 @@ def searchDB(events, pbar, jobList, filename):
pbar.refresh()
# Name
- response = translateGPT(weaponsList[0], 'Reply with only the '+ LANGUAGE +' translation of the RPG item name', True)
+ response = translateGPT(
+ weaponsList[0],
+ "Reply with only the " + LANGUAGE + " translation of the RPG item name",
+ True,
+ )
nameListTL = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Desc 1
- response = translateGPT(weaponsList[1], '', True)
+ response = translateGPT(weaponsList[1], "", True)
descListTL1 = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Desc 2
- response = translateGPT(weaponsList[2], '', True)
+ response = translateGPT(weaponsList[2], "", True)
descListTL2 = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Check Mismatch
- if len(nameListTL) != len(weaponsList[0]) or\
- len(descListTL1) != len(weaponsList[1]) or\
- len(descListTL2) != len(weaponsList[2]):
+ if (
+ len(nameListTL) != len(weaponsList[0])
+ or len(descListTL1) != len(weaponsList[1])
+ or len(descListTL2) != len(weaponsList[2])
+ ):
with LOCK:
if filename not in MISMATCH:
MISMATCH.append(filename)
else:
weaponsListTL = [nameListTL, descListTL1, descListTL2]
- translate = True
+ translate = True
# Collection
for list in collectionList:
@@ -1431,34 +1699,42 @@ def searchDB(events, pbar, jobList, filename):
pbar.refresh()
# Name
- response = translateGPT(collectionList[0], 'reply with only the gender neutral '+ LANGUAGE +' translation of the action log. Always start the sentence with Taro. For example, Translate \'Taroを倒した!\' as \'Taro was defeated!\'', True)
+ response = translateGPT(
+ collectionList[0],
+ "reply with only the gender neutral "
+ + LANGUAGE
+ + " translation of the action log. Always start the sentence with Taro. For example, Translate 'Taroを倒した!' as 'Taro was defeated!'",
+ True,
+ )
nameListTL = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Desc 1
- response = translateGPT(collectionList[1], '', True)
+ response = translateGPT(collectionList[1], "", True)
descListTL1 = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Desc 2
- response = translateGPT(collectionList[2], '', True)
+ response = translateGPT(collectionList[2], "", True)
descListTL2 = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Check Mismatch
- if len(nameListTL) != len(collectionList[0]) or\
- len(descListTL1) != len(collectionList[1]) or\
- len(descListTL2) != len(collectionList[2]):
+ if (
+ len(nameListTL) != len(collectionList[0])
+ or len(descListTL1) != len(collectionList[1])
+ or len(descListTL2) != len(collectionList[2])
+ ):
with LOCK:
if filename not in MISMATCH:
MISMATCH.append(filename)
else:
collectionListTL = [nameListTL, descListTL1, descListTL2]
- translate = True
-
+ translate = True
+
# Start Pass 2
if translate == True:
jobList.append(scenarioListTL)
@@ -1468,34 +1744,43 @@ def searchDB(events, pbar, jobList, filename):
jobList.append(armorListTL)
jobList.append(enemyListTL)
jobList.append(weaponsListTL)
- searchDB(events, pbar, jobList, filename)
+ searchDB(events, pbar, jobList, filename)
except IndexError as e:
traceback.print_exc()
- raise Exception(str(e) + 'Failed to translate: ' + initialJAString) from None
+ raise Exception(str(e) + "Failed to translate: " + initialJAString) from None
except Exception as e:
traceback.print_exc()
- raise Exception(str(e) + 'Failed to translate: ' + initialJAString) from None
+ raise Exception(str(e) + "Failed to translate: " + initialJAString) from None
return totalTokens
+
# Save some money and enter the character before translation
def getSpeaker(speaker):
match speaker:
- case 'ファイン':
- return ['Fine', [0,0]]
- case '':
- return ['', [0,0]]
+ case "ファイン":
+ return ["Fine", [0, 0]]
+ case "":
+ return ["", [0, 0]]
case _:
# Store Speaker
if speaker not in str(NAMESLIST):
- response = translateGPT(speaker, 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ response = translateGPT(
+ speaker,
+ "Reply with the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
response[0] = response[0].replace("'S", "'s")
# Retry if name doesn't translate for some reason
- if re.search(r'([a-zA-Z??])', response[0]) == None:
- response = translateGPT(speaker, 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ if re.search(r"([a-zA-Z??])", response[0]) == None:
+ response = translateGPT(
+ speaker,
+ "Reply with the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
response[0] = response[0].replace("'S", "'s")
@@ -1506,66 +1791,72 @@ def getSpeaker(speaker):
else:
for i in range(len(NAMESLIST)):
if speaker == NAMESLIST[i][0]:
- return [NAMESLIST[i][1],[0,0]]
-
- return [speaker,[0,0]]
+ return [NAMESLIST[i][1], [0, 0]]
+
+ return [speaker, [0, 0]]
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Formatting
count = 0
- codeList = re.findall(r'[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
+ 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) + ']')
+ jaString = jaString.replace(var, "[FCode_" + str(count) + "]")
count += 1
# WOLF Images
count = 0
- humList = re.findall(r'(\\?r?\\?n?_.*?\d\r\n@?)', jaString)
+ humList = re.findall(r"(\\?r?\\?n?_.*?\d\r\n@?)", jaString)
humList = set(humList)
if len(humList) != 0:
for var in humList:
- jaString = jaString.replace(var, '[ICode_' + str(count) + ']')
+ jaString = jaString.replace(var, "[ICode_" + str(count) + "]")
count += 1
# Put all lists in list and return
return [jaString, [codeList, humList]]
+
def resubVars(translatedText, varList):
# Fix Spacing and ChatGPT Nonsense
- matchList = re.findall(r'\[\s?.+?\s?\]', translatedText)
+ 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(varList[0]) != 0:
for var in varList[0]:
- translatedText = translatedText.replace('[FCode_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[FCode_" + str(count) + "]", var)
count += 1
# Formatting
count = 0
if len(varList[1]) != 0:
for var in varList[1]:
- translatedText = translatedText.replace('[ICode_' + str(count) + ']', var)
+ translatedText = translatedText.replace("[ICode_" + 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
ロラン (Roland) - Male\n\
リュカ (Ryuka) - Male\n\
レックス (Rex) - Male\n\
@@ -1610,10 +1901,12 @@ def createContext(fullPromptFlag, subbedT):
アロマ (Aroma) - Female\n\
ピッケ (Pikke) - Female\n\
ドラオ (Dorao) - Male\n\
-'
-
- system = PROMPT + VOCAB if fullPromptFlag else \
- f"\
+"
+
+ system = (
+ PROMPT + VOCAB
+ if fullPromptFlag
+ else f"\
You are an expert Eroge Game translator who translates Japanese text to {LANGUAGE}.\n\
Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`\n\
- You translate everything, including erotic and explicit content.\n\
@@ -1625,12 +1918,14 @@ Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{
- `...` can be a part of the dialogue. Translate it as it is.\n\
{VOCAB}\n\
"
+ )
if isinstance(subbedT, list):
- user = f'```json\n{subbedT}```'
+ user = f"```json\n{subbedT}```"
else:
user = subbedT
return characters, system, user
+
def translateText(characters, system, user, history, penalty, format):
# Prompt
msg = [{"role": "system", "content": system}]
@@ -1645,13 +1940,13 @@ def translateText(characters, system, user, history, penalty, format):
msg.append({"role": "system", "content": history})
# Response Format
- if format == 'json':
- responseFormat = { "type": "json_object" }
+ if format == "json":
+ responseFormat = {"type": "json_object"}
else:
- responseFormat = { "type": "text" }
-
+ responseFormat = {"type": "text"}
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0,
frequency_penalty=penalty,
@@ -1661,18 +1956,19 @@ def translateText(characters, system, user, history, penalty, format):
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- '「': '\\"',
- '」': '\\"',
- '- ': '-',
- 'Placeholder Text': '',
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "「": '\\"',
+ "」": '\\"',
+ "- ": "-",
+ "Placeholder Text": "",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
@@ -1683,11 +1979,12 @@ def cleanTranslatedText(translatedText, varResponse):
translatedText = resubVars(translatedText, varResponse[1])
return translatedText
+
def elongateCharacters(text):
# Define a pattern to match one character followed by one or more `ー` characters
# Using a positive lookbehind assertion to capture the preceding character
- pattern = r'(?<=(.))ー+'
-
+ pattern = r"(?<=(.))ー+"
+
# Define a replacement function that elongates the captured character
def repl(match):
char = match.group(1) # The character before the ー sequence
@@ -1697,6 +1994,7 @@ def elongateCharacters(text):
# Use re.sub() to replace the pattern in the text
return re.sub(pattern, repl, text)
+
def extractTranslation(translatedTextList, is_list):
try:
translatedTextList = re.sub(r'\\"+\"([^,\n}])', r'\\"\1', translatedTextList)
@@ -1709,15 +2007,15 @@ def extractTranslation(translatedTextList, is_list):
return string_list[0]
except Exception as e:
- PBAR.write(f'extractTranslation Error: {e} on String {translatedTextList}')
+ PBAR.write(f"extractTranslation Error: {e} on String {translatedTextList}")
return None
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -1729,26 +2027,28 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*3)
+ outputTotalTokens += round(len(enc.encode(user)) * 3)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag):
global PBAR, MISMATCH, FILENAME
-
+
mismatch = False
totalTokens = [0, 0]
if isinstance(text, list):
- format = 'json'
+ format = "json"
tList = batchList(text, BATCHSIZE)
else:
- format = 'text'
+ format = "text"
tList = [text]
for index, tItem in enumerate(tList):
@@ -1763,7 +2063,7 @@ def translateGPT(text, history, fullPromptFlag):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
if PBAR is not None:
PBAR.update(len(tItem))
continue
@@ -1788,9 +2088,13 @@ def translateGPT(text, history, fullPromptFlag):
translatedText = cleanTranslatedText(translatedText, varResponse)
if isinstance(tItem, list):
extractedTranslations = extractTranslation(translatedText, True)
- if extractedTranslations == None or len(tItem) != len(extractedTranslations):
+ if extractedTranslations == None or len(tItem) != len(
+ extractedTranslations
+ ):
# Mismatch. Try Again
- response = translateText(characters, system, user, history, 0.05, format)
+ response = translateText(
+ characters, system, user, history, 0.05, format
+ )
translatedText = response.choices[0].message.content
totalTokens[0] += response.usage.prompt_tokens
totalTokens[1] += response.usage.completion_tokens
@@ -1799,13 +2103,17 @@ def translateGPT(text, history, fullPromptFlag):
translatedText = cleanTranslatedText(translatedText, varResponse)
if isinstance(tItem, list):
extractedTranslations = extractTranslation(translatedText, True)
- if extractedTranslations == None or len(tItem) != len(extractedTranslations):
- mismatch = True # Just here for breakpoint
-
+ if extractedTranslations == None or len(tItem) != len(
+ extractedTranslations
+ ):
+ mismatch = True # Just here for breakpoint
+
# Set if no mismatch
if mismatch == False:
tList[index] = extractedTranslations
- history = extractedTranslations[-10:] # Update history if we have a list
+ history = extractedTranslations[
+ -10:
+ ] # Update history if we have a list
else:
history = text[-10:]
mismatch = False
@@ -1818,7 +2126,7 @@ def translateGPT(text, history, fullPromptFlag):
PBAR.update(len(tItem))
else:
# Ensure we're passing a single string to extractTranslation
- tList[index] = translatedText
+ tList[index] = translatedText
finalList = combineList(tList, text)
return [finalList, totalTokens]
diff --git a/modules/wolf2.py b/modules/wolf2.py
index aa51a47..a66b7d8 100644
--- a/modules/wolf2.py
+++ b/modules/wolf2.py
@@ -16,49 +16,50 @@ from tqdm import tqdm
# Open AI
load_dotenv()
-if os.getenv('api').replace(' ', '') != '':
- openai.base_url = os.getenv('api')
-openai.organization = os.getenv('org')
-openai.api_key = os.getenv('key')
+if os.getenv("api").replace(" ", "") != "":
+ openai.base_url = os.getenv("api")
+openai.organization = os.getenv("org")
+openai.api_key = os.getenv("key")
-#Globals
-MODEL = os.getenv('model')
-TIMEOUT = int(os.getenv('timeout'))
-LANGUAGE = os.getenv('language').capitalize()
-PROMPT = Path('prompt.txt').read_text(encoding='utf-8')
-VOCAB = Path('vocab.txt').read_text(encoding='utf-8')
-THREADS = int(os.getenv('threads'))
+# Globals
+MODEL = os.getenv("model")
+TIMEOUT = int(os.getenv("timeout"))
+LANGUAGE = os.getenv("language").capitalize()
+PROMPT = Path("prompt.txt").read_text(encoding="utf-8")
+VOCAB = Path("vocab.txt").read_text(encoding="utf-8")
+THREADS = int(os.getenv("threads"))
LOCK = threading.Lock()
-WIDTH = int(os.getenv('width'))
-LISTWIDTH = int(os.getenv('listWidth'))
+WIDTH = int(os.getenv("width"))
+LISTWIDTH = int(os.getenv("listWidth"))
NOTEWIDTH = 70
MAXHISTORY = 10
-ESTIMATE = ''
+ESTIMATE = ""
TOKENS = [0, 0]
NAMESLIST = []
-NAMES = False # Output a list of all the character names found
-BRFLAG = False # If the game uses
instead
+NAMES = False # Output a list of all the character names found
+BRFLAG = False # If the game uses
instead
FIXTEXTWRAP = True # Overwrites textwrap
-IGNORETLTEXT = False # Ignores all translated text.
-MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
+IGNORETLTEXT = False # Ignores all translated text.
+MISMATCH = [] # Lists files that throw a mismatch error (Length of GPT list response is wrong)
-#tqdm Globals
-BAR_FORMAT='{l_bar}{bar:10}{r_bar}{bar:-10b}'
+# tqdm Globals
+BAR_FORMAT = "{l_bar}{bar:10}{r_bar}{bar:-10b}"
POSITION = 0
LEAVE = False
# Pricing - Depends on the model https://openai.com/pricing
# Batch Size - GPT 3.5 Struggles past 15 lines per request. GPT4 struggles past 50 lines per request
# If you are getting a MISMATCH LENGTH error, lower the batch size.
-if 'gpt-3.5' in MODEL:
- INPUTAPICOST = .002
- OUTPUTAPICOST = .002
+if "gpt-3.5" in MODEL:
+ INPUTAPICOST = 0.002
+ OUTPUTAPICOST = 0.002
BATCHSIZE = 10
-elif 'gpt-4' in MODEL:
- INPUTAPICOST = .005
- OUTPUTAPICOST = .015
+elif "gpt-4" in MODEL:
+ INPUTAPICOST = 0.005
+ OUTPUTAPICOST = 0.015
BATCHSIZE = 40
+
def handleWOLF2(filename, estimate):
global ESTIMATE
ESTIMATE = estimate
@@ -75,17 +76,21 @@ def handleWOLF2(filename, estimate):
TOKENS[1] += translatedData[1][1]
# Print Total
- totalString = getResultString(['', TOKENS, None], end - start, 'TOTAL')
+ totalString = getResultString(["", TOKENS, None], end - start, "TOTAL")
# Print any errors on maps
if len(MISMATCH) > 0:
- return totalString + Fore.RED + f'\nMismatch Errors: {MISMATCH}' + Fore.RESET
+ return (
+ totalString + Fore.RED + f"\nMismatch Errors: {MISMATCH}" + Fore.RESET
+ )
else:
return totalString
-
+
else:
try:
- with open('translated/' + filename, 'w', encoding='shift_jis', errors='ignore') as outFile:
+ with open(
+ "translated/" + filename, "w", encoding="shift_jis", errors="ignore"
+ ) as outFile:
start = time.time()
translatedData = openFiles(filename)
@@ -98,23 +103,36 @@ def handleWOLF2(filename, estimate):
TOKENS[1] += translatedData[1][1]
except Exception:
traceback.print_exc()
- return 'Fail'
+ return "Fail"
+
+ return getResultString(["", TOKENS, None], end - start, "TOTAL")
- return getResultString(['', TOKENS, None], end - start, 'TOTAL')
def getResultString(translatedData, translationTime, filename):
# File Print String
- totalTokenstring =\
- Fore.YELLOW +\
- '[Input: ' + str(translatedData[1][0]) + ']'\
- '[Output: ' + str(translatedData[1][1]) + ']'\
- '[Cost: ${:,.4f}'.format((translatedData[1][0] * .001 * INPUTAPICOST) +\
- (translatedData[1][1] * .001 * OUTPUTAPICOST)) + ']'
- timeString = Fore.BLUE + '[' + str(round(translationTime, 1)) + 's]'
+ totalTokenstring = (
+ Fore.YELLOW + "[Input: " + str(translatedData[1][0]) + "]"
+ "[Output: "
+ + str(translatedData[1][1])
+ + "]" "[Cost: ${:,.4f}".format(
+ (translatedData[1][0] * 0.001 * INPUTAPICOST)
+ + (translatedData[1][1] * 0.001 * OUTPUTAPICOST)
+ )
+ + "]"
+ )
+ timeString = Fore.BLUE + "[" + str(round(translationTime, 1)) + "s]"
if translatedData[2] == None:
# Success
- return filename + ': ' + totalTokenstring + timeString + Fore.GREEN + u' \u2713 ' + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.GREEN
+ + " \u2713 "
+ + Fore.RESET
+ )
else:
# Fail
@@ -123,31 +141,41 @@ def getResultString(translatedData, translationTime, filename):
except Exception as e:
traceback.print_exc()
errorString = str(e) + Fore.RED
- return filename + ': ' + totalTokenstring + timeString + Fore.RED + u' \u2717 ' +\
- errorString + Fore.RESET
+ return (
+ filename
+ + ": "
+ + totalTokenstring
+ + timeString
+ + Fore.RED
+ + " \u2717 "
+ + errorString
+ + Fore.RESET
+ )
+
def openFiles(filename):
- with open('files/' + filename, 'r', encoding='shift_jis') as readFile:
+ with open("files/" + filename, "r", encoding="shift_jis") as readFile:
translatedData = parseWOLF(readFile, filename)
# Delete lines marked for deletion
finalData = []
for line in translatedData[0]:
- if line != '\\d\n':
+ if line != "\\d\n":
finalData.append(line)
translatedData[0] = finalData
-
+
return translatedData
+
def parseWOLF(readFile, filename):
- totalTokens = [0,0]
+ totalTokens = [0, 0]
# Read File into data
data = readFile.readlines()
# Create Progress Bar
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
- pbar.desc=filename
+ pbar.desc = filename
try:
result = translateWOLF(data, [], pbar, filename)
@@ -158,39 +186,40 @@ def parseWOLF(readFile, filename):
return [data, totalTokens, e]
return [data, totalTokens, None]
+
def translateWOLF(data, translatedList, pbar, filename):
stringList = []
currentGroup = []
- tokens = [0,0]
- speaker = ''
+ tokens = [0, 0]
+ speaker = ""
global LOCK, ESTIMATE, PBAR
PBAR = pbar
i = 0
while i < len(data):
# Speaker
- matchList = re.findall(r'(.*):', data[i])
+ matchList = re.findall(r"(.*):", data[i])
if len(matchList) != 0:
response = getSpeaker(matchList[0])
speaker = response[0]
tokens[0] += response[1][0]
tokens[1] += response[1][1]
- data[i] = f'{speaker}:\n'
+ data[i] = f"{speaker}:\n"
i += 1
else:
- speaker = ''
+ speaker = ""
# Options
- if '//選択肢' in data[i]:
+ if "//選択肢" in data[i]:
i += 1
choiceList = []
initialIndex = i
- while('//' in data[i] and 'の場合' not in data[i]):
- choiceList.append(re.search(r'\/\/(.*)', data[i]).group(1))
+ while "//" in data[i] and "の場合" not in data[i]:
+ choiceList.append(re.search(r"\/\/(.*)", data[i]).group(1))
i += 1
-
+
# Translate
- response = translateGPT(choiceList, 'This will be a dialogue option', True)
+ response = translateGPT(choiceList, "This will be a dialogue option", True)
tokens[0] += response[1][0]
tokens[1] += response[1][1]
choiceListTL = response[0]
@@ -199,9 +228,9 @@ def translateWOLF(data, translatedList, pbar, filename):
if len(choiceList) == len(choiceListTL):
# Set Data
i = initialIndex
- while('//' in data[i] and 'の場合' not in data[i]):
- choiceListTL[0] = choiceListTL[0].replace(', ', '、')
- data[i] = f'//{choiceListTL[0]}\n'
+ while "//" in data[i] and "の場合" not in data[i]:
+ choiceListTL[0] = choiceListTL[0].replace(", ", "、")
+ data[i] = f"//{choiceListTL[0]}\n"
choiceListTL.pop(0)
i += 1
@@ -212,36 +241,46 @@ def translateWOLF(data, translatedList, pbar, filename):
MISMATCH.append(filename)
# Lines
- if r'/' not in data[i] and '@' not in data[i] and data[i] != '\n':
+ if r"/" not in data[i] and "@" not in data[i] and data[i] != "\n":
# Pass 1
if translatedList == []:
# Grab Consecutive Strings
currentGroup.append(data[i])
i += 1
- while i < len(data) and r'/' not in data[i] and '@' not in data[i] and data[i] != '\n':
+ while (
+ i < len(data)
+ and r"/" not in data[i]
+ and "@" not in data[i]
+ and data[i] != "\n"
+ ):
currentGroup.append(data[i])
i += 1
-
+
# Join up 401 groups for better translation.
if len(currentGroup) > 0:
- jaString = ''.join(currentGroup)
+ jaString = "".join(currentGroup)
currentGroup = []
-
+
# Remove any textwrap
- jaString = jaString.replace('\n', ' ')
+ jaString = jaString.replace("\n", " ")
# Add Speaker (If there is one)
- if speaker != '':
- jaString = f'{speaker}: {jaString}'
+ if speaker != "":
+ jaString = f"{speaker}: {jaString}"
# Add String
stringList.append(jaString)
i += 1
-
+
# Pass 2
else:
# Insert Strings
- while i < len(data) and r'/' not in data[i] and '@' not in data[i] and data[i] != '\n':
+ while (
+ i < len(data)
+ and r"/" not in data[i]
+ and "@" not in data[i]
+ and data[i] != "\n"
+ ):
data.pop(i)
# Get Text
@@ -252,13 +291,13 @@ def translateWOLF(data, translatedList, pbar, filename):
translatedList = None
# Remove added speaker
- translatedText = re.sub(r'^.+?:\s', '', translatedText)
+ translatedText = re.sub(r"^.+?:\s", "", translatedText)
# Textwrap
translatedText = textwrap.fill(translatedText, width=WIDTH)
# Set Data
- data.insert(i, f'{translatedText}\n')
+ data.insert(i, f"{translatedText}\n")
i += 1
# Nothing relevant. Skip Line.
@@ -270,9 +309,9 @@ def translateWOLF(data, translatedList, pbar, filename):
# Set Progress
pbar.total = len(stringList)
pbar.refresh()
-
+
# Translate
- response = translateGPT(stringList, '', True)
+ response = translateGPT(stringList, "", True)
tokens[0] += response[1][0]
tokens[1] += response[1][1]
translatedList = response[0]
@@ -288,23 +327,32 @@ def translateWOLF(data, translatedList, pbar, filename):
MISMATCH.append(filename)
return tokens
+
# Save some money and enter the character before translation
def getSpeaker(speaker):
match speaker:
- case 'ファイン':
- return ['Fine', [0,0]]
- case '':
- return ['', [0,0]]
+ case "ファイン":
+ return ["Fine", [0, 0]]
+ case "":
+ return ["", [0, 0]]
case _:
# Store Speaker
if speaker not in str(NAMESLIST):
- response = translateGPT(speaker, 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ response = translateGPT(
+ speaker,
+ "Reply with the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
response[0] = response[0].replace("'S", "'s")
# Retry if name doesn't translate for some reason
- if re.search(r'([a-zA-Z??])', response[0]) == None:
- response = translateGPT(speaker, 'Reply with the '+ LANGUAGE +' translation of the NPC name.', False)
+ if re.search(r"([a-zA-Z??])", response[0]) == None:
+ response = translateGPT(
+ speaker,
+ "Reply with the " + LANGUAGE + " translation of the NPC name.",
+ False,
+ )
response[0] = response[0].title()
response[0] = response[0].replace("'S", "'s")
@@ -315,50 +363,56 @@ def getSpeaker(speaker):
else:
for i in range(len(NAMESLIST)):
if speaker == NAMESLIST[i][0]:
- return [NAMESLIST[i][1],[0,0]]
-
- return [speaker,[0,0]]
+ return [NAMESLIST[i][1], [0, 0]]
+
+ return [speaker, [0, 0]]
+
def subVars(jaString):
- jaString = jaString.replace('\u3000', ' ')
+ jaString = jaString.replace("\u3000", " ")
# Formatting
count = 0
- codeList = re.findall(r'[\\]+[\w]+\[[a-zA-Z0-9\\\[\]\_,\s-]+\]', jaString)
+ 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) + ']')
+ 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)
+ 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)
+ 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")
-
- return [input_list[i:i + batch_size] for i in range(0, len(input_list), batch_size)]
+
+ return [
+ input_list[i : i + batch_size] for i in range(0, len(input_list), batch_size)
+ ]
+
def createContext(fullPromptFlag, subbedT):
- characters = 'Game Characters:\n\
+ characters = "Game Characters:\n\
ロラン (Roland) - Male\n\
リュカ (Ryuka) - Male\n\
レックス (Rex) - Male\n\
@@ -403,10 +457,12 @@ def createContext(fullPromptFlag, subbedT):
アロマ (Aroma) - Female\n\
ピッケ (Pikke) - Female\n\
ドラオ (Dorao) - Male\n\
-'
-
- system = PROMPT + VOCAB if fullPromptFlag else \
- f"\
+"
+
+ system = (
+ PROMPT + VOCAB
+ if fullPromptFlag
+ else f"\
You are an expert Eroge Game translator who translates Japanese text to {LANGUAGE}.\n\
Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{LANGUAGE.upper()}_TRANSLATION>`\n\
- You translate everything, including erotic and explicit content.\n\
@@ -418,12 +474,14 @@ Output ONLY the {LANGUAGE} translation in the following format: `Translation: <{
- `...` can be a part of the dialogue. Translate it as it is.\n\
{VOCAB}\n\
"
+ )
if isinstance(subbedT, list):
- user = f'```json\n{subbedT}```'
+ user = f"```json\n{subbedT}```"
else:
user = subbedT
return characters, system, user
+
def translateText(characters, system, user, history, penalty, format):
# Prompt
msg = [{"role": "system", "content": system + characters}]
@@ -438,13 +496,13 @@ def translateText(characters, system, user, history, penalty, format):
msg.append({"role": "system", "content": history})
# Response Format
- if format == 'json':
- responseFormat = { "type": "json_object" }
+ if format == "json":
+ responseFormat = {"type": "json_object"}
else:
- responseFormat = { "type": "text" }
-
+ responseFormat = {"type": "text"}
+
# Content to TL
- msg.append({"role": "user", "content": f'{user}'})
+ msg.append({"role": "user", "content": f"{user}"})
response = openai.chat.completions.create(
temperature=0,
frequency_penalty=penalty,
@@ -454,18 +512,19 @@ def translateText(characters, system, user, history, penalty, format):
)
return response
+
def cleanTranslatedText(translatedText, varResponse):
placeholders = {
- f'{LANGUAGE} Translation: ': '',
- 'Translation: ': '',
- 'っ': '',
- '〜': '~',
- 'ッ': '',
- '。': '.',
- '「': '\\"',
- '」': '\\"',
- '- ': '-',
- 'Placeholder Text': '',
+ f"{LANGUAGE} Translation: ": "",
+ "Translation: ": "",
+ "っ": "",
+ "〜": "~",
+ "ッ": "",
+ "。": ".",
+ "「": '\\"',
+ "」": '\\"',
+ "- ": "-",
+ "Placeholder Text": "",
# Add more replacements as needed
}
for target, replacement in placeholders.items():
@@ -476,11 +535,12 @@ def cleanTranslatedText(translatedText, varResponse):
translatedText = resubVars(translatedText, varResponse[1])
return translatedText
+
def elongateCharacters(text):
# Define a pattern to match one character followed by one or more `ー` characters
# Using a positive lookbehind assertion to capture the preceding character
- pattern = r'(?<=(.))ー+'
-
+ pattern = r"(?<=(.))ー+"
+
# Define a replacement function that elongates the captured character
def repl(match):
char = match.group(1) # The character before the ー sequence
@@ -490,6 +550,7 @@ def elongateCharacters(text):
# Use re.sub() to replace the pattern in the text
return re.sub(pattern, repl, text)
+
def extractTranslation(translatedTextList, is_list):
try:
translatedTextList = re.sub(r'\\"+\"([^,\n}])', r'\\"\1', translatedTextList)
@@ -502,15 +563,15 @@ def extractTranslation(translatedTextList, is_list):
return string_list[0]
except Exception as e:
- PBAR.write(f'extractTranslation Error: {e} on String {translatedTextList}')
+ PBAR.write(f"extractTranslation Error: {e} on String {translatedTextList}")
return None
def countTokens(characters, system, user, history):
inputTotalTokens = 0
outputTotalTokens = 0
- enc = tiktoken.encoding_for_model('gpt-4')
-
+ enc = tiktoken.encoding_for_model("gpt-4")
+
# Input
if isinstance(history, list):
for line in history:
@@ -522,26 +583,28 @@ def countTokens(characters, system, user, history):
inputTotalTokens += len(enc.encode(user))
# Output
- outputTotalTokens += round(len(enc.encode(user))*3)
+ outputTotalTokens += round(len(enc.encode(user)) * 3)
return [inputTotalTokens, outputTotalTokens]
+
def combineList(tlist, text):
if isinstance(text, list):
return [t for sublist in tlist for t in sublist]
return tlist[0]
+
@retry(exceptions=Exception, tries=5, delay=5)
def translateGPT(text, history, fullPromptFlag):
global PBAR
-
+
mismatch = False
totalTokens = [0, 0]
if isinstance(text, list):
- format = 'json'
+ format = "json"
tList = batchList(text, BATCHSIZE)
else:
- format = 'text'
+ format = "text"
tList = [text]
for index, tItem in enumerate(tList):
@@ -556,7 +619,7 @@ def translateGPT(text, history, fullPromptFlag):
subbedT = varResponse[0]
# Things to Check before starting translation
- if not re.search(r'[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+', subbedT):
+ if not re.search(r"[一-龠ぁ-ゔァ-ヴーa-zA-Z0-9]+", subbedT):
if PBAR is not None:
PBAR.update(len(tItem))
continue
@@ -581,9 +644,13 @@ def translateGPT(text, history, fullPromptFlag):
translatedText = cleanTranslatedText(translatedText, varResponse)
if isinstance(tItem, list):
extractedTranslations = extractTranslation(translatedText, True)
- if extractedTranslations == None or len(tItem) != len(extractedTranslations):
+ if extractedTranslations == None or len(tItem) != len(
+ extractedTranslations
+ ):
# Mismatch. Try Again
- response = translateText(characters, system, user, history, 0.05, format)
+ response = translateText(
+ characters, system, user, history, 0.05, format
+ )
translatedText = response.choices[0].message.content
totalTokens[0] += response.usage.prompt_tokens
totalTokens[1] += response.usage.completion_tokens
@@ -592,13 +659,17 @@ def translateGPT(text, history, fullPromptFlag):
translatedText = cleanTranslatedText(translatedText, varResponse)
if isinstance(tItem, list):
extractedTranslations = extractTranslation(translatedText, True)
- if extractedTranslations == None or len(tItem) != len(extractedTranslations):
- mismatch = True # Just here for breakpoint
-
+ if extractedTranslations == None or len(tItem) != len(
+ extractedTranslations
+ ):
+ mismatch = True # Just here for breakpoint
+
# Set if no mismatch
if mismatch == False:
tList[index] = extractedTranslations
- history = extractedTranslations[-10:] # Update history if we have a list
+ history = extractedTranslations[
+ -10:
+ ] # Update history if we have a list
else:
history = text[-10:]
mismatch = False
@@ -609,7 +680,7 @@ def translateGPT(text, history, fullPromptFlag):
PBAR.update(len(tItem))
else:
# Ensure we're passing a single string to extractTranslation
- tList[index] = translatedText
+ tList[index] = translatedText
finalList = combineList(tList, text)
return [finalList, totalTokens]