forked from organicmaps/organicmaps
[search][android][ios] Exposed categories synonyms.
This commit is contained in:
parent
e34ff29fc1
commit
e8a77fb0fb
10 changed files with 97 additions and 37 deletions
|
@ -5,8 +5,8 @@
|
|||
extern "C"
|
||||
{
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_com_mapswithme_maps_search_DisplayedCategories_nativeGet(JNIEnv * env, jclass clazz)
|
||||
Java_com_mapswithme_maps_search_DisplayedCategories_nativeGetKeys(JNIEnv * env, jclass clazz)
|
||||
{
|
||||
return jni::ToJavaStringArray(env, search::GetDisplayedCategories());
|
||||
return jni::ToJavaStringArray(env, search::DisplayedCategories::GetKeys());
|
||||
}
|
||||
} // extern "C"
|
||||
|
|
|
@ -36,22 +36,20 @@ class CategoriesAdapter extends RecyclerView.Adapter<CategoriesAdapter.ViewHolde
|
|||
final boolean isNightTheme = ThemeUtils.isNightTheme();
|
||||
final Resources resources = fragment.getActivity().getResources();
|
||||
|
||||
final String[] categories = DisplayedCategories.get();
|
||||
final String[] keys = DisplayedCategories.getKeys();
|
||||
final int numKeys = keys.length;
|
||||
|
||||
final int len = categories.length;
|
||||
|
||||
mCategoryResIds = new int[len];
|
||||
mIconResIds = new int[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
mCategoryResIds = new int[numKeys];
|
||||
mIconResIds = new int[numKeys];
|
||||
for (int i = 0; i < numKeys; i++)
|
||||
{
|
||||
mCategoryResIds[i] = resources.getIdentifier(categories[i], "string", packageName);
|
||||
if (mCategoryResIds[i] == 0)
|
||||
{
|
||||
throw new IllegalStateException(
|
||||
"Can't get string resource id for category:" + categories[i]);
|
||||
}
|
||||
String key = keys[i];
|
||||
|
||||
String iconId = "ic_category_" + categories[i];
|
||||
mCategoryResIds[i] = resources.getIdentifier(key, "string", packageName);
|
||||
if (mCategoryResIds[i] == 0)
|
||||
throw new IllegalStateException("Can't get string resource id for category:" + key);
|
||||
|
||||
String iconId = "ic_category_" + key;
|
||||
if (isNightTheme)
|
||||
iconId = iconId + "_night";
|
||||
mIconResIds[i] = resources.getIdentifier(iconId, "drawable", packageName);
|
||||
|
|
|
@ -2,7 +2,7 @@ package com.mapswithme.maps.search;
|
|||
|
||||
class DisplayedCategories
|
||||
{
|
||||
public static String[] get() { return nativeGet(); }
|
||||
public static String[] getKeys() { return nativeGetKeys(); }
|
||||
|
||||
private static native String[] nativeGet();
|
||||
private static native String[] nativeGetKeys();
|
||||
}
|
||||
|
|
|
@ -22,8 +22,12 @@ enum State
|
|||
// static
|
||||
int8_t const CategoriesHolder::kEnglishCode = 1;
|
||||
int8_t const CategoriesHolder::kUnsupportedLocaleCode = -1;
|
||||
// *NOTE* These constants should be updated when
|
||||
// adding new translation to categories.txt.
|
||||
|
||||
// *NOTE* These constants should be updated when adding new
|
||||
// translation to categories.txt. When editing, keep in mind to check
|
||||
// CategoriesHolder::MapLocaleToInteger() and
|
||||
// CategoriesHolder::MapIntegerToLocale() as their implementations
|
||||
// highly depend on the contents of the variable.
|
||||
vector<CategoriesHolder::Mapping> const CategoriesHolder::kLocaleMapping = {{"en", 1},
|
||||
{"ru", 2},
|
||||
{"uk", 3},
|
||||
|
@ -111,6 +115,7 @@ void CategoriesHolder::LoadFromStream(istream & s)
|
|||
{
|
||||
m_type2cat.clear();
|
||||
m_name2type.clear();
|
||||
m_groupTranslations.clear();
|
||||
|
||||
State state = EParseTypes;
|
||||
string line;
|
||||
|
@ -118,7 +123,6 @@ void CategoriesHolder::LoadFromStream(istream & s)
|
|||
Category cat;
|
||||
vector<uint32_t> types;
|
||||
vector<string> currentGroups;
|
||||
multimap<string, Category::Name> groupTranslations;
|
||||
|
||||
Classificator const & c = classif();
|
||||
|
||||
|
@ -184,9 +188,11 @@ void CategoriesHolder::LoadFromStream(istream & s)
|
|||
{
|
||||
for (string const & group : currentGroups)
|
||||
{
|
||||
auto trans = groupTranslations.equal_range(group);
|
||||
for (auto it = trans.first; it != trans.second; ++it)
|
||||
cat.m_synonyms.push_back(it->second);
|
||||
auto it = m_groupTranslations.find(group);
|
||||
if (it == m_groupTranslations.end())
|
||||
continue;
|
||||
for (auto const & synonym : it->second)
|
||||
cat.m_synonyms.push_back(synonym);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,7 +248,7 @@ void CategoriesHolder::LoadFromStream(istream & s)
|
|||
if (currentGroups.size() == 1 && types.empty())
|
||||
{
|
||||
// Not a translation, but a category group definition
|
||||
groupTranslations.emplace(currentGroups[0], name);
|
||||
m_groupTranslations[currentGroups[0]].push_back(name);
|
||||
}
|
||||
else
|
||||
cat.m_synonyms.push_back(name);
|
||||
|
@ -308,6 +314,7 @@ bool CategoriesHolder::IsTypeExist(uint32_t type) const
|
|||
return range.first != range.second;
|
||||
}
|
||||
|
||||
// static
|
||||
int8_t CategoriesHolder::MapLocaleToInteger(string const & locale)
|
||||
{
|
||||
ASSERT(!kLocaleMapping.empty(), ());
|
||||
|
@ -338,3 +345,11 @@ int8_t CategoriesHolder::MapLocaleToInteger(string const & locale)
|
|||
|
||||
return kUnsupportedLocaleCode;
|
||||
}
|
||||
|
||||
// static
|
||||
string CategoriesHolder::MapIntegerToLocale(int8_t code)
|
||||
{
|
||||
if (code <= 0 || code > kLocaleMapping.size())
|
||||
return string();
|
||||
return kLocaleMapping[code - 1].m_name;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ public:
|
|||
int8_t m_code;
|
||||
};
|
||||
|
||||
using GroupTranslations = unordered_map<string, vector<Category::Name>>;
|
||||
|
||||
private:
|
||||
typedef strings::UniString StringT;
|
||||
typedef multimap<uint32_t, shared_ptr<Category> > Type2CategoryContT;
|
||||
|
@ -49,6 +51,7 @@ private:
|
|||
|
||||
Type2CategoryContT m_type2cat;
|
||||
Name2CatContT m_name2type;
|
||||
GroupTranslations m_groupTranslations;
|
||||
|
||||
public:
|
||||
static int8_t const kEnglishCode;
|
||||
|
@ -107,6 +110,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
inline GroupTranslations const & GetGroupTranslations() const { return m_groupTranslations; }
|
||||
|
||||
/// Search name for type with preffered locale language.
|
||||
/// If no name for this language, return first (en) name.
|
||||
/// @return false if no categories for type.
|
||||
|
@ -123,9 +128,15 @@ public:
|
|||
m_name2type.swap(r.m_name2type);
|
||||
}
|
||||
|
||||
/// Converts any language locale from UI to internal integer code
|
||||
// Converts any language |locale| from UI to the corresponding
|
||||
// internal integer code
|
||||
static int8_t MapLocaleToInteger(string const & locale);
|
||||
|
||||
// Returns corresponding string representation for an internal
|
||||
// integer |code|. Returns an empty string in case of invalid
|
||||
// |code|.
|
||||
static string MapIntegerToLocale(int8_t code);
|
||||
|
||||
private:
|
||||
void AddCategory(Category & cat, vector<uint32_t> & types);
|
||||
static bool ValidKeyToken(StringT const & s);
|
||||
|
|
|
@ -18,7 +18,7 @@ static NSString * const kCellIdentifier = @"MWMSearchCategoryCell";
|
|||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
m_categories = search::GetDisplayedCategories();
|
||||
m_categories = search::DisplayedCategories::GetKeys();
|
||||
return self;
|
||||
}
|
||||
|
||||
|
|
|
@ -351,6 +351,7 @@ Framework::Framework()
|
|||
m_model.SetOnMapDeregisteredCallback(bind(&Framework::OnMapDeregistered, this, _1));
|
||||
LOG(LDEBUG, ("Classificator initialized"));
|
||||
|
||||
m_displayedCategories = make_unique<search::DisplayedCategories>(GetDefaultCategories());
|
||||
|
||||
// To avoid possible races - init country info getter once in constructor.
|
||||
InitCountryInfoGetter();
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "editor/user_stats.hpp"
|
||||
|
||||
#include "search/displayed_categories.hpp"
|
||||
#include "search/downloader_search_callback.hpp"
|
||||
#include "search/engine.hpp"
|
||||
#include "search/mode.hpp"
|
||||
|
@ -117,12 +118,15 @@ protected:
|
|||
|
||||
StringsBundle m_stringsBundle;
|
||||
|
||||
model::FeaturesFetcher m_model;
|
||||
|
||||
// The order matters here: DisplayedCategories may be used only when
|
||||
// classificator is loaded (by |m_model|).
|
||||
unique_ptr<search::DisplayedCategories> m_displayedCategories;
|
||||
|
||||
// The order matters here: storage::CountryInfoGetter and
|
||||
// m_model::FeaturesFetcher must be initialized before
|
||||
// search::Engine and, therefore, destroyed after search::Engine.
|
||||
|
||||
model::FeaturesFetcher m_model;
|
||||
|
||||
unique_ptr<storage::CountryInfoGetter> m_infoGetter;
|
||||
|
||||
unique_ptr<search::Engine> m_searchEngine;
|
||||
|
@ -241,6 +245,10 @@ public:
|
|||
|
||||
storage::Storage & GetStorage() { return m_storage; }
|
||||
storage::Storage const & GetStorage() const { return m_storage; }
|
||||
search::DisplayedCategories const & GetDisplayedCategories() const
|
||||
{
|
||||
return *m_displayedCategories;
|
||||
}
|
||||
storage::CountryInfoGetter & GetCountryInfoGetter() { return *m_infoGetter; }
|
||||
StorageDownloadingPolicy & GetDownloadingPolicy() { return m_storageDownloadingPolicy; }
|
||||
|
||||
|
|
|
@ -2,12 +2,15 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
vector<string> const kDisplayedCategories = {
|
||||
"food", "hotel", "tourism", "wifi", "transport", "fuel", "parking", "shop",
|
||||
"atm", "bank", "entertainment", "hospital", "pharmacy", "police", "toilet", "post"};
|
||||
vector<string> const kKeys = {"food", "hotel", "tourism", "wifi", "transport", "fuel",
|
||||
"parking", "shop", "atm", "bank", "entertainment", "hospital",
|
||||
"pharmacy", "police", "toilet", "post"};
|
||||
} // namespace
|
||||
|
||||
namespace search
|
||||
{
|
||||
vector<string> const & GetDisplayedCategories() { return kDisplayedCategories; }
|
||||
DisplayedCategories::DisplayedCategories(CategoriesHolder const & holder) : m_holder(holder) {}
|
||||
|
||||
// static
|
||||
vector<string> const & DisplayedCategories::GetKeys() { return kKeys; }
|
||||
} // namespace search
|
||||
|
|
|
@ -1,12 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include "indexer/categories_holder.hpp"
|
||||
|
||||
#include "std/string.hpp"
|
||||
#include "std/vector.hpp"
|
||||
|
||||
namespace search
|
||||
{
|
||||
// Returns a list of English names of displayed categories for the
|
||||
// categories search tab. It's guaranteed that the list remains the
|
||||
// same during the application lifetime.
|
||||
vector<string> const & GetDisplayedCategories();
|
||||
class DisplayedCategories
|
||||
{
|
||||
public:
|
||||
DisplayedCategories(CategoriesHolder const & holder);
|
||||
|
||||
// Returns a list of English names of displayed categories for the
|
||||
// categories search tab. It's guaranteed that the list remains the
|
||||
// same during the application lifetime, keys may be used as parts
|
||||
// of resources ids.
|
||||
static vector<string> const & GetKeys();
|
||||
|
||||
template <typename Fn>
|
||||
void ForEachSynonym(string const & key, Fn && fn) const
|
||||
{
|
||||
auto const & translations = m_holder.GetGroupTranslations();
|
||||
auto const it = translations.find("@" + key);
|
||||
if (it == translations.end())
|
||||
return;
|
||||
|
||||
for (auto const & name : it->second)
|
||||
fn(name.m_name, CategoriesHolder::MapIntegerToLocale(name.m_locale));
|
||||
}
|
||||
|
||||
private:
|
||||
CategoriesHolder const & m_holder;
|
||||
};
|
||||
} // namespace search
|
||||
|
|
Loading…
Add table
Reference in a new issue