[glib/wip/resources2: 1/2] Support Localized resources



commit b1ef79eb0d93bbf5533ad2f0d612b9fba91faff4
Author: Alexander Larsson <alexl redhat com>
Date:   Fri Jan 13 17:06:06 2012 +0100

    Support Localized resources

 gio/gioenums.h               |    8 +++++++-
 gio/glib-compile-resources.c |   25 +++++++++++++++++++++++--
 gio/gresource.c              |   33 +++++++++++++++++++++++++++++++++
 gio/tests/resources.c        |   41 +++++++++++++++++++++++++++++++++++++++--
 gio/tests/test.gresource.xml |    3 +++
 5 files changed, 105 insertions(+), 5 deletions(-)
---
diff --git a/gio/gioenums.h b/gio/gioenums.h
index ecb6b97..17ddb10 100644
--- a/gio/gioenums.h
+++ b/gio/gioenums.h
@@ -649,23 +649,29 @@ typedef enum {
  * GResourceFlags:
  * @G_RESOURCE_FLAGS_NONE: No flags set.
  * @G_RESOURCE_FLAGS_COMPRESSED: The file is compressed.
+ * @G_RESOURCE_FLAGS_LOCALIZED: The file has alternate versions based on locale.
  *
  * GResourceFlags give information about a particular file inside a resource
  * bundle.
  **/
 typedef enum {
   G_RESOURCE_FLAGS_NONE       = 0,
-  G_RESOURCE_FLAGS_COMPRESSED = (1<<0)
+  G_RESOURCE_FLAGS_COMPRESSED = (1<<0),
+  G_RESOURCE_FLAGS_LOCALIZED  = (1<<1)
 } GResourceFlags;
 
 /**
  * GResourceLookupFlags:
  * @G_RESOURCE_LOOKUP_FLAGS_NONE: No flags set.
+ * @G_RESOURCE_LOOKUP_FLAGS_NO_ALTERNATIVE: If there is an alternative
+ * (for instance a locale-specific version of the file) return the original
+ * version, not the alternative.
  *
  * GResourceLookupFlags determine how resource path lookups are handled.
  **/
 typedef enum {
   G_RESOURCE_LOOKUP_FLAGS_NONE       = 0,
+  G_RESOURCE_LOOKUP_FLAGS_NO_ALTERNATIVE = (1<<0),
 } GResourceLookupFlags;
 
 /**
diff --git a/gio/glib-compile-resources.c b/gio/glib-compile-resources.c
index f4a787e..de5e95d 100644
--- a/gio/glib-compile-resources.c
+++ b/gio/glib-compile-resources.c
@@ -54,6 +54,7 @@ typedef struct
 
   /* per gresource */
   char *prefix;
+  char *lang;
 
   /* per file */
   char *alias;
@@ -106,7 +107,8 @@ start_element (GMarkupParseContext  *context,
       if (strcmp (element_name, "gresource") == 0)
 	{
 	  COLLECT (OPTIONAL | STRDUP,
-		   "prefix", &state->prefix);
+		   "prefix", &state->prefix,
+		   OPTIONAL | STRDUP, "lang", &state->lang);
 	  return;
 	}
     }
@@ -172,12 +174,14 @@ end_element (GMarkupParseContext  *context,
     {
       g_free (state->prefix);
       state->prefix = NULL;
+      g_free (state->lang);
+      state->lang = NULL;
     }
 
   else if (strcmp (element_name, "file") == 0)
     {
       gchar *file, *real_file;
-      gchar *key;
+      gchar *key, *old_key;
       FileData *data;
 
       file = state->string->str;
@@ -190,6 +194,23 @@ end_element (GMarkupParseContext  *context,
       else
 	key = g_build_path ("/", "/", key, NULL);
 
+      if (state->lang)
+	{
+	  data = g_hash_table_lookup (state->table, key);
+	  if (data == NULL)
+	    {
+	      g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+			   _("File %s is in lang=%s, but not without lang"),
+			   key, state->lang);
+	      return;
+	    }
+	  data->flags |= G_RESOURCE_FLAGS_LOCALIZED;
+
+	  old_key = key;
+	  key = g_build_path ("/", "/", state->lang, key, NULL);
+	  g_free (old_key);
+	}
+
       if (g_hash_table_lookup (state->table, key) != NULL)
 	{
 	  g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
diff --git a/gio/gresource.c b/gio/gresource.c
index aa4cae5..d659df0 100644
--- a/gio/gresource.c
+++ b/gio/gresource.c
@@ -58,6 +58,9 @@ G_DEFINE_BOXED_TYPE (GResource, g_resource, g_resource_ref, g_resource_unref)
  * simple (no need to check for things like I/O errors or locate the files in the filesystem). It
  * also makes it easier to create relocatable applications.
  *
+ * Resource files can have locale specific alternatives, so that the current locale causes resource
+ * lookups to automatically pick up an alternate file.
+ *
  * Resource files can also be marked as compresses. Such files will be included in the resource bundle
  * in a compressed form, but will be automatically uncompressed when the resource is used. This
  * is very useful e.g. for larger text files that are parsed once (or rarely) and then thrown away.
@@ -75,6 +78,9 @@ G_DEFINE_BOXED_TYPE (GResource, g_resource, g_resource_ref, g_resource_unref)
  *     <file compressed="true">dialog.ui</file>
  *     <file>menumarkup.xml</file>
  *   </gresource>
+ *   <gresource lang="sv" prefix="/org/gtk/Example">
+ *     <file alias="menumarkup.xml">menumarkup_SV.xml</file>
+ *   </gresource>
  * </gresources>
  * ]]></programlisting></example>
  *
@@ -83,8 +89,12 @@ G_DEFINE_BOXED_TYPE (GResource, g_resource, g_resource_ref, g_resource_unref)
  * /org/gtk/Example/data/splashscreen.png
  * /org/gtk/Example/dialog.ui
  * /org/gtk/Example/menumarkup.xml
+ * /sv/org/gtk/Example/menumarkup.xml
  * ]]></programlisting>
  *
+ * Where the contents at "/org/gtk/Example/menumarkup.xml" automatically redirects
+ * to "/sv/org/gtk/Example/menumarkup.xml" when run in e.g. a sv_SE locale.
+ *
  * Note that all resources in the process share the same namespace, so use java-style
  * path prefixes (like in the above example) to avoid conflicts.
  *
@@ -277,6 +287,29 @@ static gboolean do_lookup (GResource *resource,
 		     &_flags,
 		     &array);
 
+      if (!(lookup_flags & G_RESOURCE_LOOKUP_FLAGS_NO_ALTERNATIVE) &&
+	  (_flags & G_RESOURCE_FLAGS_LOCALIZED))
+	{
+	  const gchar * const *langs = g_get_language_names ();
+	  int i;
+
+	  for (i = 0; langs[i] != NULL; i++)
+	    {
+	      char *prefixed_path = g_strconcat ("/", langs[i], path, NULL);
+	      res = do_lookup (resource, prefixed_path,
+			       lookup_flags | G_RESOURCE_LOOKUP_FLAGS_NO_ALTERNATIVE,
+			       size, flags, data, data_size, NULL);
+              g_free (prefixed_path);
+	      if (res)
+		{
+		  /* Mark the target as localized too if we followed the "link" */
+		  if (flags)
+		    *flags |= G_RESOURCE_FLAGS_LOCALIZED;
+		  break;
+		}
+	    }
+	}
+
       if (!res)
 	{
 	  if (size)
diff --git a/gio/tests/resources.c b/gio/tests/resources.c
index 3da0e0a..ed6a249 100644
--- a/gio/tests/resources.c
+++ b/gio/tests/resources.c
@@ -48,7 +48,7 @@ test_resource (GResource *resource)
   g_assert (found);
   g_assert_no_error (error);
   g_assert (size == 6);
-  g_assert (flags == (G_RESOURCE_FLAGS_COMPRESSED));
+  g_assert (flags == (G_RESOURCE_FLAGS_LOCALIZED | G_RESOURCE_FLAGS_COMPRESSED));
 
   found = g_resource_get_info (resource,
 			       "/a_prefix/test2.txt",
@@ -68,6 +68,15 @@ test_resource (GResource *resource)
   g_assert (size == 6);
   g_assert (flags == 0);
 
+  found = g_resource_get_info (resource,
+			       "/sv/test1.txt",
+			       G_RESOURCE_LOOKUP_FLAGS_NONE,
+			       &size, &flags, &error);
+  g_assert (found);
+  g_assert_no_error (error);
+  g_assert (size == 6);
+  g_assert (flags == 0);
+
   data = g_resource_lookup_data (resource,
 				 "/test1.txt",
 				 G_RESOURCE_LOOKUP_FLAGS_NONE,
@@ -116,6 +125,16 @@ test_resource (GResource *resource)
   g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test2\n");
   g_bytes_unref (data);
 
+  data = g_resource_lookup_data (resource,
+				 "/sv/test1.txt",
+				 G_RESOURCE_LOOKUP_FLAGS_NONE,
+				 &error);
+  g_assert (data != NULL);
+  g_assert_no_error (error);
+  g_assert (size == 6);
+  g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test3\n");
+  g_bytes_unref (data);
+
   children = g_resource_enumerate_children  (resource,
 					     "/not/here",
 					     G_RESOURCE_LOOKUP_FLAGS_NONE,
@@ -209,7 +228,7 @@ test_resource_registred (void)
   g_assert (found);
   g_assert_no_error (error);
   g_assert (size == 6);
-  g_assert (flags == (G_RESOURCE_FLAGS_COMPRESSED));
+  g_assert (flags == (G_RESOURCE_FLAGS_LOCALIZED | G_RESOURCE_FLAGS_COMPRESSED));
 
   found = g_resources_get_info ("/a_prefix/test2.txt",
 				G_RESOURCE_LOOKUP_FLAGS_NONE,
@@ -227,6 +246,14 @@ test_resource_registred (void)
   g_assert (size == 6);
   g_assert (flags == 0);
 
+  found = g_resources_get_info ("/sv/test1.txt",
+				G_RESOURCE_LOOKUP_FLAGS_NONE,
+				&size, &flags, &error);
+  g_assert (found);
+  g_assert_no_error (error);
+  g_assert (size == 6);
+  g_assert (flags == 0);
+
   data = g_resources_lookup_data ("/test1.txt",
 				  G_RESOURCE_LOOKUP_FLAGS_NONE,
 				  &error);
@@ -272,6 +299,16 @@ test_resource_registred (void)
   g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test2\n");
   g_bytes_unref (data);
 
+  data = g_resources_lookup_data ("/sv/test1.txt",
+				  G_RESOURCE_LOOKUP_FLAGS_NONE,
+				  &error);
+  g_assert (data != NULL);
+  g_assert_no_error (error);
+  size = g_bytes_get_size (data);
+  g_assert (size == 6);
+  g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, "test3\n");
+  g_bytes_unref (data);
+
   children = g_resources_enumerate_children ("/not/here",
 					     G_RESOURCE_LOOKUP_FLAGS_NONE,
 					     &error);
diff --git a/gio/tests/test.gresource.xml b/gio/tests/test.gresource.xml
index d66d08a..c9885e5 100644
--- a/gio/tests/test.gresource.xml
+++ b/gio/tests/test.gresource.xml
@@ -7,4 +7,7 @@
     <file alias="test2-alias.txt">test2.txt</file>
     <file>test2.txt</file>
   </gresource>
+  <gresource lang="sv">
+    <file alias="test1.txt">test3.txt</file>
+  </gresource>
 </gresources>



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