├── windows ├── requirements.txt ├── images │ ├── blue │ │ ├── settingsIcon.png │ │ ├── clipboardIcon.png │ │ ├── translateIcon.png │ │ └── translateMenuIcon.png │ └── dark │ │ ├── settingsIcon.png │ │ ├── clipboardIcon.png │ │ ├── translateIcon.png │ │ └── translateMenuIcon.png └── screentranslater.pyw ├── crossPlatform ├── requirements.txt ├── images │ ├── blue │ │ ├── clipboardIcon.png │ │ ├── settingsIcon.png │ │ ├── translateIcon.png │ │ └── translateMenuIcon.png │ └── dark │ │ ├── clipboardIcon.png │ │ ├── settingsIcon.png │ │ ├── translateIcon.png │ │ └── translateMenuIcon.png └── screentranslater.pyw ├── README.md └── LICENSE.md /windows/requirements.txt: -------------------------------------------------------------------------------- 1 | googletrans==3.1.0a0 2 | Pillow==9.1.1 3 | pyperclip==1.8.2 4 | -------------------------------------------------------------------------------- /crossPlatform/requirements.txt: -------------------------------------------------------------------------------- 1 | PyAutoGUI==0.9.53 2 | pytesseract==0.3.8 3 | googletrans==3.1.0a0 4 | Pillow==9.1.1 5 | pyperclip==1.8.2 6 | -------------------------------------------------------------------------------- /windows/images/blue/settingsIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaankarakoc42/tesseract-ocr-screen-translater/HEAD/windows/images/blue/settingsIcon.png -------------------------------------------------------------------------------- /windows/images/dark/settingsIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaankarakoc42/tesseract-ocr-screen-translater/HEAD/windows/images/dark/settingsIcon.png -------------------------------------------------------------------------------- /windows/images/blue/clipboardIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaankarakoc42/tesseract-ocr-screen-translater/HEAD/windows/images/blue/clipboardIcon.png -------------------------------------------------------------------------------- /windows/images/blue/translateIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaankarakoc42/tesseract-ocr-screen-translater/HEAD/windows/images/blue/translateIcon.png -------------------------------------------------------------------------------- /windows/images/dark/clipboardIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaankarakoc42/tesseract-ocr-screen-translater/HEAD/windows/images/dark/clipboardIcon.png -------------------------------------------------------------------------------- /windows/images/dark/translateIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaankarakoc42/tesseract-ocr-screen-translater/HEAD/windows/images/dark/translateIcon.png -------------------------------------------------------------------------------- /windows/images/blue/translateMenuIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaankarakoc42/tesseract-ocr-screen-translater/HEAD/windows/images/blue/translateMenuIcon.png -------------------------------------------------------------------------------- /windows/images/dark/translateMenuIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaankarakoc42/tesseract-ocr-screen-translater/HEAD/windows/images/dark/translateMenuIcon.png -------------------------------------------------------------------------------- /crossPlatform/images/blue/clipboardIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaankarakoc42/tesseract-ocr-screen-translater/HEAD/crossPlatform/images/blue/clipboardIcon.png -------------------------------------------------------------------------------- /crossPlatform/images/blue/settingsIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaankarakoc42/tesseract-ocr-screen-translater/HEAD/crossPlatform/images/blue/settingsIcon.png -------------------------------------------------------------------------------- /crossPlatform/images/blue/translateIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaankarakoc42/tesseract-ocr-screen-translater/HEAD/crossPlatform/images/blue/translateIcon.png -------------------------------------------------------------------------------- /crossPlatform/images/dark/clipboardIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaankarakoc42/tesseract-ocr-screen-translater/HEAD/crossPlatform/images/dark/clipboardIcon.png -------------------------------------------------------------------------------- /crossPlatform/images/dark/settingsIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaankarakoc42/tesseract-ocr-screen-translater/HEAD/crossPlatform/images/dark/settingsIcon.png -------------------------------------------------------------------------------- /crossPlatform/images/dark/translateIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaankarakoc42/tesseract-ocr-screen-translater/HEAD/crossPlatform/images/dark/translateIcon.png -------------------------------------------------------------------------------- /crossPlatform/images/blue/translateMenuIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaankarakoc42/tesseract-ocr-screen-translater/HEAD/crossPlatform/images/blue/translateMenuIcon.png -------------------------------------------------------------------------------- /crossPlatform/images/dark/translateMenuIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaankarakoc42/tesseract-ocr-screen-translater/HEAD/crossPlatform/images/dark/translateMenuIcon.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tesseract-ocr-screen-translater 2 | screen translater runs with tesseract-ocr and tkinter-gui 3 | 4 | # First install tesseract-orc 5 | https://github.com/UB-Mannheim/tesseract/wiki 6 | ## Windows 7 | | Architecture | download url| 8 | |--------------|---------------------------------------------------------------------------| 9 | |x86| https://digi.bib.uni-mannheim.de/tesseract/tesseract-ocr-w32-setup-v5.1.0.20220510.exe| 10 | |x64|https://digi.bib.uni-mannheim.de/tesseract/tesseract-ocr-w64-setup-v5.1.0.20220510.exe| 11 | 12 | 13 | ## Linux 14 | Debian,Ubuntu -> ```sudo apt install tesseract-ocr -y``` 15 | 16 | ## Execution 17 | ```pip install -r requirements.txt``` 18 | 19 | ```python ui.pyw``` 20 | 21 | # Shot screen and translate it 22 | ![a437df7d_AdobeExpress](https://user-images.githubusercontent.com/56826739/179417314-ebc1cfee-405b-419c-a74b-62a84cf98e3d.gif) 23 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Mevlüt kaan karakoç 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /crossPlatform/screentranslater.pyw: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from tkinter import messagebox 3 | import pyautogui,os,pytesseract 4 | from googletrans import Translator 5 | from PIL import Image,ImageTk 6 | from pyperclip import copy 7 | from glob import glob 8 | from threading import Thread 9 | 10 | translator = Translator() 11 | destination_language = "tr" 12 | def translate(sentence): 13 | return translator.translate(sentence,dest=destination_language) 14 | 15 | #creating window 16 | window=Tk() 17 | window.title('Screen Translater') 18 | window.attributes("-fullscreen", True) 19 | window.wm_attributes("-topmost", True) 20 | window.wm_attributes("-transparentcolor", "pink") 21 | window.config(bg='pink') 22 | 23 | screen_width = window.winfo_screenwidth() 24 | screen_height = window.winfo_screenheight() 25 | 26 | #check if somebody didnt read the md file 27 | windows_path = r"C:\Program Files\Tesseract-OCR\tesseract.exe" 28 | linux_path = r"/usr/share/tesseract-ocr/4.00/tessdata" 29 | if os.name == "nt": 30 | if os.path.exists(windows_path): 31 | pytesseract.pytesseract.tesseract_cmd =windows_path 32 | else: 33 | messagebox.showwarning("Exe not found","tesseract-ocr not found check github project page") 34 | 35 | else: 36 | if os.path.exists(linux_path): 37 | pytesseract.pytesseract.tesseract_cmd =linux_path 38 | else: 39 | messagebox.showwarning("Exe not found","tesseract-ocr not found check github project page (dude read the md file)") 40 | 41 | #colors 42 | blue="#2f84ea" 43 | dark = "#1c1d22" 44 | dbfe = "#84bbfc" 45 | dbfb = "#7ab4fa" 46 | theme = blue 47 | 48 | #uploading assets 49 | folder_path = os.path.abspath(os.getcwd()) 50 | def replaceColor(picture,datas=None): 51 | if datas==None: return picture 52 | oldHex,newHex=datas 53 | width, height = picture.size 54 | hexToRgb =lambda hex:tuple(int(hex.lstrip("#")[i:i+2], 16) for i in (0, 2, 4)) 55 | for x in range(width): 56 | for y in range(height): 57 | current_color = picture.getpixel( (x,y) ) 58 | if current_color == hexToRgb(oldHex): 59 | picture.putpixel( (x,y), hexToRgb(newHex)) 60 | return picture 61 | 62 | 63 | def Loader(assetFolder): 64 | files = glob(f"{assetFolder}/*") 65 | paths = {};[paths.update({i.split("\\")[-1].split(".")[0]:i}) for i in files] 66 | def loadAsset(paths,name,size=None,replaceColorHex=None): 67 | if size: 68 | replaceColor(Image.open(paths[name]),datas=replaceColorHex).resize(size).save(f"./images/dark/{name}.png") 69 | return ImageTk.PhotoImage(replaceColor(Image.open(paths[name]),datas=replaceColorHex).resize(size)) 70 | else: return ImageTk.PhotoImage(replaceColor(Image.open(paths[name]),datas=replaceColorHex)) 71 | return lambda name,size=None,replaceColorHex=None:loadAsset(paths,name,size,replaceColorHex) 72 | 73 | def setTheme(stheme): 74 | if stheme == "dark": 75 | theme = dark 76 | dbfe = "#373943" 77 | dbfb = "#5d6171" 78 | loader = Loader(f"{folder_path}/images/dark") 79 | elif stheme == "blue": 80 | loader = Loader(f"{folder_path}/images/blue") 81 | photo = loader("translateIcon",(22,22)) 82 | photo2 = loader("clipboardIcon",(22,22)) 83 | settingphoto = loader("settingsIcon",(35,35)) 84 | translatephoto = loader("translateMenuIcon",(35,35)) 85 | globals().update(locals()) 86 | 87 | setTheme("dark") 88 | 89 | languages = {'Afrikaans': 'af', 'Irish': 'ga', 'Albanian': 'sq', 'Italian': 'it', 'Arabic': 'ar', 'Japanese': 'ja', 'Azerbaijani': 'az', 'Kannada': 'kn', 'Basque': 'eu', 'Korean': 'ko', 'Bengali': 'bn', 'Latin': 'la', 'Belarusian': 'be', 'Latvian': 'lv', 'Bulgarian': 'bg', 'Lithuanian': 'lt', 'Catalan': 'ca', 'Macedonian': 'mk', 'Chinese Simplified': 'zh-CN', 'Malay': 'ms', 'Chinese Traditional': 'zh-TW', 'Maltese': 'mt', 'Croatian': 'hr', 'Norwegian': 'no', 'Czech': 'cs', 'Persian': 'fa', 'Danish': 'da', 'Polish': 'pl', 'Dutch': 'nl', 'Portuguese': 'pt', 'English': 'en', 'Romanian': 'ro', 'Esperanto': 'eo', 'Russian': 'ru', 'Estonian': 'et', 'Serbian': 'sr', 'Filipino': 'tl', 'Slovak': 'sk', 'Finnish': 'fi', 'Slovenian': 'sl', 'French': 'fr', 'Spanish': 'es', 'Galician': 'gl', 'Swahili': 'sw', 'Georgian': 'ka', 'Swedish': 'sv', 'German': 'de', 'Tamil': 'ta', 'Greek': 'el', 'Telugu': 'te', 'Gujarati': 'gu', 'Thai': 'th', 'Haitian Creole': 'ht', 'Turkish': 'tr', 'Hebrew': 'iw', 'Ukrainian': 'uk', 'Hindi':'hi', 'Urdu': 'ur', 'Hungarian': 'hu', 'Vietnamese': 'vi', 'Icelandic': 'is', 'Welsh': 'cy', 'Indonesian': 'id', 'Yiddish': 'yi'} 90 | tkvar = StringVar(window) 91 | options = [i for i in list(languages.keys())] 92 | rect = None 93 | startingPoint = () 94 | rectDrawingState = False 95 | coords = () 96 | 97 | def move(widget:Canvas): 98 | def e(e): 99 | x,y=pyautogui.position() 100 | widget.place(x=x-(widget.winfo_width()/2),y=y-(widget.winfo_height()/2)) 101 | widget.bind('',e) 102 | 103 | 104 | def create(widget,x,y): 105 | widget.place(x=x,y=y) 106 | return widget 107 | 108 | def defaultButtonFunctions(widget,buttonFunction): 109 | widget.bind("",lambda x:widget.configure(bg=dbfe)) 110 | widget.bind("",lambda x:widget.configure(bg=theme)) 111 | widget.bind("",lambda x:(widget.configure(bg=dbfb),buttonFunction(x))) 112 | 113 | def translatePopup(text,translation): 114 | canvas = create(Canvas(window,width=180,height=120,bg=theme,highlightthickness=2, highlightbackground="gray"),150,70) 115 | move(canvas) 116 | closeButton = create(Label(canvas,text=" X ",bg=theme,fg="white"),158,4) 117 | iconButton = create(Label(canvas,image = photo,bg=theme),8,2) 118 | copyButton = create(Label(canvas,image = photo2,bg=theme),132,3) 119 | textbox = create(Text(canvas, height = 5, width = 20),9.5,30) 120 | textbox.insert(END,translation) 121 | defaultButtonFunctions(iconButton,lambda x:(os.startfile(f"https://translate.google.com/?sl=auto&tl={destination_language}&text={text}&op=translate"))) 122 | defaultButtonFunctions(copyButton,lambda x:(copy(text))) 123 | defaultButtonFunctions(closeButton,lambda x:(canvas.destroy())) 124 | return canvas 125 | 126 | box = None 127 | def menuBar(): 128 | canvas = create(Canvas(window,width=40,height=190,bg=theme,highlightthickness=2, highlightbackground="gray"),10,screen_height/2+50) 129 | popup = Menu(window, tearoff=0) 130 | popup.add_command(label="Github",command=lambda :os.startfile("https://github.com/kaankarakoc42/translater")) 131 | def lang(): 132 | global box 133 | x,y = pyautogui.position() 134 | tkvar.set(destination_language) 135 | def setLang(value): 136 | global destination_language,box 137 | destination_language = languages[value] 138 | box.destroy() 139 | box = create(OptionMenu(window,tkvar,*options,command=lambda x:setLang(x)),x+5,y) 140 | 141 | popup.add_command(label="language",command=lambda :lang()) 142 | popup.add_separator() 143 | popup.add_command(label="Hide",command=lambda :(window.iconify())) 144 | def menu_popup(event): 145 | try: popup.tk_popup(event.x_root+50, event.y_root, 0) 146 | finally: popup.grab_release() 147 | settingsButton = create(Label(canvas,image = settingphoto,bg=theme),2,10) 148 | defaultButtonFunctions(settingsButton,lambda x:(menu_popup(x))) 149 | translateButton = create(Label(canvas,image = translatephoto,bg=theme),2,55) 150 | defaultButtonFunctions(translateButton,lambda x:(Thread(target=grabScreen).start())) 151 | closeButton = create(Label(canvas,width=4,text="Exit",bg=theme,fg="white"),4,160) 152 | defaultButtonFunctions(closeButton,lambda x:window.destroy()) 153 | move(canvas) 154 | 155 | 156 | def setStarting(canvas): 157 | global startingPoint,rectDrawingState,rect,coords; 158 | startingPoint = pyautogui.position() 159 | rectDrawingState = True 160 | if not rect: 161 | rect = canvas.create_rectangle(startingPoint[0], startingPoint[1],2,2, outline='red') 162 | 163 | def setEnding(canvas): 164 | global startingPoint,rectDrawingState,rect,coords; 165 | if not rectDrawingState: return 166 | x,y=pyautogui.position() 167 | canvas.coords(rect,startingPoint[0], startingPoint[1], x,y) 168 | coords = [int(i) for i in (startingPoint[0]+1,startingPoint[1]+1,x-startingPoint[0]-1,y-startingPoint[1]-1)] 169 | 170 | def drawingDone(canvas): 171 | global rectDrawingState,rect,coords; 172 | rectDrawingState = False 173 | canvas.delete(rect) 174 | canvas.destroy() 175 | rect = None 176 | 177 | def on_double_click_release(func): 178 | global rectDrawingState; 179 | if rectDrawingState: 180 | func() 181 | 182 | def on_release(canvas): 183 | drawingDone(canvas) 184 | window.attributes('-alpha', 1) 185 | window.config(cursor="arrow") 186 | window.update() 187 | text =pytesseract.image_to_string(pyautogui.screenshot(region=coords)) 188 | textTranslation = translate(text).text 189 | translatePopup(text,textTranslation) 190 | 191 | 192 | def grabScreen(): 193 | canvas = create(Canvas(window,width = screen_width,height=screen_height),0,0) 194 | window.config(cursor="tcross") 195 | window.attributes('-alpha', 0.3) 196 | canvas.bind("",lambda x:setStarting(canvas)) 197 | canvas.bind("",lambda x:setEnding(canvas)) 198 | canvas.bind("",lambda x:on_double_click_release(lambda :on_release(canvas))) 199 | 200 | 201 | menuBar() 202 | window.mainloop() 203 | -------------------------------------------------------------------------------- /windows/screentranslater.pyw: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from tkinter import messagebox 3 | from googletrans import Translator 4 | from PIL import Image,ImageTk,ImageGrab 5 | from pyperclip import copy 6 | from glob import glob 7 | from threading import Thread 8 | from subprocess import run 9 | import ctypes 10 | import ctypes.wintypes 11 | from time import time 12 | import os 13 | 14 | def timer(function): 15 | def wrapper(*args, **kwargs): 16 | start = time() 17 | function(*args, **kwargs) 18 | end = time() 19 | print(f'[{function.__name__}] It took {(end-start):.3f} seconds') 20 | 21 | return wrapper 22 | 23 | def position(): 24 | cursor = ctypes.wintypes.POINT() 25 | ctypes.windll.user32.GetCursorPos(ctypes.byref(cursor)) 26 | return cursor.x,cursor.y 27 | 28 | def screenshot(imageFilename=None, region=None): 29 | im = ImageGrab.grab() 30 | if region is not None: 31 | assert len(region) == 4, 'region argument must be a tuple of four ints' 32 | region = [int(x) for x in region] 33 | im = im.crop((region[0], region[1], region[2] + region[0], region[3] + region[1])) 34 | return im 35 | 36 | translator = Translator() 37 | destination_language = "tr" 38 | def translate(sentence): 39 | return translator.translate(sentence,dest=destination_language) 40 | 41 | #creating window 42 | window=Tk() 43 | window.title('Screen Translater') 44 | window.attributes("-fullscreen", True) 45 | window.wm_attributes("-topmost", True) 46 | window.wm_attributes("-transparentcolor", "pink") 47 | window.config(bg='pink') 48 | 49 | screen_width = window.winfo_screenwidth() 50 | screen_height = window.winfo_screenheight() 51 | 52 | #check if somebody didnt read the md file 53 | windows_path = r"C:\Program Files\Tesseract-OCR\tesseract.exe" 54 | 55 | if os.name == "nt": 56 | if os.path.exists(windows_path): 57 | tesseract_path = windows_path 58 | else: 59 | messagebox.showwarning("Exe not found","tesseract-ocr not found check github project page") 60 | else: 61 | exit() 62 | 63 | def image_to_string(image:Image): 64 | image.save("./te.png") 65 | x=run(f'"{tesseract_path}" ./te.png - pm20', capture_output=True, text=True,shell=True).stdout.lower() 66 | os.remove("./te.png") 67 | print(x) 68 | return x 69 | 70 | #colors 71 | blue="#2f84ea" 72 | dark = "#1c1d22" 73 | dbfe = "#84bbfc" 74 | dbfb = "#7ab4fa" 75 | theme = blue 76 | 77 | #uploading assets 78 | folder_path = os.path.abspath(os.getcwd()) 79 | def replaceColor(picture,datas=None): 80 | if datas==None: return picture 81 | oldHex,newHex=datas 82 | width, height = picture.size 83 | print(width,height) 84 | hexToRgb =lambda hex:tuple(int(hex.lstrip("#")[i:i+2], 16) for i in (0, 2, 4)) 85 | for x in range(width): 86 | for y in range(height): 87 | current_color = picture.getpixel( (x,y) ) 88 | if current_color == hexToRgb(oldHex): 89 | picture.putpixel( (x,y), hexToRgb(newHex)) 90 | return picture 91 | 92 | def Loader(assetFolder): 93 | files = glob(f"{assetFolder}/*") 94 | paths = {};[paths.update({i.split("\\")[-1].split(".")[0]:i}) for i in files] 95 | def loadAsset(paths,name,size=None,replaceColorHex=None): 96 | if size: 97 | #replaceColor(Image.open(paths[name]),datas=replaceColorHex).resize(size).save(f"./images/dark/{name}.png") 98 | return ImageTk.PhotoImage(replaceColor(Image.open(paths[name]),datas=replaceColorHex).resize(size)) 99 | else: return ImageTk.PhotoImage(replaceColor(Image.open(paths[name]),datas=replaceColorHex)) 100 | return lambda name,size=None,replaceColorHex=None:loadAsset(paths,name,size,replaceColorHex) 101 | 102 | @timer 103 | def setTheme(stheme): 104 | if stheme == "dark": 105 | theme = dark 106 | dbfe = "#373943" 107 | dbfb = "#5d6171" 108 | loader = Loader(f"{folder_path}/images/dark") 109 | elif stheme == "blue": 110 | loader = Loader(f"{folder_path}/images/blue") 111 | photo = loader("translateIcon",(22,22)) 112 | photo2 = loader("clipboardIcon",(22,22)) 113 | settingphoto = loader("settingsIcon",(35,35)) 114 | translatephoto = loader("translateMenuIcon",(35,35)) 115 | globals().update(locals()) 116 | 117 | 118 | 119 | languages = {'Afrikaans': 'af', 'Irish': 'ga', 'Albanian': 'sq', 'Italian': 'it', 'Arabic': 'ar', 'Japanese': 'ja', 'Azerbaijani': 'az', 'Kannada': 'kn', 'Basque': 'eu', 'Korean': 'ko', 'Bengali': 'bn', 'Latin': 'la', 'Belarusian': 'be', 'Latvian': 'lv', 'Bulgarian': 'bg', 'Lithuanian': 'lt', 'Catalan': 'ca', 'Macedonian': 'mk', 'Chinese Simplified': 'zh-CN', 'Malay': 'ms', 'Chinese Traditional': 'zh-TW', 'Maltese': 'mt', 'Croatian': 'hr', 'Norwegian': 'no', 'Czech': 'cs', 'Persian': 'fa', 'Danish': 'da', 'Polish': 'pl', 'Dutch': 'nl', 'Portuguese': 'pt', 'English': 'en', 'Romanian': 'ro', 'Esperanto': 'eo', 'Russian': 'ru', 'Estonian': 'et', 'Serbian': 'sr', 'Filipino': 'tl', 'Slovak': 'sk', 'Finnish': 'fi', 'Slovenian': 'sl', 'French': 'fr', 'Spanish': 'es', 'Galician': 'gl', 'Swahili': 'sw', 'Georgian': 'ka', 'Swedish': 'sv', 'German': 'de', 'Tamil': 'ta', 'Greek': 'el', 'Telugu': 'te', 'Gujarati': 'gu', 'Thai': 'th', 'Haitian Creole': 'ht', 'Turkish': 'tr', 'Hebrew': 'iw', 'Ukrainian': 'uk', 'Hindi':'hi', 'Urdu': 'ur', 'Hungarian': 'hu', 'Vietnamese': 'vi', 'Icelandic': 'is', 'Welsh': 'cy', 'Indonesian': 'id', 'Yiddish': 'yi'} 120 | tkvar = StringVar(window) 121 | options = [i for i in list(languages.keys())] 122 | rect = None 123 | startingPoint = () 124 | rectDrawingState = False 125 | coords = () 126 | box = None 127 | 128 | def move(widget:Canvas): 129 | def e(e): 130 | x,y=position() 131 | widget.place(x=x-(widget.winfo_width()/2),y=y-(widget.winfo_height()/2)) 132 | widget.bind('',e) 133 | 134 | 135 | def create(widget,x,y): 136 | widget.place(x=x,y=y) 137 | return widget 138 | 139 | def defaultButtonFunctions(widget,buttonFunction): 140 | widget.bind("",lambda x:widget.configure(bg=dbfe)) 141 | widget.bind("",lambda x:widget.configure(bg=theme)) 142 | widget.bind("",lambda x:(widget.configure(bg=dbfb),buttonFunction(x))) 143 | 144 | @timer 145 | def translatePopup(text,translation): 146 | canvas = create(Canvas(window,width=180,height=120,bg=theme,highlightthickness=2, highlightbackground="gray"),150,70) 147 | move(canvas) 148 | closeButton = create(Label(canvas,text=" X ",bg=theme,fg="white"),158,4) 149 | iconButton = create(Label(canvas,image = photo,bg=theme),8,2) 150 | copyButton = create(Label(canvas,image = photo2,bg=theme),132,3) 151 | textbox = create(Text(canvas, height = 5, width = 20),9.5,30) 152 | textbox.insert(END,translation) 153 | defaultButtonFunctions(iconButton,lambda x:(os.startfile(f"https://translate.google.com/?sl=auto&tl={destination_language}&text={text}&op=translate"))) 154 | defaultButtonFunctions(copyButton,lambda x:(copy(text))) 155 | defaultButtonFunctions(closeButton,lambda x:(canvas.destroy())) 156 | return canvas 157 | 158 | @timer 159 | def menuBar(): 160 | canvas = create(Canvas(window,width=40,height=190,bg=theme,highlightthickness=2, highlightbackground="gray"),10,screen_height/2+50) 161 | popup = Menu(window, tearoff=0) 162 | popup.add_command(label="Github",command=lambda :os.startfile("https://github.com/kaankarakoc42/translater")) 163 | def lang(): 164 | global box 165 | x,y = position() 166 | tkvar.set(destination_language) 167 | def setLang(value): 168 | global destination_language,box 169 | destination_language = languages[value] 170 | box.destroy() 171 | box = create(OptionMenu(window,tkvar,*options,command=lambda x:setLang(x)),x+5,y) 172 | 173 | popup.add_command(label="language",command=lambda :lang()) 174 | popup.add_separator() 175 | popup.add_command(label="Hide",command=lambda :(window.iconify())) 176 | def menu_popup(event): 177 | try: popup.tk_popup(event.x_root+50, event.y_root, 0) 178 | finally: popup.grab_release() 179 | settingsButton = create(Label(canvas,image = settingphoto,bg=theme),2,10) 180 | defaultButtonFunctions(settingsButton,lambda x:(menu_popup(x))) 181 | translateButton = create(Label(canvas,image = translatephoto,bg=theme),2,55) 182 | defaultButtonFunctions(translateButton,lambda x:(Thread(target=grabScreen).start())) 183 | closeButton = create(Label(canvas,width=4,text="Exit",bg=theme,fg="white"),4,160) 184 | defaultButtonFunctions(closeButton,lambda x:window.destroy()) 185 | move(canvas) 186 | 187 | def setStarting(canvas): 188 | global startingPoint,rectDrawingState,rect,coords; 189 | startingPoint = position() 190 | rectDrawingState = True 191 | if not rect: 192 | rect = canvas.create_rectangle(startingPoint[0], startingPoint[1],2,2, outline='red') 193 | 194 | def setEnding(canvas): 195 | global startingPoint,rectDrawingState,rect,coords; 196 | if not rectDrawingState: return 197 | x,y=position() 198 | canvas.coords(rect,startingPoint[0], startingPoint[1], x,y) 199 | coords = [int(i) for i in (startingPoint[0]+1,startingPoint[1]+1,x-startingPoint[0]-1,y-startingPoint[1]-1)] 200 | 201 | def drawingDone(canvas): 202 | global rectDrawingState,rect,coords; 203 | rectDrawingState = False 204 | canvas.delete(rect) 205 | canvas.destroy() 206 | rect = None 207 | 208 | def on_double_click_release(func): 209 | global rectDrawingState; 210 | if rectDrawingState: 211 | func() 212 | 213 | def on_release(canvas): 214 | drawingDone(canvas) 215 | window.attributes('-alpha', 1) 216 | window.config(cursor="arrow") 217 | window.update() 218 | text =image_to_string(screenshot(region=coords)) 219 | print(text) 220 | textTranslation = translate(text).text 221 | translatePopup(text,textTranslation) 222 | 223 | 224 | def grabScreen(): 225 | canvas = create(Canvas(window,width = screen_width,height=screen_height),0,0) 226 | window.config(cursor="tcross") 227 | window.attributes('-alpha', 0.3) 228 | canvas.bind("",lambda x:setStarting(canvas)) 229 | canvas.bind("",lambda x:setEnding(canvas)) 230 | canvas.bind("",lambda x:on_double_click_release(lambda :on_release(canvas))) 231 | 232 | setTheme("dark") 233 | menuBar() 234 | window.mainloop() 235 | 236 | 237 | --------------------------------------------------------------------------------