summaryrefslogtreecommitdiff
path: root/configmgr/source/access.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'configmgr/source/access.cxx')
-rw-r--r--configmgr/source/access.cxx75
1 files changed, 75 insertions, 0 deletions
diff --git a/configmgr/source/access.cxx b/configmgr/source/access.cxx
index 30d05420573d..8d6d9cf4cdd5 100644
--- a/configmgr/source/access.cxx
+++ b/configmgr/source/access.cxx
@@ -1484,6 +1484,81 @@ rtl::Reference< Node > Access::getParentNode() {
}
rtl::Reference< ChildAccess > Access::getChild(rtl::OUString const & name) {
+ if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY && name.match("*")) {
+ OUString locale(name.copy(1));
+ if (locale.match("*")) {
+ SAL_WARN(
+ "configmgr",
+ ("access best-matching localized property value via"
+ " \"*<locale>\" with <locale> \"")
+ << locale << "\" recursively starting with \"*\"");
+ return getChild(locale);
+ }
+ SAL_WARN_IF(
+ locale.isEmpty(), "configmgr",
+ ("access best-matching localized property value via \"*<locale>\""
+ " with empty <locale>; falling back to defaults"));
+ if (!locale.isEmpty()) {
+ // Find best match using an adaption of RFC 4647 lookup matching
+ // rules, removing "-" or "_" delimited segments from the end:
+ for (;;) {
+ rtl::Reference< ChildAccess > child(getChild(locale));
+ if (child.is()) {
+ return child;
+ }
+ sal_Int32 i = locale.getLength() - 1;
+ while (i > 0 && locale[i] != '-' && locale[i] != '_') {
+ --i;
+ }
+ if (i <= 0) {
+ break;
+ }
+ locale = locale.copy(0, i);
+ }
+ // As a workaround for broken xcu data that does not use shortest
+ // xml:lang attributes, look for the first entry with the same first
+ // segment as the requested language tag before falling back to
+ // defaults (see fdo#33638):
+ assert(
+ !locale.isEmpty() && locale.indexOf('-') == -1 &&
+ locale.indexOf('_') == -1);
+ std::vector< rtl::Reference< ChildAccess > > children(
+ getAllChildren());
+ for (std::vector< rtl::Reference< ChildAccess > >::iterator i(
+ children.begin());
+ i != children.end(); ++i)
+ {
+ OUString name2((*i)->getNameInternal());
+ if (name2.match(locale) &&
+ (name2.getLength() == locale.getLength() ||
+ name2[locale.getLength()] == '-' ||
+ name2[locale.getLength()] == '_'))
+ {
+ return *i;
+ }
+ }
+ }
+ // Defaults are the "en-US" locale, the "en" locale, the empty string
+ // locale, the first child (if any), or a null ChildAccess, in that
+ // order:
+ rtl::Reference< ChildAccess > child(getChild("en-US"));
+ if (child.is()) {
+ return child;
+ }
+ child = getChild("en");
+ if (child.is()) {
+ return child;
+ }
+ child = getChild(OUString());
+ if (child.is()) {
+ return child;
+ }
+ std::vector< rtl::Reference< ChildAccess > > children(getAllChildren());
+ if (!children.empty()) {
+ return children.front();
+ }
+ return rtl::Reference< ChildAccess >();
+ }
ModifiedChildren::iterator i(modifiedChildren_.find(name));
return i == modifiedChildren_.end()
? getUnmodifiedChild(name) : getModifiedChild(i);