wxLocale and static wxString's translation

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
ollydbg23
Super wx Problem Solver
Super wx Problem Solver
Posts: 438
Joined: Fri Dec 12, 2008 10:31 am

wxLocale and static wxString's translation

Post by ollydbg23 »

Hi, What is the best place to set the language translation initialization?

For me, I have initialization the language here:

Code: Select all

bool MainApp::OnInit()
{
    int sysLang =  wxLocale::GetSystemLanguage();
    m_locale.Init(sysLang, wxLOCALE_LOAD_DEFAULT);
    wxLocale::AddCatalogLookupPathPrefix("yyyyy");
    if(!m_locale.AddCatalog("xxx.mo", xxxxx))
    {
        wxMessageBox("Can not load locals files");
    }
    ...
While, in some other cpp files, I have some static wxString members, such as:

Code: Select all

wxString SomeClass::m_Text = _("hello world");
But as the m_Text is a static member, it initialized before the MainApp::OnInit() function call.

So, my question is: What is the best place to initialize the language translation?

One possible way is to set this static member variable after MainApp::OnInit() function call, that it means I have to set this static member string twice. Any ideas? Thanks.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxLocale and static wxString's translation

Post by PB »

I think the only other way besides initializing the string after the locale is set would be something like the code here
https://docs.wxwidgets.org/trunk/group_ ... 5ae9e14c45
ollydbg23
Super wx Problem Solver
Super wx Problem Solver
Posts: 438
Joined: Fri Dec 12, 2008 10:31 am

Re: wxLocale and static wxString's translation

Post by ollydbg23 »

Thanks for the suggestion.
PB wrote: Thu Apr 02, 2020 7:10 am I think the only other way besides initializing the string after the locale is set would be something like the code here
https://docs.wxwidgets.org/trunk/group_ ... 5ae9e14c45
I'm a little puzzled, that:

I see the link suggest such usage:

Code: Select all

static const char * const elements[] = { wxTRANSLATE("Hydrogen"), wxTRANSLATE("Helium"), ... };
 ...
// use wxGetTranslation(elements[n])
But I see this still works:

Code: Select all

static const char * const elements[] = { _("Hydrogen"), _("Helium"), ... };
 ...
// use wxGetTranslation(elements[n])
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxLocale and static wxString's translation

Post by PB »

You mean it works when you only use _() when initializing elements and never calling wxGetTranslation()/_() on it?

I did not test it but TBH I find it suprising, unless elements is local and hence initialized after the locale is changed, i.e., when a function where it is defined is called for the first time...


EDIT
Does not work for me without wxGetTranslation(). Running this

Code: Select all

#include <wx/wx.h>

class MyDialog : public wxDialog
{
public:
    MyDialog(): wxDialog(nullptr, wxID_ANY, "Test")
    {
        wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);

        wxButton* button = new wxButton(this, wxID_ANY, "Show strings");
        mainSizer->Add(button, wxSizerFlags().Expand().Border());
        button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyDialog::OnShowStrings, this);

        wxTextCtrl* logCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2);
        mainSizer->Add(logCtrl, wxSizerFlags().Proportion(1).Expand().Border());        
        wxLog::DisableTimestamp();
        wxLog::SetActiveTarget(new wxLogTextCtrl(logCtrl));    

        SetSizer(mainSizer);
    }	
private:
    static const char* ms_staticStr1;
    static const char* ms_staticStr2;
    
    void OnShowStrings(wxCommandEvent&)
    {    
        wxLogMessage("ms_staticStr1: %s", ms_staticStr1);        
        
        wxLogMessage("wxGetTranslation(ms_staticStr1): %s", wxGetTranslation(ms_staticStr1));
        wxLogMessage("wxGetTranslation(ms_staticStr2): %s", wxGetTranslation(ms_staticStr2));
    }
};

const char* MyDialog::ms_staticStr1 = _("ms_staticStr1 English");
const char* MyDialog::ms_staticStr2 = wxTRANSLATE("ms_staticStr2 English");

class MyApp : public wxApp
{
public:
    bool OnInit() override
    {
        wxLog::AddTraceMask(wxS("i18n"));

        if ( !m_locale.Init(wxLANGUAGE_CZECH) )
        {
            return false;
        }
        
        wxLocale::AddCatalogLookupPathPrefix(".");
        m_locale.AddCatalog("minimal");    
        m_locale.AddCatalog("wxstd");

        MyDialog().ShowModal();
        return false;
    }
private:
    wxLocale m_locale;
}; wxIMPLEMENT_APP(MyApp);
I get this

Code: Select all

ms_staticStr1: ms_staticStr1 English
wxGetTranslation(ms_staticStr1): ms_staticStr1 CZECH
wxGetTranslation(ms_staticStr2): ms_staticStr2 CZECH
ollydbg23
Super wx Problem Solver
Super wx Problem Solver
Posts: 438
Joined: Fri Dec 12, 2008 10:31 am

Re: wxLocale and static wxString's translation

Post by ollydbg23 »

PB wrote: Thu Apr 02, 2020 4:04 pm You mean it works when you only use _() when initializing elements and never calling wxGetTranslation()/_() on it?
I mean I use _() in the initialization of the static string instead of wxTRANSLATE(), and later I call wxGetTranslation() on the string.
I mean using _() is still OK, but we must call wxGetTranslation() later.

But the link https://docs.wxwidgets.org/trunk/group_ ... 5ae9e14c45
says we must use wxTRANSLATE() for the initialization of the static string, and later call wxGetTranslation() on the string.

And I see that in your below example, you have test both _() and wxTRANSLATE() cases, and the result is the same.

Code: Select all

const char* MyDialog::ms_staticStr1 = _("ms_staticStr1 English");
const char* MyDialog::ms_staticStr2 = wxTRANSLATE("ms_staticStr2 English");
result:

Code: Select all

wxGetTranslation(ms_staticStr1): ms_staticStr1 CZECH
wxGetTranslation(ms_staticStr2): ms_staticStr2 CZECH
Thanks for your time and effort to test it.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxLocale and static wxString's translation

Post by doublemax »

The main issue is still that if you use _() for global variables, wxWidgets functions will be called before wxWidgets itself is initialized. Which may work or not and should be avoided.

In general, there shall be no global variable of a non-trivial wxWidgets class.
Use the source, Luke!
ollydbg23
Super wx Problem Solver
Super wx Problem Solver
Posts: 438
Joined: Fri Dec 12, 2008 10:31 am

Re: wxLocale and static wxString's translation

Post by ollydbg23 »

doublemax wrote: Thu Apr 02, 2020 11:40 pm The main issue is still that if you use _() for global variables, wxWidgets functions will be called before wxWidgets itself is initialized. Which may work or not and should be avoided.
I see, thanks.
In general, there shall be no global variable of a non-trivial wxWidgets class.
So, you suggest that using wxString as static member of a class is not a good idea?

Well, I do need to share some const strings(wxString) between classes, any good way to avoid this issue?
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7477
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxLocale and static wxString's translation

Post by ONEEYEMAN »

Hi,
What's wrong with passing it between functions as parameters?

And yes - static variable of all wx classes, but wxApp-descendant should be avoided.

Thank you.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxLocale and static wxString's translation

Post by doublemax »

Well, I do need to share some const strings(wxString) between classes, any good way to avoid this issue?
Initialize them at run-time, e.g. with a static Init() function you call from wxApp::OnInit()
Use the source, Luke!
ollydbg23
Super wx Problem Solver
Super wx Problem Solver
Posts: 438
Joined: Fri Dec 12, 2008 10:31 am

Re: wxLocale and static wxString's translation

Post by ollydbg23 »

doublemax wrote: Fri Apr 03, 2020 12:21 am
Well, I do need to share some const strings(wxString) between classes, any good way to avoid this issue?
Initialize them at run-time, e.g. with a static Init() function you call from wxApp::OnInit()
OK, I understand, thanks.

The steps are:
1, leave the static member string as empty string in cpp, this way, the wxString default constructor will be call when initialized.

Code: Select all

wxString MyClass::s_String;
2, define a static member function like: MyClass::InitializedStaticString()

Code: Select all

MyClass::InitializedStaticString()
{
	s_String = _("XXX");
}
3, call this static function after I initialized the wxLocale staff in wxApp::OnInit().
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7477
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxLocale and static wxString's translation

Post by ONEEYEMAN »

Hi,
Why not just make it a member of wxApp-derived class and then make a getter/setter pair?

Thank you.
ollydbg23
Super wx Problem Solver
Super wx Problem Solver
Posts: 438
Joined: Fri Dec 12, 2008 10:31 am

Re: wxLocale and static wxString's translation

Post by ollydbg23 »

ONEEYEMAN wrote: Fri Apr 03, 2020 3:30 am Hi,
Why not just make it a member of wxApp-derived class and then make a getter/setter pair?

Thank you.
Hi, ONEEYEMAN, a bit late reply.
In-fact, I have a string array which is used to construct a wxChoice list in a setting dialog or a panel. I don't think this string array should belong to a wxApp-derived class.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7477
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxLocale and static wxString's translation

Post by ONEEYEMAN »

Hi,
No it shouldn't.

Look at the widgets sample. It has a code showing how to implement it without using static variable.

Thank you.
ollydbg23
Super wx Problem Solver
Super wx Problem Solver
Posts: 438
Joined: Fri Dec 12, 2008 10:31 am

Re: wxLocale and static wxString's translation

Post by ollydbg23 »

ONEEYEMAN wrote: Wed Apr 08, 2020 3:06 pm Hi,
No it shouldn't.

Look at the widgets sample. It has a code showing how to implement it without using static variable.

Thank you.
Which sample? Thanks.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7477
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxLocale and static wxString's translation

Post by ONEEYEMAN »

Hi,
widgets sample.
Found in the wxWidgets\samples\widgets.

Thank you.
Post Reply