[GO] [Automatic translation] English input support tool Translate-chan [Python]

English is weak, so English ...

Hello. It's wonderful to say that I studied English because my English is weak. In my case, "I'm weak in English, so I thought of a way to escape from English." That's why I made it. (Abrupt) ** For those who want to "copy the source code quickly!" Or who are looking for a technical story [It's about time for a technical story](https://qiita.com/branch/items/5f5cf4be81980074431b#%E3 % 81% 9D% E3% 82% 8D% E3% 81% 9D% E3% 82% 8D% E6% 8A% 80% E8% A1% 93% E7% 9A% 84% E3% 81% AA% E8% A9 Please go to% B1)! ** ** ** If you are in a hurry, if you have win10 (64bit), please see below [Appendix: Simple installer (.bat)](https://qiita.com/branch/items/5f5cf4be81980074431b#%E4%BB%98% E9% 8C% B2win10-64bit% E7% 94% A8% E7% B0% A1% E6% 98% 93% E3% 82% A4% E3% 83% B3% E3% 82% B9% E3% 83% 88% If you use E3% 83% BC% E3% 83% A9), you can install it in about 10 minutes. ** **

As a prerequisite, Python 3.X must be installed, so refer to Download and install Python 3.7.3 --Lets programming. Please try to introduce it to. Of course, it doesn't have to be 3.7.3. It doesn't have to be the latest version.

If you put the background first

I communicate with overseas business partners in English. In other words, there are relatively many opportunities to communicate in English, not just email, but what if you ask a man who cannot speak English to communicate in English? Yes, you have to rely on Google Translate. You will be able to do this kind of thing.

1.Think about the content in Japanese
2.Throw to Google Translate
3.Get English
4.Retranslate the English text you got on Google
5.Examine the retranslated Japanese
→ If there is a discrepancy between the original text and the meaning, return to 1 and rework the text if necessary.

** Isn't this impossible! ?? ** ** It's really annoying. No, I'm talking about becoming able to speak English. If you are not good at English, you have no choice but to do this work. Isn't it especially true for people in their 40s and 50s who suddenly have to use English?

Perhaps because it takes time, the overtime hours of the department are supposed to be doerai, so I made it.

Next, I will introduce Kas,

If you start this translation with the input Japanese copied to the clipboard, it will be divided into sentences by "." ~~ At the end of the sentence and translated. ** Updated 8/3: Changed delimiter to line break. ** When the translation is complete, you can press the button and copy the translated English to the clipboard. Below is a screenshot of the manual and trial presets at initial startup. カス

** It looks completely dregs. ** Especially the bottom three buttons are terrible. I could only do something like this because I didn't have enough technical skills, I designed the GUI with wxpython for the first time, so Please forgive me Sai,

It's about technical talk

Thank you for staying with us so far. Below, I will introduce the code for introduction while showing the environment.

Prerequisite environment

win10 64bit ** python3.8.4 ** Assuming that python's PATH is in place Only this. If you are using win10 32bit version, please read it well and proceed with the introduction.

Install a browser called Chromium in this environment and install a package to handle it.

Installation of required packages for python

Start the command prompt and hit the following command.

pip install chromedriver_binary==84.0.4147.30.0
pip install wxpython
pip install pyperclip
pip install selenium
pip install beautifulsoup4

I think it will end unexpectedly soon.

Install Chromium

[Official website for Chromium for Win10 64bit](https://www.googleapis.com/download/storage/v1/b/chromium-browser-snapshots/o/Win_x64%2F768952%2Fchrome-win.zip?generation=1589490546798193&alt= Please download from media) and unzip it. Probably a folder called chrome-win will be created, so please move it directly under C: \ Program Files. If you can move it, Chromium is ready. If you are not Win10 64bit and want to download from the official repository, please make sure that the version of Chromium is 84.0.4147.0. Strictly speaking, the major version should be 84, but I haven't confirmed the operation, so ...

What is Chromium?

It is an open source web browser and is the base of Google Chrome as you can see from the icon below. Besides that, as of July 2020, Opera and Microsoft Edge are also being developed based on Chromium. chromium_logo

-Wikipwdia The name of the Chromium project comes from the metallic element chromium (chromium in English), which is known to be used for plating iron and the like. Since the chrome-plated metal is called chrome in English, it came to this name in the sense of "things used to make (Google) Chrome".

However, in the range of everyday use, it feels almost like Google Chrome, and you can use Chromium without thinking deeply (at least for me).

Benefits of using Chromium

This time, the browser to be controlled was Chromium instead of Google Chrome in the following three points.

  1. Google Chrome has automatic updates
  2. There are few people who operate it in the main
  3. Still, it can be operated with the same usability as Google Chrome

First of all, regarding 1, it is inconvenient not only for browsers but also for apps that do not have automatic updates due to various restrictions including security problems. However, in this application, it is rather advantageous because it is necessary to match the major version of the driver and the application. Furthermore, this time it starts in headless mode, but in this case the user tends to recognize it as "just a background application", so Chromium does not intentionally connect to the web. In other words, there is almost no security concern (of course, it is not zero).

Regarding 2, this translation-chan was originally supposed to be deployed within the department, so there was a possibility that "inconvenience would occur if the browser you normally use is controlled". I'm not very good at browsers, so I wanted to avoid IE, MS Edge, Google Chrome, FireFox, Opera, Sleipnir just in case.

Regarding ** 3, honestly, this is the biggest developer. ** Because it works with the same driver as Google Chrome, it was easy to develop it with Google Chrome, implement it with Chromium → test it in a situation close to the production environment. It goes up.

That's why Chromium was so convenient.

Translation-chan

It is finally the source code of the main body. Translate the Chromium installed above with control from Selenium.

import wx
import wx.lib.scrolledpanel
import pyperclip
import time
import urllib.parse
import chromedriver_binary
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
from time import sleep


class Translator:       #Class that defines translation by selenium
    def __init__(self):
        self.options = Options()
        self.options.binary_location =  "C:\\Program Files\\chrome-win\\chrome.exe"
        self.options.add_argument("--headless")          #Start in headless mode
        self.browser = webdriver.Chrome(options=self.options)
        #self.browser.minimize_window()                   #Minimize if proxy is enabled
        self.browser.implicitly_wait(2)

    def trans(self, txt , lg1 , lg2):      #Function to translate from lg1 to lg2
        if txt == "":                      #Returns empty if input is empty
            return txt
        #Access after embedding the sentence you want to translate in the URL
        text_for_url = urllib.parse.quote_plus(txt, safe='')
        url = "https://translate.google.co.jp/#{1}/{2}/{0}".format(text_for_url , lg1 , lg2)
        self.browser.get(url)

        #wait a bit
        wait_time = len(txt) / 1000
        if wait_time < 0.5:
            wait_time = 0.5
        time.sleep(wait_time)

        #Extract translation results
        soup = BeautifulSoup(self.browser.page_source, "html.parser")
        ret =  soup.find(class_="tlid-translation translation")

        return ret.text    

    def quit(self):
        self.browser.quit()


def main():
    #Get the contents of the clipboard
    orig = str(pyperclip.paste())

    #Detects line breaks and splits. At this time, line feed information"\r\n"Will be lost
    orignal_elements = orig.splitlines()
    print(orignal_elements)

    #Variable that stores the character string related to translation
    origs = []
    en_txt = []
    jp_txt = []

    #Global variable to get a blank line
    global blank_row
    blank_row = []
    count = 0
    while count < len(orignal_elements):
        buf = orignal_elements[count]           #"   "Eliminate blank-only elements like
        buf = buf.replace(" " , "")             #Since it is not possible to correspond to a foreign language simply by erasing the space, take the difference
        if buf != "":                           #If it is not blank, add it to the translation target
            origs.append(orignal_elements[count])
        else:
            blank_row.append(count)             #If it is blank, it was originally a blank line, so get the location of the element with an int.
        count += 1
    
    #Set 2 languages to translate[Native language,Foreign language]We plan to build it so that the language can be selected from the pull-down menu in the future.
    global lg
    lg = ["ja" , "en"]

    #Set two languages for reverse translation[Foreign language,Japanese]
    global rev_lg
    rev_lg = list(reversed(lg))

    #GUI preparation
    app = wx.App()

    #Display during loading
    read_frame = wx.Frame(None, wx.ID_ANY, "In translation...", size=(250,0))
    read_frame.Centre() #Displayed in the center
    read_frame.Show()

    global rows
    rows = len(origs)           #Note the number of lines because len contains 0

    for row in range(rows):     #Translate first based on the original text
        #Original
        txt = origs[row]
        #print("Original:",txt)

        #English
        en_txt.append(translator.trans(origs[row], *lg))
        #print("English:",en_txt)

        #Retranslation
        jp_txt.append(translator.trans(en_txt[row], *rev_lg))

    size = (900,600)
    global frame
    frame = wx.Frame(None, wx.ID_ANY, 'Translation-chan', size=size)
    panel = wx.lib.scrolledpanel.ScrolledPanel(frame,-1, size=size, pos=(0,28), style=wx.SIMPLE_BORDER)
    panel.SetupScrolling()
    panel.SetBackgroundColour('#AFAFAF')

    global text
    global en_text
    global jp_text
    global btn
    layout = wx.FlexGridSizer(rows+1,4,0,0)

    text = [""]*rows            #Source text widget preparation
    en_text = [""]*rows         #Preparation of English text widget
    jp_text = [""]*rows         #Retranslation Text Widget Preparation
    btn = [""]*rows             #Translation button widget preparation

    cellsize = (270,90)
    for row in range(rows):
        #Original
        txt = origs[row]
        text[row] = wx.TextCtrl(panel, row , txt, style = wx.TE_MULTILINE,size=cellsize)
        #print("Original:",txt)

        #English
        en_text[row] = wx.TextCtrl(panel, row , en_txt[row], style = wx.TE_MULTILINE,size=cellsize)
        en_text[row].Disable()      #Write-protected
        #print("English:",en_txt)

        #Retranslation
        jp_text[row] = wx.TextCtrl(panel, row , jp_txt[row], style = wx.TE_MULTILINE,size=cellsize)
        jp_text[row].Disable()      #Write-protected
        #print("Retranslation:",jp_txt)

        #Translate button
        btn[row] = wx.Button(panel, row, "translation", size=(60, 40))
        btn[row].Bind(wx.EVT_BUTTON, OnClickBtn)            #Bind button to event


        #Widget placement
        #layout.Add(text[row], flag=wx.ALIGN_LEFT | wx.GROW)         #Original
        layout.Add(text[row], flag=wx.SHAPED)         #Original
        layout.Add(jp_text[row], flag=wx.SHAPED)      #Retranslation
        layout.Add(en_text[row], flag=wx.SHAPED)      #English
        layout.Add(btn[row],flag=wx.SHAPED | 
            wx.ALIGN_CENTER_VERTICAL | wx.TE_MULTILINE)             #Translate button
    
    copy_btn = wx.Button(panel, wx.ID_ANY, "Translation completed", size=(80, 40))
    copy_btn.Bind(wx.EVT_BUTTON, OnClickCopyBtn)
    layout.Add(copy_btn,flag=wx.SHAPED | 
        wx.ALIGN_CENTER_VERTICAL | wx.TE_MULTILINE)

    retrans_btn = wx.Button(panel, wx.ID_ANY, "Reset each cell and retranslate", size=(200, 40))
    retrans_btn.Bind(wx.EVT_BUTTON, OnClickRetransBtn)
    layout.Add(retrans_btn,flag=wx.SHAPED | 
        wx.ALIGN_CENTER_VERTICAL | wx.TE_MULTILINE)
    
    exit_btn = wx.Button(panel, wx.ID_ANY, "Finish translation", size=(120, 40))
    exit_btn.Bind(wx.EVT_BUTTON, OnClickExitBtn)
    layout.Add(exit_btn,flag=wx.SHAPED | 
        wx.ALIGN_CENTER_VERTICAL | wx.TE_MULTILINE)

    #Button placement
    layout.AddGrowableCol(0, 3)
    layout.AddGrowableCol(1, 3)
    layout.AddGrowableCol(2, 3)
    layout.AddGrowableCol(3, 1)

    #Layout update
    panel.SetSizer(layout)

    #Define status bar
    frame.CreateStatusBar()
    frame.SetStatusText("Please observe the confidentiality obligation before using the online service.")
    
    read_frame.Close()
    frame.Centre() #Displayed in the center
    frame.Show()
    app.MainLoop()


def OnClickBtn(event):
    num = event.GetId()

    btn[num].Disable()
    
    n_txt = text[num].GetValue()
    n_en_txt = translator.trans(n_txt, *lg)
    n_jp_txt = translator.trans(n_en_txt, *rev_lg)
    
    en_text[num].SetValue(n_en_txt)
    jp_text[num].SetValue(n_jp_txt)

    btn[num].Enable()

def copy_all():         #Function to copy the English sentence of the translation result to the clipboard

    fin_txt = ""        #String to copy to clipboard
    fin_txts = []       #A character string that stores the translated English text for each cell

    for row in range(rows):
        fin_txts.append(en_text[row].GetValue()+"\r\n")     #Restore lost line feed information with splitlines method

    for blank in blank_row:
        fin_txts.insert(blank,"\r\n")                       #Blank line location is blank_Since it is stored in row, add a blank row

    for element in fin_txts:
        fin_txt += element                                  #Since the line feed information has been restored, it is combined as an output character string.

    return fin_txt

def OnClickCopyBtn(event):          #When the [Translation complete] button is pressed
    pyperclip.copy(copy_all())

def OnClickRetransBtn(event):       #When the [Reset each cell and retranslate] button is pressed
    frame.Close()
    main()

def OnClickExitBtn(event):          #When the [End Translation] button is pressed
    pyperclip.copy(copy_all())
    frame.Close()
    translator.quit()


if __name__ == "__main__":
    translator=Translator()
main()

Save this as a python script file (.py) with an appropriate name. If you right-click and execute this, Translation will start. Try starting with a copy of the appropriate Japanese on the clipboard.

Regarding Selenium [Python] Selenium usage memo (@ motoki1990) Complete automatic operation of Chrome with Python + Selenium (@ mekakura),

Regarding how to use wxpthon Try using wxPython (@ Kenta-Han),

Regarding automatic translation Automating Google Translate with Selenium --Haruko Ameyomi,

I referred to each. It's just a combination and arrangement, but since it's a code created by rush work, I feel that it's structurally strange in various ways. Especially the structure around the main function is suspicious. Isn't it suspicious? Originally it was made into main in plain text, so there are some parts that have been made global in a hurry so that it works. The strange part around here is because I am still a beginner, so I am waiting for a professor from an expert.

Also, for the wonderful person who makes this translation heavy use, I will tell you that it is possible to start it with a hot key (shortcut key). Please try to create it referring to here. You don't need to install anything new in this regard. Create a shortcut for Python program (Windows10)-@ Odanny

In future updates, we plan to support not only English but also other languages, so we will continue learning so that it can be handled with one function.

Appendix: Simple installer for win10 64bit

Finally, I would like to introduce a simple installer. ** Be sure to execute with administrator privileges **


@echo off
Check rem character encoding
chcp 65001
setlocal

start https://www.googleapis.com/download/storage/v1/b/chromium-browser-snapshots/o/Win_x64%%2F768952%%2Fchrome-win.zip?generation=1589490546798193^&alt=media
When echo DL is complete[Enter]Please press key&& pause
Powershell -command "Expand-Archive -Path $env:USERPROFILE\Downloads\Win_x64_768952_chrome-win.zip -DestinationPath C:\Program` Files"
del %USERPROFILE%\Downloads\Win_x64_768952_chrome-win.zip

py -m pip install chromedriver_binary==84.0.4147.30.0
py -m pip install wxpython
py -m pip install pyperclip
py -m pip install selenium
py -m pip install beautifulsoup4

endlocal
exit

Save this as a batch file (.bat) and execute it with ** administrator privileges. ** **

Translation-chan's outlook

This translation has a lot of lack of functions. For now, we are planning to implement the following functions.

  1. GUI / UX sophistication 1-1. Resize function of each cell 1-2. Add cell button 1-3. Displayed sequentially from translated cells
  2. Select a language in the combo box ~~ 3. Set the delimiter to [. ] To [. (Full-width period)] [? ] Etc. ~~ → 7/29: Improved to support the retention of line feed information.
  3. Wordbook with dictionary function (corresponds to industry terms and in-house terms) Example: Confidental
  4. Resident mode
  5. Word conversion function

List of references

This is a very helpful article that I have visited many times. We would like to take this opportunity to thank you. Also, if there is a problem with this article, I will delete it immediately.

[Python] Selenium usage memo-@ motoki1990 ・ Complete automatic operation of Chrome with Python + Selenium-@ mekakura ・ Try using wxPython-@ Kenta-Han ・ Automating Google Translate with Selenium --Haruko Ameyomi -Create a shortcut for Python program (Windows10)-@ Odanny

It's okay if you copy it, so I hope various people will be interested in Python.

update information

7/29 Update source code ・ Speeding up operation -Supports retention of line feed information → Change the delimiter accordingly (punctuation → line break) It has been reflected in the source code. Since I changed the specifications, I updated the image of Translate-chan (an image like a dreg).

Recommended Posts

[Automatic translation] English input support tool Translate-chan [Python]
[Python] Simple Japanese ⇒ I tried to make an English translation tool
English word spell check tool (made by python)
[Python] Standard input