Support creating Unix wxUILocale for languages without region
Unlike MSW and macOS, creating wxUILocale for e.g. "en" doesn't necessarily succeed under Linux even if "en_US" is available, so try to find a working language+region combination if just language doesn't work. This requires access to the languages database, so add a private wxGetLanguageInfos() to avoid having to depend on wxLocale just for this.
This commit is contained in:
@@ -12,6 +12,12 @@
|
|||||||
|
|
||||||
#include "wx/localedefs.h"
|
#include "wx/localedefs.h"
|
||||||
#include "wx/string.h"
|
#include "wx/string.h"
|
||||||
|
#include "wx/vector.h"
|
||||||
|
|
||||||
|
typedef wxVector<wxLanguageInfo> wxLanguageInfos;
|
||||||
|
|
||||||
|
// Return the vector of all known languages.
|
||||||
|
const wxLanguageInfos& wxGetLanguageInfos();
|
||||||
|
|
||||||
// Function returning hard-coded values for the "C" locale.
|
// Function returning hard-coded values for the "C" locale.
|
||||||
wxString wxGetStdCLocaleInfo(wxLocaleInfo index, wxLocaleCategory cat);
|
wxString wxGetStdCLocaleInfo(wxLocaleInfo index, wxLocaleCategory cat);
|
||||||
|
@@ -51,7 +51,8 @@
|
|||||||
#include "wx/stdpaths.h"
|
#include "wx/stdpaths.h"
|
||||||
#include "wx/hashset.h"
|
#include "wx/hashset.h"
|
||||||
#include "wx/uilocale.h"
|
#include "wx/uilocale.h"
|
||||||
#include "wx/vector.h"
|
|
||||||
|
#include "wx/private/uilocale.h"
|
||||||
|
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
#include "wx/msw/private/uilocale.h"
|
#include "wx/msw/private/uilocale.h"
|
||||||
@@ -193,9 +194,16 @@ wxString wxLanguageInfo::GetLocaleName() const
|
|||||||
// wxLocale
|
// wxLocale
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
static wxVector<wxLanguageInfo> gs_languagesDB;
|
static wxLanguageInfos gs_languagesDB;
|
||||||
static bool gs_languagesDBInitialized = false;
|
static bool gs_languagesDBInitialized = false;
|
||||||
|
|
||||||
|
const wxLanguageInfos& wxGetLanguageInfos()
|
||||||
|
{
|
||||||
|
wxLocale::CreateLanguagesDB();
|
||||||
|
|
||||||
|
return gs_languagesDB;
|
||||||
|
}
|
||||||
|
|
||||||
/*static*/ void wxLocale::CreateLanguagesDB()
|
/*static*/ void wxLocale::CreateLanguagesDB()
|
||||||
{
|
{
|
||||||
if (!gs_languagesDBInitialized)
|
if (!gs_languagesDBInitialized)
|
||||||
|
@@ -80,6 +80,22 @@ inline locale_t TryCreateLocale(const wxLocaleIdent& locId)
|
|||||||
return newlocale(LC_ALL_MASK, locId.GetName().mb_str(), NULL);
|
return newlocale(LC_ALL_MASK, locId.GetName().mb_str(), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrapper around newlocale() also trying to append UTF-8 codeset (and
|
||||||
|
// modifying its wxLocaleIdent argument if it succeeds).
|
||||||
|
locale_t TryCreateLocaleWithUTF8(wxLocaleIdent& locId)
|
||||||
|
{
|
||||||
|
locale_t loc = TryCreateLocale(locId);
|
||||||
|
if ( !loc && locId.GetCharset().empty() )
|
||||||
|
{
|
||||||
|
wxLocaleIdent locIdUTF8 = wxLocaleIdent(locId).Charset("UTF-8");
|
||||||
|
loc = TryCreateLocale(locIdUTF8);
|
||||||
|
if ( loc )
|
||||||
|
locId = locIdUTF8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // HAVE_LOCALE_T
|
#endif // HAVE_LOCALE_T
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
@@ -337,7 +353,7 @@ wxUILocaleImpl* wxUILocaleImpl::CreateForLocale(const wxLocaleIdent& locIdOrig)
|
|||||||
// Make a copy of it because it can be modified below.
|
// Make a copy of it because it can be modified below.
|
||||||
wxLocaleIdent locId = locIdOrig;
|
wxLocaleIdent locId = locIdOrig;
|
||||||
|
|
||||||
locale_t loc = TryCreateLocale(locId);
|
locale_t loc = TryCreateLocaleWithUTF8(locId);
|
||||||
if ( !loc )
|
if ( !loc )
|
||||||
{
|
{
|
||||||
// Try to find a variant of this locale available on this system: first
|
// Try to find a variant of this locale available on this system: first
|
||||||
@@ -345,28 +361,38 @@ wxUILocaleImpl* wxUILocaleImpl::CreateForLocale(const wxLocaleIdent& locIdOrig)
|
|||||||
// does _not_ work under Linux, so try adding one if we don't have it.
|
// does _not_ work under Linux, so try adding one if we don't have it.
|
||||||
if ( locId.GetRegion().empty() )
|
if ( locId.GetRegion().empty() )
|
||||||
{
|
{
|
||||||
const wxLanguageInfo* const info =
|
const wxString lang = locId.GetLanguage();
|
||||||
wxLocale::FindLanguageInfo(locId.GetLanguage());
|
|
||||||
if ( info )
|
const wxLanguageInfos& infos = wxGetLanguageInfos();
|
||||||
|
for ( wxLanguageInfos::const_iterator it = infos.begin();
|
||||||
|
it != infos.end();
|
||||||
|
++it )
|
||||||
{
|
{
|
||||||
wxString region = info->CanonicalName.AfterFirst('_');
|
const wxString& fullname = it->CanonicalName;
|
||||||
if ( !region.empty() )
|
if ( fullname.BeforeFirst('_') == lang )
|
||||||
{
|
{
|
||||||
// We never have encoding in our canonical names, but we
|
// We never have encoding in our canonical names, but we
|
||||||
// can have modifiers, so get rid of them if necessary.
|
// can have modifiers, so get rid of them if necessary.
|
||||||
region = region.BeforeFirst('@');
|
const wxString&
|
||||||
|
region = fullname.AfterFirst('_').BeforeFirst('@');
|
||||||
|
if ( !region.empty() )
|
||||||
|
{
|
||||||
|
loc = TryCreateLocaleWithUTF8(locId.Region(region));
|
||||||
|
if ( loc )
|
||||||
|
{
|
||||||
|
// We take the first available region, we don't
|
||||||
|
// have enough data to know how to prioritize them
|
||||||
|
// (and wouldn't want to start any geopolitical
|
||||||
|
// disputes).
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loc = TryCreateLocale(locId.Region(region));
|
// Don't bother reverting region to the old value as it will
|
||||||
|
// be overwritten during the next loop iteration anyhow.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// And sometimes the locale without encoding is not available, but one
|
|
||||||
// with UTF-8 encoding is, so try this too.
|
|
||||||
if ( !loc && locId.GetCharset().empty() )
|
|
||||||
{
|
|
||||||
loc = TryCreateLocale(locId.Charset("UTF-8"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !loc )
|
if ( !loc )
|
||||||
|
Reference in New Issue
Block a user