--- glib/gunicollate.c	2017-07-14 09:03:39.000000000 +1000
+++ glib/gunicollate.c	2018-03-07 19:44:12.270478851 +1100
@@ -28,6 +28,7 @@
 #include <CoreServices/CoreServices.h>
 #endif
 
+#include "genviron.h"
 #include "gmem.h"
 #include "gunicode.h"
 #include "gunicodeprivate.h"
@@ -471,6 +472,48 @@ g_utf8_collate_key (const gchar *str,
   return result;
 }
 
+/* Does the user's locale require that we treat some characters specially
+   before calling the glibc collation? */
+static const gboolean
+locale_requires_special_case (void)
+{
+  const gchar *locale;
+
+  /* Find the most relevant environment variable that is set. */
+  locale = g_getenv ("LC_ALL");
+  if (!locale || locale[0] == '\0')
+    {
+      locale = g_getenv ("LC_COLLATE");
+      if (!locale || locale[0] == '\0')
+	{
+	  locale = g_getenv ("LANG");
+	  if (!locale || locale[0] == '\0')
+	    {
+#ifdef G_PLATFORM_WIN32
+	      /* Finally, check the ISO/IEC translation of Windows' "locale"
+	       * as well. This has the side-effect of additionally testing
+	       * LC_MESSAGES.
+	       */
+	      char *winlocale = g_win32_getlocale ();
+	      locale = g_intern_string (winlocale);
+	      g_free (winlocale);
+	      if (!locale || locale[0] == '\0')
+#endif
+	        return FALSE;
+	    }
+	}
+    }
+
+  /* We found at least one environment variable overriding collation;
+   * now test if it is one of the traditional ASCIIbetical locales.
+   */
+  if (!locale || !strcmp (locale, "C") || !strncmp (locale, "C.", 2) ||
+      strcasestr (locale, "posix") || !strncmp (locale, "UTF.", 4))
+    return FALSE;
+
+  return TRUE;
+}
+
 /* This is a collation key that is very very likely to sort before any
  * collation key that libc strxfrm generates. We use this before any
  * special case (dot or number) to make sure that its sorted before
@@ -493,7 +536,8 @@ g_utf8_collate_key (const gchar *str,
  * would like to treat numbers intelligently so that "file1" "file10" "file5"
  * is sorted as "file1" "file5" "file10".
  * 
- * Note that this function depends on the [current locale][setlocale].
+ * Note that this function depends on the [current locale][setlocale]. The
+ * traditional C/POSIX locales disable any special casing of '.' and digits.
  *
  * Returns: a newly allocated string. This string should
  *   be freed with g_free() when you are done with it.
@@ -563,12 +607,20 @@ g_utf8_collate_key_for_filename (const g
   if (len < 0)
     len = strlen (str);
 
-  result = g_string_sized_new (len * 2);
+  /* The worst case, a filename comprising entirely dots, will produce a
+   * collation key four times the size of the original filename.
+   */
+  result = g_string_sized_new (len * 4);
   append = g_string_sized_new (0);
 
   end = str + len;
-
-  /* No need to use utf8 functions, since we're only looking for ascii chars */
+ 
+/* This if ... else is negatively indented to minimise the diff.
+ * Indent this properly if the patch is accepted.
+ */
+if (locale_requires_special_case ())
+  {
+  /* No need to use UTF8 functions, since we're only looking for ASCII chars */
   for (prev = p = str; p < end; p++)
     {
       switch (*p)
@@ -664,6 +716,12 @@ g_utf8_collate_key_for_filename (const g
 	  break;
 	}
     }
+  }
+else
+  {
+    prev = str;
+    p = str + len;
+  }  
   
   if (prev != p) 
     {
