はじめに
Googletrans APIを使ってGoogle翻訳簡易verを作ってみました。
実行環境
- Windows10
- Python3.8
- Eel 0.14.0
- Bootstrap4
- Vue.js 2.6.12
どうやらEelはPython3.9系未対応のようです。
こんな感じの完成物
Eelの使い方
簡単にPythonでGUI作れるんですね。
[[Python] EelをつかってHTML/CSS/JavaScriptでGUIを構築][1]
[1]:https://qiita.com/inoory/items/f431c581332c8d500a3b
Googletransでお手軽Google翻訳
とりあえず実行。
[Python – googletransを試してみました。][2]
[2]:https://dev.classmethod.jp/articles/python-py-googletrans/
が、下記エラーが出ます。
AttributeError: 'NoneType' object has no attribute 'group'
上手くいったりいかなかったりという謎エラーなようです。
以下を参考にさせていただいてクリア。
[【python】googletransの『AttributeError: 'NoneType' object has no attribute 'group'』対策【2020/12/02追記】][3]
[3]:https://qiita.com/_yushuu/items/83c51e29771530646659
from googletrans import Translator
class MyTranslator:
@staticmethod
def translate(org_text,src_lang,dest_lang):
tr = Translator(service_urls=['translate.googleapis.com'])
# エラーが出る時と出ない時があるので、
# 成功するまでインスタンスを作り直してから再度実行
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
BootstrapできれいめGUIにする
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ぷち翻訳</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
</head>
<body>
<div class="container p-5" id="app">
<!-- 日英or英日切り替えラジオボタン -->
<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="翻訳" checked>
<label class="custom-control-label" for="custom-radio-1">
日本語 → 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 → 英語
</label>
</div>
</div>
</form>
<!-- 翻訳ボタン -->
<button id="translate-btn" class="btn btn-primary btn-block mb-2" type="button">
{{trans_str}}
</button>
<!-- ユーザー入力 -->
<div class="form-group mb-2">
<textarea class="form-control" id="input" rows="3" placeholder="Please input..."></textarea>
</div>
<!-- 翻訳結果 -->
<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>
<!-- 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>
ついでにVue.jsデビュー
日英、英日のラジオボタンでの切り替えに合わせて、「翻訳ボタン」のラベルを変えます。
[Vue.jsでラジオボタンをデータバインディングする][4]
[4]:https://www.paveway.info/entry/2020/03/10/vue_vmodelradiobutton
// 翻訳関数をpythonから呼ぶ
async function translate(src, src_lang, dest_lang) {
let ret = await eel.translate(src, src_lang, dest_lang)();
return ret;
}
// 翻訳ボタンクリックイベント
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'
// 日英or英日 切り替え
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
});
}
})
// 翻訳ボタンの文字列をVueで操作
Vue.config.productionTip = false
var app = new Vue({
el: '#app',
data: {
trans_str: '翻訳'
}
})
Pythonから実行する
@eel.expose
を付けた関数がJavascriptから呼びだされます。
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()
[Eel]起動時のオプション設定
# -*- coding: utf-8 -*-
import eel
import sys
import socket
# 定数
# ENTRY_POINT = 'index.html'
CHROME_ARGS = [
'--incognit', # シークレットモード
'--disable-http-cache', # キャッシュ無効
'--disable-plugins', # プラグイン無効
'--disable-extensions', # 拡張機能無効
'--disable-dev-tools', # デベロッパーツールを無効にする
]
ALLOW_EXTENSIONS = ['.html', '.css', '.js', '.ico']
def start(start_dir, start_page, size):
# 画面生成
eel.init(start_dir, allowed_extensions=ALLOW_EXTENSIONS)
# 未使用ポート取得
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): # 終了時の処理
sys.exit(0)