[gnome-control-center] user-accounts: Update gdm-languages.c from GDM
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center] user-accounts: Update gdm-languages.c from GDM
- Date: Fri, 21 Jan 2011 13:52:20 +0000 (UTC)
commit 0bbdc8727f401fab45d9b0177575b1f25fcdc126
Author: Bastien Nocera <hadess hadess net>
Date: Fri Jan 21 13:51:00 2011 +0000
user-accounts: Update gdm-languages.c from GDM
Fixes a number of bugs, and keeps the 2 versions in sync.
panels/user-accounts/gdm-languages.c | 299 ++++++++++++++++++++++++----------
1 files changed, 214 insertions(+), 85 deletions(-)
---
diff --git a/panels/user-accounts/gdm-languages.c b/panels/user-accounts/gdm-languages.c
index 2c99e15..5607221 100644
--- a/panels/user-accounts/gdm-languages.c
+++ b/panels/user-accounts/gdm-languages.c
@@ -45,8 +45,9 @@
#endif
#include "locarchive.h"
-#define ALIASES_FILE LIBLOCALEDIR "/locale.alias"
+#define ALIASES_FILE DATADIR "/gdm/locale.alias"
#define ARCHIVE_FILE LIBLOCALEDIR "/locale-archive"
+#define SYSTEM_ARCHIVE_FILE "/usr/lib/locale/locale-archive"
#define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes"
#define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale"
@@ -63,6 +64,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 +127,12 @@ gdm_parse_language_name (const char *name,
GMatchInfo *match_info;
gboolean res;
GError *error;
+ gchar *normalized_codeset = NULL;
+ gchar *normalized_name = NULL;
+ gboolean retval;
+
+ match_info = NULL;
+ retval = FALSE;
error = NULL;
re = g_regex_new ("^(?P<language>[^_ [:space:]]+)"
@@ -127,26 +141,24 @@ gdm_parse_language_name (const char *name,
"(@(?P<modifier>[[:ascii:]]+))?$",
0, 0, &error);
if (re == NULL) {
- g_critical ("%s", error->message);
- return FALSE;
+ g_warning ("%s", error->message);
+ goto out;
}
if (!g_regex_match (re, name, 0, &match_info) ||
g_match_info_is_partial_match (match_info)) {
- g_match_info_free (match_info);
- g_regex_unref (re);
g_warning ("locale %s isn't valid\n", name);
- return FALSE;
+ goto out;
}
res = g_match_info_matches (match_info);
if (! res) {
- g_match_info_free (match_info);
- g_regex_unref (re);
g_warning ("Unable to parse locale: %s", name);
- return FALSE;
+ goto out;
}
+ retval = TRUE;
+
if (language_codep != NULL) {
*language_codep = g_match_info_fetch_named (match_info, "language");
}
@@ -169,14 +181,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) {
@@ -189,10 +193,27 @@ 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);
+ }
+
+ out:
g_match_info_free (match_info);
g_regex_unref (re);
- return TRUE;
+ return retval;
}
static char *
@@ -220,24 +241,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)
{
@@ -256,10 +259,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);
@@ -276,38 +275,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 = g_strdup (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
@@ -347,29 +358,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);
+
+ language_name_get_codeset_details (language_name, NULL, &is_utf8);
- if (language_name_is_utf8 (language_name)) {
+ 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_debug ("Ignoring '%s' as a locale, since it's invalid", name);
g_free (name);
return FALSE;
}
-
locale = g_new0 (GdmLocale, 1);
gdm_parse_language_name (name,
&locale->language_code,
@@ -379,17 +399,35 @@ 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_debug ("Ignoring '%s' as a locale, since it lacks translations", locale->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) {
@@ -427,9 +465,13 @@ collect_locales_from_archive (void)
error = NULL;
mapped = g_mapped_file_new (ARCHIVE_FILE, FALSE, &error);
if (mapped == NULL) {
- g_warning ("Mapping failed for %s: %s", ARCHIVE_FILE, error->message);
+ mapped = g_mapped_file_new (SYSTEM_ARCHIVE_FILE, FALSE, NULL);
+ if (mapped == NULL) {
+ g_warning ("Mapping failed for %s: %s", ARCHIVE_FILE, error->message);
+ g_error_free (error);
+ return FALSE;
+ }
g_error_free (error);
- return FALSE;
}
locales_collected = FALSE;
@@ -456,7 +498,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);
@@ -508,7 +550,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) {
@@ -517,6 +559,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)
{
@@ -524,15 +619,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
@@ -610,7 +706,7 @@ get_translated_language (const char *code,
}
if (is_fallback_language (code)) {
- name = _("Unspecified");
+ name = g_strdup (_("Unspecified"));
} else {
translated_name = dgettext ("iso_639", language);
name = get_first_item_in_semicolon_list (translated_name);
@@ -643,12 +739,12 @@ get_territory (const char *code)
return name;
}
-static const char *
+static char *
get_translated_territory (const char *code,
const char *locale)
{
const char *territory;
- char *name;
+ char *name;
territory = get_territory (code);
@@ -929,11 +1025,20 @@ char *
gdm_get_language_from_name (const char *name,
const char *locale)
{
- char *full_language;
+ GString *full_language;
char *language_code;
char *territory_code;
- const char *language;
- const char *territory;
+ char *codeset_code;
+ char *langinfo_codeset;
+ char *translated_language;
+ char *translated_territory;
+ gboolean is_utf8 = TRUE;
+
+ translated_territory = NULL;
+ translated_language = NULL;
+ langinfo_codeset = NULL;
+
+ full_language = g_string_new (NULL);
if (gdm_languages_map == NULL) {
languages_init ();
@@ -945,36 +1050,60 @@ 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);
+ gdm_parse_language_name (name,
+ &language_code,
+ &territory_code,
+ &codeset_code,
+ NULL);
if (language_code == NULL) {
goto out;
}
- language = get_translated_language (language_code, locale);
+ translated_language = get_translated_language (language_code, locale);
+ if (translated_language == NULL) {
+ goto out;
+ }
+
+ full_language = g_string_append (full_language, translated_language);
if (territory_code != NULL) {
- territory = get_translated_territory (territory_code, locale);
- } else {
- territory = NULL;
+ translated_territory = get_translated_territory (territory_code, locale);
+ }
+ if (translated_territory != NULL) {
+ g_string_append_printf (full_language,
+ " (%s)",
+ translated_territory);
}
- if (territory != NULL) {
- full_language = g_strdup_printf ("%s (%s)",
- language ? language : "",
- territory ? territory : "");
- } else {
- full_language = g_strdup (language);
+ language_name_get_codeset_details (name, &langinfo_codeset, &is_utf8);
+
+ if (codeset_code == NULL && langinfo_codeset != NULL) {
+ codeset_code = g_strdup (langinfo_codeset);
+ }
+
+ if (!is_utf8 && codeset_code) {
+ g_string_append_printf (full_language,
+ " [%s]",
+ codeset_code);
}
out:
g_free (language_code);
g_free (territory_code);
+ g_free (codeset_code);
+ g_free (langinfo_codeset);
+ g_free (translated_language);
+ g_free (translated_territory);
+
+ if (full_language->len == 0) {
+ g_string_free (full_language, TRUE);
+ return NULL;
+ }
- return full_language;
+ return g_string_free (full_language, FALSE);
}
char **
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]