summaryrefslogtreecommitdiffstats
path: root/src/query.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/query.c')
-rw-r--r--src/query.c119
1 files changed, 98 insertions, 21 deletions
diff --git a/src/query.c b/src/query.c
index 0acd0d0..9382fdc 100644
--- a/src/query.c
+++ b/src/query.c
@@ -38,41 +38,118 @@ slv2_plugin_find_statements(SLV2Plugin plugin,
return sord_find(plugin->world->model, pat);
}
+typedef enum {
+ SLV2_LANG_MATCH_NONE, ///< Language does not match at all
+ SLV2_LANG_MATCH_PARTIAL, ///< Partial (language, but not country) match
+ SLV2_LANG_MATCH_EXACT ///< Exact (language and country) match
+} SLV2LangMatch;
+
+static SLV2LangMatch
+slv2_lang_matches(const char* a, const char* b)
+{
+ if (!strcmp(a, b)) {
+ return SLV2_LANG_MATCH_EXACT;
+ }
+
+ const char* a_dash = strchr(a, '-');
+ const size_t a_lang_len = a_dash ? (a_dash - a) : 0;
+ const char* b_dash = strchr(b, '-');
+ const size_t b_lang_len = b_dash ? (b_dash - b) : 0;
+
+ if (a_lang_len && b_lang_len) {
+ if (a_lang_len == b_lang_len && !strncmp(a, b, a_lang_len)) {
+ return SLV2_LANG_MATCH_PARTIAL; // e.g. a="en-gb", b="en-ca"
+ }
+ } else if (a_lang_len && !strncmp(a, b, a_lang_len)) {
+ return SLV2_LANG_MATCH_PARTIAL; // e.g. a="en", b="en-ca"
+ } else if (b_lang_len && !strncmp(a, b, b_lang_len)) {
+ return SLV2_LANG_MATCH_PARTIAL; // e.g. a="en-ca", b="en"
+ }
+ return SLV2_LANG_MATCH_NONE;
+}
+
SLV2Values
-slv2_values_from_stream_i18n(SLV2Plugin p,
- SLV2Matches stream)
+slv2_values_from_stream_objects_i18n(SLV2Plugin p,
+ SLV2Matches stream)
{
- SLV2Values values = slv2_values_new();
- SLV2Node nolang = NULL;
+ SLV2Values values = slv2_values_new();
+ SLV2Node nolang = NULL; // Untranslated value
+ SLV2Node partial = NULL; // Partial language match
+ char* syslang = slv2_get_lang();
FOREACH_MATCH(stream) {
SLV2Node value = slv2_match_object(stream);
if (sord_node_get_type(value) == SORD_LITERAL) {
- const char* lang = sord_literal_get_lang(value);
+ const char* lang = sord_literal_get_lang(value);
+ SLV2LangMatch lm = SLV2_LANG_MATCH_NONE;
if (lang) {
- if (!strcmp(lang, slv2_get_lang())) {
- g_ptr_array_add(
- values, (uint8_t*)slv2_value_new_string(
- p->world, (const char*)sord_node_get_string(value)));
- }
+ lm = (syslang)
+ ? slv2_lang_matches(lang, syslang)
+ : SLV2_LANG_MATCH_PARTIAL;
} else {
nolang = value;
+ if (!syslang) {
+ lm = SLV2_LANG_MATCH_EXACT;
+ }
}
+
+ if (lm == SLV2_LANG_MATCH_EXACT) {
+ // Exact language match, add to results
+ g_ptr_array_add(values, slv2_value_new_from_node(p->world, value));
+ } else if (lm == SLV2_LANG_MATCH_PARTIAL) {
+ // Partial language match, save in case we find no exact
+ partial = value;
+ }
+ } else {
+ g_ptr_array_add(values, slv2_value_new_from_node(p->world, value));
}
- break;
}
slv2_match_end(stream);
+ free(syslang);
- if (slv2_values_size(values) == 0) {
- // No value with a matching language, use untranslated default
- if (nolang) {
- g_ptr_array_add(
- values, (uint8_t*)slv2_value_new_string(
- p->world, (const char*)sord_node_get_string(nolang)));
- } else {
- slv2_values_free(values);
- values = NULL;
- }
+ if (slv2_values_size(values) > 0) {
+ return values;
+ }
+
+ SLV2Node best = nolang;
+ if (syslang && partial) {
+ // Partial language match for system language
+ best = partial;
+ } else if (!best) {
+ // No languages matches at all, and no untranslated value
+ // Use any value, if possible
+ best = partial;
+ }
+
+ if (best) {
+ g_ptr_array_add(values, slv2_value_new_from_node(p->world, best));
+ } else {
+ // No matches whatsoever
+ slv2_values_free(values);
+ values = NULL;
}
return values;
}
+
+SLV2Values
+slv2_values_from_stream_objects(SLV2Plugin p,
+ SLV2Matches stream)
+{
+ if (slv2_matches_end(stream)) {
+ slv2_match_end(stream);
+ return NULL;
+ } else if (p->world->filter_language) {
+ return slv2_values_from_stream_objects_i18n(p, stream);
+ } else {
+ SLV2Values values = slv2_values_new();
+ FOREACH_MATCH(stream) {
+ g_ptr_array_add(
+ values,
+ slv2_value_new_from_node(
+ p->world,
+ slv2_match_object(stream)));
+ }
+ slv2_match_end(stream);
+ return values;
+ }
+}