Improve wxLocale backwards compatibility and enhance wxUILocale
Restore the old behaviour of wxLocale, which is supposed to use the default locale and not the preferred language, which may not be the same (see #22281). Also apply the following fixes and improvements to wxUILocale: - Add new GetSystemLocale() method. - Change the MSW implementation to use the default locale instead of the preferred UI language for Windows versions below Windows 10. - Change the Unix implementation to respect LANGUAGE environment variable and use it for determining the preferred UI languages. - Use wxUILocale in wxTranslations to determine the preferred UI languages. - Use wxUILocale during initialization of internat sample. Closes #22281. Closes #22318.
This commit is contained in:
parent
4a3098aebb
commit
8ab635b451
@ -159,9 +159,13 @@ public:
|
||||
~wxUILocale();
|
||||
|
||||
// Try to get user's (or OS's) preferred language setting.
|
||||
// Return wxLANGUAGE_UNKNOWN if language-guessing algorithm failed
|
||||
// Return wxLANGUAGE_UNKNOWN if the language-guessing algorithm failed
|
||||
static int GetSystemLanguage();
|
||||
|
||||
// Try to get user's (or OS's) default locale setting.
|
||||
// Return wxLANGUAGE_UNKNOWN if the locale-guessing algorithm failed
|
||||
static int GetSystemLocale();
|
||||
|
||||
// Try to retrieve a list of user's (or OS's) preferred UI languages.
|
||||
// Return empty list if language-guessing algorithm failed
|
||||
static wxVector<wxString> GetPreferredUILanguages();
|
||||
|
@ -278,20 +278,37 @@ public:
|
||||
static wxString GetLanguageCanonicalName(int lang);
|
||||
|
||||
/**
|
||||
Tries to detect the user's default locale setting.
|
||||
Tries to detect the user's default user interface language setting.
|
||||
|
||||
Returns the ::wxLanguage value or @c wxLANGUAGE_UNKNOWN if the language-guessing
|
||||
algorithm failed.
|
||||
|
||||
@note Where possible this function returns the user's preferred UI @em language.
|
||||
This may be, and usually is, the same as the user's default locale, but it's
|
||||
not the same thing. If retrieving the preferred UI language is not supported
|
||||
by the operating system (for example, Windows 7 and below), the user's
|
||||
default @em locale will be used.
|
||||
|
||||
@see wxTranslations::GetBestTranslation().
|
||||
*/
|
||||
static int GetSystemLanguage();
|
||||
|
||||
/**
|
||||
Tries to detect the user's default locale setting.
|
||||
|
||||
Returns the ::wxLanguage value or @c wxLANGUAGE_UNKNOWN if the locale-guessing
|
||||
algorithm failed.
|
||||
|
||||
@note This function works with @em locales and returns the user's default
|
||||
locale. This may be, and usually is, the same as their preferred UI
|
||||
language, but it's not the same thing. Use wxTranslation to obtain
|
||||
@em language information.
|
||||
|
||||
@since 3.1.7
|
||||
|
||||
@see wxTranslations::GetBestTranslation().
|
||||
*/
|
||||
static int GetSystemLanguage();
|
||||
};
|
||||
static int GetSystemLocale();};
|
||||
|
||||
/**
|
||||
Return the format to use for formatting user-visible dates.
|
||||
|
@ -207,10 +207,10 @@ bool MyApp::OnInit()
|
||||
// it unconditionally for localized programs -- or never do it at all for
|
||||
// the other ones.
|
||||
const wxLanguageInfo* const
|
||||
langInfo = wxLocale::GetLanguageInfo(wxLANGUAGE_DEFAULT);
|
||||
langInfo = wxUILocale::GetLanguageInfo(wxLANGUAGE_DEFAULT);
|
||||
const wxString
|
||||
langDesc = langInfo ? langInfo->Description
|
||||
: wxString("the default system locale");
|
||||
: wxString("the default system language");
|
||||
|
||||
if ( m_setLocale == Locale_Ask )
|
||||
{
|
||||
|
@ -513,7 +513,10 @@ bool wxLocale::Init(int lang, int flags)
|
||||
/*static*/
|
||||
int wxLocale::GetSystemLanguage()
|
||||
{
|
||||
return wxUILocale::GetSystemLanguage();
|
||||
// Despite the method name wxLocale always determines the system language
|
||||
// based on the default user locale (and not the preferred UI language).
|
||||
// Therefore we need to call wxUILocale::GetSystemLocale() here.
|
||||
return wxUILocale::GetSystemLocale();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -679,6 +682,12 @@ void wxLocale::AddLanguage(const wxLanguageInfo& info)
|
||||
/* static */
|
||||
const wxLanguageInfo* wxLocale::GetLanguageInfo(int lang)
|
||||
{
|
||||
// We need to explicitly handle the case "lang == wxLANGUAGE_DEFAULT" here,
|
||||
// because wxUILocale::GetLanguageInfo() determines the system language
|
||||
// based on the the preferred UI language while wxLocale uses the default
|
||||
// user locale for that purpose.
|
||||
if (lang == wxLANGUAGE_DEFAULT)
|
||||
lang = GetSystemLanguage();
|
||||
return wxUILocale::GetLanguageInfo(lang);
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "wx/stdpaths.h"
|
||||
#include "wx/version.h"
|
||||
#include "wx/private/threadinfo.h"
|
||||
#include "wx/uilocale.h"
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include "wx/dynlib.h"
|
||||
@ -54,11 +55,6 @@
|
||||
#include "wx/msw/wrapwin.h"
|
||||
#include "wx/msw/missing.h"
|
||||
#endif
|
||||
#ifdef __WXOSX__
|
||||
#include "wx/osx/core/cfstring.h"
|
||||
#include <CoreFoundation/CFBundle.h>
|
||||
#include <CoreFoundation/CFLocale.h>
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// simple types
|
||||
@ -96,11 +92,23 @@ wxStringToStringHashMap gs_msgIdCharset;
|
||||
|
||||
#if wxUSE_LOG_TRACE
|
||||
|
||||
void LogTraceArray(const char *prefix, const wxArrayString& arr)
|
||||
void LogTraceArray(const char* prefix, const wxArrayString& arr)
|
||||
{
|
||||
wxLogTrace(TRACE_I18N, "%s: [%s]", prefix, wxJoin(arr, ','));
|
||||
}
|
||||
|
||||
void LogTraceArray(const char *prefix, const wxVector<wxString>& arr)
|
||||
{
|
||||
wxString s;
|
||||
for (wxVector<wxString>::const_iterator j = arr.begin(); j != arr.end(); ++j)
|
||||
{
|
||||
if (j != arr.begin())
|
||||
s += ",";
|
||||
s += *j;
|
||||
}
|
||||
wxLogTrace(TRACE_I18N, "%s: [%s]", prefix, s);
|
||||
}
|
||||
|
||||
void LogTraceLargeArray(const wxString& prefix, const wxArrayString& arr)
|
||||
{
|
||||
wxLogTrace(TRACE_I18N, "%s:", prefix);
|
||||
@ -118,184 +126,58 @@ void LogTraceLargeArray(const wxString& prefix, const wxArrayString& arr)
|
||||
// Use locale-based detection as a fallback
|
||||
wxString GetPreferredUILanguageFallback(const wxArrayString& WXUNUSED(available))
|
||||
{
|
||||
const wxString lang = wxLocale::GetLanguageCanonicalName(wxLocale::GetSystemLanguage());
|
||||
const wxString lang = wxUILocale::GetLanguageCanonicalName(wxUILocale::GetSystemLocale());
|
||||
wxLogTrace(TRACE_I18N, " - obtained best language from locale: %s", lang);
|
||||
return lang;
|
||||
}
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
|
||||
wxString GetPreferredUILanguage(const wxArrayString& available)
|
||||
{
|
||||
typedef BOOL (WINAPI *GetUserPreferredUILanguages_t)(DWORD, PULONG, PWSTR, PULONG);
|
||||
static GetUserPreferredUILanguages_t s_pfnGetUserPreferredUILanguages = NULL;
|
||||
static bool s_initDone = false;
|
||||
if ( !s_initDone )
|
||||
{
|
||||
wxLoadedDLL dllKernel32("kernel32.dll");
|
||||
wxDL_INIT_FUNC(s_pfn, GetUserPreferredUILanguages, dllKernel32);
|
||||
s_initDone = true;
|
||||
}
|
||||
wxVector<wxString> preferred = wxUILocale::GetPreferredUILanguages();
|
||||
LogTraceArray(" - system preferred languages", preferred);
|
||||
|
||||
if ( s_pfnGetUserPreferredUILanguages )
|
||||
{
|
||||
ULONG numLangs;
|
||||
ULONG bufferSize = 0;
|
||||
if ( s_pfnGetUserPreferredUILanguages(MUI_LANGUAGE_NAME,
|
||||
&numLangs,
|
||||
NULL,
|
||||
&bufferSize) )
|
||||
{
|
||||
wxScopedArray<WCHAR> langs(bufferSize);
|
||||
if ( s_pfnGetUserPreferredUILanguages(MUI_LANGUAGE_NAME,
|
||||
&numLangs,
|
||||
langs.get(),
|
||||
&bufferSize) )
|
||||
{
|
||||
wxArrayString preferred;
|
||||
|
||||
WCHAR *buf = langs.get();
|
||||
for ( unsigned i = 0; i < numLangs; i++ )
|
||||
{
|
||||
const wxString lang(buf);
|
||||
preferred.push_back(lang);
|
||||
buf += lang.length() + 1;
|
||||
}
|
||||
LogTraceArray(" - system preferred languages", preferred);
|
||||
|
||||
for ( wxArrayString::const_iterator j = preferred.begin();
|
||||
j != preferred.end();
|
||||
++j )
|
||||
{
|
||||
wxString lang(*j);
|
||||
lang.Replace("-", "_");
|
||||
if ( available.Index(lang, /*bCase=*/false) != wxNOT_FOUND )
|
||||
return lang;
|
||||
size_t pos = lang.find('_');
|
||||
if ( pos != wxString::npos )
|
||||
{
|
||||
lang = lang.substr(0, pos);
|
||||
if ( available.Index(lang, /*bCase=*/false) != wxNOT_FOUND )
|
||||
return lang;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GetPreferredUILanguageFallback(available);
|
||||
}
|
||||
|
||||
#elif defined(__WXOSX__)
|
||||
|
||||
#if wxUSE_LOG_TRACE
|
||||
|
||||
void LogTraceArray(const char *prefix, CFArrayRef arr)
|
||||
{
|
||||
wxString s;
|
||||
const unsigned count = CFArrayGetCount(arr);
|
||||
if ( count )
|
||||
{
|
||||
s += wxCFStringRef::AsString((CFStringRef)CFArrayGetValueAtIndex(arr, 0));
|
||||
for ( unsigned i = 1 ; i < count; i++ )
|
||||
s += "," + wxCFStringRef::AsString((CFStringRef)CFArrayGetValueAtIndex(arr, i));
|
||||
}
|
||||
wxLogTrace(TRACE_I18N, "%s: [%s]", prefix, s);
|
||||
}
|
||||
|
||||
#endif // wxUSE_LOG_TRACE
|
||||
|
||||
wxString GetPreferredUILanguage(const wxArrayString& available)
|
||||
{
|
||||
wxStringToStringHashMap availableNormalized;
|
||||
wxCFRef<CFMutableArrayRef> availableArr(
|
||||
CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
|
||||
|
||||
for ( wxArrayString::const_iterator i = available.begin();
|
||||
i != available.end();
|
||||
++i )
|
||||
{
|
||||
wxString lang(*i);
|
||||
wxCFStringRef code_wx(*i);
|
||||
wxCFStringRef code_norm(
|
||||
CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorDefault, code_wx));
|
||||
CFArrayAppendValue(availableArr, code_norm);
|
||||
availableNormalized[code_norm.AsString()] = *i;
|
||||
}
|
||||
LogTraceArray(" - normalized available list", availableArr);
|
||||
|
||||
wxCFRef<CFArrayRef> prefArr(
|
||||
CFBundleCopyLocalizationsForPreferences(availableArr, NULL));
|
||||
LogTraceArray(" - system preferred languages", prefArr);
|
||||
|
||||
unsigned prefArrLength = CFArrayGetCount(prefArr);
|
||||
if ( prefArrLength > 0 )
|
||||
{
|
||||
// Lookup the name in 'available' by index -- we need to get the
|
||||
// original value corresponding to the normalized one chosen.
|
||||
wxString lang(wxCFStringRef::AsString((CFStringRef)CFArrayGetValueAtIndex(prefArr, 0)));
|
||||
wxStringToStringHashMap::const_iterator i = availableNormalized.find(lang);
|
||||
if ( i == availableNormalized.end() )
|
||||
return lang;
|
||||
else
|
||||
return i->second;
|
||||
}
|
||||
|
||||
return GetPreferredUILanguageFallback(available);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// When the preferred UI language is determined, the LANGUAGE environment
|
||||
// variable is the primary source of preference.
|
||||
// http://www.gnu.org/software/gettext/manual/html_node/Locale-Environment-Variables.html
|
||||
//
|
||||
// The LANGUAGE variable may contain a colon separated list of language
|
||||
// codes in the order of preference.
|
||||
// http://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html
|
||||
wxString GetPreferredUILanguage(const wxArrayString& available)
|
||||
{
|
||||
wxString languageFromEnv;
|
||||
wxArrayString preferred;
|
||||
if ( wxGetEnv("LANGUAGE", &languageFromEnv) )
|
||||
{
|
||||
wxStringTokenizer tknzr(languageFromEnv, ":");
|
||||
while ( tknzr.HasMoreTokens() )
|
||||
{
|
||||
const wxString tok = tknzr.GetNextToken();
|
||||
if ( const wxLanguageInfo *li = wxLocale::FindLanguageInfo(tok) )
|
||||
{
|
||||
preferred.push_back(li->CanonicalName);
|
||||
}
|
||||
}
|
||||
if ( preferred.empty() )
|
||||
{
|
||||
wxLogTrace(TRACE_I18N, " - LANGUAGE was set, but it didn't contain any languages recognized by the system");
|
||||
}
|
||||
}
|
||||
|
||||
LogTraceArray(" - preferred languages from environment", preferred);
|
||||
for ( wxArrayString::const_iterator j = preferred.begin();
|
||||
wxString langNoMatchRegion;
|
||||
for ( wxVector<wxString>::const_iterator j = preferred.begin();
|
||||
j != preferred.end();
|
||||
++j )
|
||||
{
|
||||
wxString lang(*j);
|
||||
if ( available.Index(lang) != wxNOT_FOUND )
|
||||
wxLocaleIdent localeId = wxLocaleIdent::FromTag(*j);
|
||||
wxString lang = localeId.GetTag(wxLOCALE_TAGTYPE_POSIX);
|
||||
|
||||
if (available.Index(lang, /*bCase=*/false) != wxNOT_FOUND)
|
||||
return lang;
|
||||
|
||||
size_t pos = lang.find('_');
|
||||
if ( pos != wxString::npos )
|
||||
if (pos != wxString::npos)
|
||||
{
|
||||
lang = lang.substr(0, pos);
|
||||
if ( available.Index(lang) != wxNOT_FOUND )
|
||||
if (available.Index(lang, /*bCase=*/false) != wxNOT_FOUND)
|
||||
return lang;
|
||||
}
|
||||
|
||||
if (langNoMatchRegion.empty())
|
||||
{
|
||||
// lang now holds only the language
|
||||
// check for an available language with potentially non-matching region
|
||||
for ( wxArrayString::const_iterator k = available.begin();
|
||||
k != available.end();
|
||||
++k )
|
||||
{
|
||||
if ((*k).Lower().StartsWith(lang.Lower()))
|
||||
{
|
||||
langNoMatchRegion = *k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!langNoMatchRegion.empty())
|
||||
return langNoMatchRegion;
|
||||
|
||||
return GetPreferredUILanguageFallback(available);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -1501,7 +1383,7 @@ void wxTranslations::SetLanguage(wxLanguage lang)
|
||||
if ( lang == wxLANGUAGE_DEFAULT )
|
||||
SetLanguage(wxString());
|
||||
else
|
||||
SetLanguage(wxLocale::GetLanguageCanonicalName(lang));
|
||||
SetLanguage(wxUILocale::GetLanguageCanonicalName(lang));
|
||||
}
|
||||
|
||||
void wxTranslations::SetLanguage(const wxString& lang)
|
||||
@ -1546,7 +1428,7 @@ bool wxTranslations::AddCatalog(const wxString& domain,
|
||||
bool wxTranslations::AddCatalog(const wxString& domain,
|
||||
wxLanguage msgIdLanguage)
|
||||
{
|
||||
const wxString msgIdLang = wxLocale::GetLanguageCanonicalName(msgIdLanguage);
|
||||
const wxString msgIdLang = wxUILocale::GetLanguageCanonicalName(msgIdLanguage);
|
||||
const wxString domain_lang = GetBestTranslation(domain, msgIdLang);
|
||||
|
||||
if ( domain_lang.empty() )
|
||||
@ -1641,7 +1523,7 @@ bool wxTranslations::IsLoaded(const wxString& domain) const
|
||||
wxString wxTranslations::GetBestTranslation(const wxString& domain,
|
||||
wxLanguage msgIdLanguage)
|
||||
{
|
||||
const wxString lang = wxLocale::GetLanguageCanonicalName(msgIdLanguage);
|
||||
const wxString lang = wxUILocale::GetLanguageCanonicalName(msgIdLanguage);
|
||||
return GetBestTranslation(domain, lang);
|
||||
}
|
||||
|
||||
|
@ -652,7 +652,7 @@ int wxUILocale::GetSystemLanguage()
|
||||
}
|
||||
if (pos != wxString::npos)
|
||||
{
|
||||
if (languagesDB[ixLanguage].LocaleTag == lang)
|
||||
if (languagesDB[ixLanguage].LocaleTag == langShort)
|
||||
{
|
||||
ixShort = ixLanguage;
|
||||
}
|
||||
@ -664,8 +664,20 @@ int wxUILocale::GetSystemLanguage()
|
||||
}
|
||||
}
|
||||
|
||||
// no info about this language in the database
|
||||
return wxLANGUAGE_UNKNOWN;
|
||||
// no info about the preferred UI language in the database
|
||||
// fall back to default locale
|
||||
return GetSystemLocale();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
int wxUILocale::GetSystemLocale()
|
||||
{
|
||||
// Create default wxUILocale
|
||||
wxUILocale defaultLocale(wxUILocaleImpl::CreateUserDefault());
|
||||
|
||||
// Find corresponding wxLanguageInfo
|
||||
const wxLanguageInfo* defaultLanguage = wxUILocale::FindLanguageInfo(defaultLocale.GetLocaleId());
|
||||
return defaultLanguage ? defaultLanguage->Language : wxLANGUAGE_UNKNOWN;
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -32,6 +32,10 @@
|
||||
#define LOCALE_NAME_USER_DEFAULT NULL
|
||||
#endif
|
||||
|
||||
#ifndef LOCALE_NAME_MAX_LENGTH
|
||||
#define LOCALE_NAME_MAX_LENGTH 85
|
||||
#endif
|
||||
|
||||
#ifndef MUI_LANGUAGE_NAME
|
||||
#define MUI_LANGUAGE_NAME 8
|
||||
#endif
|
||||
@ -398,6 +402,9 @@ public:
|
||||
wxDL_INIT_FUNC(ms_, GetUserPreferredUILanguages, dllKernel32);
|
||||
if (!ms_GetUserPreferredUILanguages)
|
||||
return false;
|
||||
wxDL_INIT_FUNC(ms_, GetUserDefaultLocaleName, dllKernel32);
|
||||
if (!ms_GetUserDefaultLocaleName)
|
||||
return false;
|
||||
|
||||
wxDL_INIT_FUNC(ms_, CompareStringEx, dllKernel32);
|
||||
if ( !ms_CompareStringEx )
|
||||
@ -415,19 +422,29 @@ public:
|
||||
|
||||
if (CanUse())
|
||||
{
|
||||
ULONG numberOfLanguages = 0;
|
||||
ULONG bufferSize = 0;
|
||||
if (ms_GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numberOfLanguages, NULL, &bufferSize))
|
||||
// Check if Windows supports preferred UI languages.
|
||||
// Note: Windows 8.x might support them as well, but Windows 7
|
||||
// and below definitely do not.
|
||||
if (wxGetWinVersion() >= wxWinVersion_10)
|
||||
{
|
||||
wxScopedArray<WCHAR> languages(bufferSize);
|
||||
if (ms_GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numberOfLanguages, languages.get(), &bufferSize))
|
||||
ULONG numberOfLanguages = 0;
|
||||
ULONG bufferSize = 0;
|
||||
if (ms_GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numberOfLanguages, NULL, &bufferSize))
|
||||
{
|
||||
WCHAR* buf = languages.get();
|
||||
for (unsigned k = 0; k < numberOfLanguages; ++k)
|
||||
wxScopedArray<WCHAR> languages(bufferSize);
|
||||
if (ms_GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numberOfLanguages, languages.get(), &bufferSize))
|
||||
{
|
||||
const wxString language(buf);
|
||||
preferred.push_back(language);
|
||||
buf += language.length() + 1;
|
||||
WCHAR* buf = languages.get();
|
||||
for (unsigned k = 0; k < numberOfLanguages; ++k)
|
||||
{
|
||||
const wxString language(buf);
|
||||
preferred.push_back(language);
|
||||
buf += language.length() + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogLastError(wxT("GetUserPreferredUILanguages"));
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -437,7 +454,16 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogLastError(wxT("GetUserPreferredUILanguages"));
|
||||
// Use the default user locale for Windows 7 resp Windows 8.x and below
|
||||
wchar_t buf[LOCALE_NAME_MAX_LENGTH];
|
||||
if (!ms_GetUserDefaultLocaleName(buf, LOCALE_NAME_MAX_LENGTH))
|
||||
{
|
||||
preferred.push_back(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogLastError(wxT("GetUserDefaultLocaleName"));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -724,6 +750,9 @@ private:
|
||||
typedef BOOL (WINAPI *GetUserPreferredUILanguages_t)(DWORD, ULONG*, WCHAR*, ULONG*);
|
||||
static GetUserPreferredUILanguages_t ms_GetUserPreferredUILanguages;
|
||||
|
||||
typedef int (WINAPI* GetUserDefaultLocaleName_t)(LPWSTR, int);
|
||||
static GetUserDefaultLocaleName_t ms_GetUserDefaultLocaleName;
|
||||
|
||||
// Note: we currently don't use NLSVERSIONINFO output parameter and so we
|
||||
// don't bother dealing with the different sizes of this struct under
|
||||
// different OS versions and define the function type as using "void*" to
|
||||
@ -766,6 +795,7 @@ private:
|
||||
wxUILocaleImplName::GetLocaleInfoEx_t wxUILocaleImplName::ms_GetLocaleInfoEx;
|
||||
wxUILocaleImplName::SetThreadPreferredUILanguages_t wxUILocaleImplName::ms_SetThreadPreferredUILanguages;
|
||||
wxUILocaleImplName::GetUserPreferredUILanguages_t wxUILocaleImplName::ms_GetUserPreferredUILanguages;
|
||||
wxUILocaleImplName::GetUserDefaultLocaleName_t wxUILocaleImplName::ms_GetUserDefaultLocaleName;
|
||||
wxUILocaleImplName::CompareStringEx_t wxUILocaleImplName::ms_CompareStringEx;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include "wx/unix/private/uilocale.h"
|
||||
|
||||
#include "wx/intl.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/tokenzr.h"
|
||||
#include "wx/utils.h"
|
||||
|
||||
#include <locale.h>
|
||||
@ -33,6 +35,8 @@
|
||||
#include <langinfo.h>
|
||||
#endif
|
||||
|
||||
#define TRACE_I18N wxS("i18n")
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
@ -559,6 +563,32 @@ wxVector<wxString> wxUILocaleImpl::GetPreferredUILanguages()
|
||||
{
|
||||
wxVector<wxString> preferred;
|
||||
|
||||
// When the preferred UI language is determined, the LANGUAGE environment
|
||||
// variable is the primary source of preference.
|
||||
// http://www.gnu.org/software/gettext/manual/html_node/Locale-Environment-Variables.html
|
||||
//
|
||||
// The LANGUAGE variable may contain a colon separated list of language
|
||||
// codes in the order of preference.
|
||||
// http://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html
|
||||
wxString languageFromEnv;
|
||||
if (wxGetNonEmptyEnvVar("LANGUAGE", &languageFromEnv))
|
||||
{
|
||||
wxStringTokenizer tknzr(languageFromEnv, ":");
|
||||
while (tknzr.HasMoreTokens())
|
||||
{
|
||||
const wxString tok = tknzr.GetNextToken();
|
||||
if (const wxLanguageInfo* li = wxUILocale::FindLanguageInfo(tok))
|
||||
{
|
||||
preferred.push_back(li->CanonicalName);
|
||||
}
|
||||
}
|
||||
if (!preferred.empty())
|
||||
return preferred;
|
||||
wxLogTrace(TRACE_I18N, " - LANGUAGE was set, but it didn't contain any languages recognized by the system");
|
||||
}
|
||||
|
||||
wxLogTrace(TRACE_I18N, " - LANGUAGE was not set or empty, check LC_ALL, LC_MESSAGES, and LANG");
|
||||
|
||||
// first get the string identifying the language from the environment
|
||||
wxString langFull;
|
||||
if (!wxGetNonEmptyEnvVar(wxS("LC_ALL"), &langFull) &&
|
||||
|
Loading…
Reference in New Issue
Block a user