1 /* Some ELinks' auxiliary routines (ELinks<->gettext support) */
2
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include "elinks.h"
11
12 #include "intl/gettext/libintl.h"
13 #include "intl/gettext/gettextP.h"
14 #include "util/error.h"
15 #include "util/memory.h"
16 #include "util/string.h"
17
18
19 /* See libintl.h for comments. */
20 int current_charset = -1;
21
22 /* This is a language lookup table. Indexed by code. */
23 /* Update this everytime you add a new translation. */
24 /* TODO: Try to autogenerate it somehow. Maybe just a complete table? Then we
25 * will anyway need a table of real translations. */
26 struct language languages[] = {
27 {N_("System"), "system"},
28 {N_("English"), "en"},
29
30 {N_("Belarusian"), "be"},
31 {N_("Brazilian Portuguese"), "pt-BR"},
32 {N_("Bulgarian"), "bg"},
33 {N_("Catalan"), "ca"},
34 {N_("Croatian"), "hr"},
35 {N_("Czech"), "cs"},
36 {N_("Danish"), "da"},
37 {N_("Dutch"), "nl"},
38 {N_("Estonian"), "et"},
39 {N_("Finnish"), "fi"},
40 {N_("French"), "fr"},
41 {N_("Galician"), "gl"},
42 {N_("German"), "de"},
43 {N_("Greek"), "el"},
44 {N_("Hungarian"), "hu"},
45 {N_("Icelandic"), "is"},
46 {N_("Indonesian"), "id"},
47 {N_("Italian"), "it"},
48 {N_("Lithuanian"), "lt"},
49 {N_("Norwegian"), "no"},
50 {N_("Polish"), "pl"},
51 {N_("Portuguese"), "pt"},
52 {N_("Romanian"), "ro"},
53 {N_("Russian"), "ru"},
54 {N_("Serbian"), "sr"},
55 {N_("Slovak"), "sk"},
56 {N_("Spanish"), "es"},
57 {N_("Swedish"), "sv"},
58 {N_("Turkish"), "tr"},
59 {N_("Ukrainian"), "uk"},
60
61 {NULL, NULL},
62 };
63
64 /* XXX: In fact this is _NOT_ a real ISO639 code but RFC3066 code (as we're
65 * supposed to use that one when sending language tags through HTTP/1.1) and
66 * that one consists basically from ISO639[-ISO3166]. This is important for
67 * ie. pt vs pt-BR. */
68 /* TODO: We should reflect this in name of this function and of the tag. On the
69 * other side, it's ISO639 for gettext as well etc. So what? --pasky */
70
71 int
iso639_to_language(unsigned char * iso639)72 iso639_to_language(unsigned char *iso639)
73 {
74 unsigned char *l = stracpy(iso639);
75 unsigned char *p;
76 int i, ll;
77
78 if (!l)
79 return 1;
80
81 /* The environment variable transformation. */
82
83 p = strchr(l, '.');
84 if (p)
85 *p = '\0';
86
87 p = strchr(l, '_');
88 if (p)
89 *p = '-';
90 else
91 p = strchr(l, '-');
92
93 /* Exact match. */
94
95 for (i = 0; languages[i].name; i++) {
96 if (strcmp(languages[i].iso639, l))
97 continue;
98 mem_free(l);
99 return i;
100 }
101
102 /* Base language match. */
103
104 if (p) {
105 *p = '\0';
106 for (i = 0; languages[i].name; i++) {
107 if (strcmp(languages[i].iso639, l))
108 continue;
109 mem_free(l);
110 return i;
111 }
112 }
113
114 /* Any dialect match. */
115
116 ll = strlen(l);
117 for (i = 0; languages[i].name; i++) {
118 int il = strcspn(languages[i].iso639, "-");
119
120 if (strncmp(languages[i].iso639, l, il > ll ? ll : il))
121 continue;
122 mem_free(l);
123 return i;
124 }
125
126 /* Default to english. */
127
128 mem_free(l);
129 return 1;
130 }
131
132 int system_language = 0;
133
134 unsigned char *
language_to_iso639(int language)135 language_to_iso639(int language)
136 {
137 /* Language is "system", we need to extract the index from
138 * the environment */
139 if (language == 0) {
140 return system_language ?
141 languages[system_language].iso639 :
142 languages[get_system_language_index()].iso639;
143 }
144
145 return languages[language].iso639;
146 }
147
148 int
name_to_language(const unsigned char * name)149 name_to_language(const unsigned char *name)
150 {
151 int i;
152
153 for (i = 0; languages[i].name; i++) {
154 if (c_strcasecmp(languages[i].name, name))
155 continue;
156 return i;
157 }
158 return 1;
159 }
160
161 unsigned char *
language_to_name(int language)162 language_to_name(int language)
163 {
164 return languages[language].name;
165 }
166
167 int
get_system_language_index(void)168 get_system_language_index(void)
169 {
170 unsigned char *l;
171
172 /* At this point current_language must be "system" yet. */
173 l = getenv("LANGUAGE");
174 if (!l)
175 l = getenv("LC_ALL");
176 if (!l)
177 l = getenv("LC_MESSAGES");
178 if (!l)
179 l = getenv("LANG");
180
181 return (l) ? iso639_to_language(l) : 1;
182 }
183
184 int current_language = 0;
185
186 void
set_language(int language)187 set_language(int language)
188 {
189 unsigned char *p;
190
191 if (!system_language)
192 system_language = get_system_language_index();
193
194 if (language == current_language) {
195 /* Nothing to do. */
196 return;
197 }
198
199 current_language = language;
200
201 if (!language)
202 language = system_language;
203
204 if (!LANGUAGE) {
205 /* We never free() this, purely intentionally. */
206 LANGUAGE = malloc(256);
207 }
208 strcpy(LANGUAGE, language_to_iso639(language));
209 p = strchr(LANGUAGE, '-');
210 if (p)
211 *p = '_';
212
213 /* Propagate the change to gettext. From the info manual. */
214 {
215 extern int _nl_msg_cat_cntr;
216
217 _nl_msg_cat_cntr++;
218 }
219 }
220