Change locale by creating wxLocale objects in wxpython 3.0.2.0

Hi all :slight_smile:

I posted on SO: https://stackoverflow.com/q/54178028/281545

You can reply to me there

Post:

I am maintaining a legacy python 2 app and I am trying to move from wxpython 2.8.12.1 to 3.0.2 - I get this assertion error:

 Traceback (most recent call last):
      File "Wrye Bash Launcher.pyw", line 88, in <module>
        bash.main()
      File "bash\bash.py", line 428, in main
        frame = app.Init() # Link.Frame is set here !
      File "bash\basher\__init__.py", line 4316, in Init
        size=settings['bash.frameSize'])
      File "bash\basher\__init__.py", line 3906, in __init__
        self.SetStatusBar(BashStatusBar(self))
      File "bash\basher\__init__.py", line 3669, in __init__
        self.UpdateIconSizes()
      File "bash\basher\__init__.py", line 3707, in UpdateIconSizes
        self._addButton(link)
      File "bash\basher\__init__.py", line 3681, in _addButton
        gButton = link.GetBitmapButton(self,style=wx.NO_BORDER)
      File "bash\basher\app_buttons.py", line 657, in GetBitmapButton
        image=staticBitmap(window, special='undo', size=(size,size)))
      File "bash\balt.py", line 509, in staticBitmap
        return bmp(wx.ART_UNDO,wx.ART_TOOLBAR,size)
      File "C:\_\Python27\lib\site-packages\wx-3.0-msw\wx\_misc.py", line 3013, in ArtProvider_GetBitmap
        return _misc_.ArtProvider_GetBitmap(*args, **kwargs)
    wx._core.PyAssertionError: C++ assertion "strcmp(setlocale(LC_ALL, NULL), "C") == 0" failed at ..\..\src\common\intl.cpp(1449) in wxLocale::GetInfo(): You probably called setlocale() directly instead of using wxLocale and now there is a mismatch between C/C++ and Windows locale.
    Things are going to break, please only change locale by creating wxLocale objects to avoid this!

``

It says:

You probably called setlocale() directly instead of using wxLocale and now there is a mismatch between C/C++ and Windows locale

(what is the Windows and what is the C/C++ locale btw?)

Well, this I did as in:

#--Do translator test and set
if locale.getlocale() == (None,None):
    locale.setlocale(locale.LC_ALL,u'')
initTranslator(language)

``

In the docs of locale.setlocale we read:

Applications typically start with a call of
import locale
locale.setlocale(locale.LC_ALL, ‘’)

``

This sets the locale for all categories to the user’s default setting

Then in the program, locale-aware functions are defined all over as in

def formatInteger(value):
“”“Convert integer to string formatted to locale.”“”
return decode(locale.format(‘%d’, int(value), True),
locale.getpreferredencoding())

``

Omitting the call to locale.setlocale lets the program start but I don’t believe these functions will do anything useful anymore (edit: confirmed).

There are similar questions as in python - wx.Image is throwing PyAssertionError - Stack Overflow but the solution suggested modify the locale of the wx.App while the setlocale call in my code is issued well before wx is even imported. People also use constructs as wx.Locale(wx.LANGUAGE_ENGLISH) but this is obviously a hack, I do not want to force user locale to english - for another hack see here

The initTranslator method above uses the standard gettext and msgfmt mechanism.

QUESTION

I need a standard non hacky way to replace the locale.setlocale call with the wx analog without breaking the translation and the locale aware parts of the program. I have this question for almost four years now and have found no canonical answer.

EDIT: omitting the setlocale call does not affect the translation (yey!) but does indeed break the locale aware displaying functions.

EDIT2: replacing the call above by:

-    # if locale.getlocale() == (None,None):
-    #     locale.setlocale(locale.LC_ALL,u'')
+    if locale.getlocale() == (None,None):
+        # locale.setlocale(locale.LC_ALL,u'')
+        import wx
+        wx.Locale(wx.LANGUAGE_DEFAULT)
     if not lang:

``

results in a bunch of warnings:

7:12:22 AM: Debug: …..\src\common\stdpbase.cpp(56): assert “traits” failed in wxStandardPathsBase::Get(): create wxApp before calling this
7:12:41 AM: Debug: …..\src\common\stdpbase.cpp(56): assert “traits” failed in wxStandardPathsBase::Get(): create wxApp before calling this
7:12:42 AM: Debug: …..\src\common\stdpbase.cpp(56): assert “traits” failed in wxStandardPathsBase::Get(): create wxApp before calling this
7:12:42 AM: Debug: …..\src\common\platinfo.cpp(171): assert “wxAssertFailure” failed in wxPlatformInfo::InitForCurrentPlatform(): failed to initialize wxPlatformInfo
7:12:52 AM: Debug: …..\src\common\platinfo.cpp(109): assert “value” failed in wxGetIndexFromEnumValue(): invalid enum value
7:13:12 AM: Debug: …..\src\common\platinfo.cpp(240): assert “idx < (sizeof(wxPortIdNames)/sizeof(wxPortIdNames[0]))” failed in wxPlatformInfo::GetPortIdName(): invalid port id

``

So so I have to create the wx.App (I would really like to avoid this as I want to be able to translate (possibly fatal) error messages long before wx.App is created)