Index: Source/GSLocale.m
===================================================================
--- Source/GSLocale.m	(révision 33814)
+++ Source/GSLocale.m	(copie de travail)
@@ -247,7 +247,8 @@
   NSString	*aliases = nil;
   NSBundle      *gbundle;
 
-  if (locale == nil || [locale isEqual: @"C"] || [locale isEqual: @"POSIX"])
+  if (locale == nil || [locale isEqual: @"C"] || [locale isEqual: @"POSIX"]
+      || [locale length] < 2)
     return @"English";
 
   gbundle = [NSBundle bundleForLibrary: @"gnustep-base"];
@@ -276,3 +277,36 @@
 
   return language;
 }
+
+NSArray *
+GSLocaleVariants(NSString *locale)
+{
+  NSRange under = [locale rangeOfString: @"_"];
+  if (under.location != NSNotFound)
+    {
+      return [NSArray arrayWithObjects:
+			locale,
+		      [locale substringToIndex: under.location],
+		      nil];
+    }
+  return [NSArray arrayWithObject: locale];
+}
+
+NSArray *
+GSLanguagesFromLocale(NSString *locale)
+{
+  NSArray *variants = GSLocaleVariants(locale);
+  NSMutableArray *result = [NSMutableArray arrayWithCapacity: [variants count]];
+
+  NSEnumerator *enumerator = [variants objectEnumerator];
+  NSString *variant;
+  while ((variant = [enumerator nextObject]) != nil)
+    {
+      NSString *language = GSLanguageFromLocale(variant);
+      if (language != nil)
+	{
+	  [result addObject: language];
+	}
+    }
+  return result;
+}
Index: Source/NSUserDefaults.m
===================================================================
--- Source/NSUserDefaults.m	(révision 33814)
+++ Source/NSUserDefaults.m	(copie de travail)
@@ -178,44 +178,69 @@
   return NO;
 }
 
+/**
+ * Returns the list of languages retrieved from the operating system, in
+ * decreasing order of preference. Returns an empty array if the information
+ * could not be retrieved.
+ */
+static NSArray *
+systemLanguages()
+{
+  NSMutableArray *names = [NSMutableArray arrayWithCapacity: 10];
+
+  // Add the languages listed in the LANGUAGE environment variable
+  // (a non-POSIX GNU extension)
+  {
+    NSString	*env = [[[NSProcessInfo processInfo] environment]
+				 objectForKey: @"LANGUAGE"];
+    if (env != nil && [env length] > 0)
+      {
+	NSArray *array = [env componentsSeparatedByString: @":"];
+	NSEnumerator *enumerator = [array objectEnumerator];
+	NSString *locale;
+	while (nil != (locale = [enumerator nextObject]))
+	  {
+	    [names addObjectsFromArray: GSLanguagesFromLocale(locale)];
+	  }
+      }
+  }	
+  
+  // If LANGUAGES did not yield any languages, try LC_MESSAGES
+#ifdef HAVE_LOCALE_H
+#ifdef LC_MESSAGES
+  if ([names count] == 0)
+    {
+      NSString *locale = GSSetLocale(LC_MESSAGES, nil);
+
+      if (locale != nil)
+	{
+	  [names addObjectsFromArray: GSLanguagesFromLocale(locale)];
+	}
+    }
+#endif
+#endif
+
+  return names;
+}
+
 static NSMutableArray *
 newLanguages(NSArray *oldNames)
 {
   NSMutableArray	*newNames;
   NSEnumerator		*enumerator;
   NSString		*language;
-  NSString		*locale = nil;
 
-#ifdef HAVE_LOCALE_H
-#ifdef LC_MESSAGES
-  locale = GSSetLocale(LC_MESSAGES, nil);
-#endif
-#endif
   newNames = [NSMutableArray arrayWithCapacity: 5];
 
-  if (oldNames == nil && locale != nil)
+  if (oldNames == nil || [oldNames count] == 0)
     {
-      NSString	*locLang = GSLanguageFromLocale(locale);
+      oldNames = systemLanguages();
+    }
 
-      if (nil != locLang)
-	{
-	  oldNames = [NSArray arrayWithObject: locLang];
-	}
-#ifdef __MINGW__
-      if (oldNames == nil)
-	{
-	  /* Check for language as the first part of the locale string */
-	  NSRange under = [locale rangeOfString: @"_"];
+  // If the user default was not set, and the system languages couldn't
+  // be retrieved, try the GNUstep environment variable LANGUAGES
 
-	  if (under.location)
-	    {
-	      oldNames = [NSArray arrayWithObject:
-		[locale substringToIndex: under.location]];
-	    }
-	}
-#endif
-    }
-  if (oldNames == nil)
+  if (oldNames == nil || [oldNames count] == 0)
     {
       NSString	*env;
 
Index: Headers/GNUstepBase/GSLocale.h
===================================================================
--- Headers/GNUstepBase/GSLocale.h	(révision 33814)
+++ Headers/GNUstepBase/GSLocale.h	(copie de travail)
@@ -44,8 +44,31 @@
 
 GS_EXPORT NSDictionary *GSDomainFromDefaultLocale(void);
 
+/**
+ * Returns a language name string for a given locale.
+ * e.g. GSLanguageFromLocale(@"en_CA") returns @"CanadaEnglish"
+ */
 GS_EXPORT NSString *GSLanguageFromLocale(NSString *locale);
 
+/**
+ * Return an array of variants of a locale, formed by stripping
+ * off parts of the identifier, ordered from most similar to 
+ * least similar.
+ *
+ * e.g. GSLocaleVariants(@"en_CA") returns  (@"en_CA", @"en").
+ */
+GS_EXPORT NSArray *GSLocaleVariants(NSString *locale);
+
+/**
+ * Convenience function which calls GSLocaleVariants to expand
+ * the given locale to a list of variants, and then calls 
+ * GSLanguageFromLocale on each.
+ * 
+ * e.g. GSLanguagesFromLocale(@"en_CA") returns
+ * (@"CanadaEnglish", @"English")
+ */
+GS_EXPORT NSArray *GSLanguagesFromLocale(NSString *locale);
+
 #if	defined(__cplusplus)
 }
 #endif
Index: ChangeLog
===================================================================
--- ChangeLog	(révision 33814)
+++ ChangeLog	(copie de travail)
@@ -1,3 +1,28 @@
+2011-09-07  Eric Wasylishen  <ewasylishen@gmail.com>
+
+	* Source/NSUserDefaults.m:
+	- Refactoring of the code to read the system language list
+	  into a separate function, systemLanguages().
+	- Add support for the LANGUAGE environment variable, a GNU extension.
+	  It holds a colon-separated list of locales, and is intended to let
+	  the user specify a list of their preferred languages in order.
+	  For example, the language settings GUI in Ubuntu modifies the
+	  LANGUAGE variable.
+
+	  More info here:
+	  http://www.gnu.org/software/gettext/manual/gettext.html#The-LANGUAGE-variable
+	- When populating NSLanguages, "expand" locales into a list of
+	  related variants, formed by stripping off region suffixes. This
+	  ensures that if a user's environment is set to a regional version
+	  of a language (say CanadaFrench) but an application is only
+	  traslated into French, the plain French translation will still be used.
+
+	  e.g. if the system locales are {fr_CA, en_CA}, expand the list to
+	  {fr_CA, fr, en_CA, en}.
+	* Headers/GNUstepBase/GSLocale.h:
+	* Source/GSLocale.m:
+	New functions GSLocaleVariants and GSLanguagesFromLocale
+
 2011-09-07  Richard Frith-Macdonald <rfm@gnu.org>
 
 	* Source/GSFFIInvocation.m: Check that we have a typed selector
