I've recently come across the need to create a Python3 app with a GUI and translated texts into several languages. I quickly found out that Babel and PySimpleGui are the tools of my choice but it took me some time to find out how to integrate the two. So here's how I did it.
If you want to jump right to the complete Repo you can do that TranslatedPySimpleGUI.
Requirements
I want to have an application where I could change the language dynamically in the menu without any further user action.
Python app with PySimpleGui
The key takeaway here is to replace the existing window with a new one if the language changes. By this the texts are updated to the new language as well:
def main_window(my_window=None):
menu_def = [_('&About'), [_('Close::close')]], [_('&Language'), ['&de', 'en']],
layout_mainwindow = [
[
[sg.Menu(menu_def, pad=(10, 10))],
[sg.Text(_('Select direction: '), key='txt_direction')], [sg.Combo([_('Left'), _('Right')], key='cmb_direction', size=20)],
[sg.Button(_('Close'), key='btn_close')],
]
]
new_window = sg.Window("Demo TranslatedPySimpleGui", layout_mainwindow, finalize=True)
if my_window is not None:
my_window.close()
return new_window
Translations are used with the built-in function gettext
## Setup translations
localedir = 'locale'
translate = gettext.translation('messages', localedir=localedir, languages=['de'])
_ = translate.gettext
In order to change the translations dynamically we need to update the _ function whenever needed and then recreate the window:
elif event == 'de':
translate = gettext.translation('messages', localedir=localedir, languages=['de'])
_ = translate.gettext
print(_("Language changed to DE"))
window = main_window(window)
elif event == 'en':
translate = gettext.translation('messages', localedir=localedir, languages=['en'])
_ = translate.gettext
print(_("Language changed to EN"))
window = main_window(window)
Translation
With Babel we can comfortably extract all text we would like to translate and process them into language specific files we can translate. These files are then compiled into binaries that are used by the application:
First we need to extract the text that shall be translated:
pybabel extract . -o locale/base.pot
As a second step we need, if the locale does not yet exist, create the desired locales. 'de' and 'en' in my case:
pybabel init -l de -i locale/base.pot -d locale
Third we need to update the locales with the texts generated in step 1:
pybabel update -i locale/base.pot -d locale/
Fourth we need to add the translated texts to files messages.po in the locales (here de and en) manually.
Fifth we need to compile the po files into mo binaries that are then used in the application:
pybabel compile -d locale
In my demo app I've automated this in a bat file:
@ECHO OFF
ECHO Creating and Updating Translations
ECHO Initiating directory locale if necessary
if not exist locale\ (
mkdir locale\
)
ECHO Initiating base translation file
venv\Scripts\pybabel extract . -o locale/base.pot
if not exist locale\de\ (
echo Init Language DE
venv\Scripts\pybabel init -l de -i locale/base.pot -d locale
)
if not exist locale\en\ (
echo Init Language EN
venv\Scripts\pybabel init -l en -i locale/base.pot -d locale
)
ECHO Create and compile translations
venv\Scripts\pybabel update -i locale/base.pot -d locale/
:: Between these 2 steps you have to add the translations manually to e.g. locale/de/messages.po
venv\Scripts\pybabel compile -d locale
Repo
The whole code I've just explained can be found in this repo: TranslatedPySimpleGUI
Top comments (0)