From e0dd57c50e6f4995bd1e9faccd9e86aeade64d72 Mon Sep 17 00:00:00 2001 From: Arsentiy Milchakov Date: Tue, 25 Apr 2017 18:50:16 +0300 Subject: [PATCH] extended languages for device language --- indexer/feature_utils.cpp | 108 +++++++++++++------ indexer/feature_utils.hpp | 12 ++- indexer/indexer_tests/feature_names_test.cpp | 49 +++++++++ 3 files changed, 133 insertions(+), 36 deletions(-) diff --git a/indexer/feature_utils.cpp b/indexer/feature_utils.cpp index 5947948079..9f81a91212 100644 --- a/indexer/feature_utils.cpp +++ b/indexer/feature_utils.cpp @@ -13,11 +13,24 @@ #include "base/base.hpp" #include "std/vector.hpp" +#include "std/unordered_map.hpp" +#include "std/utility.hpp" namespace { using StrUtf8 = StringUtf8Multilang; +int8_t GetIndex(string const & lang) +{ + return StrUtf8::GetLangIndex(lang); +} + +unordered_map> const kExtendedDevicelang = +{ + {GetIndex("be"), {GetIndex("be"), GetIndex("ru")}}, + {GetIndex("ru"), {GetIndex("ru"), GetIndex("be")}} +}; + void GetMwmLangName(feature::RegionData const & regionData, StringUtf8Multilang const & src, string & out) { vector mwmLangCodes; @@ -49,14 +62,13 @@ bool GetTransliteratedName(feature::RegionData const & regionData, StringUtf8Mul bool GetBestName(StringUtf8Multilang const & src, vector const & priorityList, string & out) { - auto const priorityListSize = static_cast(priorityList.size()); - auto bestIndex = priorityListSize; + auto bestIndex = priorityList.size(); auto const findAndSet = [](vector const & langs, int8_t const code, string const & name, - long & bestIndex, string & outName) + size_t & bestIndex, string & outName) { auto const it = find(langs.begin(), langs.end(), code); - if (it != langs.end() && bestIndex > distance(langs.begin(), it)) + if (it != langs.end() && bestIndex > static_cast(distance(langs.begin(), it))) { bestIndex = distance(langs.begin(), it); outName = name; @@ -73,13 +85,53 @@ bool GetBestName(StringUtf8Multilang const & src, vector const & priorit }); // There are many "junk" names in Arabian island. - if (bestIndex < priorityListSize && + if (bestIndex < priorityList.size() && priorityList[bestIndex] == StrUtf8::kInternationalCode) { out = out.substr(0, out.find_first_of(',')); } - return bestIndex < priorityListSize; + return bestIndex < priorityList.size(); +} + +vector GetExtendedDeviceLanguages(int8_t deviceLang) +{ + vector result; + + auto const it = kExtendedDevicelang.find(deviceLang); + if (it != kExtendedDevicelang.cend()) + result = it->second; + else + result.push_back(deviceLang); + + return result; +} + +void GetReadableNameImpl(feature::RegionData const & regionData, StringUtf8Multilang const & src, + vector deviceLangs, bool preferDefault, bool allowTranslit, + string & out) +{ + ASSERT(!deviceLangs.empty(), ()); + + if (preferDefault) + deviceLangs.insert(deviceLangs.cend(), {StrUtf8::kDefaultCode, StrUtf8::kInternationalCode, + StrUtf8::kEnglishCode}); + else + deviceLangs.insert(deviceLangs.cend(), {StrUtf8::kInternationalCode, StrUtf8::kEnglishCode}); + + if (GetBestName(src, deviceLangs, out)) + return; + + if (allowTranslit && GetTransliteratedName(regionData, src, out)) + return; + + if (!preferDefault) + { + if (GetBestName(src, {StrUtf8::kDefaultCode}, out)) + return; + } + + GetMwmLangName(regionData, src, out); } } // namespace @@ -232,20 +284,22 @@ void GetPreferredNames(RegionData const & regionData, StringUtf8Multilang const if (src.IsEmpty()) return; + vector primaryCodes = GetExtendedDeviceLanguages(deviceLang); + // When the language of the user is equal to one of the languages of the MWM // only single name scheme is used. - if (regionData.HasLanguage(deviceLang)) - return GetReadableName(regionData, src, deviceLang, allowTranslit, primary); + for (auto const code : primaryCodes) + { + if (regionData.HasLanguage(code)) + return GetReadableNameImpl(regionData, src, move(primaryCodes), true, allowTranslit, primary); + } - vector const primaryCodes = {deviceLang, - StrUtf8::kInternationalCode, - StrUtf8::kEnglishCode}; + primaryCodes.insert(primaryCodes.cend(), {StrUtf8::kInternationalCode, StrUtf8::kEnglishCode}); if (!GetBestName(src, primaryCodes, primary) && allowTranslit) GetTransliteratedName(regionData, src, primary); - vector secondaryCodes = {StrUtf8::kDefaultCode, - StrUtf8::kInternationalCode}; + vector secondaryCodes = {StrUtf8::kDefaultCode, StrUtf8::kInternationalCode}; vector mwmLangCodes; regionData.GetLanguages(mwmLangCodes); @@ -269,28 +323,20 @@ void GetReadableName(RegionData const & regionData, StringUtf8Multilang const & if (src.IsEmpty()) return; - vector codes; + vector deviceLangs = GetExtendedDeviceLanguages(deviceLang); + // If MWM contains user's language. - bool const preferDefault = regionData.HasLanguage(deviceLang); - if (preferDefault) - codes = {deviceLang, StrUtf8::kDefaultCode, StrUtf8::kInternationalCode, StrUtf8::kEnglishCode}; - else - codes = {deviceLang, StrUtf8::kInternationalCode, StrUtf8::kEnglishCode}; - - if (GetBestName(src, codes, out)) - return; - - if (allowTranslit && GetTransliteratedName(regionData, src, out)) - return; - - if (!preferDefault) + bool preferDefault = false; + for (auto const lang : deviceLangs) { - codes = {StrUtf8::kDefaultCode}; - if (GetBestName(src, codes, out)) - return; + if (regionData.HasLanguage(lang)) + { + preferDefault = true; + break; + } } - GetMwmLangName(regionData, src, out); + GetReadableNameImpl(regionData, src, move(deviceLangs), preferDefault, allowTranslit, out); } int8_t GetNameForSearchOnBooking(RegionData const & regionData, StringUtf8Multilang const & src, diff --git a/indexer/feature_utils.hpp b/indexer/feature_utils.hpp index 7b91c797d9..fca3da00bc 100644 --- a/indexer/feature_utils.hpp +++ b/indexer/feature_utils.hpp @@ -16,7 +16,7 @@ namespace feature int GetFeatureViewportScale(TypesHolder const & types); /// Primary name using priority: - /// - device language name; + /// - device language name (or extended device languages if provided); /// - international name; /// - english name; /// - transliterated name (if allowed). @@ -30,15 +30,17 @@ namespace feature void GetPreferredNames(RegionData const & regionData, StringUtf8Multilang const & src, int8_t const deviceLang, bool allowTranslit, string & primary, string & secondary); - /// When MWM contains user's language, the priority is the following: - /// - device language name; + /// When MWM contains user's language (or extended device languages if provided), + /// the priority is the following: + /// - device language name (or extended device languages if provided); /// - default name; /// - international name; /// - english name; /// - transliterated name (if allowed); /// - country language name. - /// When MWM does not contain user's language, the priority is the following: - /// - device language name; + /// When MWM does not contain user's language (or extended device languages), + /// the priority is the following: + /// - device language name (or extended device languages if provided); /// - international name; /// - english name; /// - transliterated name (if allowed); diff --git a/indexer/indexer_tests/feature_names_test.cpp b/indexer/indexer_tests/feature_names_test.cpp index 282513d8c5..9e2273b764 100644 --- a/indexer/indexer_tests/feature_names_test.cpp +++ b/indexer/indexer_tests/feature_names_test.cpp @@ -167,6 +167,32 @@ UNIT_TEST(GetPrefferedNames) TEST_EQUAL(primary, "en name", ()); TEST_EQUAL(secondary, "", ()); } + { + int8_t deviceLang = StrUtf8::GetLangIndex("ru"); + StrUtf8 src; + src.AddString("int_name", "int name"); + src.AddString("en", "en name"); + src.AddString("be", "be name"); + + feature::GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary); + + TEST_EQUAL(primary, "be name", ()); + TEST_EQUAL(secondary, "int name", ()); + } + { + feature::RegionData regionData; + regionData.SetLanguages({"ru"}); + int8_t deviceLang = StrUtf8::GetLangIndex("be"); + StrUtf8 src; + src.AddString("int_name", "int name"); + src.AddString("en", "en name"); + src.AddString("ru", "ru name"); + + feature::GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary); + + TEST_EQUAL(primary, "ru name", ()); + TEST_EQUAL(secondary, "", ()); + } } UNIT_TEST(GetPrefferedNamesLocal) @@ -188,6 +214,18 @@ UNIT_TEST(GetPrefferedNamesLocal) TEST_EQUAL(primary, "default name", ()); TEST_EQUAL(secondary, "", ()); } + { + int8_t deviceLang = StrUtf8::GetLangIndex("ru"); + StrUtf8 src; + src.AddString("int_name", "int name"); + src.AddString("en", "en name"); + src.AddString("be", "be name"); + + feature::GetPreferredNames(regionData, src, deviceLang, allowTranslit, primary, secondary); + + TEST_EQUAL(primary, "be name", ()); + TEST_EQUAL(secondary, "", ()); + } } UNIT_TEST(GetReadableName) @@ -333,6 +371,17 @@ UNIT_TEST(GetReadableName) TEST_EQUAL(name, "ko name", ()); } + { + int8_t deviceLang = StrUtf8::GetLangIndex("be"); + StrUtf8 src; + src.AddString("int_name", "int name"); + src.AddString("en", "en name"); + src.AddString("ru", "ru name"); + + feature::GetReadableName(regionData, src, deviceLang, allowTranslit, name); + + TEST_EQUAL(name, "ru name", ()); + } } UNIT_TEST(GetNameForSearchOnBooking)