summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorLéo Lam <leolino.lam@gmail.com>2018-04-09 20:03:48 +0200
committerGitHub <noreply@github.com>2018-04-09 20:03:48 +0200
commit0e1ca1e17cdb9f42ab2b59512dfd79e3373fd937 (patch)
treee90390ad59ae3a89ddd5d73d310715f90a57b4f6 /Source
parent7aaaf442290717c39a08815c6bb24851e55430f2 (diff)
parenta66d56aece307431337fba99acdbe27602430eb6 (diff)
Merge pull request #5805 from JosJuice/date-time-locale
Set C++ locale
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Common/StringUtil.h4
-rw-r--r--Source/Core/DolphinQt2/Translation.cpp5
-rw-r--r--Source/Core/DolphinWX/Main.cpp3
-rw-r--r--Source/Core/UICommon/UICommon.cpp67
-rw-r--r--Source/Core/UICommon/UICommon.h4
5 files changed, 78 insertions, 5 deletions
diff --git a/Source/Core/Common/StringUtil.h b/Source/Core/Common/StringUtil.h
index ec2e5c6337..ef84fb6dcd 100644
--- a/Source/Core/Common/StringUtil.h
+++ b/Source/Core/Common/StringUtil.h
@@ -51,10 +51,6 @@ std::string ThousandSeparate(I value, int spaces = 0)
std::ostringstream stream;
#endif
-// std::locale("") seems to be broken on many platforms
-#if defined _WIN32 || (defined __linux__ && !defined __clang__)
- stream.imbue(std::locale(""));
-#endif
stream << std::setw(spaces) << value;
#ifdef _WIN32
diff --git a/Source/Core/DolphinQt2/Translation.cpp b/Source/Core/DolphinQt2/Translation.cpp
index e22b4dbb6b..191a721c3b 100644
--- a/Source/Core/DolphinQt2/Translation.cpp
+++ b/Source/Core/DolphinQt2/Translation.cpp
@@ -18,6 +18,7 @@
#include "Common/MsgHandler.h"
#include "Common/StringUtil.h"
#include "Core/ConfigManager.h"
+#include "UICommon/UICommon.h"
constexpr u32 MO_MAGIC_NUMBER = 0x950412de;
@@ -270,6 +271,10 @@ static bool TryInstallTranslator(const QString& exact_language_code)
if (translator->load(filename))
{
QApplication::instance()->installTranslator(translator);
+
+ QLocale::setDefault(QLocale(exact_language_code));
+ UICommon::SetLocale(exact_language_code.toStdString());
+
return true;
}
translator->deleteLater();
diff --git a/Source/Core/DolphinWX/Main.cpp b/Source/Core/DolphinWX/Main.cpp
index ff6b3810cb..ab301df0be 100644
--- a/Source/Core/DolphinWX/Main.cpp
+++ b/Source/Core/DolphinWX/Main.cpp
@@ -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)
diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp
index 423fe2d0ea..f761313add 100644
--- a/Source/Core/UICommon/UICommon.cpp
+++ b/Source/Core/UICommon/UICommon.cpp
@@ -2,8 +2,13 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
+#include <algorithm>
+#include <clocale>
#include <cmath>
+#include <iomanip>
+#include <locale>
#include <memory>
+#include <sstream>
#ifdef _WIN32
#include <shlobj.h> // for SHGetFolderPath
#endif
@@ -66,6 +71,63 @@ 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
+
+ // Users who use a system language other than English are unlikely to prefer American date and
+ // time formats, so let's explicitly request "en_GB" if Dolphin's language is set to "en".
+ // (The settings window only allows setting "en", not anything like "en_US" or "en_GB".)
+ // Users who prefer the American formats are likely to have their system language set to en_US,
+ // and are thus likely to leave Dolphin's language as the default value "" (<System Language>).
+ if (locale_name == "en")
+ locale_name = "en_GB";
+
+ 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.
@@ -346,7 +408,10 @@ std::string FormatSize(u64 bytes)
// Don't need exact values, only 5 most significant digits
const double unit_size = std::pow(2, unit * 10);
- return StringFromFormat("%.2f %s", bytes / unit_size, GetStringT(unit_symbols[unit]).c_str());
+ std::stringstream ss;
+ ss << std::fixed << std::setprecision(2);
+ ss << bytes / unit_size << ' ' << GetStringT(unit_symbols[unit]);
+ return ss.str();
}
} // namespace UICommon
diff --git a/Source/Core/UICommon/UICommon.h b/Source/Core/UICommon/UICommon.h
index 8bbd864ec0..b32e0f410b 100644
--- a/Source/Core/UICommon/UICommon.h
+++ b/Source/Core/UICommon/UICommon.h
@@ -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);