diff --git a/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp b/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp index 6f1c7d542d..50f4e48b14 100644 --- a/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp +++ b/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp @@ -36,7 +36,7 @@ JNIEXPORT void JNICALL Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeShowBookmarkOnMap( JNIEnv * env, jobject thiz, jint c, jint b) { - BookmarkAndCategory bnc = BookmarkAndCategory(b,c); + BookmarkAndCategory bnc = BookmarkAndCategory(b, c); frm()->ShowBookmark(bnc); } diff --git a/drape_frontend/stylist.cpp b/drape_frontend/stylist.cpp index 54df0b0f8a..c6b3128b6a 100644 --- a/drape_frontend/stylist.cpp +++ b/drape_frontend/stylist.cpp @@ -79,30 +79,48 @@ void FilterRulesByRuntimeSelector(FeatureType const & f, int zoomLevel, drule::K }); } -class KeyFunctor +class Aggregator { public: - KeyFunctor(FeatureType const & f, - feature::EGeomType type, + Aggregator(FeatureType const & f, + feature::EGeomType const type, int const zoomLevel, - int const keyCount, - CaptionDescription & descr) + int const keyCount) : m_pointStyleFound(false) , m_lineStyleFound(false) - , m_iconFound(false) - , m_captionWithoutOffsetFound(false) , m_auxCaptionFound(false) , m_mainTextType(drule::text_type_name) - , m_descrInit(false) , m_f(f) , m_geomType(type) , m_zoomLevel(zoomLevel) - , m_descr(descr) { m_rules.reserve(keyCount); Init(); } + void AggregateKeys(drule::KeysT const & keys) + { + for (auto const & key : keys) + ProcessKey(key); + } + + void AggregateStyleFlags(drule::KeysT const & keys, bool const nameExists) + { + for (auto const & key : keys) + { + bool const isNonEmptyCaption = IsTypeOf(key, Caption) && nameExists; + m_pointStyleFound |= (IsTypeOf(key, Symbol | Circle) || isNonEmptyCaption); + m_lineStyleFound |= IsTypeOf(key, Line); + } + } + + bool m_pointStyleFound; + bool m_lineStyleFound; + bool m_auxCaptionFound; + drule::text_type_t m_mainTextType; + buffer_vector m_rules; + +private: void ProcessKey(drule::Key const & key) { double depth = key.m_priority; @@ -117,36 +135,23 @@ public: if (IsTypeOf(key, Caption | Symbol | Circle | PathText)) { depth += m_priorityModifier; - if (m_geomType == feature::GEOM_POINT) ++depth; + if (m_geomType == feature::GEOM_POINT) + ++depth; } else if (IsTypeOf(key, Area)) - depth -= m_priorityModifier; - - drule::BaseRule const * const dRule = drule::rules().Find(key); - m_rules.push_back(make_pair(dRule, depth)); - - if (dRule->GetCaption(0) != nullptr) { - InitCaptionDescription(); - m_mainTextType = dRule->GetCaptionTextType(0); + depth -= m_priorityModifier; } - bool const isNonEmptyCaption = IsTypeOf(key, Caption) && IsNameExists(); - m_pointStyleFound |= (IsTypeOf(key, Symbol | Circle) || isNonEmptyCaption); - m_lineStyleFound |= IsTypeOf(key, Line); + drule::BaseRule const * const dRule = drule::rules().Find(key); + m_rules.emplace_back(make_pair(dRule, depth)); + + if (dRule->GetCaption(0) != nullptr) + m_mainTextType = dRule->GetCaptionTextType(0); + m_auxCaptionFound |= (dRule->GetCaption(1) != nullptr); } - bool m_pointStyleFound; - bool m_lineStyleFound; - bool m_iconFound; - bool m_captionWithoutOffsetFound; - bool m_auxCaptionFound; - buffer_vector m_rules; - drule::text_type_t m_mainTextType; - bool m_descrInit; - -private: void Init() { m_depthLayer = m_f.GetLayer(); @@ -162,28 +167,11 @@ private: } } - void InitCaptionDescription() - { - if (!m_descrInit) - { - m_descr.Init(m_f, m_zoomLevel); - m_descrInit = true; - } - } - - inline bool IsNameExists() const - { - ASSERT(m_descrInit, ()); - return m_descr.IsNameExists(); - } - -private: FeatureType const & m_f; feature::EGeomType m_geomType; int const m_zoomLevel; double m_priorityModifier; int m_depthLayer; - CaptionDescription & m_descr; }; const uint8_t CoastlineFlag = 1; @@ -196,41 +184,21 @@ const uint8_t PointStyleFlag = 1 << 3; // ==================================== // void CaptionDescription::Init(FeatureType const & f, - int const zoomLevel) + int const zoomLevel, + feature::EGeomType const type, + drule::text_type_t const mainTextType, + bool const auxCaptionExists) { - f.GetPreferredNames(m_mainText, m_auxText); + if (auxCaptionExists || type == feature::GEOM_LINE) + f.GetPreferredNames(m_mainText, m_auxText); + else + f.GetReadableName(m_mainText); m_roadNumber = f.GetRoadNumber(); m_houseNumber = f.GetHouseNumber(); - SwapCaptions(zoomLevel); - DiscardLongCaption(zoomLevel); -} - -void CaptionDescription::FormatCaptions(FeatureType const & f, - feature::EGeomType type, - drule::text_type_t mainTextType, - bool auxCaptionExists) -{ - if (!auxCaptionExists && !m_auxText.empty() && type != feature::GEOM_LINE) - { - m_mainText.swap(m_auxText); - m_auxText.clear(); - } - - if (mainTextType == drule::text_type_housenumber) - { - m_mainText.swap(m_houseNumber); - m_houseNumber.clear(); - } - else if (mainTextType == drule::text_type_name) - { - if (!m_houseNumber.empty()) - { - if (m_mainText.empty() || m_houseNumber.find(m_mainText) != string::npos) - m_houseNumber.swap(m_mainText); - } - } + ProcessZoomLevel(zoomLevel); + ProcessMainTextType(mainTextType); } string const & CaptionDescription::GetMainText() const @@ -262,21 +230,34 @@ bool CaptionDescription::IsNameExists() const return !m_mainText.empty() || !m_houseNumber.empty(); } -void CaptionDescription::SwapCaptions(int const zoomLevel) +void CaptionDescription::ProcessZoomLevel(int const zoomLevel) { if (zoomLevel <= scales::GetUpperWorldScale() && !m_auxText.empty()) { - m_mainText.swap(m_auxText); m_auxText.clear(); } -} -void CaptionDescription::DiscardLongCaption(int const zoomLevel) -{ if (zoomLevel < 5 && m_mainText.size() > 50) m_mainText.clear(); } +void CaptionDescription::ProcessMainTextType(drule::text_type_t const & mainTextType) +{ + if (mainTextType == drule::text_type_housenumber) + { + m_mainText.swap(m_houseNumber); + m_houseNumber.clear(); + } + else if (mainTextType == drule::text_type_name) + { + if (!m_houseNumber.empty()) + { + if (m_mainText.empty() || m_houseNumber.find(m_mainText) != string::npos) + m_houseNumber.swap(m_mainText); + } + } +} + // ==================================== // Stylist::Stylist() @@ -385,21 +366,20 @@ bool InitStylist(FeatureType const & f, int const zoomLevel, bool buildings3d, S return false; } + Aggregator aggregator(f, mainGeomType, zoomLevel, keys.size()); + aggregator.AggregateKeys(keys); + CaptionDescription & descr = s.GetCaptionDescriptionImpl(); + descr.Init(f, zoomLevel, mainGeomType, aggregator.m_mainTextType, aggregator.m_auxCaptionFound); - KeyFunctor keyFunctor(f, mainGeomType, zoomLevel, keys.size(), descr); - for (auto const & key : keys) - keyFunctor.ProcessKey(key); + aggregator.AggregateStyleFlags(keys, descr.IsNameExists()); - if (keyFunctor.m_pointStyleFound) + if (aggregator.m_pointStyleFound) s.RaisePointStyleFlag(); - if (keyFunctor.m_lineStyleFound) + if (aggregator.m_lineStyleFound) s.RaiseLineStyleFlag(); - s.m_rules.swap(keyFunctor.m_rules); - - if (keyFunctor.m_descrInit) - descr.FormatCaptions(f, mainGeomType, keyFunctor.m_mainTextType, keyFunctor.m_auxCaptionFound); + s.m_rules.swap(aggregator.m_rules); return true; } @@ -413,14 +393,11 @@ double GetFeaturePriority(FeatureType const & f, int const zoomLevel) feature::EGeomType const mainGeomType = feature::EGeomType(geomType.first); - CaptionDescription descr; - - KeyFunctor keyFunctor(f, mainGeomType, zoomLevel, keys.size(), descr); - for (auto const & key : keys) - keyFunctor.ProcessKey(key); + Aggregator aggregator(f, mainGeomType, zoomLevel, keys.size()); + aggregator.AggregateKeys(keys); double maxPriority = kMinPriority; - for (auto const & rule : keyFunctor.m_rules) + for (auto const & rule : aggregator.m_rules) { if (rule.second > maxPriority) maxPriority = rule.second; diff --git a/drape_frontend/stylist.hpp b/drape_frontend/stylist.hpp index 2540c68c39..53ef1fdd0f 100644 --- a/drape_frontend/stylist.hpp +++ b/drape_frontend/stylist.hpp @@ -18,12 +18,10 @@ namespace df struct CaptionDescription { void Init(FeatureType const & f, - int const zoomLevel); - - void FormatCaptions(FeatureType const & f, - feature::EGeomType type, - drule::text_type_t mainTextType, - bool auxCaptionExists); + int const zoomLevel, + feature::EGeomType const type, + drule::text_type_t const mainTextType, + bool const auxCaptionExists); string const & GetMainText() const; string const & GetAuxText() const; @@ -32,10 +30,11 @@ struct CaptionDescription bool IsNameExists() const; private: - void SwapCaptions(int const zoomLevel); - void DiscardLongCaption(int const zoomLevel); + /// Clear aux name on high zoom and clear long main name on low zoom. + void ProcessZoomLevel(int const zoomLevel); + /// Try to use house number as name of the object. + void ProcessMainTextType(drule::text_type_t const & mainTextType); -private: string m_mainText; string m_auxText; string m_roadNumber; diff --git a/indexer/drules_selector.cpp b/indexer/drules_selector.cpp index 275cc21e3b..bacc660246 100644 --- a/indexer/drules_selector.cpp +++ b/indexer/drules_selector.cpp @@ -106,8 +106,7 @@ bool GetPopulation(FeatureType const & ft, uint32_t & population) // Feature tag value evaluator for tag 'name' bool GetName(FeatureType const & ft, string & name) { - string intName; - ft.GetPreferredNames(name, intName); + ft.GetReadableName(name); return true; } diff --git a/indexer/feature.cpp b/indexer/feature.cpp index e9e8e4a1a9..f36263f55f 100644 --- a/indexer/feature.cpp +++ b/indexer/feature.cpp @@ -8,6 +8,8 @@ #include "indexer/feature_visibility.hpp" #include "indexer/osm_editor.hpp" +#include "platform/preferred_languages.hpp" + #include "geometry/distance.hpp" #include "geometry/robust_orientation.hpp" @@ -487,13 +489,19 @@ FeatureType::geom_stat_t FeatureType::GetTrianglesSize(int scale) const return geom_stat_t(sz, m_triangles.size()); } -void FeatureType::GetPreferredNames(string & defaultName, string & intName) const +void FeatureType::GetPreferredNames(string & primary, string & secondary) const { if (!HasName()) return; + auto const mwmInfo = GetID().m_mwmId.GetInfo(); + + if (!mwmInfo) + return; + ParseCommon(); - ::GetPreferredNames(GetID(), GetNames(), defaultName, intName); + auto const deviceLang = StringUtf8Multilang::GetLangIndex(languages::GetCurrentNorm()); + ::GetPreferredNames(mwmInfo->GetRegionData(), GetNames(), deviceLang, primary, secondary); } void FeatureType::GetReadableName(string & name) const @@ -501,8 +509,14 @@ void FeatureType::GetReadableName(string & name) const if (!HasName()) return; + auto const mwmInfo = GetID().m_mwmId.GetInfo(); + + if (!mwmInfo) + return; + ParseCommon(); - ::GetReadableName(GetID(), GetNames(), name); + auto const deviceLang = StringUtf8Multilang::GetLangIndex(languages::GetCurrentNorm()); + ::GetReadableName(mwmInfo->GetRegionData(), GetNames(), deviceLang, name); } string FeatureType::GetHouseNumber() const diff --git a/indexer/feature_utils.cpp b/indexer/feature_utils.cpp index 1da89805d2..a4b94028c3 100644 --- a/indexer/feature_utils.cpp +++ b/indexer/feature_utils.cpp @@ -7,8 +7,6 @@ #include "geometry/point2d.hpp" -#include "platform/preferred_languages.hpp" - #include "coding/multilang_utf8_string.hpp" #include "base/base.hpp" @@ -17,15 +15,12 @@ namespace { -void GetMwmLangName(FeatureID const & id, StringUtf8Multilang const & src, string & out) +using StrUtf8 = StringUtf8Multilang; + +void GetMwmLangName(feature::RegionData const & regionData, StringUtf8Multilang const & src, string & out) { - auto const mwmInfo = id.m_mwmId.GetInfo(); - - if (!mwmInfo) - return; - vector mwmLangCodes; - mwmInfo->GetRegionData().GetLanguages(mwmLangCodes); + regionData.GetLanguages(mwmLangCodes); for (auto const code : mwmLangCodes) { @@ -34,22 +29,9 @@ void GetMwmLangName(FeatureID const & id, StringUtf8Multilang const & src, strin } } -void GetNames(FeatureID const & id, StringUtf8Multilang const & src, string & primary, - string & secondary) +void GetBestName(StringUtf8Multilang const & src, vector const & priorityList, string & out) { - primary.clear(); - secondary.clear(); - - if (src.IsEmpty()) - return; - - vector primaryCodes = {StringUtf8Multilang::kDefaultCode}; - vector secondaryCodes = {StringUtf8Multilang::GetLangIndex(languages::GetCurrentNorm()), - StringUtf8Multilang::kInternationalCode, - StringUtf8Multilang::kEnglishCode}; - - auto primaryIndex = primaryCodes.size(); - auto secondaryIndex = secondaryCodes.size(); + auto bestIndex = priorityList.size(); auto const findAndSet = [](vector const & langs, int8_t const code, string const & name, size_t & bestIndex, string & outName) @@ -64,23 +46,19 @@ void GetNames(FeatureID const & id, StringUtf8Multilang const & src, string & pr src.ForEach([&](int8_t code, string const & name) { - if (primaryIndex != 0) - findAndSet(primaryCodes, code, name, primaryIndex, primary); + if (bestIndex == 0) + return false; - if (secondaryIndex != 0) - findAndSet(secondaryCodes, code, name, secondaryIndex, secondary); + findAndSet(priorityList, code, name, bestIndex, out); return true; }); - if (primary.empty()) - GetMwmLangName(id, src, primary); - - if (secondaryIndex < secondaryCodes.size() && - secondaryCodes[secondaryIndex] == StringUtf8Multilang::kInternationalCode) + // There are many "junk" names in Arabian island. + if (bestIndex < priorityList.size() && + priorityList[bestIndex] == StrUtf8::kInternationalCode) { - // There are many "junk" names in Arabian island. - secondary = secondary.substr(0, secondary.find_first_of(',')); + out = out.substr(0, out.find_first_of(',')); } } } // namespace @@ -225,41 +203,54 @@ int GetFeatureViewportScale(TypesHolder const & types) return impl::GetFeatureEstimator().GetViewportScale(types); } -void GetPreferredNames(FeatureID const & id, StringUtf8Multilang const & src, string & primary, - string & secondary) +void GetPreferredNames(RegionData const & regionData, StringUtf8Multilang const & src, + int8_t const deviceLang, string & primary, string & secondary) { - // Primary name using priority: - // - default name; - // - country language name. - // Secondary name using priority: - // - device language name; - // - international name; - // - english name. - GetNames(id, src, primary, secondary); + primary.clear(); + secondary.clear(); + + if (src.IsEmpty()) + return; + + vector const primaryCodes = {deviceLang, + StrUtf8::kInternationalCode, + StrUtf8::kEnglishCode}; + vector secondaryCodes = {StrUtf8::kDefaultCode, + StrUtf8::kInternationalCode}; + + vector mwmLangCodes; + regionData.GetLanguages(mwmLangCodes); + + secondaryCodes.insert(secondaryCodes.end(), mwmLangCodes.begin(), mwmLangCodes.end()); + secondaryCodes.push_back(StrUtf8::kEnglishCode); + + GetBestName(src, primaryCodes, primary); + GetBestName(src, secondaryCodes, secondary); if (primary.empty()) - { - primary.swap(secondary); - } - else - { - // Filter out similar intName. - if (!secondary.empty() && primary.find(secondary) != string::npos) - secondary.clear(); - } + primary.swap(secondary); + else if (!secondary.empty() && primary.find(secondary) != string::npos) + secondary.clear(); } -void GetReadableName(FeatureID const & id, StringUtf8Multilang const & src, string & out) +void GetReadableName(RegionData const & regionData, StringUtf8Multilang const & src, + int8_t const deviceLang, string & out) { - // Names using priority: - // - device language name; - // - international name; - // - english name; - // - default name; - // - country language name. - // Secondary name is preffered to display on the map and place page. - string primary, secondary; - GetNames(id, src, primary, secondary); - out = secondary.empty() ? primary : secondary; + out.clear(); + + if (src.IsEmpty()) + return; + + vector codes; + // If MWM contains user's language. + if (regionData.HasLanguage(deviceLang)) + codes = {deviceLang, StrUtf8::kDefaultCode, StrUtf8::kInternationalCode, StrUtf8::kEnglishCode}; + else + codes = {deviceLang, StrUtf8::kInternationalCode, StrUtf8::kEnglishCode, StrUtf8::kDefaultCode}; + + GetBestName(src, codes, out); + + if (out.empty()) + GetMwmLangName(regionData, src, out); } } // namespace feature diff --git a/indexer/feature_utils.hpp b/indexer/feature_utils.hpp index e7e0f46306..d6ff2ff180 100644 --- a/indexer/feature_utils.hpp +++ b/indexer/feature_utils.hpp @@ -10,11 +10,37 @@ class StringUtf8Multilang; namespace feature { class TypesHolder; + class RegionData; /// Get viewport scale to show given feature. Used in search. int GetFeatureViewportScale(TypesHolder const & types); - void GetPreferredNames(FeatureID const & id, StringUtf8Multilang const & src, string & primary, - string & secondary); - void GetReadableName(FeatureID const & id, StringUtf8Multilang const & src, string & out); + /// Primary name using priority: + /// - device language name; + /// - international name; + /// - english name. + /// Secondary name using priority: + /// - default name; + /// - international name; + /// - country language name; + /// - english name. + /// In case when primary name is empty it will be propagated from secondary and secondary will be + /// cleared. In case when primary name contains secondary name then secondary will be cleared. + void GetPreferredNames(RegionData const & regionData, StringUtf8Multilang const & src, + int8_t const deviceLang, string & primary, string & secondary); + + /// When MWM contains user's language, the priority is the following: + /// - device language name; + /// - default name; + /// - international name; + /// - english name; + /// - country language name. + /// When MWM does not contain user's language, the priority is the following: + /// - device language name; + /// - international name; + /// - english name; + /// - default name; + /// - country language name. + void GetReadableName(RegionData const & regionData, StringUtf8Multilang const & src, + int8_t const deviceLang, string & out); } // namespace feature diff --git a/indexer/indexer_tests/feature_names_test.cpp b/indexer/indexer_tests/feature_names_test.cpp index bc44e5bcec..d11b245d98 100644 --- a/indexer/indexer_tests/feature_names_test.cpp +++ b/indexer/indexer_tests/feature_names_test.cpp @@ -1,39 +1,314 @@ #include "testing/testing.hpp" +#include "indexer/feature_utils.hpp" #include "indexer/features_vector.hpp" #include "indexer/index.hpp" #include "indexer/mwm_set.hpp" #include "platform/local_country_file.hpp" +#include "platform/preferred_languages.hpp" using namespace platform; namespace { -UNIT_TEST(GetFeatureNames) +using StrUtf8 = StringUtf8Multilang; + +UNIT_TEST(GetPrefferedNames) { - LocalCountryFile localFile = LocalCountryFile::MakeForTesting("minsk-pass"); + feature::RegionData regionData; + regionData.SetLanguages({"de", "ko"}); - Index index; - auto result = index.RegisterMap(localFile); - TEST_EQUAL(result.second, MwmSet::RegResult::Success, ()); + int8_t deviceLang = StrUtf8::GetLangIndex("ru"); + string primary, secondary; - auto const & id = result.first; - MwmSet::MwmHandle handle = index.GetMwmHandleById(id); - TEST(handle.IsAlive(), ()); - - auto const * value = handle.GetValue(); - FeaturesVector fv(value->m_cont, value->GetHeader(), value->m_table.get()); - string primary, secondary, readable; - - fv.ForEach([&](FeatureType & ft, uint32_t /* index */) { - ft.GetPreferredNames(primary, secondary); - if (!secondary.empty()) - { - ft.GetReadableName(readable); - TEST_EQUAL(secondary, readable, ()); - } - }); + StrUtf8 src; + src.AddString("fr", "fr name"); + + feature::GetPreferredNames(regionData, src, deviceLang, primary, secondary); + + TEST_EQUAL(primary, "", ()); + TEST_EQUAL(secondary, "", ()); + } + + { + StrUtf8 src; + src.AddString("default", "default name"); + + feature::GetPreferredNames(regionData, src, deviceLang, primary, secondary); + + TEST_EQUAL(primary, "default name", ()); + TEST_EQUAL(secondary, "", ()); + } + + { + StrUtf8 src; + src.AddString("default", "default name"); + src.AddString("en", "en name"); + + feature::GetPreferredNames(regionData, src, deviceLang, primary, secondary); + + TEST_EQUAL(primary, "en name", ()); + TEST_EQUAL(secondary, "default name", ()); + } + + { + StrUtf8 src; + src.AddString("default", "default name"); + src.AddString("en", "en name"); + src.AddString("ru", "ru name"); + + feature::GetPreferredNames(regionData, src, deviceLang, primary, secondary); + + TEST_EQUAL(primary, "ru name", ()); + TEST_EQUAL(secondary, "default name", ()); + } + + { + StrUtf8 src; + src.AddString("default", "same name"); + src.AddString("en", "en name"); + src.AddString("ru", "same name"); + src.AddString("int_name", "int name"); + + feature::GetPreferredNames(regionData, src, deviceLang, primary, secondary); + + TEST_EQUAL(primary, "same name", ()); + TEST_EQUAL(secondary, "", ()); + } + + { + StrUtf8 src; + src.AddString("default", "default name"); + src.AddString("en", "en name"); + src.AddString("ru", "ru name"); + src.AddString("int_name", "int name"); + src.AddString("de", "de name"); + + feature::GetPreferredNames(regionData, src, deviceLang, primary, secondary); + + TEST_EQUAL(primary, "ru name", ()); + TEST_EQUAL(secondary, "default name", ()); + } + + { + StrUtf8 src; + src.AddString("default", "default name"); + src.AddString("en", "en name"); + src.AddString("ru", "ru name"); + src.AddString("int_name", "int name"); + src.AddString("de", "de name"); + src.AddString("ko", "ko name"); + + feature::GetPreferredNames(regionData, src, deviceLang, primary, secondary); + + TEST_EQUAL(primary, "ru name", ()); + TEST_EQUAL(secondary, "default name", ()); + } + + { + StrUtf8 src; + src.AddString("default", "default name"); + src.AddString("en", "en name"); + src.AddString("int_name", "int name"); + src.AddString("de", "de name"); + src.AddString("ko", "ko name"); + + feature::GetPreferredNames(regionData, src, deviceLang, primary, secondary); + + TEST_EQUAL(primary, "int name", ()); + TEST_EQUAL(secondary, "default name", ()); + } + + { + StrUtf8 src; + src.AddString("en", "en name"); + src.AddString("int_name", "int name"); + src.AddString("de", "de name"); + src.AddString("ko", "ko name"); + + feature::GetPreferredNames(regionData, src, deviceLang, primary, secondary); + + TEST_EQUAL(primary, "int name", ()); + TEST_EQUAL(secondary, "", ()); + } + + { + StrUtf8 src; + src.AddString("en", "en name"); + src.AddString("de", "de name"); + src.AddString("ko", "ko name"); + + feature::GetPreferredNames(regionData, src, deviceLang, primary, secondary); + + TEST_EQUAL(primary, "en name", ()); + TEST_EQUAL(secondary, "de name", ()); + } + + { + StrUtf8 src; + src.AddString("en", "en name"); + src.AddString("ko", "ko name"); + + feature::GetPreferredNames(regionData, src, deviceLang, primary, secondary); + + TEST_EQUAL(primary, "en name", ()); + TEST_EQUAL(secondary, "ko name", ()); + } + + { + StrUtf8 src; + src.AddString("en", "en name"); + + feature::GetPreferredNames(regionData, src, deviceLang, primary, secondary); + + TEST_EQUAL(primary, "en name", ()); + TEST_EQUAL(secondary, "", ()); + } +} + +UNIT_TEST(GetReadableName) +{ + feature::RegionData regionData; + regionData.SetLanguages({"de", "ko"}); + + int8_t deviceLang = StrUtf8::GetLangIndex("ru"); + string name; + + { + StrUtf8 src; + src.AddString("fr", "fr name"); + + feature::GetReadableName(regionData, src, deviceLang, name); + + TEST_EQUAL(name, "", ()); + } + + { + StrUtf8 src; + src.AddString("ko", "ko name"); + + feature::GetReadableName(regionData, src, deviceLang, name); + + TEST_EQUAL(name, "ko name", ()); + } + + { + StrUtf8 src; + src.AddString("ko", "ko name"); + src.AddString("de", "de name"); + + feature::GetReadableName(regionData, src, deviceLang, name); + + TEST_EQUAL(name, "de name", ()); + } + + { + StrUtf8 src; + src.AddString("ko", "ko name"); + src.AddString("de", "de name"); + src.AddString("default", "default name"); + + feature::GetReadableName(regionData, src, deviceLang, name); + + TEST_EQUAL(name, "default name", ()); + } + + { + StrUtf8 src; + src.AddString("ko", "ko name"); + src.AddString("de", "de name"); + src.AddString("default", "default name"); + src.AddString("en", "en name"); + + feature::GetReadableName(regionData, src, deviceLang, name); + + TEST_EQUAL(name, "en name", ()); + } + + { + StrUtf8 src; + src.AddString("ko", "ko name"); + src.AddString("de", "de name"); + src.AddString("default", "default name"); + src.AddString("en", "en name"); + src.AddString("int_name", "int name"); + + feature::GetReadableName(regionData, src, deviceLang, name); + + TEST_EQUAL(name, "int name", ()); + } + + { + StrUtf8 src; + src.AddString("ko", "ko name"); + src.AddString("de", "de name"); + src.AddString("default", "default name"); + src.AddString("en", "en name"); + src.AddString("int_name", "int name"); + src.AddString("ru", "ru name"); + + feature::GetReadableName(regionData, src, deviceLang, name); + + TEST_EQUAL(name, "ru name", ()); + } + + deviceLang = StrUtf8::GetLangIndex("de"); + + { + StrUtf8 src; + src.AddString("ko", "ko name"); + src.AddString("de", "de name"); + src.AddString("default", "default name"); + src.AddString("en", "en name"); + src.AddString("int_name", "int name"); + + feature::GetReadableName(regionData, src, deviceLang, name); + + TEST_EQUAL(name, "de name", ()); + } + + { + StrUtf8 src; + src.AddString("ko", "ko name"); + src.AddString("default", "default name"); + src.AddString("en", "en name"); + src.AddString("int_name", "int name"); + + feature::GetReadableName(regionData, src, deviceLang, name); + + TEST_EQUAL(name, "default name", ()); + } + + { + StrUtf8 src; + src.AddString("ko", "ko name"); + src.AddString("en", "en name"); + src.AddString("int_name", "int name"); + + feature::GetReadableName(regionData, src, deviceLang, name); + + TEST_EQUAL(name, "int name", ()); + } + + { + StrUtf8 src; + src.AddString("ko", "ko name"); + src.AddString("en", "en name"); + + feature::GetReadableName(regionData, src, deviceLang, name); + + TEST_EQUAL(name, "en name", ()); + } + + { + StrUtf8 src; + src.AddString("ko", "ko name"); + + feature::GetReadableName(regionData, src, deviceLang, name); + + TEST_EQUAL(name, "ko name", ()); + } } } // namespace diff --git a/map/place_page_info.cpp b/map/place_page_info.cpp index 9cd2997405..8daf71c4af 100644 --- a/map/place_page_info.cpp +++ b/map/place_page_info.cpp @@ -4,6 +4,7 @@ #include "indexer/osm_editor.hpp" #include "platform/measurement_utils.hpp" +#include "platform/preferred_languages.hpp" namespace place_page { @@ -49,7 +50,12 @@ string Info::GetTitle() const return m_customName; string name; - feature::GetReadableName(GetID(), m_name, name); + auto const deviceLang = StringUtf8Multilang::GetLangIndex(languages::GetCurrentNorm()); + + auto const mwmInfo = GetID().m_mwmId.GetInfo(); + + if (mwmInfo) + feature::GetReadableName(mwmInfo->GetRegionData(), m_name, deviceLang, name); return name; }