10 /* taken from gnome-libs/libgnome/gnome-i18n.c ... */
11 /* FIXME: is this still necessary, or has gtk2.0 swallowed this ? */
13 static GHashTable
*alias_table
= NULL
;
15 /*read an alias file for the locales*/
17 read_aliases (char *file
)
23 alias_table
= g_hash_table_new_full (g_str_hash
, g_str_equal
,
25 fp
= fopen (file
,"r");
28 while (fgets (buf
,256,fp
)) {
31 if(buf
[0]=='#' || buf
[0]=='\0')
33 p
= strtok(buf
,"\t ");
35 p
= strtok(NULL
,"\t ");
37 g_hash_table_insert (alias_table
, g_strdup(buf
), g_strdup(p
));
43 free_alias_table(void)
47 g_hash_table_destroy(alias_table
);
51 /*return the un-aliased language as a newly allocated string*/
53 unalias_lang (char *lang
)
58 read_aliases ("/usr/share/locale/locale.alias");
59 read_aliases ("/usr/local/share/locale/locale.alias");
60 read_aliases ("/usr/lib/X11/locale/locale.alias");
61 read_aliases ("/usr/openwin/lib/locale/locale.alias");
63 while((p
=g_hash_table_lookup(alias_table
,lang
)) && strcmp(p
, lang
))
68 /* Mask for components of locale spec. The ordering here is from
69 * least significant to most significant
73 COMPONENT_CODESET
= 1 << 0,
74 COMPONENT_TERRITORY
= 1 << 1,
75 COMPONENT_MODIFIER
= 1 << 2
78 /* Break an X/Open style locale specification into components
81 explode_locale (const gchar
*locale
,
87 const gchar
*uscore_pos
;
93 uscore_pos
= strchr (locale
, '_');
94 dot_pos
= strchr (uscore_pos
? uscore_pos
: locale
, '.');
95 at_pos
= strchr (dot_pos
? dot_pos
: (uscore_pos
? uscore_pos
: locale
), '@');
98 mask
|= COMPONENT_MODIFIER
;
99 *modifier
= g_strdup (at_pos
);
101 at_pos
= locale
+ strlen (locale
);
104 mask
|= COMPONENT_CODESET
;
105 *codeset
= g_new (gchar
, 1 + at_pos
- dot_pos
);
106 strncpy (*codeset
, dot_pos
, at_pos
- dot_pos
);
107 (*codeset
)[at_pos
- dot_pos
] = '\0';
112 mask
|= COMPONENT_TERRITORY
;
113 *territory
= g_new (gchar
, 1 + dot_pos
- uscore_pos
);
114 strncpy (*territory
, uscore_pos
, dot_pos
- uscore_pos
);
115 (*territory
)[dot_pos
- uscore_pos
] = '\0';
117 uscore_pos
= dot_pos
;
119 *language
= g_new (gchar
, 1 + uscore_pos
- locale
);
120 strncpy (*language
, locale
, uscore_pos
- locale
);
121 (*language
)[uscore_pos
- locale
] = '\0';
127 * Compute all interesting variants for a given locale name -
128 * by stripping off different components of the value.
130 * For simplicity, we assume that the locale is in
131 * X/Open format: language[_territory][.codeset][@modifier]
133 * TODO: Extend this to handle the CEN format (see the GNUlibc docs)
134 * as well. We could just copy the code from glibc wholesale
135 * but it is big, ugly, and complicated, so I'm reluctant
136 * to do so when this should handle 99% of the time...
139 compute_locale_variants (const gchar
*locale
)
141 GList
*retval
= NULL
;
151 g_return_val_if_fail (locale
!= NULL
, NULL
);
153 mask
= explode_locale (locale
, &language
, &territory
, &codeset
, &modifier
);
155 /* Iterate through all possible combinations, from least attractive
156 * to most attractive.
158 for (i
=0; i
<=mask
; i
++)
159 if ((i
& ~mask
) == 0)
161 gchar
*val
= g_strconcat(language
,
162 (i
& COMPONENT_TERRITORY
) ? territory
: "",
163 (i
& COMPONENT_CODESET
) ? codeset
: "",
164 (i
& COMPONENT_MODIFIER
) ? modifier
: "",
166 retval
= g_list_prepend (retval
, val
);
170 if (mask
& COMPONENT_CODESET
)
172 if (mask
& COMPONENT_TERRITORY
)
174 if (mask
& COMPONENT_MODIFIER
)
180 /* The following is (partly) taken from the gettext package.
181 Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. */
184 guess_category_value (const gchar
*categoryname
)
188 /* The highest priority value is the `LANGUAGE' environment
189 variable. This is a GNU extension. */
190 retval
= getenv ("LANGUAGE");
191 if (retval
!= NULL
&& retval
[0] != '\0')
194 /* `LANGUAGE' is not set. So we have to proceed with the POSIX
195 methods of looking to `LC_ALL', `LC_xxx', and `LANG'. On some
196 systems this can be done by the `setlocale' function itself. */
198 /* Setting of LC_ALL overwrites all other. */
199 retval
= getenv ("LC_ALL");
200 if (retval
!= NULL
&& retval
[0] != '\0')
203 /* Next comes the name of the desired category. */
204 retval
= getenv (categoryname
);
205 if (retval
!= NULL
&& retval
[0] != '\0')
208 /* Last possibility is the LANG environment variable. */
209 retval
= getenv ("LANG");
210 if (retval
!= NULL
&& retval
[0] != '\0')
217 get_language_list(const gchar
*category_name
)
220 gint c_locale_defined
= FALSE
;
222 const gchar
*category_value
;
223 gchar
*category_memory
, *orig_category_memory
;
226 category_name
= "LC_ALL";
228 category_value
= guess_category_value (category_name
);
229 if (! category_value
)
230 category_value
= "C";
231 orig_category_memory
= category_memory
=
232 g_malloc (strlen (category_value
)+1);
234 while (category_value
[0] != '\0') {
235 while (category_value
[0] != '\0' && category_value
[0] == ':')
238 if (category_value
[0] != '\0') {
239 char *cp
= category_memory
;
241 while (category_value
[0] != '\0' && category_value
[0] != ':')
242 *category_memory
++= *category_value
++;
244 category_memory
[0]= '\0';
247 cp
= unalias_lang(cp
);
249 if (strcmp (cp
, "C") == 0)
250 c_locale_defined
= TRUE
;
252 list
= g_list_concat (list
, compute_locale_variants (cp
));
256 g_free (orig_category_memory
);
258 if (!c_locale_defined
)
259 list
= g_list_append (list
, "C");
267 intl_get_language_list(void)
269 static const GList
*list
= NULL
;
273 list
= gnome_i18n_get_language_list("LC_MESSAGES");
275 list
= get_language_list("LC_MESSAGES");
282 /* low numbers are better */
284 intl_score_locale(const gchar
*locale
)
286 const GList
*list
= intl_get_language_list();
290 /* NULL is same as C locale */
292 return g_list_length((GList
*)list
) - 1;
293 for (tmp
= list
, i
= 0; tmp
; tmp
= tmp
->next
, i
++)
294 if (!strcmp((const char *)tmp
->data
, locale
))
296 if (!tmp
) /* not found */