wx.Locale: Missing translations are using other languages instead of falling back to English immediately

Got an odd problem. Here’s the app (run app.py):


I have a string “Firepower” that is translated in Russian and Chinese, but not in Korean or Turkish. This string is set as the title of the window for the app in the example. If I set the language to Russian or Chine, I get the translated version. This is expected.

If I set the language to Korean, since it doesn’t have a translation for this term, it fall back to English. Again, this is expected.

However, if I set the language to Turkish, which also doesn’t have a translation for this term, it uses the Russian translation for the term instead of the English fallback.

I have no idea why. Any ideas?

Also, and I don’t have this demonstrated in the example app because I forgot, but if the Turkish catalog has an explicit translation, it seems to correctly use it.

Original description form our project:

Python 3.6
wxPython 4.0.6 (our app has issues with the newer versions, but I haven’t tried the newer versions as it relates to this specific problem. Will try that and report back)

wxPython 4.1.0 also displays this oddity, so don’t think it’s related to the version

It appears it’s not just Turkish either. In our project, we have a string “Sensor Str.”. if set to Russian, which doesn’t have a translation for this string, it’s using our Japanese translation:

We have another string “Remote Reps” that has neither Russian nor Japanese translations, and it’s displaying as English. This string, in our project, is translated only to Chinese for now. If I add a French translation for it, it shows the french version instead of English.

So, from what I can gather, wxPython is trying to go up the list of available translations and uses the first one it fins, English if not found. So, if we have the following languages:

  • en_US (English)
  • it_IT (Italian)
  • ja_JP (Japanese)
  • ko_KR (Korean)
  • ru_RU (Russian)
  • tr_TR (Turkish)
  • zh_CN (Chinese)

If we have our app set to Turkish, it’s going to look for a translation from the Turkish messages. If it doesn’t find one, it’ll look for Russian. If it still doesn’t find one, it basically goes up that list until it does find one (so, when Turkish is set, I’m noticing Turkish, Russian, Japanese, etc due to all the missing translations from various languages).

How can I fix this?

I might be wrong, but I’m afraid that wxWidgets just picks the fist one available (maybe in alphabetical order?), see

and there is no way to set a smart fallback mechanism like the one of Python’s gettext.translation.

Thanks for linking to the literal line in the codebase that does this. Very interesting to see it. But I’m super curious on why anyone would think that would is useful? If you say “I want the Russian language” and a translation doesn’t exist for it, why would anyone want some other random language?

Is there any work around for this? I can’t imagine most applications would tolerate the current implementation.

I’ll be opening up a discussion on the github repo as well to get more exposure

One of our contributors recommended using msgen during build time to explicitly replace all empty translations with the source string. https://www.gnu.org/software/gettext/manual/html_node/msgen-Invocation.html

This has proved to be a good workaround for this - technically the message catalog now has a translation, but it’s the English version so effectively it doesn’t. But at least it doesn’t get random languages.

Hoping that information may be useful to someone else that run into a similar issue. :grin:

Indeed, msgen is the way to go, according to the gettext philosophy.
The point is, gnu gettext has almost no concept of “uncomplete catalog”. As an exercise, try opening the single-page html manual https://www.gnu.org/software/gettext/manual/gettext.htm and finding the word “fallback”. You will be rather disappointed.
The Python module gettext provides, indeed, a fallback mechanism, but it is an higher level interface, beyond the scope of basic gnu gettext. Babel http://babel.pocoo.org/en/latest/ goes even further.
But if you stick to gnu gettext, you should never give “empty” po templates to translators: always use msgen to pre-fill the templates, and have translators overwrite them with the intended translation. This way, if they miss a few strings in a template, you will always have a natural fallback in place.