[gdm] Add build time option to allow locales without translations



commit d3009cfe5835a3348ba50ddcb447beb029eed849
Author: Takao Fujiwara <tfujiwar redhat com>
Date:   Wed Jan 13 11:21:12 2010 -0500

    Add build time option to allow locales without translations
    
    This allows incomplete languages to be shown in the list,
    along with the underspecified "C" locale.

 configure.ac                       |   13 ++
 data/Makefile.am                   |    4 +
 gui/simple-greeter/gdm-languages.c |  237 ++++++++++++++++++++++++++----------
 3 files changed, 192 insertions(+), 62 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 896ba3f..2dcfb07 100644
--- a/configure.ac
+++ b/configure.ac
@@ -271,6 +271,19 @@ else
 fi
 AC_SUBST(LANG_CONFIG_FILE)
 
+dnl
+dnl Whether or not to show locales in the language list that
+dnl lack translations
+dnl
+AC_ARG_WITH(incomplete-locales,
+            AS_HELP_STRING([--with-incomplete-locales=yes|no],
+                           [Show incomplete locales in lang list]),,
+            with_incomplete_locales=no)
+
+if test x$with_incomplete_locales != xno; then
+        AC_DEFINE(WITH_INCOMPLETE_LOCALES, 1, [Show incomplete locales in lang list])
+fi
+
 # stropts has been removed from glibc
 # https://bugzilla.redhat.com/show_bug.cgi?id=436349
 AC_CHECK_HEADERS(stropts.h)
diff --git a/data/Makefile.am b/data/Makefile.am
index e2c1d63..60d7624 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -75,10 +75,14 @@ gdm.schemas.in: $(srcdir)/gdm.schemas.in.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 		\
diff --git a/gui/simple-greeter/gdm-languages.c b/gui/simple-greeter/gdm-languages.c
index fe647c9..91e4888 100644
--- a/gui/simple-greeter/gdm-languages.c
+++ b/gui/simple-greeter/gdm-languages.c
@@ -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 *name,
         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 *name,
                         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 *name,
                 }
         }
 
+        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 *language,
         return name;
 }
 
-static void
-make_codeset_canonical_for_locale (const char  *name,
-                                   char       **codeset)
-{
-        char *old_locale;
-
-        old_locale = setlocale (LC_CTYPE, NULL);
-
-        if (setlocale (LC_CTYPE, name) == 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 *name)
                                  &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,38 +267,50 @@ language_name_is_valid (const char *language_name)
 {
         char     *old_locale;
         gboolean  is_valid;
+#ifdef WITH_INCOMPLETE_LOCALES
+        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;
 }
 
-static gboolean
-language_name_is_utf8 (const char *language_name)
+static void
+language_name_get_codeset_details (const char  *language_name,
+                                   char       **pcodeset,
+                                   gboolean    *is_utf8)
 {
         char     *old_locale;
         char     *codeset;
-        gboolean  is_utf8;
 
         old_locale = g_strdup (setlocale (LC_CTYPE, NULL));
 
         if (setlocale (LC_CTYPE, language_name) == NULL) {
                 g_free (old_locale);
-                return FALSE;
+                return;
         }
 
-        codeset = normalize_codeset (nl_langinfo (CODESET));
+        codeset = nl_langinfo (CODESET);
 
-        is_utf8 = strcmp (codeset, "utf8") == 0;
-        g_free (codeset);
+        if (pcodeset != NULL) {
+                *pcodeset = codeset;
+        }
+
+        if (is_utf8 != NULL) {
+                codeset = normalize_codeset (codeset);
+
+                *is_utf8 = strcmp (codeset, "utf8") == 0;
+                g_free (codeset);
+        }
 
         setlocale (LC_CTYPE, old_locale);
         g_free (old_locale);
-
-        return is_utf8;
 }
 
 static gboolean
@@ -343,29 +350,38 @@ 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;
+        gboolean   is_utf8;
+
+        g_return_val_if_fail (language_name != NULL, FALSE);
 
-        if (language_name_is_utf8 (language_name)) {
+        language_name_get_codeset_details (language_name, NULL, &is_utf8);
+
+        if (is_utf8) {
                 name = g_strdup (language_name);
-        } else {
+        } else if (utf8_only) {
                 name = g_strdup_printf ("%s.utf8", language_name);
 
-                if (!language_name_is_utf8 (name)) {
+                language_name_get_codeset_details (name, NULL, &is_utf8);
+                if (is_utf8) {
                         g_free (name);
                         return FALSE;
                 }
+        } else {
+                name = g_strdup (language_name);
         }
 
         if (!language_name_is_valid (name)) {
+                g_warning ("Your locale '%s' was failed by setlocale()", name);
                 g_free (name);
                 return FALSE;
         }
 
-
         locale = g_new0 (GdmLocale, 1);
         gdm_parse_language_name (name,
                                  &locale->language_code,
@@ -375,17 +391,36 @@ add_locale (const char *language_name)
         g_free (name);
         name = NULL;
 
+#ifdef WITH_INCOMPLETE_LOCALES
+        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->name = construct_language_name (locale->language_code, locale->territory_code,
                                                 locale->codeset, locale->modifier);
 
+#ifndef WITH_INCOMPLETE_LOCALES
         if (!language_name_has_translations (locale->name) &&
             !language_name_has_translations (locale->id) &&
-            !language_name_has_translations (locale->language_code)) {
+            !language_name_has_translations (locale->language_code) &&
+            utf8_only) {
+                g_warning ("Your locale '%s' doesn't have message catalog files",
+                           language_name);
                 gdm_locale_free (locale);
                 return FALSE;
         }
+#endif
+
+        if (!utf8_only) {
+                g_free (locale->id);
+                locale->id = g_strdup (locale->name);
+        }
 
         old_locale = g_hash_table_lookup (gdm_available_locales_map, locale->id);
         if (old_locale != NULL) {
@@ -452,7 +487,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);
@@ -504,7 +539,7 @@ collect_locales_from_directory (void)
         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 +548,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 +608,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 WITH_INCOMPLETE_LOCALES
                 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 +1017,11 @@ gdm_get_language_from_name (const char *name,
         char *full_language;
         char *language_code;
         char *territory_code;
-        const char *language;
+        char *codeset_code;
+        char *langinfo_codeset;
+        char *language;
         const char *territory;
+        gboolean is_utf8 = TRUE;
 
         if (gdm_languages_map == NULL) {
                 languages_init ();
@@ -941,10 +1033,10 @@ gdm_get_language_from_name (const char *name,
 
         language_code = NULL;
         territory_code = NULL;
-        full_language = NULL;
+        codeset_code = NULL;
 
         gdm_parse_language_name (name, &language_code, &territory_code,
-                                 NULL, NULL);
+                                 &codeset_code, NULL);
 
         if (language_code == NULL) {
                 goto out;
@@ -958,17 +1050,38 @@ gdm_get_language_from_name (const char *name,
                 territory = NULL;
         }
 
-        if (territory != NULL) {
-                full_language  = g_strdup_printf ("%s (%s)",
-                        language ? language : "",
-                        territory ? territory : "");
-        } else {
+        language_name_get_codeset_details (name, &langinfo_codeset, &is_utf8);
+
+        if (codeset_code == NULL && langinfo_codeset != NULL) {
+            codeset_code = g_strdup (langinfo_codeset);
+        }
+
+        full_language  = NULL;
+
+        if (language) {
                 full_language  = g_strdup (language);
+        } else {
+                goto out;
+        }
+
+        if (territory) {
+                language = full_language;
+                full_language  = g_strdup_printf ("%s (%s)",
+                                                  language, territory);
+                g_free (language);
+        }
+
+        if (!is_utf8 && codeset_code) {
+                language = full_language;
+                full_language  = g_strdup_printf ("%s [%s]",
+                                                  language, codeset_code);
+                g_free (language);
         }
 
 out:
        g_free (language_code);
        g_free (territory_code);
+       g_free (codeset_code);
 
        return full_language;
 }



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