iconv: Bail out of the loop when an illegal sequence of bytes occurs.
[elinks/elinks-j605.git] / src / intl / gettext / libintl.c
blob2e798b5285216b17bdff502a91c41c04c6b4ec7f
1 /* Some ELinks' auxiliary routines (ELinks<->gettext support) */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <stdlib.h>
8 #include <string.h>
10 #include "elinks.h"
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"
19 /* See libintl.h for comments. */
20 int current_charset = -1;
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"},
30 {N_("Afrikaans"), "af"},
31 {N_("Belarusian"), "be"},
32 {N_("Brazilian Portuguese"), "pt-BR"},
33 {N_("Bulgarian"), "bg"},
34 {N_("Catalan"), "ca"},
35 {N_("Croatian"), "hr"},
36 {N_("Czech"), "cs"},
37 {N_("Danish"), "da"},
38 {N_("Dutch"), "nl"},
39 {N_("Estonian"), "et"},
40 {N_("Finnish"), "fi"},
41 {N_("French"), "fr"},
42 {N_("Galician"), "gl"},
43 {N_("German"), "de"},
44 {N_("Greek"), "el"},
45 {N_("Hungarian"), "hu"},
46 {N_("Icelandic"), "is"},
47 {N_("Indonesian"), "id"},
48 {N_("Italian"), "it"},
49 {N_("Lithuanian"), "lt"},
50 {N_("Norwegian"), "no"},
51 {N_("Polish"), "pl"},
52 {N_("Portuguese"), "pt"},
53 {N_("Romanian"), "ro"},
54 {N_("Russian"), "ru"},
55 {N_("Serbian"), "sr"},
56 {N_("Slovak"), "sk"},
57 {N_("Spanish"), "es"},
58 {N_("Swedish"), "sv"},
59 {N_("Turkish"), "tr"},
60 {N_("Ukrainian"), "uk"},
62 {NULL, NULL},
65 /* XXX: In fact this is _NOT_ a real ISO639 code but RFC3066 code (as we're
66 * supposed to use that one when sending language tags through HTTP/1.1) and
67 * that one consists basically from ISO639[-ISO3166]. This is important for
68 * ie. pt vs pt-BR. */
69 /* TODO: We should reflect this in name of this function and of the tag. On the
70 * other side, it's ISO639 for gettext as well etc. So what? --pasky */
72 int
73 iso639_to_language(unsigned char *iso639)
75 unsigned char *l = stracpy(iso639);
76 unsigned char *p;
77 int i, ll;
79 if (!l)
80 return 1;
82 /* The environment variable transformation. */
84 p = strchr(l, '.');
85 if (p)
86 *p = '\0';
88 p = strchr(l, '_');
89 if (p)
90 *p = '-';
91 else
92 p = strchr(l, '-');
94 /* Exact match. */
96 for (i = 0; languages[i].name; i++) {
97 if (strcmp(languages[i].iso639, l))
98 continue;
99 mem_free(l);
100 return i;
103 /* Base language match. */
105 if (p) {
106 *p = '\0';
107 for (i = 0; languages[i].name; i++) {
108 if (strcmp(languages[i].iso639, l))
109 continue;
110 mem_free(l);
111 return i;
115 /* Any dialect match. */
117 ll = strlen(l);
118 for (i = 0; languages[i].name; i++) {
119 int il = strcspn(languages[i].iso639, "-");
121 if (strncmp(languages[i].iso639, l, il > ll ? ll : il))
122 continue;
123 mem_free(l);
124 return i;
127 /* Default to english. */
129 mem_free(l);
130 return 1;
133 int system_language = 0;
135 unsigned char *
136 language_to_iso639(int language)
138 /* Language is "system", we need to extract the index from
139 * the environment */
140 if (language == 0) {
141 return system_language ?
142 languages[system_language].iso639 :
143 languages[get_system_language_index()].iso639;
146 return languages[language].iso639;
150 name_to_language(const unsigned char *name)
152 int i;
154 for (i = 0; languages[i].name; i++) {
155 if (c_strcasecmp(languages[i].name, name))
156 continue;
157 return i;
159 return 1;
162 unsigned char *
163 language_to_name(int language)
165 return languages[language].name;
169 get_system_language_index(void)
171 unsigned char *l;
173 /* At this point current_language must be "system" yet. */
174 l = getenv("LANGUAGE");
175 if (!l)
176 l = getenv("LC_ALL");
177 if (!l)
178 l = getenv("LC_MESSAGES");
179 if (!l)
180 l = getenv("LANG");
182 return (l) ? iso639_to_language(l) : 1;
185 int current_language = 0;
187 void
188 set_language(int language)
190 unsigned char *p;
192 if (!system_language)
193 system_language = get_system_language_index();
195 if (language == current_language) {
196 /* Nothing to do. */
197 return;
200 current_language = language;
202 if (!language)
203 language = system_language;
205 if (!LANGUAGE) {
206 /* We never free() this, purely intentionally. */
207 LANGUAGE = malloc(256);
209 if (LANGUAGE) {
210 strcpy(LANGUAGE, language_to_iso639(language));
211 p = strchr(LANGUAGE, '-');
212 if (p) {
213 *p = '_';
217 /* Propagate the change to gettext. From the info manual. */
219 extern int _nl_msg_cat_cntr;
221 _nl_msg_cat_cntr++;