Allow getting all usable translations languages

Add a method to return the full list of translations that can be used,
generalizing the existing GetBestTranslation().
This commit is contained in:
Lauri Nurmi
2018-10-02 19:49:50 +03:00
committed by Vadim Zeitlin
parent 4099e75edb
commit 5d08e404c7
3 changed files with 89 additions and 18 deletions

View File

@@ -145,6 +145,11 @@ public:
wxString GetBestTranslation(const wxString& domain, wxString GetBestTranslation(const wxString& domain,
const wxString& msgIdLanguage = "en"); const wxString& msgIdLanguage = "en");
// find best and all other suitable translation languages for given domain
wxArrayString GetAllGoodTranslations(const wxString& domain, wxLanguage msgIdLanguage);
wxArrayString GetAllGoodTranslations(const wxString& domain,
const wxString& msgIdLanguage = "en");
// add standard wxWidgets catalog ("wxstd") // add standard wxWidgets catalog ("wxstd")
bool AddStdCatalog(); bool AddStdCatalog();

View File

@@ -137,6 +137,49 @@ public:
const wxString& msgIdLanguage = "en"); const wxString& msgIdLanguage = "en");
/** /**
Returns the best and all other suitable UI languages for the @a domain.
This is nearly the same as GetBestTranslation(), but returns the
whole list of preferred UI languages for which a translation for the
@a domain was found.
@param domain
The catalog domain to look for.
@param msgIdLanguage
Specifies the language of "msgid" strings in source code
(i.e. arguments to GetString(), wxGetTranslation() and the _() macro).
@return An array of language codes if any suitable matches were found, empty array
otherwise.
@since 3.1.2
*/
wxArrayString GetAllGoodTranslations(const wxString& domain, wxLanguage msgIdLanguage);
/**
Returns the best and all other suitable UI languages for the @a domain.
This is nearly the same as GetBestTranslation(), but returns the
whole list of preferred UI languages for which a translation for the
@a domain was found.
@param domain
The catalog domain to look for.
@param msgIdLanguage
Specifies the language of "msgid" strings in source code
(i.e. arguments to GetString(), wxGetTranslation() and the _() macro).
@return An array of language codes if any suitable matches were found, empty array
otherwise.
@since 3.1.2
*/
wxArrayString GetAllGoodTranslations(const wxString& domain,
const wxString& msgIdLanguage = "en");
/**
Add standard wxWidgets catalogs ("wxstd" and possible port-specific Add standard wxWidgets catalogs ("wxstd" and possible port-specific
catalogs). catalogs).

View File

@@ -127,7 +127,7 @@ wxString GetPreferredUILanguageFallback(const wxArrayString& WXUNUSED(available)
#ifdef __WINDOWS__ #ifdef __WINDOWS__
wxString GetPreferredUILanguage(const wxArrayString& available) wxString GetPreferredUILanguage(const wxArrayString& available, wxArrayString& allPreferred)
{ {
typedef BOOL (WINAPI *GetUserPreferredUILanguages_t)(DWORD, PULONG, PWSTR, PULONG); typedef BOOL (WINAPI *GetUserPreferredUILanguages_t)(DWORD, PULONG, PWSTR, PULONG);
static GetUserPreferredUILanguages_t s_pfnGetUserPreferredUILanguages = NULL; static GetUserPreferredUILanguages_t s_pfnGetUserPreferredUILanguages = NULL;
@@ -172,18 +172,20 @@ wxString GetPreferredUILanguage(const wxArrayString& available)
wxString lang(*j); wxString lang(*j);
lang.Replace("-", "_"); lang.Replace("-", "_");
if ( available.Index(lang, /*bCase=*/false) != wxNOT_FOUND ) if ( available.Index(lang, /*bCase=*/false) != wxNOT_FOUND )
return lang; allPreferred.Add(lang);
size_t pos = lang.find('_'); size_t pos = lang.find('_');
if ( pos != wxString::npos ) if ( pos != wxString::npos )
{ {
lang = lang.substr(0, pos); lang = lang.substr(0, pos);
if ( available.Index(lang, /*bCase=*/false) != wxNOT_FOUND ) if ( available.Index(lang, /*bCase=*/false) != wxNOT_FOUND )
return lang; allPreferred.Add(lang);
} }
} }
} }
} }
} }
if ( !allPreferred.empty() )
return allPreferred[0];
return GetPreferredUILanguageFallback(available); return GetPreferredUILanguageFallback(available);
} }
@@ -207,7 +209,7 @@ void LogTraceArray(const char *prefix, CFArrayRef arr)
#endif // wxUSE_LOG_TRACE #endif // wxUSE_LOG_TRACE
wxString GetPreferredUILanguage(const wxArrayString& available) wxString GetPreferredUILanguage(const wxArrayString& available, wxArrayString &allPreferred)
{ {
wxStringToStringHashMap availableNormalized; wxStringToStringHashMap availableNormalized;
wxCFRef<CFMutableArrayRef> availableArr( wxCFRef<CFMutableArrayRef> availableArr(
@@ -231,17 +233,19 @@ wxString GetPreferredUILanguage(const wxArrayString& available)
LogTraceArray(" - system preferred languages", prefArr); LogTraceArray(" - system preferred languages", prefArr);
unsigned prefArrLength = CFArrayGetCount(prefArr); unsigned prefArrLength = CFArrayGetCount(prefArr);
if ( prefArrLength > 0 ) for ( size_t x = 0; x < prefArrLength; ++x )
{ {
// Lookup the name in 'available' by index -- we need to get the // Lookup the name in 'available' by index -- we need to get the
// original value corresponding to the normalized one chosen. // original value corresponding to the normalized one chosen.
wxString lang(wxCFStringRef::AsString((CFStringRef)CFArrayGetValueAtIndex(prefArr, 0))); wxString lang(wxCFStringRef::AsString((CFStringRef)CFArrayGetValueAtIndex(prefArr, x)));
wxStringToStringHashMap::const_iterator i = availableNormalized.find(lang); wxStringToStringHashMap::const_iterator i = availableNormalized.find(lang);
if ( i == availableNormalized.end() ) if ( i == availableNormalized.end() )
return lang; allPreferred.push_back(lang);
else else
return i->second; allPreferred.push_back(i->second);
} }
if ( allPreferred.empty() == false )
return allPreferred[0];
return GetPreferredUILanguageFallback(available); return GetPreferredUILanguageFallback(available);
} }
@@ -255,7 +259,7 @@ wxString GetPreferredUILanguage(const wxArrayString& available)
// The LANGUAGE variable may contain a colon separated list of language // The LANGUAGE variable may contain a colon separated list of language
// codes in the order of preference. // codes in the order of preference.
// http://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html // http://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html
wxString GetPreferredUILanguage(const wxArrayString& available) wxString GetPreferredUILanguage(const wxArrayString& available, wxArrayString &allPreferred)
{ {
wxString languageFromEnv; wxString languageFromEnv;
wxArrayString preferred; wxArrayString preferred;
@@ -283,15 +287,17 @@ wxString GetPreferredUILanguage(const wxArrayString& available)
{ {
wxString lang(*j); wxString lang(*j);
if ( available.Index(lang) != wxNOT_FOUND ) if ( available.Index(lang) != wxNOT_FOUND )
return lang; allPreferred.Add(lang);
size_t pos = lang.find('_'); size_t pos = lang.find('_');
if ( pos != wxString::npos ) if ( pos != wxString::npos )
{ {
lang = lang.substr(0, pos); lang = lang.substr(0, pos);
if ( available.Index(lang) != wxNOT_FOUND ) if ( available.Index(lang) != wxNOT_FOUND )
return lang; allPreferred.Add(lang);
} }
} }
if ( allPreferred.empty() == false )
return allPreferred[0];
return GetPreferredUILanguageFallback(available); return GetPreferredUILanguageFallback(available);
} }
@@ -1650,20 +1656,37 @@ wxString wxTranslations::GetBestTranslation(const wxString& domain,
wxString wxTranslations::GetBestTranslation(const wxString& domain, wxString wxTranslations::GetBestTranslation(const wxString& domain,
const wxString& msgIdLanguage) const wxString& msgIdLanguage)
{ {
// explicitly set language should always be respected const wxArrayString allGoodOnes = GetAllGoodTranslations(domain, msgIdLanguage);
if ( !m_lang.empty() )
return m_lang;
wxLogTrace(TRACE_I18N, " => using language '%s'", allGoodOnes[0]);
return allGoodOnes[0];
}
wxArrayString wxTranslations::GetAllGoodTranslations(const wxString& domain,
wxLanguage msgIdLanguage)
{
const wxString lang = wxLocale::GetLanguageCanonicalName(msgIdLanguage);
return GetAllGoodTranslations(domain, lang);
}
wxArrayString wxTranslations::GetAllGoodTranslations(const wxString& domain,
const wxString& msgIdLanguage)
{
wxArrayString available(GetAvailableTranslations(domain)); wxArrayString available(GetAvailableTranslations(domain));
// it's OK to have duplicates, so just add msgid language // it's OK to have duplicates, so just add msgid language
available.push_back(msgIdLanguage); available.push_back(msgIdLanguage);
available.push_back(msgIdLanguage.BeforeFirst('_')); available.push_back(msgIdLanguage.BeforeFirst('_'));
wxLogTrace(TRACE_I18N, "choosing best language for domain '%s'", domain); wxLogTrace(TRACE_I18N, "choosing best languages for domain '%s'", domain);
LogTraceArray(" - available translations", available); LogTraceArray(" - available translations", available);
const wxString lang = GetPreferredUILanguage(available); wxArrayString allPreferred;
wxLogTrace(TRACE_I18N, " => using language '%s'", lang); GetPreferredUILanguage(available, allPreferred);
return lang;
// explicitly set language should always be preferred the most
if ( !m_lang.empty() )
allPreferred.insert(allPreferred.begin(), m_lang);
return allPreferred;
} }