1 #include "config.h"
2
3 #include <stdlib.h>
4 #include <stdio.h>
5
6 #ifdef HAVE_UNISTD_H
7 #include <unistd.h>
8 #endif
9
10 #include <string.h>
11 #include <errno.h>
12 #include <locale.h>
13 #include <sys/stat.h>
14
15 #include <glib.h>
16 #include <glib/gi18n.h>
17 #include <glib/gstdio.h>
18 #include <hb-ot.h>
19
20 #include "language-names.h"
21
22 #ifndef ISO_CODES_PREFIX
23 #define ISO_CODES_PREFIX "/usr"
24 #endif
25
26 #define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes"
27 #define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale"
28
29 static GHashTable *language_map;
30
31 static char *
get_first_item_in_semicolon_list(const char * list)32 get_first_item_in_semicolon_list (const char *list)
33 {
34 char **items;
35 char *item;
36
37 items = g_strsplit (list, "; ", 2);
38
39 item = g_strdup (items[0]);
40 g_strfreev (items);
41
42 return item;
43 }
44
45 static char *
capitalize_utf8_string(const char * str)46 capitalize_utf8_string (const char *str)
47 {
48 char first[8] = { 0 };
49
50 if (!str)
51 return NULL;
52
53 g_unichar_to_utf8 (g_unichar_totitle (g_utf8_get_char (str)), first);
54
55 return g_strconcat (first, g_utf8_offset_to_pointer (str, 1), NULL);
56 }
57
58 static char *
get_display_name(const char * language)59 get_display_name (const char *language)
60 {
61 const char *translated;
62 char *tmp;
63 char *name;
64
65 translated = dgettext ("iso_639", language);
66
67 tmp = get_first_item_in_semicolon_list (translated);
68 name = capitalize_utf8_string (tmp);
69 g_free (tmp);
70
71 return name;
72 }
73
74 static void
languages_parse_start_tag(GMarkupParseContext * ctx,const char * element_name,const char ** attr_names,const char ** attr_values,gpointer user_data,GError ** error)75 languages_parse_start_tag (GMarkupParseContext *ctx,
76 const char *element_name,
77 const char **attr_names,
78 const char **attr_values,
79 gpointer user_data,
80 GError **error)
81 {
82 const char *ccode_longB;
83 const char *ccode_longT;
84 const char *ccode;
85 const char *ccode_id;
86 const char *lang_name;
87 char *display_name;
88 const char *long_names[] = {
89 "Dogri",
90 "Greek, Modern",
91 "Interlingua",
92 "Konkani",
93 "Tonga",
94 "Turkish, Ottoman",
95 };
96 int i;
97
98 if (!(g_str_equal (element_name, "iso_639_entry") ||
99 g_str_equal (element_name, "iso_639_3_entry")) ||
100 attr_names == NULL ||
101 attr_values == NULL)
102 return;
103
104 ccode = NULL;
105 ccode_longB = NULL;
106 ccode_longT = NULL;
107 ccode_id = NULL;
108 lang_name = NULL;
109
110 while (*attr_names && *attr_values)
111 {
112 if (g_str_equal (*attr_names, "iso_639_1_code"))
113 {
114 if (**attr_values)
115 {
116 if (strlen (*attr_values) != 2)
117 return;
118 ccode = *attr_values;
119 }
120 }
121 else if (g_str_equal (*attr_names, "iso_639_2B_code"))
122 {
123 if (**attr_values)
124 {
125 if (strlen (*attr_values) != 3)
126 return;
127 ccode_longB = *attr_values;
128 }
129 }
130 else if (g_str_equal (*attr_names, "iso_639_2T_code"))
131 {
132 if (**attr_values)
133 {
134 if (strlen (*attr_values) != 3)
135 return;
136 ccode_longT = *attr_values;
137 }
138 }
139 else if (g_str_equal (*attr_names, "id"))
140 {
141 if (**attr_values)
142 {
143 if (strlen (*attr_values) != 2 &&
144 strlen (*attr_values) != 3)
145 return;
146 ccode_id = *attr_values;
147 }
148 }
149 else if (g_str_equal (*attr_names, "name"))
150 {
151 lang_name = *attr_values;
152 }
153
154 ++attr_names;
155 ++attr_values;
156 }
157
158 if (lang_name == NULL)
159 return;
160
161 display_name = get_display_name (lang_name);
162
163 /* Fix up some egregious names */
164 for (i = 0; i < G_N_ELEMENTS (long_names); i++)
165 {
166 if (g_str_has_prefix (display_name, long_names[i]))
167 display_name[strlen (long_names[i])] = '\0';
168 }
169
170
171 if (ccode != NULL)
172 g_hash_table_insert (language_map,
173 pango_language_from_string (ccode),
174 g_strdup (display_name));
175
176 if (ccode_longB != NULL)
177 g_hash_table_insert (language_map,
178 pango_language_from_string (ccode_longB),
179 g_strdup (display_name));
180
181 if (ccode_longT != NULL)
182 g_hash_table_insert (language_map,
183 pango_language_from_string (ccode_longT),
184 g_strdup (display_name));
185
186 if (ccode_id != NULL)
187 g_hash_table_insert (language_map,
188 pango_language_from_string (ccode_id),
189 g_strdup (display_name));
190
191 g_free (display_name);
192 }
193
194 static void
languages_variant_init(const char * variant)195 languages_variant_init (const char *variant)
196 {
197 gboolean res;
198 gsize buf_len;
199 char *buf;
200 char *filename;
201 GError *error;
202
203 bindtextdomain (variant, ISO_CODES_LOCALESDIR);
204 bind_textdomain_codeset (variant, "UTF-8");
205
206 error = NULL;
207 filename = g_strconcat (ISO_CODES_DATADIR, "/", variant, ".xml", NULL);
208 res = g_file_get_contents (filename, &buf, &buf_len, &error);
209 if (res)
210 {
211 GMarkupParseContext *ctx = NULL;
212 GMarkupParser parser = { languages_parse_start_tag, NULL, NULL, NULL, NULL };
213
214 ctx = g_markup_parse_context_new (&parser, 0, NULL, NULL);
215
216 res = g_markup_parse_context_parse (ctx, buf, buf_len, &error);
217 g_free (ctx);
218
219 if (!res)
220 {
221 g_warning ("Failed to parse '%s': %s\n", filename, error->message);
222 g_error_free (error);
223 }
224 }
225 else
226 {
227 g_warning ("Failed to load '%s': %s\n", filename, error->message);
228 g_error_free (error);
229 }
230
231 g_free (filename);
232 g_free (buf);
233 }
234
235 static void
languages_init(void)236 languages_init (void)
237 {
238 if (language_map)
239 return;
240
241 language_map = g_hash_table_new_full (NULL, NULL, NULL, g_free);
242 languages_variant_init ("iso_639");
243 languages_variant_init ("iso_639_3");
244 }
245
246 const char *
get_language_name(PangoLanguage * language)247 get_language_name (PangoLanguage *language)
248 {
249 languages_init ();
250
251 return (const char *) g_hash_table_lookup (language_map, language);
252 }
253
254 const char *
get_language_name_for_tag(guint32 tag)255 get_language_name_for_tag (guint32 tag)
256 {
257 hb_language_t lang;
258 const char *s;
259
260 lang = hb_ot_tag_to_language (tag);
261 s = hb_language_to_string (lang);
262
263 return get_language_name (pango_language_from_string (s));
264 }
265