DolphinWX: Set C++ locale

After 3a83ebc, the Show System Clock feature started using the
unfortunate combination of MM/DD/YY dates (rare outside of the US)
and 24-hour time (rare in the US) regardless of the user's locale
settings. This commit makes it use the configured locale again.

I've noticed one minor difference in behavior between now and
before 3a83ebc: The new way of setting the C/C++ locale seems to
treat "en" as "en-US", but the wx way of setting the C locale
treated it as "en-GB" (at least on Windows).
This commit is contained in:
JosJuice 2017-07-21 12:46:12 +02:00
parent 7aaaf44229
commit 9417fc6a3a
3 changed files with 59 additions and 0 deletions

View File

@ -343,6 +343,9 @@ void DolphinApp::InitLanguageSupport()
_("Error"));
m_locale.reset(new wxLocale(wxLANGUAGE_DEFAULT));
}
// wxWidgets sets the C locale for us, but not the C++ locale, so let's do that ourselves
UICommon::SetLocale(language_code);
}
void DolphinApp::OnEndSession(wxCloseEvent& event)

View File

@ -2,7 +2,10 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <algorithm>
#include <clocale>
#include <cmath>
#include <locale>
#include <memory>
#ifdef _WIN32
#include <shlobj.h> // for SHGetFolderPath
@ -66,6 +69,55 @@ void Shutdown()
Config::Shutdown();
}
void SetLocale(std::string locale_name)
{
auto set_locale = [](const std::string& locale) {
#ifdef __linux__
std::string adjusted_locale = locale;
if (!locale.empty())
adjusted_locale += ".UTF-8";
#else
const std::string& adjusted_locale = locale;
#endif
// setlocale sets the C locale, and global sets the C and C++ locales, so the call to setlocale
// would be redundant if it wasn't for not having any other good way to check whether
// the locale name is valid. (Constructing a std::locale object for an unsupported
// locale name throws std::runtime_error, and exception handling is disabled in Dolphin.)
if (!std::setlocale(LC_ALL, adjusted_locale.c_str()))
return false;
std::locale::global(std::locale(adjusted_locale));
return true;
};
#ifdef _WIN32
constexpr char PREFERRED_SEPARATOR = '-';
constexpr char OTHER_SEPARATOR = '_';
#else
constexpr char PREFERRED_SEPARATOR = '_';
constexpr char OTHER_SEPARATOR = '-';
#endif
std::replace(locale_name.begin(), locale_name.end(), OTHER_SEPARATOR, PREFERRED_SEPARATOR);
// Use the specified locale if supported.
if (set_locale(locale_name))
return;
// Remove subcodes until we get a supported locale. If that doesn't give us a supported locale,
// "" is passed to set_locale in order to get the system default locale.
while (!locale_name.empty())
{
const size_t separator_index = locale_name.rfind(PREFERRED_SEPARATOR);
locale_name.erase(separator_index == std::string::npos ? 0 : separator_index);
if (set_locale(locale_name))
return;
}
// If none of the locales tried above are supported, we just keep using whatever locale is set
// (which is the classic locale by default).
}
void CreateDirectories()
{
// Copy initial Wii NAND data from Sys to User.

View File

@ -19,6 +19,10 @@ void EnableScreenSaver(Display* display, Window win, bool enable);
void EnableScreenSaver(bool enable);
#endif
// Calls std::locale::global, selecting a fallback locale if the
// requested locale isn't available
void SetLocale(std::string locale_name);
void CreateDirectories();
void SetUserDirectory(const std::string& custom_path);