--- gdm/configure.ac.orig	2009-08-27 17:27:58.000000000 +0900
+++ gdm/configure.ac	2009-08-27 17:29:10.000000000 +0900
@@ -279,6 +279,20 @@ else
 fi
 AC_SUBST(LANG_CONFIG_FILE)
 
+dnl
+dnl Check mo files if GUI can show the language
+dnl
+AC_MSG_CHECKING([whether to enable mo check])
+AC_ARG_ENABLE(mo-check,
+              AS_HELP_STRING([--enable-mo-check],
+                             [Enables mo check if GUI can show the language]),
+              enable_mo_check=$enableval,enable_mo_check=yes)
+
+if test "x$enable_mo_check" != "xno"; then
+        AC_DEFINE(ENABLE_MO_CHECK, 1, [Define if we enable mo check])
+fi
+AC_MSG_RESULT($enable_mo_check)
+
 # stropts has been removed from glibc
 # https://bugzilla.redhat.com/show_bug.cgi?id=436349
 AC_CHECK_HEADERS(stropts.h)
--- gdm-2.27.4/data/Makefile.am.orig	2009-08-24 17:43:19.207044680 +0900
+++ gdm-2.27.4/data/Makefile.am	2009-08-24 17:45:28.975871911 +0900
@@ -73,10 +73,14 @@ gdm.schemas.in: $(srcdir)/gdm.schemas.in
 		-e 's,[@]sbindir[@],$(sbindir),g' \
 		<$(srcdir)/gdm.schemas.in.in >gdm.schemas.in
 
+localealiasdir = $(datadir)/gdm
+localealias_DATA = locale.alias
+
 EXTRA_DIST =			\
 	$(schemas_in_files)	\
 	$(schemas_DATA)		\
 	$(dbusconf_in_files)	\
+	$(localealias_DATA)	\
 	gdm.schemas.in.in	\
 	gdm.conf-custom.in 	\
 	Xsession.in 		\
--- gdm-2.27.4/data/locale.alias.orig	2009-08-24 17:45:43.728134754 +0900
+++ gdm-2.27.4/data/locale.alias	2009-08-24 17:46:03.282440642 +0900
@@ -0,0 +1,15 @@
+# NOTE! This is a broken way to do things.  Gdm currently reads languages ONLY
+# from this file.  This is Broken(tm).  This setup will be replaced in some
+# future version to be replaced by some automatic detection of available
+# locales.  This file is not really a locale.alias file and the first word
+# is used as a label in case gdm doesn't know this language personally,
+# else it's ignored.
+#
+# The format of this file is SIMILAR (but not the same to the locale.alias
+# format).  You could however point gdm at a real locale.alias and it would
+# still concievably work.  Note that the first word cannot contain any spaces.
+# The second word can be a comma separated list of locales to try.  GDM will
+# try if each locale exists and only if it does will it show that locale.  The
+# list is tried in order and the first working one is used.
+#
+#Unspecified   C,POSIX
--- gdm-2.27.4/gui/simple-greeter/gdm-language-chooser-widget.c.orig	2009-08-21 16:08:23.424009962 +0900
+++ gdm-2.27.4/gui/simple-greeter/gdm-language-chooser-widget.c	2009-08-27 14:59:04.265176140 +0900
@@ -196,6 +196,8 @@ add_available_languages (GdmLanguageChoo
 
         for (i = 0; language_names[i] != NULL; i++) {
                 if (!language_has_font (language_names[i])) {
+                        g_warning ("Your locale '%s' was not configured fonts",
+                                language_names[i]);
                         continue;
                 }
                 gdm_language_chooser_widget_add_language (widget,
--- gdm-2.27.4/gui/simple-greeter/gdm-languages.c.orig	2009-08-26 18:18:49.454366400 +0900
+++ gdm-2.27.4/gui/simple-greeter/gdm-languages.c	2009-08-27 14:59:49.065051124 +0900
@@ -45,7 +45,7 @@
 #endif
 #include "locarchive.h"
 
-#define ALIASES_FILE LIBLOCALEDIR "/locale.alias"
+#define ALIASES_FILE DATADIR "/gdm/locale.alias"
 #define ARCHIVE_FILE LIBLOCALEDIR "/locale-archive"
 #define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes"
 #define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale"
@@ -63,6 +63,13 @@ static GHashTable *gdm_languages_map;
 static GHashTable *gdm_territories_map;
 static GHashTable *gdm_available_locales_map;
 
+static char * construct_language_name (const char *language,
+                                       const char *territory,
+                                       const char *codeset,
+                                       const char *modifier);
+
+static gboolean language_name_is_valid (const char *language_name);
+
 static void
 gdm_locale_free (GdmLocale *locale)
 {
@@ -119,6 +126,8 @@ gdm_parse_language_name (const char *nam
         GMatchInfo *match_info;
         gboolean    res;
         GError     *error;
+        gchar      *normalized_codeset = NULL;
+        gchar      *normalized_name = NULL;
 
         error = NULL;
         re = g_regex_new ("^(?P<language>[^_.@[:space:]]+)"
@@ -167,14 +176,6 @@ gdm_parse_language_name (const char *nam
                         g_free (*codesetp);
                         *codesetp = NULL;
                 }
-
-                if (*codesetp != NULL) {
-                        char *codeset;
-
-                        codeset = normalize_codeset (*codesetp);
-                        g_free (*codesetp);
-                        *codesetp = codeset;
-                }
         }
 
         if (modifierp != NULL) {
@@ -187,6 +188,22 @@ gdm_parse_language_name (const char *nam
                 }
         }
 
+        if (codesetp != NULL && *codesetp != NULL) {
+                normalized_codeset = normalize_codeset (*codesetp);
+                normalized_name = construct_language_name (language_codep ? *language_codep : NULL,
+                                                           territory_codep ? *territory_codep : NULL,
+                                                           normalized_codeset,
+                                                           modifierp ? *modifierp : NULL);
+
+                if (language_name_is_valid (normalized_name)) {
+                        g_free (*codesetp);
+                        *codesetp = normalized_codeset;
+                } else {
+                        g_free (normalized_codeset);
+                }
+                g_free (normalized_name);
+        }
+
         g_match_info_free (match_info);
         g_regex_unref (re);
 }
@@ -216,24 +233,6 @@ construct_language_name (const char *lan
         return name;
 }
 
-static void
-make_codeset_canonical_for_locale (const char  *name,
-                                   char       **codeset)
-{
-        char *old_locale;
-
-        old_locale = setlocale (LC_CTYPE, name);
-
-        if (old_locale == NULL) {
-                return;
-        }
-
-        g_free (*codeset);
-        *codeset = g_strdup (nl_langinfo (CODESET));
-
-        setlocale (LC_CTYPE, old_locale);
-}
-
 char *
 gdm_normalize_language_name (const char *name)
 {
@@ -252,10 +251,6 @@ gdm_normalize_language_name (const char 
                                  &territory_code,
                                  &codeset, &modifier);
 
-        if (codeset != NULL) {
-                make_codeset_canonical_for_locale (name, &codeset);
-        }
-
         normalized_name = construct_language_name (language_code,
                                                    territory_code,
                                                    codeset, modifier);
@@ -272,10 +267,15 @@ language_name_is_valid (const char *lang
 {
         char     *old_locale;
         gboolean  is_valid;
+#ifdef __sun
+        int lc_type_id = LC_CTYPE;
+#else
+        int lc_type_id = LC_MESSAGES;
+#endif
 
-        old_locale = g_strdup (setlocale (LC_MESSAGES, NULL));
-        is_valid = setlocale (LC_MESSAGES, language_name) != NULL;
-        setlocale (LC_MESSAGES, old_locale);
+        old_locale = g_strdup (setlocale (lc_type_id, NULL));
+        is_valid = setlocale (lc_type_id, language_name) != NULL;
+        setlocale (lc_type_id, old_locale);
         g_free (old_locale);
 
         return is_valid;
@@ -343,24 +343,37 @@ out:
 }
 
 static gboolean
-add_locale (const char *language_name)
+add_locale (const char *language_name, gboolean utf8_only)
 {
         GdmLocale *locale;
         GdmLocale *old_locale;
         char      *name;
 
+        g_return_val_if_fail (language_name != NULL, FALSE);
+
         if (language_name_is_utf8 (language_name)) {
                 name = g_strdup (language_name);
         } else {
+#if defined(linux)
                 name = g_strdup_printf ("%s.utf8", language_name);
 
                 if (!language_name_is_utf8 (name)) {
                         g_free (name);
-                        return FALSE;
+
+                        if (utf8_only)
+                                return FALSE;
+
+                        name = g_strdup (language_name);
                 }
+#else
+                if (utf8_only)
+                        return FALSE;
+                name = g_strdup (language_name);
+#endif
         }
 
         if (!language_name_is_valid (name)) {
+                g_warning ("Your locale '%s' was failed by setlocale()", name);
                 g_free (name);
                 return FALSE;
         }
@@ -375,17 +388,28 @@ add_locale (const char *language_name)
         g_free (name);
         name = NULL;
 
+#ifdef __sun
+        if (utf8_only) {
+                if (locale->territory_code == NULL || locale->modifier) {
+                        gdm_locale_free (locale);
+                        return FALSE;
+                }
+        }
+#endif
+
         locale->id = construct_language_name (locale->language_code, locale->territory_code,
-                                              NULL, locale->modifier);
+                                              locale->codeset, locale->modifier);
         locale->name = construct_language_name (locale->language_code, locale->territory_code,
                                                 locale->codeset, locale->modifier);
 
+#if ENABLE_MO_CHECK
         if (!language_name_has_translations (locale->name) &&
             !language_name_has_translations (locale->id) &&
             !language_name_has_translations (locale->language_code)) {
                 gdm_locale_free (locale);
                 return FALSE;
         }
+#endif
 
         old_locale = g_hash_table_lookup (gdm_available_locales_map, locale->id);
         if (old_locale != NULL) {
@@ -452,7 +476,7 @@ collect_locales_from_archive (void)
         }
 
         for (cnt = 0; cnt < used; ++cnt) {
-                add_locale (names[cnt].name);
+                add_locale (names[cnt].name, TRUE);
         }
 
         g_free (names);
@@ -501,10 +525,10 @@ collect_locales_from_directory (void)
         int             ndirents;
         int             cnt;
 
-        ndirents = scandir (GNOMELOCALEDIR, &dirents, select_dirs, alphasort);
+        ndirents = scandir (LIBLOCALEDIR, &dirents, select_dirs, alphasort);
 
         for (cnt = 0; cnt < ndirents; ++cnt) {
-                add_locale (dirents[cnt]->d_name);
+                add_locale (dirents[cnt]->d_name, TRUE);
         }
 
         if (ndirents > 0) {
@@ -513,6 +537,59 @@ collect_locales_from_directory (void)
 }
 
 static void
+collect_locales_from_locale_file (const char *locale_file)
+{
+        FILE *langlist;
+        char curline[256];
+        char *getsret;
+
+        if (locale_file == NULL)
+                return;
+
+        langlist = fopen (locale_file, "r");
+
+        if (langlist == NULL)
+                return;
+
+        for (;;) {
+                char *name;
+                char *lang;
+                char **lang_list;
+                int i;
+
+                getsret = fgets (curline, sizeof (curline), langlist);
+                if (getsret == NULL)
+                        break;
+
+                if (curline[0] <= ' ' ||
+                    curline[0] == '#')
+                        continue;
+
+                name = strtok (curline, " \t\r\n");
+                if (name == NULL)
+                        continue;
+
+                lang = strtok (NULL, " \t\r\n");
+                if (lang == NULL)
+                        continue;
+
+                lang_list = g_strsplit (lang, ",", -1);
+                if (lang_list == NULL)
+                        continue;
+
+                lang = NULL;
+                for (i = 0; lang_list[i] != NULL; i++) {
+                        if (add_locale (lang_list[i], FALSE)) {
+                                break;
+                        }
+                }
+                g_strfreev (lang_list);
+        }
+
+        fclose (langlist);
+}
+
+static void
 collect_locales (void)
 {
 
@@ -520,15 +597,16 @@ collect_locales (void)
                 gdm_available_locales_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) gdm_locale_free);
         }
 
-        if (collect_locales_from_archive ()) {
-                return;
-        } else {
+        if (!collect_locales_from_archive ()) {
+#ifndef __sun
                 g_warning ("Could not read list of available locales from libc, "
                            "guessing possible locales from available translations, "
                            "but list may be incomplete!");
+#endif
 
                 collect_locales_from_directory ();
         }
+        collect_locales_from_locale_file (ALIASES_FILE);
 }
 
 static gboolean
@@ -928,8 +1006,10 @@ gdm_get_language_from_name (const char *
         char *full_language;
         char *language_code;
         char *territory_code;
+        char *codeset_code;
         const char *language;
         const char *territory;
+        gboolean is_utf8 = TRUE;
 
         if (gdm_languages_map == NULL) {
                 languages_init ();
@@ -944,7 +1024,7 @@ gdm_get_language_from_name (const char *
         full_language = NULL;
 
         gdm_parse_language_name (name, &language_code, &territory_code,
-                                 NULL, NULL);
+                                 &codeset_code, NULL);
 
         if (language_code == NULL) {
                 goto out;
@@ -958,13 +1038,19 @@ gdm_get_language_from_name (const char *
                 territory = NULL;
         }
 
-        if (territory != NULL) {
-                full_language  = g_strdup_printf ("%s (%s)",
+        if (codeset_code != NULL &&
+            g_strcasecmp (codeset_code, "utf8") != 0 &&
+            g_strcasecmp (codeset_code, "UTF-8") != 0)
+            is_utf8 = FALSE;
+
+        full_language  = g_strdup_printf ("%s%s%s%s%s%s%s",
                         language ? language : "",
-                        territory ? territory : "");
-        } else {
-                full_language  = g_strdup (language);
-        }
+                        territory ? " (" : "",
+                        territory ? territory : "",
+                        territory ? ")" : "",
+                        !is_utf8 ? " (" : "",
+                        !is_utf8 ? codeset_code : "",
+                        !is_utf8 ? ")" : "");
 
 out:
        g_free (language_code);
