Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion plugins/utilities.json
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@
}
],
"versions": {
"1.1.4": null,
"1.1.3": {
"api_version": 9,
"commit_sha": "23f90dc",
Expand Down Expand Up @@ -2585,4 +2586,4 @@
}
}
}
}
}
261 changes: 198 additions & 63 deletions plugins/utilities/translate.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,59 +9,159 @@
import bauiv1 as bui
from bauiv1lib.popup import PopupMenu
import bauiv1lib.party
import urllib
import urllib.parse
import urllib.request
import threading
import random

show_translate_result = True
config = babase.app.config
default_config = {'O Source Trans Lang': 'Auto Detect', 'O Target Trans Lang': babase.app.locale.default_locale,
'Y Source Trans Lang': 'Auto Detect', 'Y Target Trans Lang': babase.app.locale.default_locale}

for key in default_config:
if not key in config:
config[key] = default_config[key]

translate_languages = {'Auto Detect': 'auto', 'Arabic': 'ar', 'Chinese (simplified)': 'zh-CN', 'Chinese (traditional)': 'zh-TW', 'Croatian': 'hr', 'Czech': 'cs',
'Danish': 'da', 'Dutch': 'nl', 'English': 'en', 'Esperanto': 'eo',
'Finnish': 'fi',
'Tagalog': 'tl', 'French': 'fr', 'German': 'de', 'Greek': 'el',
'Hindi': 'hi', 'Hungarian': 'hu', 'Indonesian': 'id', 'Italian': 'it',
'Japanese': 'ja',
'Korean': 'ko', 'Malay': 'ms', 'Malayalam': 'ml', 'Marathi': 'mr', 'Persian': 'fa', 'Polish': 'pl',
'Portuguese': 'pt', 'Romanian': 'ro', 'Russian': 'ru', 'Serbian': 'sr',
'Slovak': 'sk', 'Spanish': 'es', 'Swedish': 'sv', 'Tamil': 'ta',
'Telugu': 'te',
'Thai': 'th', 'Turkish': 'tr', 'Ukrainian': 'uk', 'Vietnamese': 'vi'}
available_translate_languages = []
for lang in translate_languages:
available_translate_languages.append(lang)

# Convert Ballistica Locale -> this mod's language name.
def get_default_translate_language():
locale = babase.app.locale.default_locale

# Ballistica 1.7.40 Locale objects have a .value such as 'eng'.
locale_value = getattr(locale, 'value', str(locale))

locale_map = {
'eng': 'English',
'ara': 'Arabic',
'zho': 'Chinese (simplified)',
'hrv': 'Croatian',
'ces': 'Czech',
'dan': 'Danish',
'nld': 'Dutch',
'fin': 'Finnish',
'fra': 'French',
'deu': 'German',
'ell': 'Greek',
'hin': 'Hindi',
'hun': 'Hungarian',
'ind': 'Indonesian',
'ita': 'Italian',
'jpn': 'Japanese',
'kor': 'Korean',
'msa': 'Malay',
'mal': 'Malayalam',
'mar': 'Marathi',
'fas': 'Persian',
'pol': 'Polish',
'por': 'Portuguese',
'ron': 'Romanian',
'rus': 'Russian',
'srp': 'Serbian',
'slk': 'Slovak',
'spa': 'Spanish',
'swe': 'Swedish',
'tam': 'Tamil',
'tel': 'Telugu',
'tha': 'Thai',
'tur': 'Turkish',
'ukr': 'Ukrainian',
'vie': 'Vietnamese',
'tgl': 'Tagalog',
}

return locale_map.get(locale_value, 'English')


default_language = get_default_translate_language()

default_config = {
'O Source Trans Lang': 'Auto Detect',
'O Target Trans Lang': default_language,
'Y Source Trans Lang': 'Auto Detect',
'Y Target Trans Lang': default_language,
}

for key, value in default_config.items():
if key not in config:
config[key] = value

# Repair configs created with the old Locale-object behavior.
for key in ('O Target Trans Lang', 'Y Target Trans Lang'):
if not isinstance(config[key], str):
config[key] = default_language



# Language names -> Google Translate language codes.
translate_languages = {
'Auto Detect': 'auto',
'Arabic': 'ar',
'Chinese (simplified)': 'zh-CN',
'Chinese (traditional)': 'zh-TW',
'Croatian': 'hr',
'Czech': 'cs',
'Danish': 'da',
'Dutch': 'nl',
'English': 'en',
'Esperanto': 'eo',
'Finnish': 'fi',
'Tagalog': 'tl',
'French': 'fr',
'German': 'de',
'Greek': 'el',
'Hindi': 'hi',
'Hungarian': 'hu',
'Indonesian': 'id',
'Italian': 'it',
'Japanese': 'ja',
'Korean': 'ko',
'Malay': 'ms',
'Malayalam': 'ml',
'Marathi': 'mr',
'Persian': 'fa',
'Polish': 'pl',
'Portuguese': 'pt',
'Romanian': 'ro',
'Russian': 'ru',
'Serbian': 'sr',
'Slovak': 'sk',
'Spanish': 'es',
'Swedish': 'sv',
'Tamil': 'ta',
'Telugu': 'te',
'Thai': 'th',
'Turkish': 'tr',
'Ukrainian': 'uk',
'Vietnamese': 'vi',
}

available_translate_languages = list(translate_languages.keys())
available_translate_languages.sort()

available_translate_languages.remove('Auto Detect')
available_translate_languages.insert(0, 'Auto Detect')



def translate(text, _callback, source='auto', target='en'):
text = urllib.parse.quote(text)
url = f'https://translate.google.com/m?tl={target}&sl={source}&q={text}'
request = urllib.request.Request(url)
data = urllib.request.urlopen(request).read().decode('utf-8')
result = data[(data.find('"result-container">'))+len('"result-container">')
:data.find('</div><div class="links-container">')]
replace_list = [('&#39;', '\''), ('&quot;', '"'), ('&amp;', '&')]
for i in replace_list:
result = result.replace(i[0], i[1])
if show_translate_result:
bui.pushcall(bui.CallPartial(_callback, result), from_other_thread=True)
try:
text = urllib.parse.quote(text)
url = f'https://translate.google.com/m?tl={target}&sl={source}&q={text}'
request = urllib.request.Request(url)
data = urllib.request.urlopen(request).read().decode('utf-8')
result = data[(data.find('"result-container">'))+len('"result-container">')
:data.find('</div><div class="links-container">')]
replace_list = [('&#39;', '\''), ('&quot;', '"'), ('&amp;', '&')]
for i in replace_list:
result = result.replace(i[0], i[1])
if show_translate_result:
bui.pushcall(bui.CallPartial(_callback, result), from_other_thread=True)
except Exception:
print('Translation failed. Please connect to the internet.')


class NewPW(bauiv1lib.party.PartyWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._last_msg_clicked: str = None
self._last_time_pressed_msg: float = 0.0
self._last_time_pressed_translate: float = 0.0
self._double_press_interval: float = 0.3
self._last_msg_clicked = None
self._last_time_pressed_msg = 0.0
self._last_time_pressed_translate = 0.0
self._double_press_interval = 0.3
self._last_translate_widget = None
bui.buttonwidget(
parent=self._root_widget,
size=(50, 35),
Expand All @@ -74,22 +174,41 @@ def __init__(self, *args, **kwargs):

def _translate_your_chat(self):
global show_translate_result
if (babase.apptime() - self._last_time_pressed_translate < self._double_press_interval):

if (
babase.apptime() - self._last_time_pressed_translate
< self._double_press_interval
and self._last_translate_widget is self._text_field
):
show_translate_result = False
self._last_time_pressed_translate = 0.0
self._last_translate_widget = None
TranslateWindow()
return

show_translate_result = True
self._last_time_pressed_translate = babase.apptime()
self._last_translate_widget = self._text_field

text = str(bui.textwidget(query=self._text_field))

def _apply_translation(translated):
if self._text_field.exists():
bui.textwidget(edit=self._text_field, text=translated)
translated = threading.Thread(target=translate, args=(str(bui.textwidget(query=self._text_field)),
_apply_translation,
translate_languages[config['Y Source Trans Lang']],
translate_languages[config['Y Target Trans Lang']])).start()
bui.textwidget(
edit=self._text_field,
text=translated
)

threading.Thread(
target=translate,
args=(
text,
_apply_translation,
translate_languages[config['Y Source Trans Lang']],
translate_languages[config['Y Target Trans Lang']]
),
daemon=True
).start()

def _add_msg(self, msg: str):
txt = bui.textwidget(
Expand All @@ -113,35 +232,50 @@ def _add_msg(self, msg: str):
bui.containerwidget(edit=self._columnwidget, visible_child=txt)

bui.textwidget(edit=txt,
on_activate_call=bui.CallPartial(self._translate_other, msg),
on_activate_call=bui.CallPartial(self._translate_other, txt, msg),
click_activate=True)

def _translate_other(self, msg: str):
def _translate_other(self, txt, msg):
global show_translate_result
if (babase.apptime() - self._last_time_pressed_msg < self._double_press_interval) and (self._last_msg_clicked == msg):

if (
babase.apptime() - self._last_time_pressed_msg
< self._double_press_interval
and self._last_msg_clicked == txt
):
show_translate_result = False
self._last_time_pressed_msg = 0.0
self._copy_msg(msg)
return

show_translate_result = True
self._last_msg_clicked = msg
self._last_msg_clicked = txt
self._last_time_pressed_msg = babase.apptime()

nickname = ''
split_msg = msg

if len(msg.split(':')) > 1:
self._nickname = msg.split(':')[0]+': '
nickname = msg.split(':')[0] + ': '
split_msg = ':'.join(msg.split(':')[1:])[1:]

def _apply_translation(translated):
for i in self._chat_texts:
if bui.textwidget(query=i) == msg:
bui.textwidget(edit=i, text=self._nickname + translated)
break

self._translated_msg = threading.Thread(target=translate, args=(split_msg,
_apply_translation,
translate_languages[config['O Source Trans Lang']],
translate_languages[config['O Target Trans Lang']])).start()
if txt.exists():
bui.textwidget(
edit=txt,
text=nickname + translated
)

threading.Thread(
target=translate,
args=(
split_msg,
_apply_translation,
translate_languages[config['O Source Trans Lang']],
translate_languages[config['O Target Trans Lang']]
),
daemon=True
).start()


class TranslateWindow:
Expand Down Expand Up @@ -200,7 +334,7 @@ def __init__(self):
self.other_source_button = PopupMenu(parent=self._root_widget,
position=(54, 140),
autoselect=False,
on_value_change_call=babase.CallStrict(
on_value_change_call=babase.CallPartial(
self._set_translate_language, 'O Source Trans Lang'),
choices=available_translate_languages,
button_size=(150, 30),
Expand All @@ -209,7 +343,7 @@ def __init__(self):
self.other_target_button = PopupMenu(parent=self._root_widget,
position=(243, 140),
autoselect=False,
on_value_change_call=babase.CallStrict(
on_value_change_call=babase.CallPartial(
self._set_translate_language, 'O Target Trans Lang'),
choices=available_translate_languages[1:],
button_size=(150, 30),
Expand All @@ -218,7 +352,7 @@ def __init__(self):
self.your_source_button = PopupMenu(parent=self._root_widget,
position=(54, 55),
autoselect=False,
on_value_change_call=babase.CallStrict(
on_value_change_call=babase.CallPartial(
self._set_translate_language, 'Y Source Trans Lang'),
choices=available_translate_languages,
button_size=(150, 30),
Expand All @@ -227,14 +361,15 @@ def __init__(self):
self.your_target_button = PopupMenu(parent=self._root_widget,
position=(243, 55),
autoselect=False,
on_value_change_call=babase.CallStrict(
on_value_change_call=babase.CallPartial(
self._set_translate_language, 'Y Target Trans Lang'),
choices=available_translate_languages[1:],
button_size=(150, 30),
current_choice=config['Y Target Trans Lang'])

def _set_translate_language(self, lang, choice):
config[lang] = choice
config.commit()

def _back(self, sound=False):
self.other_source_button = None
Expand All @@ -256,4 +391,4 @@ def has_settings_ui(self):
return True

def show_settings_ui(self, source_widget):
TranslateWindow()
TranslateWindow()