Opened 7 years ago

Closed 7 years ago

#15257 closed defect (invalid)

wxLocale::Init(wxLANGUAGE_DEFAULT) is broken

Reported by: troelsk Owned by:
Priority: normal Milestone:
Component: base Version: stable-latest
Keywords: wxLocale Cc: vaclavslavik
Blocked By: Blocking:
Patch: no

Description

This is not working:

locale.Init(wxLANGUAGE_DEFAULT)

wxstd.mo is not loaded and subsequent AddCatalog() calls seems to load nothing either.

This on the other hand works fine, just as expected

locale.Init(wxLocale::GetSystemLanguage())

Attachment demonstrating this in the internat sample:
ran it on Windows, having created a folder for my system language holding both files:
wx\samples\internat\da\internat.mo
wx\samples\internat\da\wxstd.mo

Init(wxLANGUAGE_DEFAULT) in wx stable 2.8 seems to work as expected, doing the same as Init(wxLocale::GetSystemLanguage()).
The Init() codepaths in trunk and stable are quite alike, both looking equally suspicious: why hang on to and use the 'language' parm after the 'lang = GetSystemLanguage()' call

Attachments (1)

internat.cpp.patch download (1.6 KB) - added by troelsk 7 years ago.

Download all attachments as: .zip

Change History (12)

Changed 7 years ago by troelsk

comment:1 Changed 7 years ago by troelsk

System is English Win7, with *everything* in the "Region and Language" control panel applet set to "Danish". wx28 Init() on the same box does the right thing.

comment:2 follow-up: Changed 7 years ago by vadz

  • Cc vaclavslavik added

I think we need to apply this patch:

  • src/common/intl.cpp

    diff --git a/src/common/intl.cpp b/src/common/intl.cpp
    index ee790a5..fe5af06 100644
    a b bool wxLocale::Init(int language, int flags) 
    556556    if (IsOk()) // setlocale() succeeded
    557557        m_language = lang;
    558558
    559     // NB: don't use 'lang' here, 'language'
    560559    wxTranslations *t = wxTranslations::Get();
    561560    if ( t )
    562561    {
    563         t->SetLanguage(static_cast<wxLanguage>(language));
     562        t->SetLanguage(static_cast<wxLanguage>(lang));
    564563
    565564        if ( flags & wxLOCALE_LOAD_DEFAULT )
    566565            t->AddStdCatalog();

Could you please confirm that it fixes the problem?

Vaclav, what was the reasoning behind the comment that my patch above removes? Why exactly shouldn't we be using the system default language for the translations?

comment:3 in reply to: ↑ 2 Changed 7 years ago by vaclavslavik

Replying to vadz:

I think we need to apply this patch:

Please don't.

The reason why the original value of language is passed to wxTranslation is because it needs to know that the default should be used -- it has its own detection of the best UI language. The code responsible is in wxTranslations::GetBestTranslation() and it would be useful to enable the "i18n" trace logging to understand why it fails -- can you please try that and post the relevant output?

Vadim, to explain why wxTranslation shouldn't use the detected locale: locale and UI language are two different things that are decoupled on modern OSes other than Unix/Linux: both current Windows and OS X versions have independent locale and language configurations. The user is able to configure various date, currency etc. formatting preferences (i.e. the locale) as well as a list of preferred languages.

For example, I was getting en_GB translations with wx-2.8 under OS X, even though my languages preferences list was (en-US, cs, sk), simply because my locale settings better corresponded to European time & date formatting choices and so the locale's base name was (IMHO not unreasonably en_GB).

My wx-2.9 changes decoupled locale and translations into two classes; the code from your comment is compatibility code, so that older code that had no choice but to use wxLocale still works as intended -- wxLocale::Init(wxLANGUAGE_DEFAULT) should configure everything per user's default, which is not, as explained above, necessarily the same thing as "use the default locale for the language".

wxTranslations::GetBestTranslation() obtains the list of user's preferred languages (see the various platform-specific GetPreferredUILanguage implementations). It then finds all available translations for given domain and picks the best choice. This implements e.g. OS X's algorithm for choosing the language: if the user preferences are (cs, sk, en) and an app is only translated to sk, but not cs, then the sk translation is used rather than falling back to the en default. This is a Good Thing.

The trace messages should help explaining what the problem is. It may fail to obtain the languages, but I think it's more likely that it's not, for some reason, finding available languages for given domain (yes, this is domain specific, because you may have a different set of wxstd and myapp translations). It's possible that some previously supported MO files layout isn't recognized by wxFileTranslationsLoader::GetAvailableTranslations().

comment:4 Changed 7 years ago by vadz

  • Patch unset

Thanks for the explanation!

We still need to fix the bug which happens on this Danish Windows system where using wxLANGUAGE_DEFAULT should definitely result in using Danish translations but it does look like it's a bug in wxFileTranslationsLoader::GetAvailableTranslations() and not here. Could it be another consequence of the case-sensitivity in wxMSW file searching functions bug (#15243)? I.e., @troelsk, could you please retest with the latest svn? And if the bug is still there, please enable trace messages by setting WXTRACE environment variable to "i18n" and look at the debug output for the messages.

TIA!

comment:5 Changed 7 years ago by vaclavslavik

I don't think it's related to wxDir. But thanks for getting me on the right track, I think it may be because of case sensitive comparison of language codes between the available ones (determined from file names, i.e. could be messed up in a number of ways) and preferred ones.

Does this patch help?

  • src/common/translation.cpp

    diff --git a/src/common/translation.cpp b/src/common/translation.cpp
    a b wxString GetPreferredUILanguage(const wxArrayString& available) 
    155155                {
    156156                    wxString lang(*j);
    157157                    lang.Replace("-", "_");
    158                     if ( available.Index(lang) != wxNOT_FOUND )
     158                    if ( available.Index(lang, /*bCase=*/false) != wxNOT_FOUND )
    159159                        return lang;
    160160                    size_t pos = lang.find('_');
    161161                    if ( pos != wxString::npos )
    162162                    {
    163163                        lang = lang.substr(0, pos);
    164                         if ( available.Index(lang) != wxNOT_FOUND )
     164                        if ( available.Index(lang, /*bCase=*/false) != wxNOT_FOUND )
    165165                            return lang;
    166166                    }
    167167                }

comment:6 Changed 7 years ago by troelsk

No the case = false change does not help. The problems seems to be that the s_pfnGetUserPreferredUILanguages call returns only one item, "en_US" !

comment:7 Changed 7 years ago by vaclavslavik

This begs the question: is the display language really set to Danish? Not the locale stuff (Formats), but the display language on Keyboards and Languages (see http://windows.microsoft.com/en-ph/windows-vista/change-the-display-language). Can you please double-check, just to be 100% sure? Sorry for asking stupid question, but it's rather hard to believe GetUserPreferredUILanguages would be broken, everybody uses it...

comment:8 follow-up: Changed 7 years ago by troelsk

No, display language is not set on my system (the Keyboards and Languages tab says only "How can I install additional languages?")

But wxLocale::GetSystemLanguage() get it right, it returns wxLANGUAGE_DANISH.

comment:9 in reply to: ↑ 8 Changed 7 years ago by vaclavslavik

Replying to troelsk:

But wxLocale::GetSystemLanguage() get it right, it returns wxLANGUAGE_DANISH.

It doesn't get it "right" in the sense you mean -- it returns the system locale, which you have configured to be Danish. But as explained above, UI language is a whole different thing.

What language does Windows itself (e.g. Explorer or the Start menu or file open dialog) use? Is it English or Danish?

comment:10 follow-up: Changed 7 years ago by troelsk

Windows itself is English. Right, the new Init() behaviour seems to follow the Vista "Display Language" setting. Here is a code snippet for those who wants the old 2.8 behavious,

class wxLocaleEx : public wxLocale
{
public:
    bool Init(wxLanguage lang = wxLANGUAGE_DEFAULT, int flags = wxLOCALE_LOAD_DEFAULT)
    {
    #if (wxVERSION_NUMBER >= 2900) // trac.wxwidgets.org/ticket/15257
        if (lang == wxLANGUAGE_DEFAULT)
            lang = (wxLanguage)GetSystemLanguage();
    #endif
        return wxLocale::Init(lang, flags);
    }
};

comment:11 in reply to: ↑ 10 Changed 7 years ago by vaclavslavik

  • Resolution set to invalid
  • Status changed from new to closed

Replying to troelsk:

Windows itself is English.

IOW, the language picked is actually correct, thanks.

Here is a code snippet for those who wants the old 2.8 behavious,

Be advised that while you may think it's preferable, your users almost certainly don't and insisting on preserving the broken 2.8 behavior would be doing them disservice (just ask Google about "GetUserPreferredUILanguages" if you want to hear the same from other people). Consider offering a way to override the auto-detected language in your application instead.

Note: See TracTickets for help on using tickets.