[gnome-software] appstream: add support for translations
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] appstream: add support for translations
- Date: Mon, 9 Sep 2013 15:05:51 +0000 (UTC)
commit 5b5d58c4abde7229f39246ccf3e42bb04d68bd15
Author: Giovanni Campagna <gcampagna src gnome org>
Date: Sat Sep 7 17:02:56 2013 +0200
appstream: add support for translations
Recognize xml:lang tags in the appstream files and use them to
provide translated names, summaries and descriptions.
https://bugzilla.gnome.org/show_bug.cgi?id=707728
Signed-off-by: Richard Hughes <richard hughsie com>
src/plugins/appstream-app.c | 69 +++++++++++++++++++++++++++++++++++++---
src/plugins/appstream-app.h | 3 ++
src/plugins/appstream-cache.c | 45 +++++++++++++++++++-------
3 files changed, 99 insertions(+), 18 deletions(-)
---
diff --git a/src/plugins/appstream-app.c b/src/plugins/appstream-app.c
index bef5db9..fd58b88 100644
--- a/src/plugins/appstream-app.c
+++ b/src/plugins/appstream-app.c
@@ -21,6 +21,8 @@
#include "config.h"
+#include <string.h>
+
#include "appstream-app.h"
struct AppstreamApp
@@ -28,9 +30,12 @@ struct AppstreamApp
gchar *id;
gchar *pkgname;
gchar *name;
+ guint name_value;
gchar *summary;
- gchar *url;
+ guint summary_value;
gchar *description;
+ guint description_value;
+ gchar *url;
gchar *icon;
AppstreamAppIconKind icon_kind;
GPtrArray *appcategories;
@@ -39,6 +44,31 @@ struct AppstreamApp
};
/**
+ * appstream_app_get_locale_value:
+ *
+ * Returns a metric on how good a match the locale is, with 0 being an
+ * exact match and higher numbers meaning further away from perfect.
+ */
+static guint
+appstream_app_get_locale_value (const gchar *lang)
+{
+ const gchar * const *locales;
+ guint i;
+
+ /* shortcut as C will always match */
+ if (lang == NULL || strcmp (lang, "C") == 0)
+ return G_MAXUINT - 1;
+
+ locales = g_get_language_names ();
+ for (i = 0; locales[i] != NULL; i++) {
+ if (g_ascii_strcasecmp (locales[i], lang) == 0)
+ return i;
+ }
+
+ return G_MAXUINT;
+}
+
+/**
* appstream_app_free:
*/
void
@@ -46,11 +76,11 @@ appstream_app_free (AppstreamApp *app)
{
g_free (app->id);
g_free (app->pkgname);
+ g_free (app->url);
+ g_free (app->icon);
g_free (app->name);
g_free (app->summary);
- g_free (app->url);
g_free (app->description);
- g_free (app->icon);
g_ptr_array_unref (app->appcategories);
if (app->userdata_destroy_func != NULL)
app->userdata_destroy_func (app->userdata);
@@ -87,6 +117,9 @@ appstream_app_new (void)
AppstreamApp *app;
app = g_slice_new0 (AppstreamApp);
app->appcategories = g_ptr_array_new_with_free_func (g_free);
+ app->name_value = G_MAXUINT;
+ app->summary_value = G_MAXUINT;
+ app->description_value = G_MAXUINT;
app->icon_kind = APPSTREAM_APP_ICON_KIND_UNKNOWN;
return app;
}
@@ -207,10 +240,18 @@ appstream_app_set_pkgname (AppstreamApp *app,
*/
void
appstream_app_set_name (AppstreamApp *app,
+ const gchar *lang,
const gchar *name,
gsize length)
{
- app->name = g_strndup (name, length);
+ guint new_value;
+
+ new_value = appstream_app_get_locale_value (lang);
+ if (new_value < app->name_value) {
+ g_free (app->name);
+ app->name = g_strndup (name, length);
+ app->name_value = new_value;
+ }
}
/**
@@ -218,10 +259,18 @@ appstream_app_set_name (AppstreamApp *app,
*/
void
appstream_app_set_summary (AppstreamApp *app,
+ const gchar *lang,
const gchar *summary,
gsize length)
{
- app->summary = g_strndup (summary, length);
+ guint new_value;
+
+ new_value = appstream_app_get_locale_value (lang);
+ if (new_value < app->summary_value) {
+ g_free (app->summary);
+ app->summary = g_strndup (summary, length);
+ app->summary_value = new_value;
+ }
}
/**
@@ -240,10 +289,18 @@ appstream_app_set_url (AppstreamApp *app,
*/
void
appstream_app_set_description (AppstreamApp *app,
+ const gchar *lang,
const gchar *description,
gsize length)
{
- app->description = g_strndup (description, length);
+ guint new_value;
+
+ new_value = appstream_app_get_locale_value (lang);
+ if (new_value < app->description_value) {
+ g_free (app->description);
+ app->description = g_strndup (description, length);
+ app->description_value = new_value;
+ }
}
/**
diff --git a/src/plugins/appstream-app.h b/src/plugins/appstream-app.h
index f37a6a4..c963da2 100644
--- a/src/plugins/appstream-app.h
+++ b/src/plugins/appstream-app.h
@@ -56,15 +56,18 @@ void appstream_app_set_pkgname (AppstreamApp *app,
const gchar *pkgname,
gsize length);
void appstream_app_set_name (AppstreamApp *app,
+ const gchar *lang,
const gchar *name,
gsize length);
void appstream_app_set_summary (AppstreamApp *app,
+ const gchar *lang,
const gchar *summary,
gsize length);
void appstream_app_set_url (AppstreamApp *app,
const gchar *summary,
gsize length);
void appstream_app_set_description (AppstreamApp *app,
+ const gchar *lang,
const gchar *description,
gsize length);
void appstream_app_set_icon (AppstreamApp *app,
diff --git a/src/plugins/appstream-cache.c b/src/plugins/appstream-cache.c
index 97a282b..baa6f5a 100644
--- a/src/plugins/appstream-cache.c
+++ b/src/plugins/appstream-cache.c
@@ -184,6 +184,7 @@ appstream_cache_icon_kind_from_string (const gchar *kind_str)
typedef struct {
const gchar *path_icons;
AppstreamApp *item_temp;
+ char *lang_temp;
AppstreamCache *cache;
AppstreamCacheSection section;
} AppstreamCacheHelper;
@@ -246,9 +247,21 @@ appstream_cache_start_element_cb (GMarkupParseContext *context,
break;
case APPSTREAM_CACHE_SECTION_ID:
case APPSTREAM_CACHE_SECTION_PKGNAME:
+ case APPSTREAM_CACHE_SECTION_URL:
+ if (helper->item_temp == NULL ||
+ helper->section != APPSTREAM_CACHE_SECTION_APPLICATION) {
+ g_set_error (error,
+ APPSTREAM_CACHE_ERROR,
+ APPSTREAM_CACHE_ERROR_FAILED,
+ "XML start %s invalid, section %s",
+ element_name,
+ appstream_cache_selection_to_string (helper->section));
+ return;
+ }
+ break;
+
case APPSTREAM_CACHE_SECTION_NAME:
case APPSTREAM_CACHE_SECTION_SUMMARY:
- case APPSTREAM_CACHE_SECTION_URL:
case APPSTREAM_CACHE_SECTION_DESCRIPTION:
if (helper->item_temp == NULL ||
helper->section != APPSTREAM_CACHE_SECTION_APPLICATION) {
@@ -260,6 +273,13 @@ appstream_cache_start_element_cb (GMarkupParseContext *context,
appstream_cache_selection_to_string (helper->section));
return;
}
+ if (!g_markup_collect_attributes (element_name, attribute_names, attribute_values, error,
+ G_MARKUP_COLLECT_STRDUP | G_MARKUP_COLLECT_OPTIONAL,
+ "xml:lang", &helper->lang_temp,
+ G_MARKUP_COLLECT_INVALID))
+ return;
+ if (!helper->lang_temp)
+ helper->lang_temp = g_strdup ("C");
break;
default:
/* ignore unknown entries */
@@ -314,12 +334,16 @@ appstream_cache_end_element_cb (GMarkupParseContext *context,
case APPSTREAM_CACHE_SECTION_ID:
case APPSTREAM_CACHE_SECTION_PKGNAME:
case APPSTREAM_CACHE_SECTION_APPCATEGORIES:
- case APPSTREAM_CACHE_SECTION_NAME:
+ case APPSTREAM_CACHE_SECTION_URL:
case APPSTREAM_CACHE_SECTION_ICON:
+ helper->section = APPSTREAM_CACHE_SECTION_APPLICATION;
+ break;
+ case APPSTREAM_CACHE_SECTION_NAME:
case APPSTREAM_CACHE_SECTION_SUMMARY:
- case APPSTREAM_CACHE_SECTION_URL:
case APPSTREAM_CACHE_SECTION_DESCRIPTION:
helper->section = APPSTREAM_CACHE_SECTION_APPLICATION;
+ g_free (helper->lang_temp);
+ helper->lang_temp = NULL;
break;
default:
/* ignore unknown entries */
@@ -387,26 +411,24 @@ appstream_cache_text_cb (GMarkupParseContext *context,
appstream_app_set_pkgname (helper->item_temp, text, text_len);
break;
case APPSTREAM_CACHE_SECTION_NAME:
- if (helper->item_temp == NULL ||
- appstream_app_get_name (helper->item_temp) != NULL) {
+ if (helper->item_temp == NULL) {
g_set_error_literal (error,
APPSTREAM_CACHE_ERROR,
APPSTREAM_CACHE_ERROR_FAILED,
"item_temp name invalid");
return;
}
- appstream_app_set_name (helper->item_temp, text, text_len);
+ appstream_app_set_name (helper->item_temp, helper->lang_temp, text, text_len);
break;
case APPSTREAM_CACHE_SECTION_SUMMARY:
- if (helper->item_temp == NULL ||
- appstream_app_get_summary (helper->item_temp) != NULL) {
+ if (helper->item_temp == NULL) {
g_set_error_literal (error,
APPSTREAM_CACHE_ERROR,
APPSTREAM_CACHE_ERROR_FAILED,
"item_temp summary invalid");
return;
}
- appstream_app_set_summary (helper->item_temp, text, text_len);
+ appstream_app_set_summary (helper->item_temp, helper->lang_temp, text, text_len);
break;
case APPSTREAM_CACHE_SECTION_URL:
if (helper->item_temp == NULL ||
@@ -420,15 +442,14 @@ appstream_cache_text_cb (GMarkupParseContext *context,
appstream_app_set_url (helper->item_temp, text, text_len);
break;
case APPSTREAM_CACHE_SECTION_DESCRIPTION:
- if (helper->item_temp == NULL ||
- appstream_app_get_description (helper->item_temp) != NULL) {
+ if (helper->item_temp == NULL) {
g_set_error_literal (error,
APPSTREAM_CACHE_ERROR,
APPSTREAM_CACHE_ERROR_FAILED,
"item_temp description invalid");
return;
}
- appstream_app_set_description (helper->item_temp, text, text_len);
+ appstream_app_set_description (helper->item_temp, helper->lang_temp, text, text_len);
break;
case APPSTREAM_CACHE_SECTION_ICON:
if (helper->item_temp == NULL ||
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]