From 564235f9c9f6a28623398288c6721c20898b7215 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sat, 22 May 2021 20:07:25 -0400 Subject: [PATCH] GUIPrefs::SetLang wraps new Languages::SetLang ... ... the former uses Prefs, wxApp, and AudacityMessageBox, the latter has no dependency on them. Also move some other functions from GUIPrefs into namespace Languages. --- src/AudacityApp.cpp | 2 +- src/CrashReport.cpp | 3 +- src/Languages.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++ src/Languages.h | 19 +++++++++ src/prefs/GUIPrefs.cpp | 90 +++--------------------------------------- src/prefs/GUIPrefs.h | 8 ---- 6 files changed, 117 insertions(+), 95 deletions(-) diff --git a/src/AudacityApp.cpp b/src/AudacityApp.cpp index 7d09ab369..6e6c29a9a 100644 --- a/src/AudacityApp.cpp +++ b/src/AudacityApp.cpp @@ -1556,7 +1556,7 @@ bool AudacityApp::InitPart2() Bind(wxEVT_MENU_CLOSE, [=](wxMenuEvent &event) { - wxSetlocale(LC_NUMERIC, GUIPrefs::GetLocaleName()); + wxSetlocale(LC_NUMERIC, Languages::GetLocaleName()); event.Skip(); }); #endif diff --git a/src/CrashReport.cpp b/src/CrashReport.cpp index 18f79e16f..20ca12bd2 100644 --- a/src/CrashReport.cpp +++ b/src/CrashReport.cpp @@ -24,6 +24,7 @@ #include "AudioIOBase.h" #include "FileNames.h" #include "Internat.h" +#include "Languages.h" #include "Project.h" #include "ProjectFileIO.h" #include "prefs/GUIPrefs.h" @@ -59,7 +60,7 @@ void Generate(wxDebugReport::Context ctx) if (ctx == wxDebugReport::Context_Current) { - auto saveLang = GUIPrefs::GetLangShort(); + auto saveLang = Languages::GetLangShort(); GUIPrefs::SetLang( wxT("en") ); auto cleanup = finally( [&]{ GUIPrefs::SetLang( saveLang ); } ); diff --git a/src/Languages.cpp b/src/Languages.cpp index 05a4e6059..4208c892e 100644 --- a/src/Languages.cpp +++ b/src/Languages.cpp @@ -43,6 +43,7 @@ #include #include +#include #include using LangHash = std::unordered_map; @@ -314,4 +315,93 @@ void GetLanguages( FilePaths pathList, } } +static std::unique_ptr sLocale; +static wxString sLocaleName; + +wxString SetLang( const FilePaths &pathList, const wxString & lang ) +{ + wxString result = lang; + + sLocale.reset(); + +#if defined(__WXMAC__) + // This should be reviewed again during the wx3 conversion. + + // On OSX, if the LANG environment variable isn't set when + // using a language like Japanese, an assertion will trigger + // because conversion to Japanese from "?" doesn't return a + // valid length, so make OSX happy by defining/overriding + // the LANG environment variable with U.S. English for now. + wxSetEnv(wxT("LANG"), wxT("en_US.UTF-8")); +#endif + + const wxLanguageInfo *info = NULL; + if (!lang.empty() && lang != wxT("System")) { + // Try to find the given language + info = wxLocale::FindLanguageInfo(lang); + } + if (!info) + { + // Not given a language or can't find it; substitute the system language + result = Languages::GetSystemLanguageCode(pathList); + info = wxLocale::FindLanguageInfo(result); + if (!info) + // Return the substituted system language, but we can't complete setup + // Should we try to do something better? + return result; + } + sLocale = std::make_unique(info->Language); + + for( const auto &path : pathList ) + sLocale->AddCatalogLookupPathPrefix( path ); + + // LL: Must add the wxWidgets catalog manually since the search + // paths were not set up when mLocale was created. The + // catalogs are search in LIFO order, so add wxstd first. + sLocale->AddCatalog(wxT("wxstd")); + + // Must match TranslationExists() in Languages.cpp + sLocale->AddCatalog("audacity"); + + // Initialize internationalisation (number formats etc.) + // + // This must go _after_ creating the wxLocale instance because + // creating the wxLocale instance sets the application-wide locale. + + Internat::Init(); + + using future1 = decltype( + // The file of unused strings is part of the source tree scanned by + // xgettext when compiling the catalog template audacity.pot. + // Including it here doesn't change that but does make the C++ compiler + // check for correct syntax, but also generate no object code for them. +#include "UnusedStrings.h" + 0 + ); + + sLocaleName = wxSetlocale(LC_ALL, NULL); + + return result; +} + +wxString GetLocaleName() +{ + return sLocaleName; +} + +wxString GetLang() +{ + if (sLocale) + return sLocale->GetSysName(); + else + return {}; +} + +wxString GetLangShort() +{ + if (sLocale) + return sLocale->GetName(); + else + return {}; +} } diff --git a/src/Languages.h b/src/Languages.h index d16b36d19..34265b7a9 100644 --- a/src/Languages.h +++ b/src/Languages.h @@ -35,6 +35,25 @@ void GetLanguages( FilePaths pathList, AUDACITY_DLL_API wxString GetSystemLanguageCode(const FilePaths &pathList); +/*! + @param audacityPathList paths to search for .mo files, grouped into subdirectories for the different languages + @param lang a language code; or if empty or "System", then default to system language. + @return the language code actually used which is not lang if lang cannot be found. */ +AUDACITY_DLL_API +wxString SetLang( const FilePaths &audacityPathList, const wxString & lang ); + +/*! @return the last language code that was set */ +AUDACITY_DLL_API +wxString GetLang(); + +/*! @return the last language code that was set (minus country code) */ +AUDACITY_DLL_API +wxString GetLangShort(); + +/*! @return a string as from setlocale() */ +AUDACITY_DLL_API +wxString GetLocaleName(); + } #endif // __AUDACITY_LANGUAGES__ diff --git a/src/prefs/GUIPrefs.cpp b/src/prefs/GUIPrefs.cpp index e2790dc7c..b79348f51 100644 --- a/src/prefs/GUIPrefs.cpp +++ b/src/prefs/GUIPrefs.cpp @@ -22,7 +22,6 @@ #include #include -#include #include "../FileNames.h" #include "../Languages.h" @@ -241,7 +240,7 @@ bool GUIPrefs::Commit() wxString lang = gPrefs->Read(wxT("/Locale/Language"), wxT("")); wxString usedLang = SetLang(lang); // Bug 1523: Previously didn't check no-language (=System Language) - if (!(lang.empty()) && (lang != usedLang)) { + if (!(lang.empty() || lang == L"System") && (lang != usedLang)) { // lang was not usable and is not system language. We got overridden. gPrefs->Write(wxT("/Locale/Language"), usedLang); gPrefs->Flush(); @@ -254,59 +253,12 @@ bool GUIPrefs::Commit() return true; } -static std::unique_ptr sLocale; -static wxString sLocaleName; - wxString GUIPrefs::SetLang( const wxString & lang ) { - wxString result = lang; - - sLocale.reset(); - -#if defined(__WXMAC__) - // This should be reviewed again during the wx3 conversion. - - // On OSX, if the LANG environment variable isn't set when - // using a language like Japanese, an assertion will trigger - // because conversion to Japanese from "?" doesn't return a - // valid length, so make OSX happy by defining/overriding - // the LANG environment variable with U.S. English for now. - wxSetEnv(wxT("LANG"), wxT("en_US.UTF-8")); -#endif - - const wxLanguageInfo *info = NULL; - if (!lang.empty() && lang != wxT("System")) { - info = wxLocale::FindLanguageInfo(lang); - if (!info) - ::AudacityMessageBox( - XO("Language \"%s\" is unknown").Format( lang ) ); - } - if (!info) - { - result = Languages::GetSystemLanguageCode(FileNames::AudacityPathList()); - info = wxLocale::FindLanguageInfo(result); - if (!info) - return result; - } - sLocale = std::make_unique(info->Language); - - for( const auto &path : FileNames::AudacityPathList() ) - sLocale->AddCatalogLookupPathPrefix( path ); - - // LL: Must add the wxWidgets catalog manually since the search - // paths were not set up when mLocale was created. The - // catalogs are search in LIFO order, so add wxstd first. - sLocale->AddCatalog(wxT("wxstd")); - - // Must match TranslationExists() in Languages.cpp - sLocale->AddCatalog("audacity"); - - // Initialize internationalisation (number formats etc.) - // - // This must go _after_ creating the wxLocale instance because - // creating the wxLocale instance sets the application-wide locale. - - Internat::Init(); + auto result = Languages::SetLang(FileNames::AudacityPathList(), lang); + if (!(lang.empty() || lang == L"System") && result != lang) + ::AudacityMessageBox( + XO("Language \"%s\" is unknown").Format( lang ) ); #ifdef EXPERIMENTAL_CEE_NUMBERS_OPTION bool forceCeeNumbers; @@ -315,45 +267,13 @@ wxString GUIPrefs::SetLang( const wxString & lang ) Internat::SetCeeNumberFormat(); #endif - using future1 = decltype( - // The file of unused strings is part of the source tree scanned by - // xgettext when compiling the catalog template audacity.pot. - // Including it here doesn't change that but does make the C++ compiler - // check for correct syntax, but also generate no object code for them. -#include "UnusedStrings.h" - 0 - ); - #ifdef __WXMAC__ wxApp::s_macHelpMenuTitleName = _("&Help"); #endif - sLocaleName = wxSetlocale(LC_ALL, NULL); - return result; } -wxString GUIPrefs::GetLocaleName() -{ - return sLocaleName; -} - -wxString GUIPrefs::GetLang() -{ - if (sLocale) - return sLocale->GetSysName(); - else - return {}; -} - -wxString GUIPrefs::GetLangShort() -{ - if (sLocale) - return sLocale->GetName(); - else - return {}; -} - int ShowClippingPrefsID() { static int value = wxNewId(); diff --git a/src/prefs/GUIPrefs.h b/src/prefs/GUIPrefs.h index b440b2d4d..115fe319b 100644 --- a/src/prefs/GUIPrefs.h +++ b/src/prefs/GUIPrefs.h @@ -44,14 +44,6 @@ class AUDACITY_DLL_API GUIPrefs final : public PrefsPanel // Returns the language actually used which is not lang if lang cannot be found. static wxString SetLang( const wxString & lang ); - // Returns the last language code that was set - static wxString GetLang(); - // Returns the last language code that was set - // Unlike GetLang, gives en rather than en_GB or en_US for result. - static wxString GetLangShort(); - - static wxString GetLocaleName(); - private: void Populate();