10 /* taken from gnome-libs/libgnome/gnome-i18n.c ... */
12 static GHashTable
*alias_table
= NULL
;
14 /*read an alias file for the locales*/
16 read_aliases (char *file
)
22 alias_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
23 fp
= fopen (file
,"r");
26 while (fgets (buf
,256,fp
)) {
29 if(buf
[0]=='#' || buf
[0]=='\0')
31 p
= strtok(buf
,"\t ");
33 p
= strtok(NULL
,"\t ");
35 g_hash_table_insert (alias_table
, g_strdup(buf
), g_strdup(p
));
41 free_alias_cb(gpointer key
, gpointer value
, gpointer user_data
)
48 free_alias_table(void)
52 g_hash_table_foreach(alias_table
, free_alias_cb
, NULL
);
53 g_hash_table_destroy(alias_table
);
57 /*return the un-aliased language as a newly allocated string*/
59 unalias_lang (char *lang
)
64 read_aliases ("/usr/share/locale/locale.alias");
65 read_aliases ("/usr/local/share/locale/locale.alias");
66 read_aliases ("/usr/lib/X11/locale/locale.alias");
67 read_aliases ("/usr/openwin/lib/locale/locale.alias");
69 while((p
=g_hash_table_lookup(alias_table
,lang
)) && strcmp(p
, lang
))
74 /* Mask for components of locale spec. The ordering here is from
75 * least significant to most significant
79 COMPONENT_CODESET
= 1 << 0,
80 COMPONENT_TERRITORY
= 1 << 1,
81 COMPONENT_MODIFIER
= 1 << 2
84 /* Break an X/Open style locale specification into components
87 explode_locale (const gchar
*locale
,
93 const gchar
*uscore_pos
;
99 uscore_pos
= strchr (locale
, '_');
100 dot_pos
= strchr (uscore_pos
? uscore_pos
: locale
, '.');
101 at_pos
= strchr (dot_pos
? dot_pos
: (uscore_pos
? uscore_pos
: locale
), '@');
104 mask
|= COMPONENT_MODIFIER
;
105 *modifier
= g_strdup (at_pos
);
107 at_pos
= locale
+ strlen (locale
);
110 mask
|= COMPONENT_CODESET
;
111 *codeset
= g_new (gchar
, 1 + at_pos
- dot_pos
);
112 strncpy (*codeset
, dot_pos
, at_pos
- dot_pos
);
113 (*codeset
)[at_pos
- dot_pos
] = '\0';
118 mask
|= COMPONENT_TERRITORY
;
119 *territory
= g_new (gchar
, 1 + dot_pos
- uscore_pos
);
120 strncpy (*territory
, uscore_pos
, dot_pos
- uscore_pos
);
121 (*territory
)[dot_pos
- uscore_pos
] = '\0';
123 uscore_pos
= dot_pos
;
125 *language
= g_new (gchar
, 1 + uscore_pos
- locale
);
126 strncpy (*language
, locale
, uscore_pos
- locale
);
127 (*language
)[uscore_pos
- locale
] = '\0';
133 * Compute all interesting variants for a given locale name -
134 * by stripping off different components of the value.
136 * For simplicity, we assume that the locale is in
137 * X/Open format: language[_territory][.codeset][@modifier]
139 * TODO: Extend this to handle the CEN format (see the GNUlibc docs)
140 * as well. We could just copy the code from glibc wholesale
141 * but it is big, ugly, and complicated, so I'm reluctant
142 * to do so when this should handle 99% of the time...
145 compute_locale_variants (const gchar
*locale
)
147 GList
*retval
= NULL
;
157 g_return_val_if_fail (locale
!= NULL
, NULL
);
159 mask
= explode_locale (locale
, &language
, &territory
, &codeset
, &modifier
);
161 /* Iterate through all possible combinations, from least attractive
162 * to most attractive.
164 for (i
=0; i
<=mask
; i
++)
165 if ((i
& ~mask
) == 0)
167 gchar
*val
= g_strconcat(language
,
168 (i
& COMPONENT_TERRITORY
) ? territory
: "",
169 (i
& COMPONENT_CODESET
) ? codeset
: "",
170 (i
& COMPONENT_MODIFIER
) ? modifier
: "",
172 retval
= g_list_prepend (retval
, val
);
176 if (mask
& COMPONENT_CODESET
)
178 if (mask
& COMPONENT_TERRITORY
)
180 if (mask
& COMPONENT_MODIFIER
)
186 /* The following is (partly) taken from the gettext package.
187 Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. */
190 guess_category_value (const gchar
*categoryname
)
194 /* The highest priority value is the `LANGUAGE' environment
195 variable. This is a GNU extension. */
196 retval
= getenv ("LANGUAGE");
197 if (retval
!= NULL
&& retval
[0] != '\0')
200 /* `LANGUAGE' is not set. So we have to proceed with the POSIX
201 methods of looking to `LC_ALL', `LC_xxx', and `LANG'. On some
202 systems this can be done by the `setlocale' function itself. */
204 /* Setting of LC_ALL overwrites all other. */
205 retval
= getenv ("LC_ALL");
206 if (retval
!= NULL
&& retval
[0] != '\0')
209 /* Next comes the name of the desired category. */
210 retval
= getenv (categoryname
);
211 if (retval
!= NULL
&& retval
[0] != '\0')
214 /* Last possibility is the LANG environment variable. */
215 retval
= getenv ("LANG");
216 if (retval
!= NULL
&& retval
[0] != '\0')
223 get_language_list(const gchar
*category_name
)
226 gint c_locale_defined
= FALSE
;
228 const gchar
*category_value
;
229 gchar
*category_memory
, *orig_category_memory
;
232 category_name
= "LC_ALL";
234 category_value
= guess_category_value (category_name
);
235 if (! category_value
)
236 category_value
= "C";
237 orig_category_memory
= category_memory
=
238 g_malloc (strlen (category_value
)+1);
240 while (category_value
[0] != '\0') {
241 while (category_value
[0] != '\0' && category_value
[0] == ':')
244 if (category_value
[0] != '\0') {
245 char *cp
= category_memory
;
247 while (category_value
[0] != '\0' && category_value
[0] != ':')
248 *category_memory
++= *category_value
++;
250 category_memory
[0]= '\0';
253 cp
= unalias_lang(cp
);
255 if (strcmp (cp
, "C") == 0)
256 c_locale_defined
= TRUE
;
258 list
= g_list_concat (list
, compute_locale_variants (cp
));
262 g_free (orig_category_memory
);
264 if (!c_locale_defined
)
265 list
= g_list_append (list
, "C");
273 intl_get_language_list(void)
275 static GList
*list
= NULL
;
279 list
= gnome_i18n_get_language_list("LC_MESSAGES");
281 list
= get_language_list("LC_MESSAGES");
288 /* low numbers are better */
290 intl_score_locale(const gchar
*locale
)
292 GList
*list
= intl_get_language_list();
296 /* NULL is same as C locale */
298 return g_list_length(list
) - 1;
299 for (tmp
= list
, i
= 0; tmp
; tmp
= tmp
->next
, i
++)
300 if (!strcmp((char *)tmp
->data
, locale
))
302 if (!tmp
) /* not found */