見出し画像

TkEasyGUIでクリップボード監視リアルタイム翻訳ツールを作る

Pythonで最も簡単にGUIアプリが作れる`TkEasyGUI`を使って、以下のようなクリップボード監視型のリアルタイム翻訳ツールを作ってみます。

クリップボード監視してリアルタイムに翻訳してくれるツールを作った

前回紹介した、完全ローカル翻訳できる`Argos Translate`を使って、クリップボードが書き換わると自動で翻訳するツールをPythonで作ってみました。

必要となるPythonパッケージのインストール

GUIアプリのために、`TkEasyGUI。ローカル翻訳のために、`argostranslate`をインストールします。ターミナル(WindowsならPowerShell、macOSならターミナル.app)を起動して、次のコマンドを実行しましょう。

python -m pip install TkEasyGUI argostranslate

次に、Argos Translateの日英翻訳、英日翻訳のモデルをダウンロードします。

argospm install translate-ja_en
argospm install translate-en_ja

クリップボード監視ツールを作る

そして、さっそく監視ツールを作ります。以下がクリップボードを監視して、逐次ローカル翻訳する機能を実装したツールのプログラムです。`translate_easy.py`などの名前で保存します。

import subprocess
from queue import Queue
from threading import Thread

import TkEasyGUI as eg

# スレッドを使うので矛盾が起きないようキューを用意
ui_queue = Queue()

def main():
    # 開始時点のクリップボードを確認
    clip = eg.get_clipboard()
    # 画面レイアウトを作成
    layout = [
        [eg.Multiline("", key="input", enable_events=True, size=(60, 10))],
        [eg.Radio("英日翻訳", key="-ej-", default=True), eg.Radio("日英翻訳", key="-je-")],
        [eg.Multiline("", key="output", readonly=True, size=(60, 10))],
    ]
    # ウィンドウを作成
    with eg.Window(
        "クリップボード監視して翻訳",
        layout,
        keep_on_top=True,
        resizable=True,
        ) as window:
        # イベントループ
        for event, values in window.event_iter(timeout=100, timeout_key="-timeout-"):
            # 手動で書き換わったら翻訳実行
            if event == "input":
                translate(window)
                continue
            if event == "-timeout-":
                # check ui_queue
                if not ui_queue.empty():
                    window["output"].update(ui_queue.get())
                    continue
                # クリップボードが書き換わったか?
                clip_new = eg.get_clipboard()
                if clip_new == clip:
                    continue
                clip = clip_new
                window["input"].update(clip)
                translate(window)

# 翻訳実行(スレッドを起動)
def translate(win):
    ej = win["-ej-"].get()
    in_str = win["input"].get_text()
    Thread(target=translate_job, args=(in_str, ej)).start()

def translate_job(in_str: str, ej:bool):
    if ej:
        cmd = ["argos-translate", "--from", "en", "--to", "ja", in_str]
    else:
        cmd = ["argos-translate", "--from", "ja", "--to", "en", in_str]
    try:
        res = subprocess.run(cmd, capture_output=True, encoding="utf-8")
        result = res.stdout
        ui_queue.put(result)
    except Exception as e:
        print(e)

if __name__ == "__main__":
    main()

プログラムを実行するには、以下のコマンドを実行します。

python translate_easy.py

プログラムのポイント

このプログラムのポイントは以下の部分です。以下は、ウィンドウにMultiline(複数行入力ボックス)を二つとRadio(ラジオボタン)を二つ作成するものです。

〜抜粋〜
layout = [
    [eg.Multiline("", key="input", enable_events=True, size=(60, 10))],
    [eg.Radio("英日翻訳", key="-ej-", default=True), eg.Radio("日英翻訳", key="-je-")],
    [eg.Multiline("", key="output", readonly=True, size=(60, 10))],
]
# ウィンドウを作成
with eg.Window(
    "クリップボード監視して翻訳",
    layout,
    keep_on_top=True,
    resizable=True,
    ) as window:
    # イベントループ
    for event, values in window.event_iter(timeout=100, timeout_key="-timeout-"):
〜抜粋〜

クリップボード監視翻訳ツールの使い勝手をよくするために、ウィンドウを常に最前面に表示するために、keep_on_top=Trueを指定しているのもポイントです。

また、長文を与えると、Argos Translateからの応答が遅い時があるので、下記のように、スレッドを利用して、実行が終わった時点で、実行結果を更新するようにしています。

# 翻訳実行(スレッドを起動)
def translate(win):
    ej = win["-ej-"].get()
    in_str = win["input"].get_text()
    Thread(target=translate_job, args=(in_str, ej)).start()

# スレッドでArgos Translateを実行
def translate_job(in_str: str, ej:bool):
    if ej:
        cmd = ["argos-translate", "--from", "en", "--to", "ja", in_str]
    else:
        cmd = ["argos-translate", "--from", "ja", "--to", "en", in_str]
    try:
        res = subprocess.run(cmd, capture_output=True, encoding="utf-8")
        result = res.stdout
        ui_queue.put(result)
    except Exception as e:
        print(e)

# まとめ

わずか60行ちょっとのプログラムで、翻訳ツールが作れてしまうのですから、良い時代になりました。

実際、使い込んでいくと、Argos Translateの翻訳がかなり適当な時があるのですが、知らない単語の周辺を翻訳するようにして、なるだけ原文を読む習慣をつける練習になるのかもしれません。あるいは、翻訳機能の部分をオンライン翻訳のAPIに置き換えるなどすると、より実用的になるかもです。

参考にしてみてください!

この記事が気に入ったらサポートをしてみませんか?