diff --git a/include/wx/translation.h b/include/wx/translation.h index 3d5d5b0b83..266166019c 100644 --- a/include/wx/translation.h +++ b/include/wx/translation.h @@ -145,6 +145,11 @@ public: wxString GetBestTranslation(const wxString& domain, 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") bool AddStdCatalog(); diff --git a/interface/wx/translation.h b/interface/wx/translation.h index eed6355d0b..a57c9930d0 100644 --- a/interface/wx/translation.h +++ b/interface/wx/translation.h @@ -137,6 +137,49 @@ public: 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 catalogs). diff --git a/src/common/translation.cpp b/src/common/translation.cpp index bf92ed2942..a64327eaef 100644 --- a/src/common/translation.cpp +++ b/src/common/translation.cpp @@ -127,7 +127,7 @@ wxString GetPreferredUILanguageFallback(const wxArrayString& WXUNUSED(available) #ifdef __WINDOWS__ -wxString GetPreferredUILanguage(const wxArrayString& available) +wxString GetPreferredUILanguage(const wxArrayString& available, wxArrayString& allPreferred) { typedef BOOL (WINAPI *GetUserPreferredUILanguages_t)(DWORD, PULONG, PWSTR, PULONG); static GetUserPreferredUILanguages_t s_pfnGetUserPreferredUILanguages = NULL; @@ -172,18 +172,20 @@ wxString GetPreferredUILanguage(const wxArrayString& available) wxString lang(*j); lang.Replace("-", "_"); if ( available.Index(lang, /*bCase=*/false) != wxNOT_FOUND ) - return lang; + allPreferred.Add(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; + allPreferred.Add(lang); } } } } } + if ( !allPreferred.empty() ) + return allPreferred[0]; return GetPreferredUILanguageFallback(available); } @@ -207,7 +209,7 @@ void LogTraceArray(const char *prefix, CFArrayRef arr) #endif // wxUSE_LOG_TRACE -wxString GetPreferredUILanguage(const wxArrayString& available) +wxString GetPreferredUILanguage(const wxArrayString& available, wxArrayString &allPreferred) { wxStringToStringHashMap availableNormalized; wxCFRef availableArr( @@ -231,17 +233,19 @@ wxString GetPreferredUILanguage(const wxArrayString& available) LogTraceArray(" - system preferred languages", 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 // 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); if ( i == availableNormalized.end() ) - return lang; + allPreferred.push_back(lang); else - return i->second; + allPreferred.push_back(i->second); } + if ( allPreferred.empty() == false ) + return allPreferred[0]; return GetPreferredUILanguageFallback(available); } @@ -255,7 +259,7 @@ wxString GetPreferredUILanguage(const wxArrayString& available) // 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 GetPreferredUILanguage(const wxArrayString& available, wxArrayString &allPreferred) { wxString languageFromEnv; wxArrayString preferred; @@ -283,15 +287,17 @@ wxString GetPreferredUILanguage(const wxArrayString& available) { wxString lang(*j); if ( available.Index(lang) != wxNOT_FOUND ) - return lang; + allPreferred.Add(lang); size_t pos = lang.find('_'); if ( pos != wxString::npos ) { lang = lang.substr(0, pos); if ( available.Index(lang) != wxNOT_FOUND ) - return lang; + allPreferred.Add(lang); } } + if ( allPreferred.empty() == false ) + return allPreferred[0]; return GetPreferredUILanguageFallback(available); } @@ -1650,20 +1656,37 @@ wxString wxTranslations::GetBestTranslation(const wxString& domain, wxString wxTranslations::GetBestTranslation(const wxString& domain, const wxString& msgIdLanguage) { - // explicitly set language should always be respected - if ( !m_lang.empty() ) - return m_lang; + const wxArrayString allGoodOnes = GetAllGoodTranslations(domain, msgIdLanguage); + 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)); // it's OK to have duplicates, so just add msgid language available.push_back(msgIdLanguage); 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); - const wxString lang = GetPreferredUILanguage(available); - wxLogTrace(TRACE_I18N, " => using language '%s'", lang); - return lang; + wxArrayString allPreferred; + GetPreferredUILanguage(available, allPreferred); + + // explicitly set language should always be preferred the most + if ( !m_lang.empty() ) + allPreferred.insert(allPreferred.begin(), m_lang); + + return allPreferred; }