<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: michburkhalter</title>
    <description>The latest articles on DEV Community by michburkhalter (@michburkhalter).</description>
    <link>https://dev.to/michburkhalter</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F269257%2F7b9ea8b7-9623-43d9-9cab-4cf2d6da8a6e.jpeg</url>
      <title>DEV Community: michburkhalter</title>
      <link>https://dev.to/michburkhalter</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/michburkhalter"/>
    <language>en</language>
    <item>
      <title>Creating a python app with translations using PySimpleGUI and Babel</title>
      <dc:creator>michburkhalter</dc:creator>
      <pubDate>Fri, 08 Jul 2022 13:47:35 +0000</pubDate>
      <link>https://dev.to/michburkhalter/creating-a-python-app-with-translations-using-pysimplegui-and-babel-1lo0</link>
      <guid>https://dev.to/michburkhalter/creating-a-python-app-with-translations-using-pysimplegui-and-babel-1lo0</guid>
      <description>&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;If you want to jump right to the complete Repo you can do that &lt;a href="https://github.com/michburkhalter/TranslatedPySimpleGUI" rel="noopener noreferrer"&gt;TranslatedPySimpleGUI&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;I want to have an application where I could change the language dynamically in the menu without any further user action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6i2bbhaay9yjwm6hvu3g.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6i2bbhaay9yjwm6hvu3g.gif" alt="Translated PySimpleGui"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Python app with PySimpleGui
&lt;/h2&gt;

&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def main_window(my_window=None):
    menu_def = [_('&amp;amp;About'), [_('Close::close')]], [_('&amp;amp;Language'), ['&amp;amp;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Translations are used with the built-in function &lt;code&gt;gettext&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## Setup translations
    localedir = 'locale'
    translate = gettext.translation('messages', localedir=localedir, languages=['de'])
    _ = translate.gettext
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to change the translations dynamically we need to update the _ function whenever needed and then recreate the window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        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)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Translation
&lt;/h2&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;p&gt;First we need to extract the text that shall be translated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pybabel extract . -o locale/base.pot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a second step we need, if the locale does not yet exist, create the desired locales. 'de' and 'en' in my case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pybabel init -l de -i locale/base.pot -d locale
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Third we need to update the locales with the texts generated in step 1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pybabel update -i locale/base.pot -d locale/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fourth we need to add the translated texts to files messages.po in the locales (here de and en) manually.&lt;/p&gt;

&lt;p&gt;Fifth we need to compile the po files into mo binaries that are then used in the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pybabel compile -d locale

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my &lt;a href="https://github.com/michburkhalter/TranslatedPySimpleGUI/blob/develop/create_translations.bat" rel="noopener noreferrer"&gt;demo app&lt;/a&gt; I've automated this in a bat file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@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

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Repo
&lt;/h2&gt;

&lt;p&gt;The whole code I've just explained can be found in this repo: &lt;a href="https://github.com/michburkhalter/TranslatedPySimpleGUI" rel="noopener noreferrer"&gt;TranslatedPySimpleGUI&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>pysimplegui</category>
      <category>babel</category>
      <category>i18n</category>
    </item>
  </channel>
</rss>
