Whether learning a new natural language or just browsing foreign websites, you sometimes come across text that you want to read but is written in a language you don't fully understand. To translate one natural language into your native language you can use a translator tool, like Google Translate.
In this tutorial, we'll build a desktop translator application to translate natural language using the Google Translate APIs. The UI will be built using the Tkinter GUI library from the Python standard library.
Demo: A Translator App with Tkinter
We'll work through the process of building the app step by step. Once we finish the tutorial, the app will look and work like the following:
You can select the source and destination languages. Then, you can paste or type some text in the left-hand area and hit the Translate button to get the translated text in the right-hand area.
Installing the Required Packages
Our Translator uses the googletrans
library to perform the actual translation via Google. Tkinter is already available in the standard library, so we just need to install googletrans-py
and a library called httpcore
to deal with connection errors.
The first task will be to set up a Python virtual environment. Open the terminal, and run the following commands:
Never miss an update
Enjoyed this? Subscribe to get new updates straight in your Inbox.
- Windows
- macOS/Linux
> mkdir translator
> cd translator
> python -m venv venv
> .\venv\Scripts\activate
> python -m pip install googletrans-py httpcore
$ mkdir translator
$ cd translator/
$ python -m venv venv
$ source venv/bin/activate
(venv) $ python -m pip install googletrans-py httpcore
Working through these instructions, first we create a root directory for the Translator app. Next we create and activate a Python virtual environment for the project. Finally, we install googletrans
and httpcore
packages.
Now, create a file named translator.py
in the root of your project. Additionally, create a folder called images/
where you'll store the icons for the application. The folder structure should look like this:
translator/
│
├── images/
│ ├── arrow.png
│ └── logo.png
│
└── translator.py
The images for this project can be downloaded here.
The images/
folder contains the two icons that you'll use for the application. The translator.py
is the app's source file.
Building the Window
Open the translator.py
file with your favorite Python code editor. We'll start by creating our main window:
import tkinter as tk
class TranslatorApp(tk.Tk):
def __init__(self):
super().__init__()
self.title("Language Translator")
self.resizable(width=False, height=False)
if __name__ == "__main__":
app = TranslatorApp()
app.mainloop()
This code imports Tkinter and then defines the application's main class, which we have called TranslatorApp
. This class will hold the application's main window and allow us to run the main loop.
Importing tkinter
under the alias tk
is a common convention in Tkinter code.
Inside the class we define the __init__()
method, which handles initialization of the class. In this method we first call the initializer __init__()
of the parent class, tk.Tk
, to initialize the app's window. Then, we set the window's title using the title()
method. To make the window unresizable, we use the resizable()
method with width
and height
set to False
.
At the bottom of the code, we have the if __name__ == "__main__"
idiom to check whether the file is being run directly as an executable program. Inside the condition block we first create an instance of TranslatorApp
and then run the application's main loop or event loop.
If you run this code, you'll get an empty Tkinter window on your desktop:
python translator.py
The empty Tkinter window
Creating the GUI
Now that the main window is set up, let's start adding widgets to build the GUI. To do this, we'll create a method called setup_ui()
, as shown below:
import tkinter as tk
class TranslatorApp(tk.Tk):
def __init__(self):
super().__init__()
self.title("Language Translator")
self.resizable(width=False, height=False)
self.setup_ui()
def setup_ui(self):
frame = tk.Frame(self)
frame.pack(padx=10, pady=10)
if __name__ == "__main__":
app = TranslatorApp()
app.mainloop()
The setup_ui()
method will define the application's GUI. In this method, we first create a frame widget using the tk.Frame
class whose master
argument is set to self
(the application's main window). Next, we position the frame inside the main window using the pack()
geometry manager, using padx
and pady
arguments to set some padding around the frame.
Finally, we add the call to self.setup_ui()
to the __init__()
method.
We'll continue to develop the UI by adding code to the setup_ui()
method.
Net we'll add the app's logo. In the setup_ui()
method add the following code below the frame
definition:
import tkinter as tk
class TranslatorApp(tk.Tk):
def __init__(self):
super().__init__()
self.title("Language Translator")
self.resizable(width=False, height=False)
self.setup_ui()
def setup_ui(self):
frame = tk.Frame(self)
frame.pack(padx=10, pady=10)
self.logo = tk.PhotoImage(file="images/logo.png").subsample(5, 5)
tk.Label(frame, image=self.logo).grid(row=0, column=0, sticky="w")
if __name__ == "__main__":
app = TranslatorApp()
app.mainloop()
This code loads the logo using the tk.PhotoImage
class. To resize it, we use the subsample()
method. Then, we add the logo to the frame using a tk.Label
widget. The label takes the frame and the logo as arguments. Finally, to position the logo, we use the grid()
geometry manager with appropriate values for the row
, column
, and sticky
arguments.
The sticky
argument determines which side of a cell the widget should align -- North (top), South (bottom), East (right) or West (left). Here we're aligning it on the Wiest or left of the cell with "w"
:
Tkinter window with the Google Translate logo in it
Let's start adding some inputs to the UIs. First, we'll create the language selection drop-down boxes:
import tkinter as tk
import tkinter.ttk as ttk
from googletrans import LANGUAGES
DEFAULT_SOURCE = "English"
DEFAULT_DEST = "Dutch"
class TranslatorApp(tk.Tk):
def __init__(self):
super().__init__()
self.title("Language Translator")
self.resizable(width=False, height=False)
self.setup_ui()
def setup_ui(self):
frame = tk.Frame(self)
frame.pack(padx=10, pady=10)
self.logo = tk.PhotoImage(file="images/logo.png").subsample(5, 5)
tk.Label(frame, image=self.logo).grid(row=0, column=0, sticky="w")
# Source language combobox
languages = [lang.title() for lang in LANGUAGES.values()]
self.from_language = ttk.Combobox(frame, values=languages)
self.from_language.current(languages.index(DEFAULT_SOURCE))
self.from_language.grid(row=1, column=0, sticky="we")
# Arrow icon
self.arrows = tk.PhotoImage(file="images/arrow.png").subsample(15, 15)
tk.Label(frame, image=self.arrows).grid(row=1, column=1)
# Destination language combobox
self.to_language = ttk.Combobox(frame, values=languages)
self.to_language.current(languages.index(DEFAULT_DEST))
self.to_language.grid(row=1, column=2, sticky="we")
if __name__ == "__main__":
app = TranslatorApp()
app.mainloop()
We can get a list of languages from the googletrans
module. We also define the default languages for when the application starts up, using constants DEFAULT_SOURCE
and DEFAULT_DEST
.
To build the language list for the combo boxes we take the LANGUAGES
dictionary imported from googletrans
and convert it into a list of strings called languages
. We use a list comprehension to make all the names start with an uppercase letter, using title()
.
Next we create two combo boxes, to hold the list of source and destination langauges. The combo boxes are created using the ttk.Combobox
class. One to the left and another to the right. Between the combo boxes, we've also added an arrow icon loaded using the tk.PhotoImage
class. Again, we've added the icon to the app's window using ttk.Label
.
Both combo boxes take frame
and values
as arguments. The values
argument populates the combo boxes with languages. To specify the default language, we use the current()
method, looking up the position of our default languages in the languages
list with index()
.
To position the combo boxes inside the frame, we use the grid()
geometry manager with the appropriate arguments. Run the application, and you will see the following window:
Source and destination languages
If you click on the sources combo box on the left, then you get the following:
Source language combo box
Similarly, if you click on the destination combo box on the right, you get the following:
Destination combo box
With the source and destination combo boxes in place, let's add three more widgets: two scrollable text widgets and a button. The scrollable text on the left will hold the source text, while the scrollable text on the right will hold the translated text. The button will allow us to run the actual translation.
Get back to the code editor and update the setup_ui()
method as follows. Note that we also need to import the ScrollText
class:
import tkinter as tk
import tkinter.ttk as ttk
from tkinter.scrolledtext import ScrolledText
from googletrans import LANGUAGES
DEFAULT_SOURCE = "English"
DEFAULT_DEST = "Dutch"
class TranslatorApp(tk.Tk):
def __init__(self):
super().__init__()
self.title("Language Translator")
self.resizable(width=False, height=False)
self.setup_ui()
def setup_ui(self):
frame = tk.Frame(self)
frame.pack(padx=10, pady=10)
self.logo = tk.PhotoImage(file="images/logo.png").subsample(5, 5)
tk.Label(frame, image=self.logo).grid(row=0, column=0, sticky="w")
# Source language combobox
languages = [lang.title() for lang in LANGUAGES.values()]
self.from_language = ttk.Combobox(frame, values=languages)
self.from_language.current(languages.index(DEFAULT_SOURCE))
self.from_language.grid(row=1, column=0, sticky="we")
# Arrow icon
self.arrows = tk.PhotoImage(file="images/arrow.png").subsample(15, 15)
tk.Label(frame, image=self.arrows).grid(row=1, column=1)
# Destination language combobox
self.to_language = ttk.Combobox(frame, values=languages)
self.to_language.current(languages.index(DEFAULT_DEST))
self.to_language.grid(row=1, column=2, sticky="we")
# Source text
self.from_text = ScrolledText(
frame,
font=("Dotum", 16),
width=50,
height=20,
)
self.from_text.grid(row=2, column=0)
# Translated text
self.to_text = ScrolledText(
frame,
font=("Dotum", 16),
width=50,
height=20,
state="disabled",
)
self.to_text.grid(row=2, column=2)
# Translate button
self.translate_button = ttk.Button(
frame,
text="Translate",
command=self.translate,
)
self.translate_button.grid(row=3, column=0, columnspan=3, pady=10)
def translate(self):
pass
if __name__ == "__main__":
app = TranslatorApp()
app.mainloop()
In the code snippet, we use the ScrolledText
class to create the two scrolled text areas. Both text areas take frame
, font
, width
, and height
as arguments. The second text area also takes state
as an additional argument. Setting state
to "disabled"
allows us to create a read-only text area.
Then, we use the ttk.Button
class to create a button with frame
, text
, and command
as arguments. The command
argument allows us to bind the button's click event to the self.translate()
method, which we will define in a moment. For now, we've added a placeholder.
To position all these widgets on the app's window, we use the grid()
geometry manager. Now, the app will look like the following:
Translator app's GUI
Our translation app's GUI is ready! Finally, we can start adding functionality to the application.
Implementing the Translation Functionality
We'll implement the language translation functionality in the translate()
method. This gets the current values from the UI and then uses googletrans
to perform the translation. We need a few more imports, and to create the translator
instance at the top of the application:
import tkinter as tk
import tkinter.ttk as ttk
from tkinter.messagebox import showerror
from tkinter.scrolledtext import ScrolledText
import httpcore
from googletrans import LANGUAGES, Translator
DEFAULT_SOURCE = "English"
DEFAULT_DEST = "Dutch"
translator = Translator()
Here we've imported the showerror
helper for displaying error boxes in our application. We've imported httpcore
which we'll use to handle HTTP errors when accessing the API. Finally, we've added an import for the Translator
class from googletrans
. This is what handles the actual translation.
To use it, we create an instance of the class as translator
.
We'll continue by implementing the translate
method. Below we're just showing the function itself:
class TranslatorApp(tk.Tk):
# ...
def translate(self):
source_language = self.from_language.get()
destination_language = self.to_language.get()
text = self.from_text.get(1.0, tk.END).strip()
if not source_language or not destination_language:
showerror(
title="Error",
message="Make sure to set the source and destination language",
)
return
if not text:
showerror(
title="Error",
message="Make sure to enter some text to translate",
)
return
try:
translation = self.translator.translate(
text,
src=source_language,
dest=destination_language,
)
except httpcore.ConnectError:
showerror(
title="Error",
message="Make sure you have an internet connection",
)
return
except Exception as e:
showerror(
title="Error",
message=f"An unexpected error occurred: {e}",
)
return
self.to_text.config(state="normal")
self.to_text.delete(1.0, tk.END)
self.to_text.insert(tk.END, translation.text)
self.to_text.config(state="disabled")
The translate()
method handles the entire translation process. It starts by retrieving the source and destination languages from the corresponding combo boxes. If either language is not defined, then we display a message to inform the user about the problem. To do this, we use a showerror
dialog.
Next, we try to get the input text from the source scrolled area on the left. If the user doesn't provide any text, then we display an error with the appropriate message.
Once we have the source and destination language and some text to translate, we can perform the actual translation. To run this task, we use the translate()
method of the self.translator
object, which is an instance of googletrans.Translator
.
If the call to translate()
finds a connection error, then we tell the user to check their internet connection. To handle any other exceptions, we catch the generic Exception
class and display an error message with the exception details.
If the translation is successful, then we enable the destination scrolled area, display the translated text, and disable the area again so it remains read-only.
The complete final code is shown below:
import tkinter as tk
import tkinter.ttk as ttk
from tkinter.messagebox import showerror
from tkinter.scrolledtext import ScrolledText
import httpcore
from googletrans import LANGUAGES, Translator
DEFAULT_SOURCE = "English"
DEFAULT_DEST = "Dutch"
translator = Translator()
class TranslatorApp(tk.Tk):
def __init__(self):
super().__init__()
self.title("Language Translator")
self.resizable(width=False, height=False)
self.setup_ui()
def setup_ui(self):
languages = [lang.title() for lang in LANGUAGES.values()]
frame = tk.Frame(self)
frame.pack(padx=10, pady=10)
self.logo = tk.PhotoImage(file="images/logo.png").subsample(5, 5)
tk.Label(frame, image=self.logo).grid(row=0, column=0, sticky="w")
# Source language combobox
self.from_language = ttk.Combobox(frame, values=languages)
self.from_language.current(languages.index(DEFAULT_SOURCE))
self.from_language.grid(row=1, column=0, sticky="we")
# Arrow icon
self.arrows = tk.PhotoImage(file="images/arrow.png").subsample(15, 15)
tk.Label(frame, image=self.arrows).grid(row=1, column=1)
# Destination language combobox
self.to_language = ttk.Combobox(frame, values=languages)
self.to_language.current(languages.index(DEFAULT_DEST))
self.to_language.grid(row=1, column=2, sticky="we")
# Source text
self.from_text = ScrolledText(
frame,
font=("Dotum", 16),
width=50,
height=20,
)
self.from_text.grid(row=2, column=0)
# Translated text
self.to_text = ScrolledText(
frame,
font=("Dotum", 16),
width=50,
height=20,
state="disabled",
)
self.to_text.grid(row=2, column=2)
# Translate button
self.translate_button = ttk.Button(
frame,
text="Translate",
command=self.translate,
)
self.translate_button.grid(row=3, column=0, columnspan=3, pady=10)
def translate(self):
source_language = self.from_language.get()
destination_language = self.to_language.get()
if not source_language or not destination_language:
showerror(
title="Error",
message="Make sure to set the source and destination language",
)
return
text = self.from_text.get(1.0, tk.END).strip()
if not text:
showerror(
title="Error",
message="Make sure to enter some text to translate",
)
return
try:
translation = translator.translate(
text,
src=source_language,
dest=destination_language,
)
except httpcore.ConnectError:
showerror(
title="Error",
message="Make sure you have an internet connection",
)
return
except Exception as e:
showerror(
title="Error",
message=f"An unexpected error occurred: {e}",
)
return
self.to_text.config(state="normal")
self.to_text.delete(1.0, tk.END)
self.to_text.insert(tk.END, translation.text)
self.to_text.config(state="disabled")
if __name__ == "__main__":
app = TranslatorApp()
app.mainloop()
Using the Translator App
The video below demonstrates how we can use our app to translate some text from one natural language to another:
Great! You have successfully built a language translator using Python, Tkinter, and the googletrans
package.
Conclusion
In this tutorial we built a Translator application using the Tkinter GUI library from the Python standard library. We worked step by step through building the UI using a grid layout, and then implemented the language translation functionality with googletrans
.
Try and take what you've learnt in this tutorial & applying it to your own projects!