diff -ru glib-2.25.3.orig/glib/gutils.c glib-2.25.3/glib/gutils.c
--- glib-2.25.3.orig/glib/gutils.c	2010-04-13 14:33:16.000000000 +0100
+++ glib-2.25.3/glib/gutils.c	2010-05-08 14:11:11.000000000 +0100
@@ -2953,41 +2953,42 @@
 		gchar      **codeset, 
 		gchar      **modifier)
 {
-  const gchar *uscore_pos;
-  const gchar *at_pos;
-  const gchar *dot_pos;
+  const gchar *start_chunk, *end_chunk;
 
   guint mask = 0;
 
-  uscore_pos = strchr (locale, '_');
-  dot_pos = strchr (uscore_pos ? uscore_pos : locale, '.');
-  at_pos = strchr (dot_pos ? dot_pos : (uscore_pos ? uscore_pos : locale), '@');
+  start_chunk = end_chunk = locale;
 
-  if (at_pos)
+  while (*end_chunk && *end_chunk != '_' && *end_chunk != '.' && *end_chunk != '@')
+    ++end_chunk;
+
+  *language = g_strndup (locale, end_chunk - start_chunk);
+
+  start_chunk = end_chunk;
+
+  if (*start_chunk == '_')
     {
-      mask |= COMPONENT_MODIFIER;
-      *modifier = g_strdup (at_pos);
+      mask |= COMPONENT_TERRITORY;
+      while (*end_chunk && *end_chunk != '.' && *end_chunk != '@')
+        ++end_chunk;
+      *territory = g_strndup (start_chunk, end_chunk - start_chunk);
+      start_chunk = end_chunk;
     }
-  else
-    at_pos = locale + strlen (locale);
 
-  if (dot_pos)
+  if (*start_chunk == '.')
     {
       mask |= COMPONENT_CODESET;
-      *codeset = g_strndup (dot_pos, at_pos - dot_pos);
+      while (*end_chunk && *end_chunk != '@')
+        ++end_chunk;
+      *codeset = g_strndup (start_chunk, end_chunk - start_chunk);
+      start_chunk = end_chunk;
     }
-  else
-    dot_pos = at_pos;
 
-  if (uscore_pos)
+  if (*start_chunk == '@')
     {
-      mask |= COMPONENT_TERRITORY;
-      *territory = g_strndup (uscore_pos, dot_pos - uscore_pos);
+      mask |= COMPONENT_MODIFIER;
+      *modifier = g_strdup (start_chunk);
     }
-  else
-    uscore_pos = dot_pos;
-
-  *language = g_strndup (locale, uscore_pos - locale);
 
   return mask;
 }
