I made a Google Translate simple ver using the Googletrans API.
Execution environment
Apparently Eel does not support Python 3.9 series.
You can easily create a GUI with Python. [[Python] Build GUI with HTML/CSS/JavaScript using Eel] [1] [1]:https://qiita.com/inoory/items/f431c581332c8d500a3b
Execute for the time being. [Python – I tried googletrans. ] [2] [2]:https://dev.classmethod.jp/articles/python-py-googletrans/
However, I get the following error.
AttributeError: 'NoneType' object has no attribute 'group'
It seems to be a mysterious error that it works or does not work.
Clear by referring to the following. [[Python] Countermeasures for "AttributeError:'NoneType' object has no attribute'group'" of googletrans [2020/12/02 postscript]] [3] [3]:https://qiita.com/_yushuu/items/83c51e29771530646659
translate.py
from googletrans import Translator
class MyTranslator:
@staticmethod
def translate(org_text,src_lang,dest_lang):
tr = Translator(service_urls=['translate.googleapis.com'])
#There are times when an error occurs and times when it does not, so
#Recreate the instance until it succeeds and then run it again
i = 0
while i < 10:
try:
return tr.translate(org_text, src=src_lang, dest=dest_lang).text
except Exception as e:
tr = Translator(service_urls=['translate.googleapis.com'])
i+=1
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Petit translation</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
</head>
<body>
<div class="container p-5" id="app">
<!--Japanese-English or English-Japanese switching radio button-->
<form>
<div class="form-group">
<div class="custom-control custom-radio">
<input type="radio" name="lang_radio" class="custom-control-input" id="custom-radio-1"
v-model="trans_str" value="translation" checked>
<label class="custom-control-label" for="custom-radio-1">
Japanese → English
</label>
</div>
<div class="custom-control custom-radio">
<input type="radio" name="lang_radio" class="custom-control-input" id="custom-radio-2"
v-model="trans_str" value="Translate">
<label class="custom-control-label" for="custom-radio-2">
English → English
</label>
</div>
</div>
</form>
<!--Translate button-->
<button id="translate-btn" class="btn btn-primary btn-block mb-2" type="button">
{{trans_str}}
</button>
<!--User input-->
<div class="form-group mb-2">
<textarea class="form-control" id="input" rows="3" placeholder="Please input..."></textarea>
</div>
<!--Translation result-->
<div class="form-group">
<textarea class="form-control" id="output" readonly rows="3"></textarea>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="vue.js"></script>
<!--Use eel-->
<script type="text/javascript" src="/eel.js"></script>
<script type="text/javascript" src="js/main.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</body>
</html>
Change the label of the "translation button" according to the switching between Japanese-English and English-Japanese radio buttons. [Data binding of radio buttons in Vue.js] [4] [4]:https://www.paveway.info/entry/2020/03/10/vue_vmodelradiobutton
main.js
//Call translation function from python
async function translate(src, src_lang, dest_lang) {
let ret = await eel.translate(src, src_lang, dest_lang)();
return ret;
}
//Translate button click event
var translate_btn = document.getElementById('translate-btn');
var lang_radio_btn = document.getElementById( "custom-radio-1" );
translate_btn.addEventListener('click', () => {
var src_lang = 'en'
var dest_lang = 'ja'
//Switching between Japanese-English or English-Japanese
if ( lang_radio_btn.checked ) {
var src_lang = 'ja'
var dest_lang = 'en'
}
let original = document.getElementById('input')
let translated = document.getElementById('output')
if (original.value) {
promise = translate(original.value, src_lang, dest_lang);
promise.then((ret) => {
translated.value = ret
});
}
})
//Manipulate the character string of the translation button with Vue
Vue.config.productionTip = false
var app = new Vue({
el: '#app',
data: {
trans_str: 'translation'
}
})
The function with @ eel.expose
is called from Javascript.
view.py
import eel
import desktop
import numpy as np
import pandas as pd
from translate import MyTranslator
@eel.expose
def translate(src, src_lang, dest_lang):
return MyTranslator.translate(src, src_lang, dest_lang)
def main():
start_dir="web"
end_point="index.html"
size=(600,400)
desktop.start(start_dir, end_point, size)
if __name__ == "__main__":
main()
desktop.py
# -*- coding: utf-8 -*-
import eel
import sys
import socket
#constant
# ENTRY_POINT = 'index.html'
CHROME_ARGS = [
'--incognit', #Secret mode
'--disable-http-cache', #Cache disabled
'--disable-plugins', #Plugin disabled
'--disable-extensions', #Extension disabled
'--disable-dev-tools', #Disable developer tools
]
ALLOW_EXTENSIONS = ['.html', '.css', '.js', '.ico']
def start(start_dir, start_page, size):
#Screen generation
eel.init(start_dir, allowed_extensions=ALLOW_EXTENSIONS)
#Get unused port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 0))
port = s.getsockname()[1]
s.close()
options = {
'mode': "chrome",
'close_callback': exit,
'port': port,
'cmdline_args': CHROME_ARGS
}
eel.start(start_page, options=options,
size=size, suppress_error=True)
def exit(arg1, arg2): #Processing at the end
sys.exit(0)
Recommended Posts