Merge branch 'CTranslate2' into develop

# Conflicts:
#	config.py
#	requirements.txt
This commit is contained in:
misyaguziya
2024-01-08 22:36:48 +09:00
12 changed files with 555 additions and 178 deletions

1
.gitignore vendored
View File

@@ -6,3 +6,4 @@ VRCT.spec
*.pyc
logs/
.venv/
weight/

107
config.py
View File

@@ -5,8 +5,10 @@ from json import load as json_load
from json import dump as json_dump
import tkinter as tk
from tkinter import font
from models.translation.translation_languages import translatorEngine
from languages import selectable_languages
from models.translation.translation_languages import translation_lang
from models.transcription.transcription_utils import getInputDevices, getDefaultInputDevice
from models.translation.utils import ctranslate2_weights
from utils import generatePercentageStringsList, isUniqueStrings
json_serializable_vars = {}
@@ -43,8 +45,12 @@ class Config:
return self._ENABLE_SPEAKER2CHATBOX
@property
def LOCAL_PATH(self):
return self._LOCAL_PATH
def ENABLE_SPEAKER2CHATBOX(self):
return self._ENABLE_SPEAKER2CHATBOX
@property
def PATH_LOCAL(self):
return self._PATH_LOCAL
@property
def PATH_CONFIG(self):
@@ -90,6 +96,10 @@ class Config:
def SELECTABLE_UI_LANGUAGES_DICT(self):
return self._SELECTABLE_UI_LANGUAGES_DICT
@property
def CTRANSLATE2_WEIGHTS(self):
return self._CTRANSLATE2_WEIGHTS
@property
def MAX_MIC_ENERGY_THRESHOLD(self):
return self._MAX_MIC_ENERGY_THRESHOLD
@@ -172,13 +182,22 @@ class Config:
self._TARGET_LANGUAGE = value
@property
def CHOICE_TRANSLATOR(self):
return self._CHOICE_TRANSLATOR
def CHOICE_INPUT_TRANSLATOR(self):
return self._CHOICE_INPUT_TRANSLATOR
@CHOICE_TRANSLATOR.setter
def CHOICE_TRANSLATOR(self, value):
if value in translatorEngine:
self._CHOICE_TRANSLATOR = value
@CHOICE_INPUT_TRANSLATOR.setter
def CHOICE_INPUT_TRANSLATOR(self, value):
if value in list(translation_lang.keys()):
self._CHOICE_INPUT_TRANSLATOR= value
@property
def CHOICE_OUTPUT_TRANSLATOR(self):
return self._CHOICE_OUTPUT_TRANSLATOR
@CHOICE_OUTPUT_TRANSLATOR.setter
def CHOICE_OUTPUT_TRANSLATOR(self, value):
if value in list(translation_lang.keys()):
self._CHOICE_OUTPUT_TRANSLATOR = value
# Save Json Data
## Main Window
@@ -193,6 +212,28 @@ class Config:
self._SELECTED_TAB_NO = value
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
@property
@json_serializable('SELECTED_TAB_YOUR_TRANSLATOR_ENGINES')
def SELECTED_TAB_YOUR_TRANSLATOR_ENGINES(self):
return self._SELECTED_TAB_YOUR_TRANSLATOR_ENGINES
@SELECTED_TAB_YOUR_TRANSLATOR_ENGINES.setter
def SELECTED_TAB_YOUR_TRANSLATOR_ENGINES(self, value):
if isinstance(value, dict):
self._SELECTED_TAB_YOUR_TRANSLATOR_ENGINES = value
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
@property
@json_serializable('SELECTED_TAB_TARGET_TRANSLATOR_ENGINES')
def SELECTED_TAB_TARGET_TRANSLATOR_ENGINES(self):
return self._SELECTED_TAB_TARGET_TRANSLATOR_ENGINES
@SELECTED_TAB_TARGET_TRANSLATOR_ENGINES.setter
def SELECTED_TAB_TARGET_TRANSLATOR_ENGINES(self, value):
if isinstance(value, dict):
self._SELECTED_TAB_TARGET_TRANSLATOR_ENGINES = value
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
@property
@json_serializable('SELECTED_TAB_YOUR_LANGUAGES')
def SELECTED_TAB_YOUR_LANGUAGES(self):
@@ -509,6 +550,30 @@ class Config:
self._AUTH_KEYS[key] = value
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, self.AUTH_KEYS)
@property
@json_serializable('WEIGHT_TYPE')
def WEIGHT_TYPE(self):
return self._WEIGHT_TYPE
@WEIGHT_TYPE.setter
def WEIGHT_TYPE(self, value):
if isinstance(value, str):
self._WEIGHT_TYPE = value
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
@property
@json_serializable('MESSAGE_FORMAT')
def MESSAGE_FORMAT(self):
return self._MESSAGE_FORMAT
@MESSAGE_FORMAT.setter
def MESSAGE_FORMAT(self, value):
if isinstance(value, str):
if isUniqueStrings(["[message]", "[translation]"], value) is False:
value = "[message]([translation])"
self._MESSAGE_FORMAT = value
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
@property
@json_serializable('ENABLE_AUTO_CLEAR_MESSAGE_BOX')
def ENABLE_AUTO_CLEAR_MESSAGE_BOX(self):
@@ -662,9 +727,9 @@ class Config:
# Read Only
self._VERSION = "2.0.2"
self._ENABLE_SPEAKER2CHATBOX = False # Speaker2Chatbox
self._LOCAL_PATH = os_path.dirname(sys.argv[0])
self._PATH_CONFIG = os_path.join(self._LOCAL_PATH, "config.json")
self._PATH_LOGS = os_path.join(self._LOCAL_PATH, "logs")
self._PATH_LOCAL = os_path.dirname(sys.argv[0])
self._PATH_CONFIG = os_path.join(self._PATH_LOCAL, "config.json")
self._PATH_LOGS = os_path.join(self._PATH_LOCAL, "logs")
os_makedirs(self._PATH_LOGS, exist_ok=True)
self._GITHUB_URL = "https://api.github.com/repos/misyaguziya/VRCT/releases/latest"
self._BOOTH_URL = "https://misyaguziya.booth.pm/"
@@ -680,6 +745,7 @@ class Config:
"ko": "한국어"
# If you want to add a new language and key, please append it here.
}
self._CTRANSLATE2_WEIGHTS = ctranslate2_weights
self._MAX_MIC_ENERGY_THRESHOLD = 2000
self._MAX_SPEAKER_ENERGY_THRESHOLD = 4000
@@ -688,7 +754,8 @@ class Config:
self._ENABLE_TRANSCRIPTION_SEND = False
self._ENABLE_TRANSCRIPTION_RECEIVE = False
self._ENABLE_FOREGROUND = False
self._CHOICE_TRANSLATOR = translatorEngine[0]
self._CHOICE_INPUT_TRANSLATOR = "CTranslate2"
self._CHOICE_OUTPUT_TRANSLATOR = "CTranslate2"
self._SOURCE_LANGUAGE = "Japanese"
self._SOURCE_COUNTRY = "Japan"
self._TARGET_LANGUAGE = "English"
@@ -697,6 +764,16 @@ class Config:
# Save Json Data
## Main Window
self._SELECTED_TAB_NO = "1"
self._SELECTED_TAB_YOUR_TRANSLATOR_ENGINES = {
"1":"CTranslate2",
"2":"CTranslate2",
"3":"CTranslate2",
}
self._SELECTED_TAB_TARGET_TRANSLATOR_ENGINES = {
"1":"CTranslate2",
"2":"CTranslate2",
"3":"CTranslate2",
}
self._SELECTED_TAB_YOUR_LANGUAGES = {
"1":"Japanese\n(Japan)",
"2":"Japanese\n(Japan)",
@@ -741,10 +818,8 @@ class Config:
self._OSC_PORT = 9000
self._AUTH_KEYS = {
"DeepL_API": None,
"DeepL": None,
"Bing": None,
"Google": None,
}
self._WEIGHT_TYPE = "small"
self._SEND_MESSAGE_FORMAT = "[message]"
self._SEND_MESSAGE_FORMAT_WITH_T = "[message]([translation])"
self._RECEIVED_MESSAGE_FORMAT = "[message]"

View File

@@ -21,8 +21,8 @@ def callbackFilepathLogs():
Popen(['explorer', config.PATH_LOGS.replace('/', '\\')], shell=True)
def callbackFilepathConfigFile():
print("callbackFilepathConfigFile", config.LOCAL_PATH.replace('/', '\\'))
Popen(['explorer', config.LOCAL_PATH.replace('/', '\\')], shell=True)
print("callbackFilepathConfigFile", config.PATH_LOCAL.replace('/', '\\'))
Popen(['explorer', config.PATH_LOCAL.replace('/', '\\')], shell=True)
def callbackQuitVrct():
setMainWindowGeometry()
@@ -66,10 +66,10 @@ def sendMicMessage(message):
pass
else:
translation = model.getInputTranslate(message)
if translation is False:
config.ENABLE_TRANSLATION = False
translation = ""
view.translationEngineLimitErrorProcess()
# if translation is False:
# config.ENABLE_TRANSLATION = False
# translation = ""
# view.translationEngineLimitErrorProcess()
if config.ENABLE_TRANSCRIPTION_SEND is True:
if config.ENABLE_SEND_MESSAGE_TO_VRC is True:
@@ -133,10 +133,10 @@ def receiveSpeakerMessage(message):
pass
else:
translation = model.getOutputTranslate(message)
if translation is False:
config.ENABLE_TRANSLATION = False
translation = ""
view.translationEngineLimitErrorProcess()
# if translation is False:
# config.ENABLE_TRANSLATION = False
# translation = ""
# view.translationEngineLimitErrorProcess()
if config.ENABLE_TRANSCRIPTION_RECEIVE is True:
if config.ENABLE_NOTICE_XSOVERLAY is True:
@@ -203,10 +203,10 @@ def sendChatMessage(message):
pass
else:
translation = model.getInputTranslate(message)
if translation is False:
config.ENABLE_TRANSLATION = False
translation = ""
view.translationEngineLimitErrorProcess()
# if translation is False:
# config.ENABLE_TRANSLATION = False
# translation = ""
# view.translationEngineLimitErrorProcess()
# send OSC message
if config.ENABLE_SEND_MESSAGE_TO_VRC is True:
@@ -250,6 +250,12 @@ def messageBoxFocusOut(e):
model.oscStopSendTyping()
# func select languages
def initSetTranslateEngine():
engine = config.SELECTED_TAB_YOUR_TRANSLATOR_ENGINES[config.SELECTED_TAB_NO]
config.CHOICE_INPUT_TRANSLATOR = engine
engine = config.SELECTED_TAB_TARGET_TRANSLATOR_ENGINES[config.SELECTED_TAB_NO]
config.CHOICE_OUTPUT_TRANSLATOR = engine
def initSetLanguageAndCountry():
select = config.SELECTED_TAB_YOUR_LANGUAGES[config.SELECTED_TAB_NO]
language, country = model.getLanguageAndCountry(select)
@@ -259,7 +265,18 @@ def initSetLanguageAndCountry():
language, country = model.getLanguageAndCountry(select)
config.TARGET_LANGUAGE = language
config.TARGET_COUNTRY = country
config.CHOICE_TRANSLATOR = model.findTranslationEngine(config.SOURCE_LANGUAGE, config.TARGET_LANGUAGE)
def setYourTranslateEngine(select):
engines = config.SELECTED_TAB_YOUR_TRANSLATOR_ENGINES
engines[config.SELECTED_TAB_NO] = select
config.SELECTED_TAB_YOUR_TRANSLATOR_ENGINES = engines
config.CHOICE_INPUT_TRANSLATOR = select
def setTargetTranslateEngine(select):
engines = config.SELECTED_TAB_TARGET_TRANSLATOR_ENGINES
engines[config.SELECTED_TAB_NO] = select
config.SELECTED_TAB_TARGET_TRANSLATOR_ENGINES = engines
config.CHOICE_OUTPUT_TRANSLATOR = select
def setYourLanguageAndCountry(select):
languages = config.SELECTED_TAB_YOUR_LANGUAGES
@@ -268,7 +285,6 @@ def setYourLanguageAndCountry(select):
language, country = model.getLanguageAndCountry(select)
config.SOURCE_LANGUAGE = language
config.SOURCE_COUNTRY = country
config.CHOICE_TRANSLATOR = model.findTranslationEngine(config.SOURCE_LANGUAGE, config.TARGET_LANGUAGE)
view.printToTextbox_selectedYourLanguages(select)
def setTargetLanguageAndCountry(select):
@@ -278,7 +294,6 @@ def setTargetLanguageAndCountry(select):
language, country = model.getLanguageAndCountry(select)
config.TARGET_LANGUAGE = language
config.TARGET_COUNTRY = country
config.CHOICE_TRANSLATOR = model.findTranslationEngine(config.SOURCE_LANGUAGE, config.TARGET_LANGUAGE)
view.printToTextbox_selectedTargetLanguages(select)
def swapYourLanguageAndTargetLanguage():
@@ -293,17 +308,26 @@ def swapYourLanguageAndTargetLanguage():
def callbackSelectedLanguagePresetTab(selected_tab_no):
config.SELECTED_TAB_NO = selected_tab_no
view.updateGuiVariableByPresetTabNo(config.SELECTED_TAB_NO)
engines = config.SELECTED_TAB_YOUR_TRANSLATOR_ENGINES
engine = engines[config.SELECTED_TAB_NO]
config.CHOICE_INPUT_TRANSLATOR = engine
engines = config.SELECTED_TAB_TARGET_TRANSLATOR_ENGINES
engine = engines[config.SELECTED_TAB_NO]
config.CHOICE_OUTPUT_TRANSLATOR = engine
languages = config.SELECTED_TAB_YOUR_LANGUAGES
select = languages[config.SELECTED_TAB_NO]
language, country = model.getLanguageAndCountry(select)
config.SOURCE_LANGUAGE = language
config.SOURCE_COUNTRY = country
languages = config.SELECTED_TAB_TARGET_LANGUAGES
select = languages[config.SELECTED_TAB_NO]
language, country = model.getLanguageAndCountry(select)
config.TARGET_LANGUAGE = language
config.TARGET_COUNTRY = country
config.CHOICE_TRANSLATOR = model.findTranslationEngine(config.SOURCE_LANGUAGE, config.TARGET_LANGUAGE)
view.printToTextbox_changedLanguagePresetTab(config.SELECTED_TAB_NO)
# command func
@@ -444,7 +468,7 @@ def callbackSetEnableRestoreMainWindowGeometry(value):
def callbackSetDeeplAuthkey(value):
print("callbackSetDeeplAuthkey", str(value))
if len(value) == 39:
result = model.authenticationTranslator(choice_translator="DeepL_API", auth_key=value)
result = model.authenticationTranslatorDeepLAuthKey(auth_key=value)
if result is True:
key = value
view.printToTextbox_AuthenticationSuccess()
@@ -454,12 +478,10 @@ def callbackSetDeeplAuthkey(value):
auth_keys = config.AUTH_KEYS
auth_keys["DeepL_API"] = key
config.AUTH_KEYS = auth_keys
config.CHOICE_TRANSLATOR = model.findTranslationEngine(config.SOURCE_LANGUAGE, config.TARGET_LANGUAGE)
elif len(value) == 0:
auth_keys = config.AUTH_KEYS
auth_keys["DeepL_API"] = None
config.AUTH_KEYS = auth_keys
config.CHOICE_TRANSLATOR = model.findTranslationEngine(config.SOURCE_LANGUAGE, config.TARGET_LANGUAGE)
# Transcription Tab
# Transcription (Mic)
@@ -801,15 +823,16 @@ def createMainWindow():
# init config
initSetConfigByExeArguments()
initSetTranslateEngine()
initSetLanguageAndCountry()
if model.authenticationTranslator(config.CHOICE_TRANSLATOR, config.AUTH_KEYS[config.CHOICE_TRANSLATOR]) is False:
# error update Auth key
auth_keys = config.AUTH_KEYS
auth_keys[config.CHOICE_TRANSLATOR] = None
config.AUTH_KEYS = auth_keys
view.printToTextbox_AuthenticationError()
config.CHOICE_TRANSLATOR = model.findTranslationEngine(config.SOURCE_LANGUAGE, config.TARGET_LANGUAGE)
if config.AUTH_KEYS["DeepL_API"] is not None:
if model.authenticationTranslatorDeepLAuthKey("DeepL_API", config.AUTH_KEYS["DeepL_API"]) is False:
# error update Auth key
auth_keys = config.AUTH_KEYS
auth_keys["DeepL_API"] = None
config.AUTH_KEYS = auth_keys
view.printToTextbox_AuthenticationError()
# set word filter
model.addKeywords()

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -1,4 +1,4 @@
python.exe -m pip install --upgrade pip
pip install -r requirements.txt
pip install git+https://github.com/misyaguziya/translators
pip install git+https://github.com/misyaguziya/deepl-translate
pip install git+https://github.com/misyaguziya/custom_speech_recognition

View File

@@ -7,6 +7,10 @@ if __name__ == "__main__":
splash = SplashWindow()
splash.showSplash()
from config import config
from models.translation.utils import downloadCTranslate2Weight
downloadCTranslate2Weight(config.PATH_LOCAL, config.WEIGHT_TYPE, config.CTRANSLATE2_WEIGHTS, splash.updateDownloadProgress)
import controller
controller.createMainWindow()
splash.destroySplash()

140
model.py
View File

@@ -22,7 +22,7 @@ from models.transcription.transcription_recorder import SelectedMicRecorder, Sel
from models.transcription.transcription_recorder import SelectedMicEnergyRecorder, SelectedSpeakeEnergyRecorder
from models.transcription.transcription_transcriber import AudioTranscriber
from models.xsoverlay.notification import xsoverlayForVRCT
from models.translation.translation_languages import translatorEngine, translation_lang
from models.translation.translation_languages import translation_lang
from models.transcription.transcription_languages import transcription_lang
from config import config
@@ -45,15 +45,6 @@ class threadFnc(Thread):
self.fnc(*self._args, **self._kwargs)
class Model:
# Languages available for both transcription and translation
SUPPORTED_LANGUAGES = [
'Afrikaans', 'Arabic', 'Basque', 'Bulgarian', 'Catalan', 'Chinese', 'Croatian',
'Czech', 'Danish', 'Dutch', 'English', 'Filipino', 'Finnish', 'French', 'German',
'Greek', 'Hebrew', 'Hindi', 'Hungarian', 'Indonesian', 'Italian', 'Japanese',
'Korean', 'Lithuanian', 'Malay', 'Norwegian', 'Polish', 'Portuguese', 'Romanian',
'Russian', 'Serbian', 'Slovak', 'Slovenian', 'Spanish', 'Swedish', 'Thai', 'Turkish',
'Ukrainian', 'Vietnamese'
]
_instance = None
def __new__(cls):
@@ -72,24 +63,19 @@ class Model:
self.speaker_audio_recorder = None
self.speaker_energy_recorder = None
self.speaker_energy_plot_progressbar = None
self.translator = Translator()
self.translator = Translator(config.PATH_LOCAL, config.CTRANSLATE2_WEIGHTS[config.WEIGHT_TYPE])
self.keyword_processor = KeywordProcessor()
def resetTranslator(self):
del self.translator
self.translator = Translator()
self.translator = Translator(config.PATH_LOCAL, config.CTRANSLATE2_WEIGHTS[config.WEIGHT_TYPE])
def resetKeywordProcessor(self):
del self.keyword_processor
self.keyword_processor = KeywordProcessor()
def authenticationTranslator(self, choice_translator=None, auth_key=None):
if choice_translator is None:
choice_translator = config.CHOICE_TRANSLATOR
if auth_key is None:
auth_key = config.AUTH_KEYS[choice_translator]
result = self.translator.authentication(choice_translator, auth_key)
def authenticationTranslatorDeepLAuthKey(self, auth_key):
result = self.translator.authenticationDeepLAuthKey(auth_key)
return result
def startLogger(self):
@@ -108,13 +94,21 @@ class Model:
self.logger.disabled = True
self.logger = None
@staticmethod
def getListLanguageAndCountry():
def getListLanguageAndCountry(self):
transcription_langs = list(transcription_lang.keys())
tl_keys = translation_lang.keys()
translation_langs = []
for tl_key in tl_keys:
for lang in translation_lang[tl_key]["source"]:
translation_langs.append(lang)
translation_langs = list(set(translation_langs))
supported_langs = list(filter(lambda x: x in transcription_langs, translation_langs))
langs = []
for lang in model.SUPPORTED_LANGUAGES:
for lang in supported_langs:
for country in transcription_lang[lang]:
langs.append(f"{lang}\n({country})")
return langs
return sorted(langs)
@staticmethod
def getLanguageAndCountry(select):
@@ -123,83 +117,73 @@ class Model:
country = parts[1][1:-1]
return language, country
def findTranslationEngine(self, source_lang, target_lang):
def findTranslationEngines(self, source_lang, target_lang):
compatible_engines = []
for engine in translatorEngine:
source_languages = translation_lang.get(engine, {}).get("source", {})
target_languages = translation_lang.get(engine, {}).get("target", {})
if source_lang in source_languages and target_lang in target_languages:
for engine in list(translation_lang.keys()):
languages = translation_lang.get(engine, {}).get("source", {})
if source_lang in languages and target_lang in languages:
compatible_engines.append(engine)
engine_name = compatible_engines[0]
if "DeepL_API" in compatible_engines:
if self.translator.deepl_client is None:
compatible_engines.remove('DeepL_API')
return compatible_engines
if engine_name == "DeepL" and config.AUTH_KEYS["DeepL_API"] is not None:
if self.authenticationTranslator(engine_name, config.AUTH_KEYS["DeepL_API"]) is True:
engine_name = "DeepL_API"
elif engine_name == "DeepL_API" and config.AUTH_KEYS["DeepL_API"] is None:
engine_name = "DeepL"
return engine_name
def getInputTranslate(self, message):
translator_name=config.CHOICE_TRANSLATOR
def getInputTranslate(self, message, fnc=None):
translator_name=config.CHOICE_INPUT_TRANSLATOR
source_language=config.SOURCE_LANGUAGE
target_language=config.TARGET_LANGUAGE
target_country = config.TARGET_COUNTRY
if translator_name == "DeepL_API":
if target_language == "English":
if target_country in ["United States", "Canada", "Philippines"]:
target_language = "English American"
else:
target_language = "English British"
elif target_language == "Portuguese":
if target_country in ["Portugal"]:
target_language = "Portuguese European"
else:
target_language = "Portuguese Brazilian"
elif translator_name == "DeepL":
if target_language in ["English American", "English British"]:
target_language = "English"
elif target_language in ["Portuguese European", "Portuguese Brazilian"]:
target_language = "Portuguese"
translation = self.translator.translate(
translator_name=translator_name,
source_language=source_language,
target_language=target_language,
target_country=target_country,
message=message
)
# 翻訳失敗時のフェールセーフ処理
if translation is False:
translation = self.translator.translate(
translator_name="CTranslate2",
source_language=source_language,
target_language=target_language,
target_country=target_country,
message=message
)
try:
fnc()
except Exception:
pass
return translation
def getOutputTranslate(self, message):
translator_name=config.CHOICE_TRANSLATOR
def getOutputTranslate(self, message, fnc=None):
translator_name=config.CHOICE_OUTPUT_TRANSLATOR
source_language=config.TARGET_LANGUAGE
target_language=config.SOURCE_LANGUAGE
target_country = config.SOURCE_COUNTRY
if translator_name == "DeepL_API":
if target_language == "English":
if target_country in ["United States", "Canada", "Philippines"]:
target_language = "English American"
else:
target_language = "English British"
elif target_language == "Portuguese":
if target_country in ["Portugal"]:
target_language = "Portuguese European"
else:
target_language = "Portuguese Brazilian"
elif translator_name == "DeepL":
if target_language in ["English American", "English British"]:
target_language = "English"
elif target_language in ["Portuguese European", "Portuguese Brazilian"]:
target_language = "Portuguese"
target_country=config.SOURCE_COUNTRY
translation = self.translator.translate(
translator_name=translator_name,
source_language=source_language,
target_language=target_language,
target_country=target_country,
message=message
)
# 翻訳失敗時のフェールセーフ処理
if translation is False:
translation = self.translator.translate(
translator_name="CTranslate2",
source_language=source_language,
target_language=target_language,
target_country=target_country,
message=message
)
try:
fnc()
except Exception:
pass
return translation
def addKeywords(self):
@@ -273,7 +257,7 @@ class Model:
folder_name = '_internal'
tmp_directory_name = 'tmp'
batch_name = 'update.bat'
current_directory = config.LOCAL_PATH
current_directory = config.PATH_LOCAL
try:
res = requests_get(config.GITHUB_URL)
@@ -306,7 +290,7 @@ class Model:
program_name = 'VRCT.exe'
folder_name = '_internal'
batch_name = 'restart.bat'
current_directory = config.LOCAL_PATH
current_directory = config.PATH_LOCAL
copyfile(os_path.join(current_directory, folder_name, "batch", batch_name), os_path.join(current_directory, batch_name))
command = [os_path.join(current_directory, batch_name), program_name]
Popen(command, cwd=current_directory)

View File

@@ -1,35 +1,40 @@
translatorEngine = ["DeepL", "DeepL_API", "Google", "Bing"]
translation_lang = {}
dict_deepl_languages = {
"Japanese":"JA",
"English":"EN",
"Korean":"KO",
"Bulgarian":"BG",
"Chinese":"ZH",
"Czech":"CS",
"Danish":"DA",
"Dutch":"NL",
"Estonian":"ET",
"Finnish":"FI",
"French":"FR",
"German":"DE",
"Greek":"EL",
"Hungarian":"HU",
"Italian":"IT",
"Latvian":"LV",
"Lithuanian":"LT",
"Polish":"PL",
"Portuguese":"PT",
"Romanian":"RO",
"Russian":"RU",
"Slovak":"SK",
"Slovenian":"SL",
"Spanish":"ES",
"Swedish":"SV",
"Indonesian":"ID",
"Ukrainian":"UK",
"Turkish":"TR",
"Norwegian":"NB",
'Arabic':'ar',
'Bulgarian':'bg',
'Czech':'cs',
'Danish':'da',
'German':'de',
'Greek':'el',
'English':'en',
'Spanish':'es',
'Estonian':'et',
'Finnish':'fi',
'French':'fr',
'Irish':'ga',
'Croatian':'hr',
'Hungarian':'hu',
'Indonesian':'id',
'Icelandic':'is',
'Italian':'it',
'Japanese':'ja',
'Korean':'ko',
'Lithuanian':'lt',
'Latvian':'lv',
'Maltese':'mt',
'Bokmal':'nb',
'Dutch':'nl',
'Norwegian':'no',
'Polish':'pl',
'Portuguese':'pt',
'Romanian':'ro',
'Russian':'ru',
'Slovak':'sk',
'Slovenian':'sl',
'Swedish':'sv',
'Turkish':'tr',
'Ukrainian':'uk',
'Chinese':'zh',
}
translation_lang["DeepL"] = {
"source":dict_deepl_languages,
@@ -241,3 +246,132 @@ translation_lang["Bing"] = {
"source":dict_bing_languages,
"target":dict_bing_languages,
}
dict_papago_languages = {
'German': 'de',
'English': 'en',
'Spanish':'es',
'French': 'fr',
'Hindi': 'hi',
'Indonesian': 'id',
'Italian': 'it',
'Japanese': 'ja',
'Korean': 'ko',
'Portuguese': 'pt',
'Russian': 'ru',
'Thai': 'th',
'Vietnamese': 'vi',
'Chinese':'zh-CN',
}
translation_lang["Papago"] = {
"source":dict_papago_languages,
"target":dict_papago_languages,
}
dict_ctranslate2_languages = {
'English': 'en',
'Chinese': 'zh',
'German': 'de',
'Spanish': 'es',
'Russian': 'ru',
'Korean': 'ko',
'French': 'fr',
'Japanese': 'ja',
'Portuguese': 'pt',
'Turkish': 'tr',
'Polish': 'pl',
'Catalan': 'ca',
'Dutch': 'nl',
'Arabic': 'ar',
'Swedish': 'sv',
'Italian': 'it',
'Indonesian': 'id',
'Hindi': 'hi',
'Finnish': 'fi',
'Vietnamese': 'vi',
'Hebrew': 'he',
'Ukrainian': 'uk',
'Greek': 'el',
'Malay': 'ms',
'Czech': 'cs',
'Romanian': 'ro',
'Danish': 'da',
'Hungarian': 'hu',
'Tamil': 'ta',
'Norwegian': 'no',
'Thai': 'th',
'Urdu': 'ur',
'Croatian': 'hr',
'Bulgarian': 'bg',
'Lithuanian': 'lt',
'Latin': 'la',
'Maori': 'mi',
'Malayalam': 'ml',
'Welsh': 'cy',
'Slovak': 'sk',
'Telugu': 'te',
'Persian': 'fa',
'Latvian': 'lv',
'Bengali': 'bn',
'Serbian': 'sr',
'Azerbaijani': 'az',
'Slovenian': 'sl',
'Kannada': 'kn',
'Estonian': 'et',
'Macedonian': 'mk',
'Breton': 'br',
'Basque': 'eu',
'Icelandic': 'is',
'Armenian': 'hy',
'Nepali': 'ne',
'Mongolian': 'mn',
'Bosnian': 'bs',
'Kazakh': 'kk',
'Albanian': 'sq',
'Swahili': 'sw',
'Galician': 'gl',
'Marathi': 'mr',
'Punjabi': 'pa',
'Sinhala': 'si',
'Khmer': 'km',
'Shona': 'sn',
'Yoruba': 'yo',
'Somali': 'so',
'Afrikaans': 'af',
'Occitan': 'oc',
'Georgian': 'ka',
'Belarusian': 'be',
'Tajik': 'tg',
'Sindhi': 'sd',
'Gujarati': 'gu',
'Amharic': 'am',
'Yiddish': 'yi',
'Lao': 'lo',
'Uzbek': 'uz',
'Faroese': 'fo',
'Haitian creole': 'ht',
'Pashto': 'ps',
'Turkmen': 'tk',
'Nynorsk': 'nn',
'Maltese': 'mt',
'Sanskrit': 'sa',
'Luxembourgish': 'lb',
'Myanmar': 'my',
'Tibetan': 'bo',
'Filipino': 'tl',
'Malagasy': 'mg',
'Assamese': 'as',
'Tatar': 'tt',
'Hawaiian': 'haw',
'Lingala': 'ln',
'Hausa': 'ha',
'Bashkir': 'ba',
'Javanese': 'jw',
'Sundanese': 'su'
}
translation_lang["CTranslate2"] = {
"source":dict_ctranslate2_languages,
"target":dict_ctranslate2_languages,
}

View File

@@ -1,43 +1,69 @@
import os
from deepl import Translator as deepl_Translator
from deepl_translate import translate as deepl_web_Translator
from translators import translate_text as other_web_Translator
from .translation_languages import translation_lang
import ctranslate2
import transformers
TRANSLATE_MODELS = {
"small": "facebook/m2m100_418M",
"large": "facebook/m2m100_1.2B"
}
# Translator
class Translator():
def __init__(self):
pass
def __init__(self, path, weight_config):
self.translator_status = {}
directory_name = weight_config["directory_name"]
tokenizer = weight_config["tokenizer"]
self.weight_path = os.path.join(path, "weight", directory_name)
self.translator = ctranslate2.Translator(self.weight_path, device="cpu", device_index=0, compute_type="int8", inter_threads=1, intra_threads=4)
self.tokenizer = transformers.AutoTokenizer.from_pretrained(tokenizer)
self.deepl_client = None
def authentication(self, translator_name, authkey=None):
def authenticationDeepLAuthKey(self, authkey):
result = True
match translator_name:
case "DeepL_API":
try:
self.deepl_client = deepl_Translator(authkey)
self.deepl_client.translate_text(" ", target_lang="EN-US")
except Exception:
result = False
try:
self.deepl_client = deepl_Translator(authkey)
self.deepl_client.translate_text(" ", target_lang="EN-US")
except Exception:
self.deepl_client = None
result = False
return result
def translate(self, translator_name, source_language, target_language, message):
def translate(self, translator_name, source_language, target_language, target_country, message):
try:
result = ""
source_language=translation_lang[translator_name]["source"][source_language]
target_language=translation_lang[translator_name]["target"][target_language]
match translator_name:
case "DeepL":
result = deepl_web_Translator(
source_language=source_language,
target_language=target_language,
text=message
result = other_web_Translator(
query_text=message,
translator="deepl",
from_language=source_language,
to_language=target_language,
)
case "DeepL_API":
result = self.deepl_client.translate_text(
message,
source_lang=source_language,
target_lang=target_language,
).text
if self.deepl_client is None:
result = False
else:
if target_language == "English":
if target_country in ["United States", "Canada", "Philippines"]:
target_language = "English American"
else:
target_language = "English British"
elif target_language == "Portuguese":
if target_country in ["Portugal"]:
target_language = "Portuguese European"
else:
target_language = "Portuguese Brazilian"
result = self.deepl_client.translate_text(
message,
source_lang=source_language,
target_lang=target_language,
).text
case "Google":
result = other_web_Translator(
query_text=message,
@@ -52,6 +78,20 @@ class Translator():
from_language=source_language,
to_language=target_language,
)
case "Papago":
result = other_web_Translator(
query_text=message,
translator="papago",
from_language=source_language,
to_language=target_language,
)
case "CTranslate2":
self.tokenizer.src_lang = source_language
source = self.tokenizer.convert_ids_to_tokens(self.tokenizer.encode(message))
target_prefix = [self.tokenizer.lang_code_to_token[target_language]]
results = self.translator.translate_batch([source], target_prefix=[target_prefix])
target = results[0].hypotheses[0][1:]
result = self.tokenizer.decode(self.tokenizer.convert_tokens_to_ids(target))
except Exception:
import traceback
with open('error.log', 'a') as f:

View File

@@ -0,0 +1,81 @@
import tempfile
from zipfile import ZipFile
from os import path as os_path
from os import makedirs as os_makedirs
from requests import get as requests_get, head as requests_head
from tqdm import tqdm
from typing import Callable
import hashlib
ctranslate2_weights = {
"small": { # M2M-100 418M-parameter model
"url": "https://bit.ly/33fM1AO",
"directory_name": "m2m100_418m",
"tokenizer": "facebook/m2m100_418M",
"hash": {
"model.bin": "e7c26a9abb5260abd0268fbe3040714070dec254a990b4d7fd3f74c5230e3acb",
"sentencepiece.model": "d8f7c76ed2a5e0822be39f0a4f95a55eb19c78f4593ce609e2edbc2aea4d380a",
"shared_vocabulary.txt": "bd440aa21b8ca3453fc792a0018a1f3fe68b3464aadddd4d16a4b72f73c86d8c",
}
},
"large": { # M2M-100 1.2B-parameter model
"url": "https://bit.ly/3GYiaed",
"directory_name": "m2m100_12b",
"tokenizer": "facebook/m2m100_1.2b",
"hash": {
"model.bin": "abb7bf4ba7e5e016b6e3ed480c752459b2f783ac8fca372e7587675e5bf3a919",
"sentencepiece.model": "d8f7c76ed2a5e0822be39f0a4f95a55eb19c78f4593ce609e2edbc2aea4d380a",
"shared_vocabulary.txt": "bd440aa21b8ca3453fc792a0018a1f3fe68b3464aadddd4d16a4b72f73c86d8c",
}
},
}
def calculate_file_hash(file_path, block_size=65536):
hash_object = hashlib.sha256()
with open(file_path, 'rb') as file:
for block in iter(lambda: file.read(block_size), b''):
hash_object.update(block)
return hash_object.hexdigest()
def downloadCTranslate2Weight(path, weight_type="small", ctranslate2_weights=ctranslate2_weights, func=None):
url = ctranslate2_weights[weight_type]["url"]
filename = 'weight.zip'
directory_name = 'weight'
current_directory = path
weight_directory_name = ctranslate2_weights[weight_type]["directory_name"]
hash_data = ctranslate2_weights[weight_type]["hash"]
files = ["model.bin", "sentencepiece.model", "shared_vocabulary.txt"]
# check already downloaded
if all(os_path.exists(os_path.join(current_directory, directory_name, weight_directory_name, file)) for file in files):
# check hash
for file in files:
original_hash = hash_data[file]
current_hash = calculate_file_hash(os_path.join(current_directory, directory_name, weight_directory_name, file))
if original_hash != current_hash:
break
return
try:
os_makedirs(os_path.join(current_directory, directory_name), exist_ok=True)
print(os_path.join(current_directory, directory_name))
with tempfile.TemporaryDirectory() as tmp_path:
res = requests_get(url, stream=True)
file_size = int(res.headers.get('content-length', 0))
pbar = tqdm(total=file_size, unit="B", unit_scale=True)
total_chunk = 0
with open(os_path.join(tmp_path, filename), 'wb') as file:
for chunk in res.iter_content(chunk_size=1024*5):
file.write(chunk)
pbar.update(len(chunk))
if isinstance(func, Callable):
total_chunk += len(chunk)
func(total_chunk/file_size)
pbar.close()
with ZipFile(os_path.join(tmp_path, filename)) as zf:
zf.extractall(os_path.join(current_directory, directory_name))
except Exception as e:
print("error:downloadCTranslate2Weight()", e)

View File

@@ -8,3 +8,6 @@ pyyaml == 6.0.1
python-i18n == 0.3.9
CTkToolTip == 0.8
pyinstaller==6.2.0
transformers[torch]
sentencepiece==0.1.99
ctranslate2==3.21.0

View File

@@ -1,4 +1,4 @@
from customtkinter import CTkImage, CTkLabel, CTkToplevel
from customtkinter import CTkImage, CTkLabel, CTkToplevel, CTkProgressBar
from ..ui_utils import openImageKeepAspectRatio, getImageFileFromUiUtils, setGeometryToCenterOfScreen, fadeInAnimation
class SplashWindow(CTkToplevel):
@@ -10,6 +10,7 @@ class SplashWindow(CTkToplevel):
self.title("SplashWindow")
self.wm_attributes("-toolwindow", True)
self.is_showed_progressbar = False
sw=self.winfo_screenwidth()
@@ -28,6 +29,37 @@ class SplashWindow(CTkToplevel):
label.grid(row=1, column=1, padx=int(desired_width/7), pady=int(height/3))
self.progressbar_widget = CTkProgressBar(
self,
height=10,
corner_radius=0,
fg_color="#4b4c4f",
progress_color="#48a495",
)
self.progressbar_widget.set(0)
(img, desired_width, height) = openImageKeepAspectRatio(getImageFileFromUiUtils("VRCT_now_downloading.png"), 320)
self.text_label = CTkLabel(
self,
text=None,
height=0,
fg_color="#292a2d",
image=CTkImage(img, size=(desired_width, height))
)
def updateDownloadProgress(self, progress:float):
if self.is_showed_progressbar is False:
self.progressbar_widget.place(relwidth=0.9, relx=0.5, rely=0.9, anchor="s")
self.text_label.place(relx=0.98, rely=0.98, anchor="se")
self.is_showed_progressbar = True
self.progressbar_widget.set(progress)
self.update_idletasks()
def showSplash(self):
self.attributes("-alpha", 0)
self.deiconify()