forked from mia/Aegisub
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.
This commit is contained in:
parent
0346fbf715
commit
40f97dbfea
6 changed files with 58 additions and 168 deletions
|
@ -36,6 +36,8 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "aegisublocale.h"
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
@ -48,97 +50,59 @@
|
||||||
#include <wx/choicdlg.h> // Keep this last so wxUSE_CHOICEDLG is set.
|
#include <wx/choicdlg.h> // Keep this last so wxUSE_CHOICEDLG is set.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "aegisublocale.h"
|
|
||||||
#include "standard_paths.h"
|
#include "standard_paths.h"
|
||||||
|
|
||||||
AegisubLocale::~AegisubLocale() {
|
#ifndef AEGISUB_CATALOG
|
||||||
}
|
#define AEGISUB_CATALOG "aegisub"
|
||||||
|
|
||||||
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);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
locale->AddCatalog("wxstd");
|
AegisubLocale::AegisubLocale() {
|
||||||
setlocale(LC_NUMERIC, "C");
|
wxTranslations::Set(new wxTranslations);
|
||||||
setlocale(LC_CTYPE, "C");
|
wxFileTranslationsLoader::AddCatalogLookupPathPrefix(StandardPaths::DecodePath("?data/locale/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
int AegisubLocale::PickLanguage() {
|
void AegisubLocale::Init(wxString const& language) {
|
||||||
wxArrayInt langs = GetAvailableLanguages();
|
wxTranslations *translations = wxTranslations::Get();
|
||||||
|
translations->SetLanguage(language);
|
||||||
|
translations->AddCatalog(AEGISUB_CATALOG);
|
||||||
|
translations->AddStdCatalog();
|
||||||
|
|
||||||
// Check if english is in it, else add it
|
setlocale(LC_NUMERIC, "C");
|
||||||
if (langs.Index(wxLANGUAGE_ENGLISH) == wxNOT_FOUND) {
|
setlocale(LC_CTYPE, "C");
|
||||||
int id = EnglishId();
|
active_language = language;
|
||||||
if (id)
|
}
|
||||||
langs.Insert(id, 0);
|
|
||||||
}
|
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
|
// Check if user local language is available, if so, make it first
|
||||||
int user = wxLocale::GetSystemLanguage();
|
const wxLanguageInfo *info = wxLocale::GetLanguageInfo(wxLocale::GetSystemLanguage());
|
||||||
if (langs.Index(user) != wxNOT_FOUND) {
|
if (info) {
|
||||||
langs.Remove(user);
|
wxArrayString::iterator it = std::find(langs.begin(), langs.end(), info->CanonicalName);
|
||||||
langs.Insert(user, 0);
|
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
|
// Nothing to pick
|
||||||
if (langs.empty()) return -1;
|
if (langs.empty()) return "";
|
||||||
|
|
||||||
// Only one language, so don't bother asking the user
|
// Only one language, so don't bother asking the user
|
||||||
if (langs.size() == 1 && !locale)
|
if (langs.size() == 1 && !active_language)
|
||||||
return langs[0];
|
return langs[0];
|
||||||
|
|
||||||
// Generate names
|
// Generate names
|
||||||
wxArrayString langNames;
|
wxArrayString langNames;
|
||||||
for (size_t i = 0; i < langs.size(); ++i)
|
for (size_t i = 0; i < langs.size(); ++i) {
|
||||||
langNames.Add(wxLocale::GetLanguageName(langs[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;
|
long style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxOK | wxCENTRE;
|
||||||
if (locale)
|
if (!active_language.empty())
|
||||||
style |= wxCANCEL;
|
style |= wxCANCEL;
|
||||||
|
|
||||||
wxSingleChoiceDialog dialog(NULL, "Please choose a language:", "Language", langNames,
|
wxSingleChoiceDialog dialog(NULL, "Please choose a language:", "Language", langNames,
|
||||||
|
@ -150,75 +114,9 @@ int AegisubLocale::PickLanguage() {
|
||||||
style);
|
style);
|
||||||
if (dialog.ShowModal() == wxID_OK) {
|
if (dialog.ShowModal() == wxID_OK) {
|
||||||
int picked = dialog.GetSelection();
|
int picked = dialog.GetSelection();
|
||||||
if (locale && langs[picked] == locale->GetLanguage())
|
if (langs[picked] != active_language)
|
||||||
return -1;
|
return langs[picked];
|
||||||
return langs[picked];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return "";
|
||||||
}
|
|
||||||
|
|
||||||
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; i<len; i++) {
|
|
||||||
const wxLanguageInfo *lang = wxLocale::FindLanguageInfo(langs[i]);
|
|
||||||
|
|
||||||
// If the locale file doesn't exist then don't list it as an option.
|
|
||||||
wxString locDir = wxStandardPaths::Get().GetLocalizedResourcesDir(langs[i], wxStandardPathsBase::ResourceCat_Messages);
|
|
||||||
wxFileName file(wxString::Format("%s/%s.mo", locDir, AEGISUB_CATALOG));
|
|
||||||
if (lang && file.FileExists()) final.Add(lang->Language);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return final;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,22 +34,15 @@
|
||||||
/// @ingroup utility
|
/// @ingroup utility
|
||||||
///
|
///
|
||||||
|
|
||||||
#include <libaegisub/scoped_ptr.h>
|
|
||||||
|
|
||||||
class wxLocale;
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class AegisubLocale
|
/// @class AegisubLocale
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// DOCME
|
||||||
class AegisubLocale {
|
class AegisubLocale {
|
||||||
agi::scoped_ptr<wxLocale> locale;
|
wxString active_language;
|
||||||
wxArrayInt GetAvailableLanguages();
|
|
||||||
int EnglishId() const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~AegisubLocale();
|
AegisubLocale();
|
||||||
void Init(int language);
|
void Init(wxString const& language);
|
||||||
int PickLanguage();
|
wxString PickLanguage();
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include "../main.h"
|
#include "../main.h"
|
||||||
|
|
||||||
#include "../audio_controller.h"
|
#include "../audio_controller.h"
|
||||||
|
#include "../compat.h"
|
||||||
#include "../dialog_about.h"
|
#include "../dialog_about.h"
|
||||||
#include "../dialog_detached_video.h"
|
#include "../dialog_detached_video.h"
|
||||||
#include "../dialog_manager.h"
|
#include "../dialog_manager.h"
|
||||||
|
@ -185,19 +186,17 @@ struct app_language : public Command {
|
||||||
|
|
||||||
void operator()(agi::Context *c) {
|
void operator()(agi::Context *c) {
|
||||||
// Get language
|
// Get language
|
||||||
int newCode = wxGetApp().locale.PickLanguage();
|
wxString new_language = wxGetApp().locale.PickLanguage();
|
||||||
// Is OK?
|
if (!new_language) return;
|
||||||
if (newCode != -1) {
|
|
||||||
// Set code
|
|
||||||
OPT_SET("App/Locale")->SetInt(newCode);
|
|
||||||
|
|
||||||
// Ask to restart program
|
OPT_SET("App/Language")->SetString(STD_STR(new_language));
|
||||||
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) {
|
// Ask to restart program
|
||||||
// Restart Aegisub
|
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 (wxGetApp().frame->Close()) {
|
if (result == wxYES) {
|
||||||
RestartAegisub();
|
// Restart Aegisub
|
||||||
}
|
if (wxGetApp().frame->Close()) {
|
||||||
|
RestartAegisub();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
},
|
},
|
||||||
"Call Tips" : false,
|
"Call Tips" : false,
|
||||||
"First Start" : true,
|
"First Start" : true,
|
||||||
"Locale" : -1,
|
"Language" : "",
|
||||||
"Maximized" : false,
|
"Maximized" : false,
|
||||||
"Save Charset" : "UTF-8",
|
"Save Charset" : "UTF-8",
|
||||||
"Show Toolbar" : true,
|
"Show Toolbar" : true,
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
},
|
},
|
||||||
"Call Tips" : false,
|
"Call Tips" : false,
|
||||||
"First Start" : true,
|
"First Start" : true,
|
||||||
"Locale" : -1,
|
"Language" : "",
|
||||||
"Maximized" : false,
|
"Maximized" : false,
|
||||||
"Save Charset" : "UTF-8",
|
"Save Charset" : "UTF-8",
|
||||||
"Show Toolbar" : true,
|
"Show Toolbar" : true,
|
||||||
|
|
|
@ -233,10 +233,10 @@ bool AegisubApp::OnInit() {
|
||||||
StartupLog("Initialize final locale");
|
StartupLog("Initialize final locale");
|
||||||
|
|
||||||
// Set locale
|
// Set locale
|
||||||
int lang = OPT_GET("App/Locale")->GetInt();
|
wxString lang = lagi_wxString(OPT_GET("App/Language")->GetString());
|
||||||
if (lang == -1) {
|
if (!lang) {
|
||||||
lang = locale.PickLanguage();
|
lang = locale.PickLanguage();
|
||||||
OPT_SET("App/Locale")->SetInt(lang);
|
OPT_SET("App/Language")->SetString(STD_STR(lang));
|
||||||
}
|
}
|
||||||
locale.Init(lang);
|
locale.Init(lang);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue