1 // Copyright (c) 2005, Rodrigo Braz Monteiro
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright notice,
8 // this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright notice,
10 // this list of conditions and the following disclaimer in the documentation
11 // and/or other materials provided with the distribution.
12 // * Neither the name of the Aegisub Group nor the names of its contributors
13 // may be used to endorse or promote products derived from this software
14 // without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 // POSSIBILITY OF SUCH DAMAGE.
27 //
28 // Aegisub Project http://www.aegisub.org/
29
30 /// @file aegisublocale.cpp
31 /// @brief Enumerate available locales for picking translation on Windows
32 /// @ingroup utility
33 ///
34
35 #include "aegisublocale.h"
36
37 #include "compat.h"
38 #include "options.h"
39 #include "utils.h"
40
41 #include <libaegisub/path.h>
42
43 #include <algorithm>
44 #include <clocale>
45 #include <functional>
46 #include <wx/intl.h>
47 #include <wx/choicdlg.h> // Keep this last so wxUSE_CHOICEDLG is set.
48
49 #ifndef AEGISUB_CATALOG
50 #define AEGISUB_CATALOG "aegisub"
51 #endif
52
GetTranslations()53 wxTranslations *AegisubLocale::GetTranslations() {
54 wxTranslations *translations = wxTranslations::Get();
55 if (!translations) {
56 wxTranslations::Set(translations = new wxTranslations);
57 wxFileTranslationsLoader::AddCatalogLookupPathPrefix(config::path->Decode("?data/locale/").wstring());
58 }
59 return translations;
60 }
61
Init(std::string const & language)62 void AegisubLocale::Init(std::string const& language) {
63 wxTranslations *translations = GetTranslations();
64 translations->SetLanguage(to_wx(language));
65 translations->AddCatalog(AEGISUB_CATALOG);
66 translations->AddStdCatalog();
67
68 setlocale(LC_NUMERIC, "C");
69 setlocale(LC_CTYPE, "C");
70 active_language = language;
71 }
72
HasLanguage(std::string const & language)73 bool AegisubLocale::HasLanguage(std::string const& language) {
74 auto langs = GetTranslations()->GetAvailableTranslations(AEGISUB_CATALOG);
75 return std::find(langs.begin(), langs.end(), to_wx(language)) != langs.end();
76 }
77
PickLanguage()78 std::string AegisubLocale::PickLanguage() {
79 if (active_language.empty()) {
80 wxString os_ui_language = GetTranslations()->GetBestTranslation(AEGISUB_CATALOG);
81 if (!os_ui_language.empty())
82 return from_wx(os_ui_language);
83 }
84
85 wxArrayString langs = GetTranslations()->GetAvailableTranslations(AEGISUB_CATALOG);
86
87 // No translations available, so don't bother asking the user
88 if (langs.empty() && active_language.empty())
89 return "en_US";
90
91 langs.insert(langs.begin(), "en_US");
92
93 // Check if user local language is available, if so, make it first
94 const wxLanguageInfo *info = wxLocale::GetLanguageInfo(wxLocale::GetSystemLanguage());
95 if (info) {
96 auto it = std::find(langs.begin(), langs.end(), info->CanonicalName);
97 if (it != langs.end())
98 std::rotate(langs.begin(), it, it + 1);
99 }
100
101 // Generate names
102 wxArrayString langNames;
103 for (auto const& lang : langs)
104 langNames.push_back(LocalizedLanguageName(lang));
105
106 long style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxOK | wxCENTRE;
107 if (!active_language.empty())
108 style |= wxCANCEL;
109
110 wxSingleChoiceDialog dialog(nullptr, "Please choose a language:", "Language", langNames,
111 (void **)nullptr,
112 style);
113 if (dialog.ShowModal() == wxID_OK) {
114 int picked = dialog.GetSelection();
115 if (langs[picked] != active_language)
116 return from_wx(langs[picked]);
117 }
118
119 return "";
120 }
121