Packages: improve localised string support
This commit is contained in:
parent
854b958797
commit
46b271d75c
@ -148,6 +148,7 @@ int parseTest()
|
||||
SGPath rootPath = simgear::Dir::current().path();
|
||||
rootPath.append("testRoot");
|
||||
pkg::Root* root = new pkg::Root(rootPath, "8.1.12");
|
||||
root->setLocale("de");
|
||||
pkg::CatalogRef cat = pkg::Catalog::createFromPath(root, SGPath(SRC_DIR "/catalogTest1"));
|
||||
|
||||
SG_VERIFY(cat.valid());
|
||||
@ -172,7 +173,7 @@ int parseTest()
|
||||
pkg::PackageRef p2 = cat->getPackageById("c172p");
|
||||
SG_VERIFY(p2.valid());
|
||||
SG_CHECK_EQUAL(p2->qualifiedId(), "org.flightgear.test.catalog1.c172p");
|
||||
SG_CHECK_EQUAL(p2->description(), "A plane made by Cessna on Jupiter");
|
||||
SG_CHECK_EQUAL(p2->description(), "German description of C172");
|
||||
|
||||
pkg::Package::PreviewVec thumbs = p2->previewsForVariant(0);
|
||||
SG_CHECK_EQUAL(thumbs.size(), 3);
|
||||
@ -217,7 +218,7 @@ int parseTest()
|
||||
SG_CHECK_EQUAL(skisVariant, skisVariantFull);
|
||||
|
||||
SG_CHECK_EQUAL(p2->getLocalisedProp("description", skisVariant),
|
||||
"A plane with skis");
|
||||
"German description of C172 with skis");
|
||||
SG_CHECK_EQUAL(p2->getLocalisedProp("author", skisVariant),
|
||||
"Standard author");
|
||||
|
||||
@ -225,6 +226,7 @@ int parseTest()
|
||||
SG_VERIFY(floatsVariant > 0);
|
||||
SG_CHECK_EQUAL(p2->parentIdForVariant(floatsVariant), "c172p");
|
||||
|
||||
// no DE localisation description provided for the floats variant
|
||||
SG_CHECK_EQUAL(p2->getLocalisedProp("description", floatsVariant),
|
||||
"A plane with floats");
|
||||
SG_CHECK_EQUAL(p2->getLocalisedProp("author", floatsVariant),
|
||||
@ -257,6 +259,12 @@ int parseTest()
|
||||
string_list primaries = {"c172p", "c172r"};
|
||||
SG_VERIFY(p2->primaryVariants() == primaries);
|
||||
|
||||
///////////
|
||||
pkg::PackageRef p3 = cat->getPackageById("b737-NG");
|
||||
SG_VERIFY(p3.valid());
|
||||
SG_CHECK_EQUAL(p3->description(), "German description of B737NG XYZ");
|
||||
|
||||
|
||||
// test filtering / searching too
|
||||
string_set tags(p2->tags());
|
||||
SG_CHECK_EQUAL(tags.size(), 4);
|
||||
@ -305,6 +313,16 @@ int parseTest()
|
||||
queryText->setStringValue("any-of/description", "float");
|
||||
SG_VERIFY(p2->matches(queryText.ptr()));
|
||||
}
|
||||
|
||||
// match localized variant descriptions
|
||||
{
|
||||
SGPropertyNode_ptr queryText(new SGPropertyNode);
|
||||
queryText->setStringValue("any-of/description", "XYZ");
|
||||
SG_VERIFY(p3->matches(queryText.ptr()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
delete root;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ void Package::initWithProps(const SGPropertyNode* aProps)
|
||||
{
|
||||
m_props = const_cast<SGPropertyNode*>(aProps);
|
||||
// cache tag values
|
||||
BOOST_FOREACH(const SGPropertyNode* c, aProps->getChildren("tag")) {
|
||||
for (auto c : aProps->getChildren("tag")) {
|
||||
std::string t(c->getStringValue());
|
||||
m_tags.insert(boost::to_lower_copy(t));
|
||||
}
|
||||
@ -133,22 +133,8 @@ bool Package::matches(const SGPropertyNode* aFilter) const
|
||||
|
||||
if ((filter_name == "text") || (filter_name == "description")) {
|
||||
handled = true;
|
||||
std::string n(aFilter->getStringValue());
|
||||
boost::to_lower(n);
|
||||
size_t pos = boost::to_lower_copy(description()).find(n);
|
||||
if (pos != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto var : m_props->getChildren("variant")) {
|
||||
if (var->hasChild("description")) {
|
||||
std::string variantDesc(var->getStringValue("description"));
|
||||
boost::to_lower(variantDesc);
|
||||
size_t pos = variantDesc.find(n);
|
||||
if (pos != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (matchesDescription(aFilter->getStringValue())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,6 +144,50 @@ bool Package::matches(const SGPropertyNode* aFilter) const
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Package::matchesDescription(const std::string &search) const
|
||||
{
|
||||
std::string n(search);
|
||||
boost::to_lower(n);
|
||||
|
||||
bool localized;
|
||||
auto d = getLocalisedString(m_props, "description", &localized);
|
||||
boost::to_lower(d);
|
||||
if (d.find(n) != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// try non-localized description too, if the abovce was a localized one
|
||||
if (localized) {
|
||||
const std::string baseDesc = m_props->getStringValue("description");
|
||||
auto pos = boost::to_lower_copy(baseDesc).find(n);
|
||||
if (pos != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// try each variant's description
|
||||
for (auto var : m_props->getChildren("variant")) {
|
||||
auto vd = getLocalisedString(var, "description", &localized);
|
||||
if (!vd.empty()) {
|
||||
boost::to_lower(vd);
|
||||
if (vd.find(n) != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (localized) {
|
||||
// try non-localized variant description
|
||||
std::string vd = var->getStringValue("description");
|
||||
boost::to_lower(vd);
|
||||
if (vd.find(n) != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} // of variant iteration
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Package::isInstalled() const
|
||||
{
|
||||
@ -307,14 +337,29 @@ std::string Package::getLocalisedProp(const std::string& aName, const unsigned i
|
||||
return getLocalisedString(propsForVariant(vIndex, aName.c_str()), aName.c_str());
|
||||
}
|
||||
|
||||
std::string Package::getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const
|
||||
std::string Package::getLocalisedString(const SGPropertyNode* aRoot, const char* aName, bool* isLocalized) const
|
||||
{
|
||||
std::string locale = m_catalog->root()->getLocale();
|
||||
if (aRoot->hasChild(locale)) {
|
||||
const SGPropertyNode* localeRoot = aRoot->getChild(locale.c_str());
|
||||
if (localeRoot->hasChild(aName)) {
|
||||
return localeRoot->getStringValue(aName);
|
||||
}
|
||||
// we used to place localised strings under /sim/<locale>/name - but this
|
||||
// potentially pollutes the /sim namespace
|
||||
// we now check first in /sim/localized/<locale>/name first
|
||||
const auto& locale = m_catalog->root()->getLocale();
|
||||
if (isLocalized) *isLocalized = false;
|
||||
|
||||
if (locale.empty()) {
|
||||
return aRoot->getStringValue(aName);
|
||||
}
|
||||
|
||||
const SGPropertyNode* localeRoot;
|
||||
if (aRoot->hasChild("localized")) {
|
||||
localeRoot = aRoot->getChild("localized")->getChild(locale);
|
||||
} else {
|
||||
// old behaviour where locale nodes are directly beneath /sim
|
||||
localeRoot = aRoot->getChild(locale);
|
||||
}
|
||||
|
||||
if (localeRoot && localeRoot->hasChild(aName)) {
|
||||
if (isLocalized) *isLocalized = true;
|
||||
return localeRoot->getStringValue(aName);
|
||||
}
|
||||
|
||||
return aRoot->getStringValue(aName);
|
||||
|
@ -225,12 +225,14 @@ private:
|
||||
*/
|
||||
bool validate() const;
|
||||
|
||||
std::string getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const;
|
||||
std::string getLocalisedString(const SGPropertyNode* aRoot, const char* aName, bool* isLocalized = nullptr) const;
|
||||
|
||||
PreviewVec previewsFromProps(const SGPropertyNode_ptr& ptr) const;
|
||||
|
||||
SGPropertyNode_ptr propsForVariant(const unsigned int vIndex, const char* propName = nullptr) const;
|
||||
|
||||
bool matchesDescription(const std::string &search) const;
|
||||
|
||||
SGPropertyNode_ptr m_props;
|
||||
std::string m_id;
|
||||
string_set m_tags;
|
||||
|
@ -32,6 +32,15 @@
|
||||
<file-size-bytes type="int">860</file-size-bytes>
|
||||
<author>Standard author</author>
|
||||
|
||||
<localized>
|
||||
<de>
|
||||
<description>German description of C172</description>
|
||||
</de>
|
||||
<fr>
|
||||
<description>French description of C172</description>
|
||||
</fr>
|
||||
</localized>
|
||||
|
||||
<tag>cessna</tag>
|
||||
<tag>ga</tag>
|
||||
<tag>piston</tag>
|
||||
@ -99,6 +108,15 @@
|
||||
<name>C172 with skis</name>
|
||||
<description>A plane with skis</description>
|
||||
|
||||
<localized>
|
||||
<de>
|
||||
<description>German description of C172 with skis</description>
|
||||
</de>
|
||||
<fr>
|
||||
<description>French description of C172 with skis</description>
|
||||
</fr>
|
||||
</localized>
|
||||
|
||||
<variant-of>c172p</variant-of>
|
||||
|
||||
<preview>
|
||||
@ -157,6 +175,14 @@
|
||||
<tag>jet</tag>
|
||||
<tag>ifr</tag>
|
||||
|
||||
<!-- not within a localized element -->
|
||||
<de>
|
||||
<description>German description of B737NG XYZ</description>
|
||||
</de>
|
||||
<fr>
|
||||
<description>French description of B737NG</description>
|
||||
</fr>
|
||||
|
||||
<rating>
|
||||
<FDM type="int">5</FDM>
|
||||
<systems type="int">5</systems>
|
||||
|
Loading…
Reference in New Issue
Block a user