1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright 2008 Red Hat, Inc,
4
* 2007 William Jon McCann <mccann@jhu.edu>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
* Written by : William Jon McCann <mccann@jhu.edu>
21
* Ray Strode <rstrode@redhat.com>
37
#include <glib/gi18n.h>
38
#include <glib/gstdio.h>
40
#include "gdm-languages.h"
46
#include "locarchive.h"
48
#define ALIASES_FILE DATADIR "/gdm/locale.alias"
49
#define ARCHIVE_FILE LIBLOCALEDIR "/locale-archive"
50
#define SYSTEM_ARCHIVE_FILE "/usr/lib/locale/locale-archive"
51
#define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes"
52
#define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale"
54
typedef struct _GdmLocale {
63
static GHashTable *gdm_languages_map;
64
static GHashTable *gdm_territories_map;
65
static GHashTable *gdm_available_locales_map;
66
static GHashTable *gdm_language_count_map;
67
static GHashTable *gdm_territory_count_map;
69
static char * construct_language_name (const char *language,
70
const char *territory,
72
const char *modifier);
74
static gboolean language_name_is_valid (const char *language_name);
77
gdm_locale_free (GdmLocale *locale)
84
g_free (locale->name);
85
g_free (locale->codeset);
86
g_free (locale->modifier);
91
normalize_codeset (const char *codeset)
93
char *normalized_codeset;
97
normalized_codeset = g_strdup (codeset);
99
if (codeset != NULL) {
100
for (p = codeset, q = normalized_codeset;
103
if (*p == '-' || *p == '_') {
107
*q = g_ascii_tolower (*p);
113
return normalized_codeset;
117
* According to http://en.wikipedia.org/wiki/Locale
118
* locale names are of the form:
119
* [language[_territory][.codeset][@modifier]]
122
gdm_parse_language_name (const char *name,
123
char **language_codep,
124
char **territory_codep,
129
GMatchInfo *match_info;
132
gchar *normalized_codeset = NULL;
133
gchar *normalized_name = NULL;
140
re = g_regex_new ("^(?P<language>[^_.@[:space:]]+)"
141
"(_(?P<territory>[[:upper:]]+))?"
142
"(\\.(?P<codeset>[-_0-9a-zA-Z]+))?"
143
"(@(?P<modifier>[[:ascii:]]+))?$",
146
g_warning ("%s", error->message);
150
if (!g_regex_match (re, name, 0, &match_info) ||
151
g_match_info_is_partial_match (match_info)) {
152
g_warning ("locale '%s' isn't valid\n", name);
156
res = g_match_info_matches (match_info);
158
g_warning ("Unable to parse locale: %s", name);
164
if (language_codep != NULL) {
165
*language_codep = g_match_info_fetch_named (match_info, "language");
168
if (territory_codep != NULL) {
169
*territory_codep = g_match_info_fetch_named (match_info, "territory");
171
if (*territory_codep != NULL &&
172
*territory_codep[0] == '\0') {
173
g_free (*territory_codep);
174
*territory_codep = NULL;
178
if (codesetp != NULL) {
179
*codesetp = g_match_info_fetch_named (match_info, "codeset");
181
if (*codesetp != NULL &&
182
*codesetp[0] == '\0') {
188
if (modifierp != NULL) {
189
*modifierp = g_match_info_fetch_named (match_info, "modifier");
191
if (*modifierp != NULL &&
192
*modifierp[0] == '\0') {
198
if (codesetp != NULL && *codesetp != NULL) {
199
normalized_codeset = normalize_codeset (*codesetp);
200
normalized_name = construct_language_name (language_codep ? *language_codep : NULL,
201
territory_codep ? *territory_codep : NULL,
203
modifierp ? *modifierp : NULL);
205
if (language_name_is_valid (normalized_name)) {
207
*codesetp = normalized_codeset;
209
g_free (normalized_codeset);
211
g_free (normalized_name);
215
g_match_info_free (match_info);
222
construct_language_name (const char *language,
223
const char *territory,
225
const char *modifier)
227
const char *adj_codeset;
230
g_assert (language[0] != 0);
231
g_assert (territory == NULL || territory[0] != 0);
232
g_assert (codeset == NULL || codeset[0] != 0);
233
g_assert (modifier == NULL || modifier[0] != 0);
235
if (g_strcmp0 (codeset, "utf8") == 0) {
236
adj_codeset = "UTF-8";
238
adj_codeset = codeset;
240
name = g_strdup_printf ("%s%s%s%s%s%s%s",
242
territory != NULL? "_" : "",
243
territory != NULL? territory : "",
244
codeset != NULL? "." : "",
245
codeset != NULL? adj_codeset : "",
246
modifier != NULL? "@" : "",
247
modifier != NULL? modifier : "");
253
gdm_normalize_language_name (const char *name)
255
char *normalized_name;
257
char *territory_code;
261
if (name[0] == '\0') {
265
gdm_parse_language_name (name,
268
&codeset, &modifier);
270
normalized_name = construct_language_name (language_code,
273
g_free (language_code);
274
g_free (territory_code);
278
return normalized_name;
282
language_name_is_valid (const char *language_name)
286
#ifdef WITH_INCOMPLETE_LOCALES
287
int lc_type_id = LC_CTYPE;
289
int lc_type_id = LC_MESSAGES;
292
old_locale = g_strdup (setlocale (lc_type_id, NULL));
293
is_valid = setlocale (lc_type_id, language_name) != NULL;
294
setlocale (lc_type_id, old_locale);
301
language_name_get_codeset_details (const char *language_name,
308
old_locale = g_strdup (setlocale (LC_CTYPE, NULL));
310
if (setlocale (LC_CTYPE, language_name) == NULL) {
315
codeset = nl_langinfo (CODESET);
317
if (pcodeset != NULL) {
318
*pcodeset = g_strdup (codeset);
321
if (is_utf8 != NULL) {
322
codeset = normalize_codeset (codeset);
324
*is_utf8 = strcmp (codeset, "utf8") == 0;
328
setlocale (LC_CTYPE, old_locale);
333
gdm_language_has_translations (const char *language_name)
338
gboolean has_translations;
340
path = g_build_filename (GNOMELOCALEDIR, language_name, "LC_MESSAGES", NULL);
342
has_translations = FALSE;
343
dir = g_dir_open (path, 0, NULL);
351
name = g_dir_read_name (dir);
357
if (g_str_has_suffix (name, ".mo")) {
358
has_translations = TRUE;
361
} while (name != NULL);
365
return has_translations;
369
add_locale (const char *language_name,
373
GdmLocale *old_locale;
375
gboolean is_utf8 = FALSE;
377
g_return_val_if_fail (language_name != NULL, FALSE);
378
g_return_val_if_fail (*language_name != '\0', FALSE);
380
language_name_get_codeset_details (language_name, NULL, &is_utf8);
383
name = g_strdup (language_name);
384
} else if (utf8_only) {
385
name = g_strdup_printf ("%s.utf8", language_name);
387
language_name_get_codeset_details (name, NULL, &is_utf8);
393
name = g_strdup (language_name);
396
if (!language_name_is_valid (name)) {
397
g_debug ("Ignoring '%s' as a locale, since it's invalid", name);
402
locale = g_new0 (GdmLocale, 1);
403
gdm_parse_language_name (name,
404
&locale->language_code,
405
&locale->territory_code,
411
#ifdef WITH_INCOMPLETE_LOCALES
413
if (locale->territory_code == NULL || locale->modifier) {
414
g_debug ("Ignoring '%s' as a locale, since it lacks territory code or modifier", name);
415
gdm_locale_free (locale);
421
locale->id = construct_language_name (locale->language_code, locale->territory_code,
422
NULL, locale->modifier);
423
locale->name = construct_language_name (locale->language_code, locale->territory_code,
424
locale->codeset, locale->modifier);
426
#ifndef WITH_INCOMPLETE_LOCALES
427
if (!gdm_language_has_translations (locale->name) &&
428
!gdm_language_has_translations (locale->id) &&
429
!gdm_language_has_translations (locale->language_code) &&
431
g_debug ("Ignoring '%s' as a locale, since it lacks translations", locale->name);
432
gdm_locale_free (locale);
439
locale->id = g_strdup (locale->name);
442
old_locale = g_hash_table_lookup (gdm_available_locales_map, locale->id);
443
if (old_locale != NULL) {
444
if (strlen (old_locale->name) > strlen (locale->name)) {
445
gdm_locale_free (locale);
450
g_hash_table_insert (gdm_available_locales_map, g_strdup (locale->id), locale);
458
uint32_t locrec_offset;
462
collect_locales_from_archive (void)
467
struct locarhead *head;
468
struct namehashent *namehashtab;
469
struct nameent *names;
473
gboolean locales_collected;
476
mapped = g_mapped_file_new (ARCHIVE_FILE, FALSE, &error);
477
if (mapped == NULL) {
478
mapped = g_mapped_file_new (SYSTEM_ARCHIVE_FILE, FALSE, NULL);
479
if (mapped == NULL) {
480
g_warning ("Mapping failed for %s: %s", ARCHIVE_FILE, error->message);
481
g_error_free (error);
484
g_error_free (error);
487
locales_collected = FALSE;
489
addr = g_mapped_file_get_contents (mapped);
490
len = g_mapped_file_get_length (mapped);
492
head = (struct locarhead *) addr;
493
if (head->namehash_offset + head->namehash_size > len
494
|| head->string_offset + head->string_size > len
495
|| head->locrectab_offset + head->locrectab_size > len
496
|| head->sumhash_offset + head->sumhash_size > len) {
500
namehashtab = (struct namehashent *) (addr + head->namehash_offset);
502
names = (struct nameent *) g_new0 (struct nameent, head->namehash_used);
503
for (cnt = used = 0; cnt < head->namehash_size; ++cnt) {
504
if (namehashtab[cnt].locrec_offset != 0) {
505
names[used].name = addr + namehashtab[cnt].name_offset;
506
names[used++].locrec_offset = namehashtab[cnt].locrec_offset;
510
for (cnt = 0; cnt < used; ++cnt) {
511
add_locale (names[cnt].name, TRUE);
516
locales_collected = TRUE;
519
g_mapped_file_unref (mapped);
520
return locales_collected;
524
select_dirs (const struct dirent *dirent)
528
if (strcmp (dirent->d_name, ".") != 0 && strcmp (dirent->d_name, "..") != 0) {
531
#ifdef _DIRENT_HAVE_D_TYPE
532
if (dirent->d_type != DT_UNKNOWN && dirent->d_type != DT_LNK) {
533
mode = DTTOIF (dirent->d_type);
540
path = g_build_filename (LIBLOCALEDIR, dirent->d_name, NULL);
541
if (g_stat (path, &st) == 0) {
547
result = S_ISDIR (mode);
554
collect_locales_from_directory (void)
556
struct dirent **dirents;
560
ndirents = scandir (LIBLOCALEDIR, &dirents, select_dirs, alphasort);
562
for (cnt = 0; cnt < ndirents; ++cnt) {
563
add_locale (dirents[cnt]->d_name, TRUE);
572
collect_locales_from_locale_file (const char *locale_file)
578
if (locale_file == NULL)
581
langlist = fopen (locale_file, "r");
583
if (langlist == NULL)
592
getsret = fgets (curline, sizeof (curline), langlist);
596
if (curline[0] <= ' ' ||
600
name = strtok (curline, " \t\r\n");
604
lang = strtok (NULL, " \t\r\n");
608
lang_list = g_strsplit (lang, ",", -1);
609
if (lang_list == NULL)
613
for (i = 0; lang_list[i] != NULL; i++) {
614
if (add_locale (lang_list[i], FALSE)) {
618
g_strfreev (lang_list);
625
count_languages_and_territories (void)
630
gdm_language_count_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
631
gdm_territory_count_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
633
g_hash_table_iter_init (&iter, gdm_available_locales_map);
634
while (g_hash_table_iter_next (&iter, NULL, &value)) {
637
locale = (GdmLocale *) value;
639
if (locale->language_code != NULL) {
642
count = GPOINTER_TO_INT (g_hash_table_lookup (gdm_language_count_map, locale->language_code));
644
g_hash_table_insert (gdm_language_count_map, g_strdup (locale->language_code), GINT_TO_POINTER (count));
647
if (locale->territory_code != NULL) {
650
count = GPOINTER_TO_INT (g_hash_table_lookup (gdm_territory_count_map, locale->territory_code));
652
g_hash_table_insert (gdm_territory_count_map, g_strdup (locale->territory_code), GINT_TO_POINTER (count));
658
collect_locales (void)
661
if (gdm_available_locales_map == NULL) {
662
gdm_available_locales_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) gdm_locale_free);
665
if (!collect_locales_from_archive ()) {
666
#ifndef WITH_INCOMPLETE_LOCALES
667
g_warning ("Could not read list of available locales from libc, "
668
"guessing possible locales from available translations, "
669
"but list may be incomplete!");
673
collect_locales_from_directory ();
675
collect_locales_from_locale_file (ALIASES_FILE);
677
count_languages_and_territories ();
681
get_language_count (const char *language)
683
if (gdm_language_count_map == NULL) {
687
return GPOINTER_TO_INT (g_hash_table_lookup (gdm_language_count_map, language));
691
is_unique_language (const char *language)
693
return get_language_count (language) == 1;
697
get_territory_count (const char *territory)
699
if (gdm_territory_count_map == NULL) {
703
return GPOINTER_TO_INT (g_hash_table_lookup (gdm_territory_count_map, territory));
707
is_unique_territory (const char *territory)
709
return get_territory_count (territory) == 1;
713
is_fallback_language (const char *code)
715
const char *fallback_language_names[] = { "C", "POSIX", NULL };
718
for (i = 0; fallback_language_names[i] != NULL; i++) {
719
if (strcmp (code, fallback_language_names[i]) == 0) {
728
get_language (const char *code)
733
g_assert (code != NULL);
735
if (is_fallback_language (code)) {
736
return "Unspecified";
740
if (len != 2 && len != 3) {
744
name = (const char *) g_hash_table_lookup (gdm_languages_map, code);
750
get_first_item_in_semicolon_list (const char *list)
755
/* Some entries in iso codes have multiple values, separated
756
* by semicolons. Not really sure which one to pick, so
757
* we just arbitrarily pick the first one.
759
items = g_strsplit (list, "; ", 2);
761
item = g_strdup (items[0]);
768
get_translated_language (const char *code,
771
const char *language;
774
language = get_language (code);
777
if (language != NULL) {
778
const char *translated_name;
781
if (locale != NULL) {
782
old_locale = g_strdup (setlocale (LC_MESSAGES, NULL));
783
setlocale (LC_MESSAGES, locale);
786
if (is_fallback_language (code)) {
787
name = g_strdup (_("Unspecified"));
789
translated_name = dgettext ("iso_639", language);
790
name = get_first_item_in_semicolon_list (translated_name);
793
if (locale != NULL) {
794
setlocale (LC_MESSAGES, old_locale);
803
get_territory (const char *code)
808
g_assert (code != NULL);
811
if (len != 2 && len != 3) {
815
name = (const char *) g_hash_table_lookup (gdm_territories_map, code);
821
get_translated_territory (const char *code,
824
const char *territory;
827
territory = get_territory (code);
830
if (territory != NULL) {
831
const char *translated_territory;
834
if (locale != NULL) {
835
old_locale = g_strdup (setlocale (LC_MESSAGES, NULL));
836
setlocale (LC_MESSAGES, locale);
839
translated_territory = dgettext ("iso_3166", territory);
840
name = get_first_item_in_semicolon_list (translated_territory);
842
if (locale != NULL) {
843
setlocale (LC_MESSAGES, old_locale);
852
languages_parse_start_tag (GMarkupParseContext *ctx,
853
const char *element_name,
854
const char **attr_names,
855
const char **attr_values,
859
const char *ccode_longB;
860
const char *ccode_longT;
862
const char *ccode_id;
863
const char *lang_common_name;
864
const char *lang_name;
866
if (! (g_str_equal (element_name, "iso_639_entry") || g_str_equal (element_name, "iso_639_3_entry"))
867
|| attr_names == NULL || attr_values == NULL) {
875
lang_common_name = NULL;
878
while (*attr_names && *attr_values) {
879
if (g_str_equal (*attr_names, "iso_639_1_code")) {
882
if (strlen (*attr_values) != 2) {
885
ccode = *attr_values;
887
} else if (g_str_equal (*attr_names, "iso_639_2B_code")) {
890
if (strlen (*attr_values) != 3) {
893
ccode_longB = *attr_values;
895
} else if (g_str_equal (*attr_names, "iso_639_2T_code")) {
898
if (strlen (*attr_values) != 3) {
901
ccode_longT = *attr_values;
903
} else if (g_str_equal (*attr_names, "id")) {
906
if (strlen (*attr_values) != 2 &&
907
strlen (*attr_values) != 3) {
910
ccode_id = *attr_values;
912
} else if (g_str_equal (*attr_names, "common_name")) {
915
lang_common_name = *attr_values;
917
} else if (g_str_equal (*attr_names, "name")) {
918
lang_name = *attr_values;
925
if (lang_common_name != NULL) {
926
lang_name = lang_common_name;
929
if (lang_name == NULL) {
934
g_hash_table_insert (gdm_languages_map,
936
g_strdup (lang_name));
938
if (ccode_longB != NULL) {
939
g_hash_table_insert (gdm_languages_map,
940
g_strdup (ccode_longB),
941
g_strdup (lang_name));
943
if (ccode_longT != NULL) {
944
g_hash_table_insert (gdm_languages_map,
945
g_strdup (ccode_longT),
946
g_strdup (lang_name));
948
if (ccode_id != NULL) {
949
g_hash_table_insert (gdm_languages_map,
951
g_strdup (lang_name));
956
territories_parse_start_tag (GMarkupParseContext *ctx,
957
const char *element_name,
958
const char **attr_names,
959
const char **attr_values,
966
const char *territory_common_name;
967
const char *territory_name;
969
if (! g_str_equal (element_name, "iso_3166_entry") || attr_names == NULL || attr_values == NULL) {
976
territory_common_name = NULL;
977
territory_name = NULL;
979
while (*attr_names && *attr_values) {
980
if (g_str_equal (*attr_names, "alpha_2_code")) {
983
if (strlen (*attr_values) != 2) {
986
acode_2 = *attr_values;
988
} else if (g_str_equal (*attr_names, "alpha_3_code")) {
991
if (strlen (*attr_values) != 3) {
994
acode_3 = *attr_values;
996
} else if (g_str_equal (*attr_names, "numeric_code")) {
999
if (strlen (*attr_values) != 3) {
1002
ncode = *attr_values;
1004
} else if (g_str_equal (*attr_names, "common_name")) {
1006
if (**attr_values) {
1007
territory_common_name = *attr_values;
1009
} else if (g_str_equal (*attr_names, "name")) {
1010
territory_name = *attr_values;
1017
if (territory_common_name != NULL) {
1018
territory_name = territory_common_name;
1021
if (territory_name == NULL) {
1025
if (acode_2 != NULL) {
1026
g_hash_table_insert (gdm_territories_map,
1028
g_strdup (territory_name));
1030
if (acode_3 != NULL) {
1031
g_hash_table_insert (gdm_territories_map,
1033
g_strdup (territory_name));
1035
if (ncode != NULL) {
1036
g_hash_table_insert (gdm_territories_map,
1038
g_strdup (territory_name));
1043
languages_variant_init (const char *variant)
1051
bindtextdomain (variant, ISO_CODES_LOCALESDIR);
1052
bind_textdomain_codeset (variant, "UTF-8");
1055
filename = g_strdup_printf (ISO_CODES_DATADIR "/%s.xml", variant);
1056
res = g_file_get_contents (filename,
1061
GMarkupParseContext *ctx;
1062
GMarkupParser parser = { languages_parse_start_tag, NULL, NULL, NULL, NULL };
1064
ctx = g_markup_parse_context_new (&parser, 0, NULL, NULL);
1067
res = g_markup_parse_context_parse (ctx, buf, buf_len, &error);
1070
g_warning ("Failed to parse '%s': %s\n",
1073
g_error_free (error);
1076
g_markup_parse_context_free (ctx);
1079
g_warning ("Failed to load '%s': %s\n",
1082
g_error_free (error);
1089
languages_init (void)
1091
gdm_languages_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1093
languages_variant_init ("iso_639");
1094
languages_variant_init ("iso_639_3");
1098
territories_init (void)
1105
bindtextdomain ("iso_3166", ISO_CODES_LOCALESDIR);
1106
bind_textdomain_codeset ("iso_3166", "UTF-8");
1108
gdm_territories_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1111
res = g_file_get_contents (ISO_CODES_DATADIR "/iso_3166.xml",
1116
GMarkupParseContext *ctx;
1117
GMarkupParser parser = { territories_parse_start_tag, NULL, NULL, NULL, NULL };
1119
ctx = g_markup_parse_context_new (&parser, 0, NULL, NULL);
1122
res = g_markup_parse_context_parse (ctx, buf, buf_len, &error);
1125
g_warning ("Failed to parse '%s': %s\n",
1126
ISO_CODES_DATADIR "/iso_3166.xml",
1128
g_error_free (error);
1131
g_markup_parse_context_free (ctx);
1134
g_warning ("Failed to load '%s': %s\n",
1135
ISO_CODES_DATADIR "/iso_3166.xml",
1137
g_error_free (error);
1142
gdm_get_language_from_name (const char *name,
1145
GString *full_language;
1146
char *language_code;
1147
char *territory_code;
1149
char *langinfo_codeset;
1150
char *translated_language;
1151
char *translated_territory;
1153
gboolean is_utf8 = TRUE;
1155
g_return_val_if_fail (name != NULL, NULL);
1156
g_return_val_if_fail (*name != '\0', NULL);
1158
translated_territory = NULL;
1159
translated_language = NULL;
1160
langinfo_codeset = NULL;
1162
full_language = g_string_new (NULL);
1164
if (gdm_languages_map == NULL) {
1168
if (gdm_territories_map == NULL) {
1169
territories_init ();
1172
language_code = NULL;
1173
territory_code = NULL;
1174
codeset_code = NULL;
1177
gdm_parse_language_name (name,
1183
if (language_code == NULL) {
1187
translated_language = get_translated_language (language_code, locale);
1188
if (translated_language == NULL) {
1192
full_language = g_string_append (full_language, translated_language);
1194
if (is_unique_language (language_code)) {
1198
if (territory_code != NULL) {
1199
translated_territory = get_translated_territory (territory_code, locale);
1201
if (translated_territory != NULL) {
1202
g_string_append_printf (full_language,
1204
translated_territory);
1207
// language_name_get_codeset_details (name, &langinfo_codeset, &is_utf8);
1209
if (codeset_code == NULL && langinfo_codeset != NULL) {
1210
codeset_code = g_strdup (langinfo_codeset);
1213
if (!is_utf8 && codeset_code) {
1214
g_string_append_printf (full_language,
1219
if (modifier != NULL) {
1220
g_string_append_printf (full_language, " - %s", modifier);
1224
g_free (language_code);
1225
g_free (territory_code);
1226
g_free (codeset_code);
1227
g_free (langinfo_codeset);
1228
g_free (translated_language);
1229
g_free (translated_territory);
1232
if (full_language->len == 0) {
1233
g_string_free (full_language, TRUE);
1237
return g_string_free (full_language, FALSE);
1241
gdm_get_region_from_name (const char *name,
1245
char *language_code;
1246
char *territory_code;
1248
char *langinfo_codeset;
1249
char *translated_language;
1250
char *translated_territory;
1251
gboolean is_utf8 = TRUE;
1253
g_return_val_if_fail (name != NULL, NULL);
1254
g_return_val_if_fail (*name != '\0', NULL);
1256
translated_territory = NULL;
1257
translated_language = NULL;
1258
langinfo_codeset = NULL;
1260
full_name = g_string_new (NULL);
1262
if (gdm_languages_map == NULL) {
1266
if (gdm_territories_map == NULL) {
1267
territories_init ();
1270
language_code = NULL;
1271
territory_code = NULL;
1272
codeset_code = NULL;
1274
gdm_parse_language_name (name,
1280
if (territory_code == NULL) {
1284
translated_territory = get_translated_territory (territory_code, locale);
1285
g_string_append (full_name, translated_territory);
1287
if (is_unique_territory (territory_code)) {
1291
if (language_code != NULL) {
1292
translated_language = get_translated_language (language_code, locale);
1294
if (translated_language != NULL) {
1295
g_string_append_printf (full_name,
1297
translated_language);
1300
language_name_get_codeset_details (name, &langinfo_codeset, &is_utf8);
1302
if (codeset_code == NULL && langinfo_codeset != NULL) {
1303
codeset_code = g_strdup (langinfo_codeset);
1306
if (!is_utf8 && codeset_code) {
1307
g_string_append_printf (full_name,
1313
g_free (language_code);
1314
g_free (territory_code);
1315
g_free (codeset_code);
1316
g_free (langinfo_codeset);
1317
g_free (translated_language);
1318
g_free (translated_territory);
1320
if (full_name->len == 0) {
1321
g_string_free (full_name, TRUE);
1325
return g_string_free (full_name, FALSE);
1329
gdm_get_all_language_names (void)
1331
GHashTableIter iter;
1332
gpointer key, value;
1335
if (gdm_available_locales_map == NULL) {
1339
array = g_ptr_array_new ();
1340
g_hash_table_iter_init (&iter, gdm_available_locales_map);
1341
while (g_hash_table_iter_next (&iter, &key, &value)) {
1344
locale = (GdmLocale *) value;
1346
g_ptr_array_add (array, g_strdup (locale->name));
1348
g_ptr_array_add (array, NULL);
1350
return (char **) g_ptr_array_free (array, FALSE);