[glib/wip/menus-rebase2: 61/64] GMenuMarkup: allow translation of attributes



commit 23247fb73668f8080ba92ce554aa25203a6e6399
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Nov 8 16:22:56 2011 -0500

    GMenuMarkup: allow translation of attributes
    
    Support gettext-based translation of attributes, using attributes
    that are understood by intltool:
    
    <attribute name='label' translatable='yes'>'My label'</attribute>

 gio/gmenumarkup.c |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 gio/gmenumarkup.h |    2 +
 2 files changed, 87 insertions(+), 1 deletions(-)
---
diff --git a/gio/gmenumarkup.c b/gio/gmenumarkup.c
index bd86526..cc1b038 100644
--- a/gio/gmenumarkup.c
+++ b/gio/gmenumarkup.c
@@ -57,8 +57,33 @@ typedef struct
   GQuark        attribute;
   GVariantType *type;
   GString      *string;
+
+  /* translation */
+  gchar        *domain;
+  gchar        *context;
+  gboolean      translatable;
 } GMenuMarkupState;
 
+static gboolean
+boolean_from_string (const gchar  *str,
+                     gboolean     *val)
+{
+  if (strcmp (str, "true") == 0 ||
+      strcmp (str, "yes") == 0 ||
+      strcmp (str, "t") == 0 ||
+      strcmp (str, "1") == 0)
+    *val = TRUE;
+  else if (strcmp (str, "false") == 0 ||
+           strcmp (str, "no") == 0 ||
+           strcmp (str, "f") == 0 ||
+           strcmp (str, "0") == 0)
+    *val = FALSE;
+  else
+    return FALSE;
+
+  return TRUE;
+}
+
 static void
 g_menu_markup_push_frame (GMenuMarkupState *state,
                           GMenu            *menu,
@@ -188,8 +213,13 @@ g_menu_markup_start_element (GMarkupParseContext  *context,
         {
           const gchar *typestr;
           const gchar *name;
+          const gchar *translatable;
+          const gchar *context;
 
           if (COLLECT (STRING,            "name", &name,
+                       OPTIONAL | STRING, "translatable", &translatable,
+                       OPTIONAL | STRING, "context", &context,
+                       OPTIONAL | STRING, "comments", NULL, /* ignore, just for translators */
                        OPTIONAL | STRING, "type", &typestr))
             {
               if (typestr && !g_variant_type_string_is_valid (typestr))
@@ -203,6 +233,17 @@ g_menu_markup_start_element (GMarkupParseContext  *context,
               state->type = typestr ? g_variant_type_new (typestr) : NULL;
               state->string = g_string_new (NULL);
               state->attribute = g_quark_from_string (name);
+              state->context = g_strdup (context);
+              if (!translatable)
+                state->translatable = FALSE;
+              else if (!boolean_from_string (translatable, &state->translatable))
+                {
+                  g_set_error (error, G_MARKUP_ERROR,
+                               G_MARKUP_ERROR_INVALID_CONTENT,
+                               "Invalid boolean attribute: '%s'", translatable);
+                  return;
+                }
+
               g_menu_markup_push_frame (state, NULL, NULL);
             }
 
@@ -273,6 +314,26 @@ g_menu_markup_end_element (GMarkupParseContext  *context,
        */
       if ((value = g_variant_parse (state->type, text, NULL, NULL, error)))
         {
+          /* Deal with translatable string attributes */
+          if (state->domain && state->translatable &&
+              g_variant_type_equal (state->type, G_VARIANT_TYPE_STRING))
+            {
+              const gchar *msgid;
+              const gchar *msgstr;
+
+              msgid = g_variant_get_string (value, NULL);
+              if (state->context)
+                msgstr = g_dpgettext2 (state->domain, state->context, msgid);
+              else
+                msgstr = g_dgettext (state->domain, msgid);
+
+              if (msgstr != msgid)
+                {
+                  g_variant_unref (value);
+                  value = g_variant_new_string (msgstr);
+                }
+            }
+
           g_menu_item_set_attribute_value (state->frame.item, state->attribute, value);
           g_variant_unref (value);
         }
@@ -283,6 +344,9 @@ g_menu_markup_end_element (GMarkupParseContext  *context,
           state->type = NULL;
         }
 
+      g_free (state->context);
+      state->context = NULL;
+
       g_free (text);
     }
 }
@@ -336,6 +400,8 @@ g_menu_markup_error (GMarkupParseContext *context,
   if (state->objects)
     g_hash_table_unref (state->objects);
 
+  g_free (state->context);
+
   g_slice_free (GMenuMarkupState, state);
 }
 
@@ -351,10 +417,14 @@ static GMarkupParser g_menu_subparser =
 /**
  * g_menu_markup_parser_start:
  * @context: a #GMarkupParseContext
+ * @domain: (allow-none): translation domain for labels, or %NULL
  * @objects: (allow-none): a #GHashTable for the objects, or %NULL
  *
  * Begin parsing a group of menus in XML form.
  *
+ * If @domain is not %NULL, it will be used to translate attributes
+ * that are marked as translatable, using gettext().
+ *
  * If @objects is specified then it must be a #GHashTable that was
  * created using g_hash_table_new_full() with g_str_hash(), g_str_equal(),
  * g_free() and g_object_unref().  Any named menus that are encountered
@@ -367,9 +437,10 @@ static GMarkupParser g_menu_subparser =
  * the element representing the group containing the menus.  In other
  * words, the content inside of this element is expected to be a list of
  * menus.
- **/
+ */
 void
 g_menu_markup_parser_start (GMarkupParseContext *context,
+                            const gchar         *domain,
                             GHashTable          *objects)
 {
   GMenuMarkupState *state;
@@ -378,6 +449,8 @@ g_menu_markup_parser_start (GMarkupParseContext *context,
 
   state = g_slice_new0 (GMenuMarkupState);
 
+  state->domain = g_strdup (domain);
+
   if (objects != NULL)
     state->objects = g_hash_table_ref (objects);
   else
@@ -408,6 +481,9 @@ g_menu_markup_parser_end (GMarkupParseContext *context)
   GHashTable *objects;
 
   objects = state->objects;
+
+  g_free (state->domain);
+
   g_slice_free (GMenuMarkupState, state);
 
   return objects;
@@ -416,6 +492,7 @@ g_menu_markup_parser_end (GMarkupParseContext *context)
 /**
  * g_menu_markup_parser_start_menu:
  * @context: a #GMarkupParseContext
+ * @domain: (allow-none): translation domain for labels, or %NULL
  * @objects: (allow-none): a #GHashTable for the objects, or %NULL
  *
  * Begin parsing the XML definition of a menu.
@@ -424,6 +501,9 @@ g_menu_markup_parser_end (GMarkupParseContext *context)
  * the element representing the menu itself.  In other words, the
  * content inside of this element is expected to be a list of items.
  *
+ * If @domain is not %NULL, it will be used to translate attributes
+ * that are marked as translatable, using gettext().
+ *
  * If @objects is specified then it must be a #GHashTable that was
  * created using g_hash_table_new_full() with g_str_hash(), g_str_equal(),
  * g_free() and g_object_unref().  Any named menus that are encountered
@@ -437,6 +517,7 @@ g_menu_markup_parser_end (GMarkupParseContext *context)
  **/
 void
 g_menu_markup_parser_start_menu (GMarkupParseContext *context,
+                                 const gchar         *domain,
                                  GHashTable          *objects)
 {
   GMenuMarkupState *state;
@@ -448,6 +529,8 @@ g_menu_markup_parser_start_menu (GMarkupParseContext *context,
   if (objects)
     state->objects = g_hash_table_ref (objects);
 
+  state->domain = g_strdup (domain);
+
   g_markup_parse_context_push (context, &g_menu_subparser, state);
 
   state->frame.menu = g_menu_new ();
@@ -474,6 +557,7 @@ g_menu_markup_parser_end_menu (GMarkupParseContext *context)
 
   if (state->objects)
     g_hash_table_unref (state->objects);
+  g_free (state->domain);
   g_slice_free (GMenuMarkupState, state);
 
   return menu;
diff --git a/gio/gmenumarkup.h b/gio/gmenumarkup.h
index 9959b8b..ed5742d 100644
--- a/gio/gmenumarkup.h
+++ b/gio/gmenumarkup.h
@@ -27,10 +27,12 @@
 G_BEGIN_DECLS
 
 void                    g_menu_markup_parser_start                      (GMarkupParseContext  *context,
+                                                                         const gchar          *domain,
                                                                          GHashTable           *objects);
 GHashTable *            g_menu_markup_parser_end                        (GMarkupParseContext  *context);
 
 void                    g_menu_markup_parser_start_menu                 (GMarkupParseContext  *context,
+                                                                         const gchar          *domain,
                                                                          GHashTable           *objects);
 GMenu *                 g_menu_markup_parser_end_menu                   (GMarkupParseContext  *context);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]