From 40f97dbfea9c410117540883c2dcd19395b0e432 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 2 Oct 2012 12:28:55 -0700 Subject: [PATCH] Redesign AegisubLocale Use wxTranslations directly rather than going through wxLocale. This significantly simplifies the code, eliminates the hardcoded list of languages for non-windows, and makes it possible to use mismatched languages and locales. Closes #1508. --- aegisub/src/aegisublocale.cpp | 178 ++++--------------- aegisub/src/aegisublocale.h | 15 +- aegisub/src/command/app.cpp | 23 ++- aegisub/src/libresrc/default_config.json | 2 +- aegisub/src/libresrc/osx/default_config.json | 2 +- aegisub/src/main.cpp | 6 +- 6 files changed, 58 insertions(+), 168 deletions(-) diff --git a/aegisub/src/aegisublocale.cpp b/aegisub/src/aegisublocale.cpp index 6d5cf2b6a..4b80ffd25 100644 --- a/aegisub/src/aegisublocale.cpp +++ b/aegisub/src/aegisublocale.cpp @@ -36,6 +36,8 @@ #include "config.h" +#include "aegisublocale.h" + #ifndef AGI_PRE #include #include @@ -48,97 +50,59 @@ #include // Keep this last so wxUSE_CHOICEDLG is set. #endif -#include "aegisublocale.h" #include "standard_paths.h" -AegisubLocale::~AegisubLocale() { -} - -int AegisubLocale::EnglishId() const { - static const int english_ids[] = { - wxLANGUAGE_ENGLISH, - wxLANGUAGE_ENGLISH_US, - wxLANGUAGE_ENGLISH_UK, - wxLANGUAGE_ENGLISH_AUSTRALIA, - wxLANGUAGE_ENGLISH_BELIZE, - wxLANGUAGE_ENGLISH_BOTSWANA, - wxLANGUAGE_ENGLISH_CANADA, - wxLANGUAGE_ENGLISH_CARIBBEAN, - wxLANGUAGE_ENGLISH_DENMARK, - wxLANGUAGE_ENGLISH_EIRE, - wxLANGUAGE_ENGLISH_JAMAICA, - wxLANGUAGE_ENGLISH_NEW_ZEALAND, - wxLANGUAGE_ENGLISH_PHILIPPINES, - wxLANGUAGE_ENGLISH_SOUTH_AFRICA, - wxLANGUAGE_ENGLISH_TRINIDAD, - wxLANGUAGE_ENGLISH_ZIMBABWE, - 0 - }; - - for (const int *id = english_ids; *id; ++id) { - if (wxLocale::IsAvailable(*id)) { - return *id; - } - } - - return -1; -} - -void AegisubLocale::Init(int language) { - if (language == -1) - language = EnglishId(); - - if (!wxLocale::IsAvailable(language)) - language = wxLANGUAGE_UNKNOWN; - - locale.reset(new wxLocale(language)); - -#ifdef __WINDOWS__ - locale->AddCatalogLookupPathPrefix(StandardPaths::DecodePath("?data/locale/")); - locale->AddCatalog("aegisub"); -#else - locale->AddCatalog(AEGISUB_CATALOG); +#ifndef AEGISUB_CATALOG +#define AEGISUB_CATALOG "aegisub" #endif - locale->AddCatalog("wxstd"); - setlocale(LC_NUMERIC, "C"); - setlocale(LC_CTYPE, "C"); +AegisubLocale::AegisubLocale() { + wxTranslations::Set(new wxTranslations); + wxFileTranslationsLoader::AddCatalogLookupPathPrefix(StandardPaths::DecodePath("?data/locale/")); } -int AegisubLocale::PickLanguage() { - wxArrayInt langs = GetAvailableLanguages(); +void AegisubLocale::Init(wxString const& language) { + wxTranslations *translations = wxTranslations::Get(); + translations->SetLanguage(language); + translations->AddCatalog(AEGISUB_CATALOG); + translations->AddStdCatalog(); - // Check if english is in it, else add it - if (langs.Index(wxLANGUAGE_ENGLISH) == wxNOT_FOUND) { - int id = EnglishId(); - if (id) - langs.Insert(id, 0); - } + setlocale(LC_NUMERIC, "C"); + setlocale(LC_CTYPE, "C"); + active_language = language; +} + +wxString AegisubLocale::PickLanguage() { + wxArrayString langs = wxTranslations::Get()->GetAvailableTranslations(AEGISUB_CATALOG); + langs.insert(langs.begin(), "en_US"); // Check if user local language is available, if so, make it first - int user = wxLocale::GetSystemLanguage(); - if (langs.Index(user) != wxNOT_FOUND) { - langs.Remove(user); - langs.Insert(user, 0); + const wxLanguageInfo *info = wxLocale::GetLanguageInfo(wxLocale::GetSystemLanguage()); + if (info) { + wxArrayString::iterator it = std::find(langs.begin(), langs.end(), info->CanonicalName); + if (it != langs.end()) + std::rotate(langs.begin(), it, it + 1); } - // Remove languages which won't work due to the locale not being installed - langs.erase(remove_if(langs.begin(), langs.end(), not1(std::ptr_fun(&wxLocale::IsAvailable))), langs.end()); - // Nothing to pick - if (langs.empty()) return -1; + if (langs.empty()) return ""; // Only one language, so don't bother asking the user - if (langs.size() == 1 && !locale) + if (langs.size() == 1 && !active_language) return langs[0]; // Generate names wxArrayString langNames; - for (size_t i = 0; i < langs.size(); ++i) - langNames.Add(wxLocale::GetLanguageName(langs[i])); + for (size_t i = 0; i < langs.size(); ++i) { + const wxLanguageInfo *info = wxLocale::FindLanguageInfo(langs[i]); + if (info) + langNames.push_back(wxLocale::GetLanguageName(info->Language)); + else + langNames.push_back(langs[i]); + } long style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxOK | wxCENTRE; - if (locale) + if (!active_language.empty()) style |= wxCANCEL; wxSingleChoiceDialog dialog(NULL, "Please choose a language:", "Language", langNames, @@ -150,75 +114,9 @@ int AegisubLocale::PickLanguage() { style); if (dialog.ShowModal() == wxID_OK) { int picked = dialog.GetSelection(); - if (locale && langs[picked] == locale->GetLanguage()) - return -1; - return langs[picked]; + if (langs[picked] != active_language) + return langs[picked]; } - return -1; -} - -wxArrayInt AegisubLocale::GetAvailableLanguages() { - wxArrayInt final; - -#ifdef __WINDOWS__ - // Open directory - wxString folder = StandardPaths::DecodePath("?data/locale/"); - wxDir dir; - if (!dir.Exists(folder)) return final; - if (!dir.Open(folder)) return final; - - // Enumerate folders - wxString temp1; - for (bool cont = dir.GetFirst(&temp1, "", wxDIR_DIRS); cont; cont = dir.GetNext(&temp1)) { - // Check if .so exists inside folder - if (wxFileName::FileExists(folder + temp1 + "/aegisub.mo")) { - const wxLanguageInfo *lang = wxLocale::FindLanguageInfo(temp1); - if (lang) { - final.Add(lang->Language); - } - } - } -#else - const char* langs[] = { - "ca", - "cs", - "da", - "de", - "el", - "es", - "eu", - "fa", - "fi", - "fr_FR", - "hu", - "id", - "it", - "ja", - "ko", - "pl", - "pt_BR", - "pt_PT", - "ru", - "sr_RS", - "sr_RS@latin", - "sr_YU", - "sr_YU@latin", - "vi", - "zh_CN", - "zh_TW" - }; - - size_t len = sizeof(langs)/sizeof(char*); - for (size_t i=0; iLanguage); - } -#endif - - return final; + return ""; } diff --git a/aegisub/src/aegisublocale.h b/aegisub/src/aegisublocale.h index 0e9d103d7..a57b29ee3 100644 --- a/aegisub/src/aegisublocale.h +++ b/aegisub/src/aegisublocale.h @@ -34,22 +34,15 @@ /// @ingroup utility /// -#include - -class wxLocale; - /// DOCME /// @class AegisubLocale /// @brief DOCME /// /// DOCME class AegisubLocale { - agi::scoped_ptr locale; - wxArrayInt GetAvailableLanguages(); - int EnglishId() const; - + wxString active_language; public: - ~AegisubLocale(); - void Init(int language); - int PickLanguage(); + AegisubLocale(); + void Init(wxString const& language); + wxString PickLanguage(); }; diff --git a/aegisub/src/command/app.cpp b/aegisub/src/command/app.cpp index 0efad2119..0236f852a 100644 --- a/aegisub/src/command/app.cpp +++ b/aegisub/src/command/app.cpp @@ -50,6 +50,7 @@ #include "../main.h" #include "../audio_controller.h" +#include "../compat.h" #include "../dialog_about.h" #include "../dialog_detached_video.h" #include "../dialog_manager.h" @@ -185,19 +186,17 @@ struct app_language : public Command { void operator()(agi::Context *c) { // Get language - int newCode = wxGetApp().locale.PickLanguage(); - // Is OK? - if (newCode != -1) { - // Set code - OPT_SET("App/Locale")->SetInt(newCode); + wxString new_language = wxGetApp().locale.PickLanguage(); + if (!new_language) return; - // Ask to restart program - int result = wxMessageBox("Aegisub needs to be restarted so that the new language can be applied. Restart now?", "Restart Aegisub?", wxYES_NO | wxICON_QUESTION | wxCENTER); - if (result == wxYES) { - // Restart Aegisub - if (wxGetApp().frame->Close()) { - RestartAegisub(); - } + OPT_SET("App/Language")->SetString(STD_STR(new_language)); + + // Ask to restart program + int result = wxMessageBox("Aegisub needs to be restarted so that the new language can be applied. Restart now?", "Restart Aegisub?", wxYES_NO | wxICON_QUESTION | wxCENTER); + if (result == wxYES) { + // Restart Aegisub + if (wxGetApp().frame->Close()) { + RestartAegisub(); } } } diff --git a/aegisub/src/libresrc/default_config.json b/aegisub/src/libresrc/default_config.json index 7598a5f62..b13fd3068 100644 --- a/aegisub/src/libresrc/default_config.json +++ b/aegisub/src/libresrc/default_config.json @@ -10,7 +10,7 @@ }, "Call Tips" : false, "First Start" : true, - "Locale" : -1, + "Language" : "", "Maximized" : false, "Save Charset" : "UTF-8", "Show Toolbar" : true, diff --git a/aegisub/src/libresrc/osx/default_config.json b/aegisub/src/libresrc/osx/default_config.json index 852db6e3f..7f6800fe8 100644 --- a/aegisub/src/libresrc/osx/default_config.json +++ b/aegisub/src/libresrc/osx/default_config.json @@ -10,7 +10,7 @@ }, "Call Tips" : false, "First Start" : true, - "Locale" : -1, + "Language" : "", "Maximized" : false, "Save Charset" : "UTF-8", "Show Toolbar" : true, diff --git a/aegisub/src/main.cpp b/aegisub/src/main.cpp index 858ae824b..ec58a57e2 100644 --- a/aegisub/src/main.cpp +++ b/aegisub/src/main.cpp @@ -233,10 +233,10 @@ bool AegisubApp::OnInit() { StartupLog("Initialize final locale"); // Set locale - int lang = OPT_GET("App/Locale")->GetInt(); - if (lang == -1) { + wxString lang = lagi_wxString(OPT_GET("App/Language")->GetString()); + if (!lang) { lang = locale.PickLanguage(); - OPT_SET("App/Locale")->SetInt(lang); + OPT_SET("App/Language")->SetString(STD_STR(lang)); } locale.Init(lang);