diff --git a/android/app/src/main/cpp/app/organicmaps/util/Language.cpp b/android/app/src/main/cpp/app/organicmaps/util/Language.cpp index 21aa697dc1..204570b1df 100644 --- a/android/app/src/main/cpp/app/organicmaps/util/Language.cpp +++ b/android/app/src/main/cpp/app/organicmaps/util/Language.cpp @@ -1,4 +1,5 @@ #include "android/app/src/main/cpp/app/organicmaps/core/jni_helper.hpp" +#include "platform/measurement_utils.hpp" #include "platform/preferred_languages.hpp" extern "C" @@ -9,4 +10,10 @@ Java_app_organicmaps_util_Language_nativeNormalize(JNIEnv *env, jclass type, jst std::string locale = languages::Normalize(jni::ToNativeString(env, lang)); return jni::ToJavaString(env, locale); } + +JNIEXPORT void JNICALL +Java_app_organicmaps_util_Language_nativeRefreshSystemLocale(JNIEnv *, jclass) +{ + measurement_utils::RefreshSystemLocale(); +} } diff --git a/android/app/src/main/java/app/organicmaps/MwmApplication.java b/android/app/src/main/java/app/organicmaps/MwmApplication.java index 4951e5936a..6e8ed005f9 100644 --- a/android/app/src/main/java/app/organicmaps/MwmApplication.java +++ b/android/app/src/main/java/app/organicmaps/MwmApplication.java @@ -4,7 +4,10 @@ import static app.organicmaps.location.LocationState.LOCATION_TAG; import android.app.Activity; import android.app.Application; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; @@ -41,6 +44,7 @@ import app.organicmaps.settings.StoragePathManager; import app.organicmaps.sound.TtsPlayer; import app.organicmaps.util.Config; import app.organicmaps.util.ConnectionState; +import app.organicmaps.util.Language; import app.organicmaps.util.SharedPropertiesUtils; import app.organicmaps.util.StorageUtils; import app.organicmaps.util.ThemeSwitcher; @@ -89,6 +93,8 @@ public class MwmApplication extends Application implements Application.ActivityL @Nullable private WeakReference mTopActivity; + private BroadcastReceiver mLocaleChangeReceiver; + @UiThread @Nullable public Activity getTopActivity() @@ -213,6 +219,22 @@ public class MwmApplication extends Application implements Application.ActivityL Config.setStoragePath(writablePath); Config.setStatisticsEnabled(SharedPropertiesUtils.isStatisticsEnabled(this)); + // Force native system locale initialization at app start-up. + Language.nativeRefreshSystemLocale(); + + // Setup BroadcastReceiver to receive changes of system locale. + mLocaleChangeReceiver = new BroadcastReceiver() + { + @Override + public void onReceive(Context context, Intent intent) + { + // Refresh the native c++ system locale. + Language.nativeRefreshSystemLocale(); + } + }; + + registerReceiver(mLocaleChangeReceiver, new IntentFilter(Intent.ACTION_LOCALE_CHANGED)); + mPlatformInitialized = true; Logger.i(TAG, "Platform initialized"); } diff --git a/android/app/src/main/java/app/organicmaps/util/Language.java b/android/app/src/main/java/app/organicmaps/util/Language.java index 4a367ded73..f3f8d11879 100644 --- a/android/app/src/main/java/app/organicmaps/util/Language.java +++ b/android/app/src/main/java/app/organicmaps/util/Language.java @@ -58,4 +58,7 @@ public class Language @NonNull public static native String nativeNormalize(@NonNull String locale); + + @NonNull + public static native void nativeRefreshSystemLocale(); } diff --git a/iphone/Maps/main.mm b/iphone/Maps/main.mm index 55df103325..551a33d9e8 100644 --- a/iphone/Maps/main.mm +++ b/iphone/Maps/main.mm @@ -1,6 +1,7 @@ #import "MapsAppDelegate.h" #import "MWMSettings.h" +#include "platform/measurement_utils.hpp" #include "platform/platform.hpp" int main(int argc, char * argv[]) @@ -9,6 +10,9 @@ int main(int argc, char * argv[]) auto & p = GetPlatform(); LOG(LINFO, (p.Version(), "started, detected CPU cores:", p.CpuCores())); + // Force system locale initialization at app start-up. + measurement_utils::RefreshSystemLocale(); + int retVal; @autoreleasepool { diff --git a/platform/measurement_utils.cpp b/platform/measurement_utils.cpp index d53e493b68..b6b1e495ed 100644 --- a/platform/measurement_utils.cpp +++ b/platform/measurement_utils.cpp @@ -18,12 +18,29 @@ namespace measurement_utils { +// Global Locale variable to store system locale. +static platform::Locale g_systemLocale = +{ + "", // Undefined language. + "", // Undefined country. + "", // Undefined currency. + ".", // Dot as default decimal separator. + "," // Comma as default grouping (thousands) separator. +}; + +void SetSystemLocale(platform::Locale const & locale) +{ + g_systemLocale = locale; +} + +void RefreshSystemLocale() +{ + SetSystemLocale(platform::GetCurrentLocale()); +} + std::string ToStringPrecision(double d, int pr) { - // We assume that the app will be restarted if a user changes device's locale. - static auto const locale = platform::GetCurrentLocale(); - - return ToStringPrecisionLocale(locale, d, pr); + return ToStringPrecisionLocale(g_systemLocale, d, pr); } std::string ToStringPrecisionLocale(platform::Locale const & loc, double d, int pr) diff --git a/platform/measurement_utils.hpp b/platform/measurement_utils.hpp index 906d4960e5..7021729d58 100644 --- a/platform/measurement_utils.hpp +++ b/platform/measurement_utils.hpp @@ -64,5 +64,9 @@ std::string OSMDistanceToMetersString(std::string const & osmRawValue, bool supportZeroAndNegativeValues = true, int digitsAfterComma = 2); std::string ToStringPrecision(double d, int pr); -std::string ToStringPrecisionLocale(platform::Locale const & locale, double d, int pr); +std::string ToStringPrecisionLocale(platform::Locale const & loc, double d, int pr); + +void SetSystemLocale(platform::Locale const & locale); +void RefreshSystemLocale(); + } // namespace measurement_utils diff --git a/platform/platform_tests/measurement_tests.cpp b/platform/platform_tests/measurement_tests.cpp index 11ab0c9ab9..b4e1fe4d9a 100644 --- a/platform/platform_tests/measurement_tests.cpp +++ b/platform/platform_tests/measurement_tests.cpp @@ -181,5 +181,10 @@ UNIT_TEST(ToStringPrecisionLocale) TEST_EQUAL(measurement_utils::ToStringPrecisionLocale(loc, d1, pr1), data.d1String, ()); TEST_EQUAL(measurement_utils::ToStringPrecisionLocale(loc, d2, pr2), AddGroupingSeparators(d2String, loc.m_groupingSeparator), ()); + + measurement_utils::SetSystemLocale(loc); + TEST_EQUAL(measurement_utils::ToStringPrecision(d1, pr1), data.d1String, ()); + TEST_EQUAL(measurement_utils::ToStringPrecision(d2, pr2), + AddGroupingSeparators(d2String, loc.m_groupingSeparator), ()); } } diff --git a/qt/main.cpp b/qt/main.cpp index 2eab11deb6..780fd84f66 100644 --- a/qt/main.cpp +++ b/qt/main.cpp @@ -102,6 +102,9 @@ public: int main(int argc, char * argv[]) { + // Refresh system locale for distance & speed formatting. + measurement_utils::RefreshSystemLocale(); + // Our double parsing code (base/string_utils.hpp) needs dots as a floating point delimiters, not commas. // TODO: Refactor our doubles parsing code to use locale-independent delimiters. // For example, https://github.com/google/double-conversion can be used. diff --git a/qt/ruler.cpp b/qt/ruler.cpp index e652b90afd..6f5d999904 100644 --- a/qt/ruler.cpp +++ b/qt/ruler.cpp @@ -1,6 +1,7 @@ #include "qt/ruler.hpp" #include "geometry/mercator.hpp" +#include "platform/distance.hpp" #include #include @@ -52,13 +53,6 @@ void Ruler::SetDistance() void Ruler::SetId() { - std::ostringstream curValStream; - curValStream << std::fixed << std::setprecision(1); - if (m_sumDistanceM >= 1000.0) - curValStream << m_sumDistanceM / 1000.0 << " km"; - else - curValStream << m_sumDistanceM << " m"; - - m_id = curValStream.str(); + m_id = platform::Distance::CreateFormatted(m_sumDistanceM).ToString(); } } // namespace qt