Improved the reliability of per-thread locale by unsetting it at the end
[citadel.git] / webcit / gettext.c
1 #define _GNU_SOURCE
2 #include "webcit.h"
3 #include "webserver.h"
4
5 #ifdef ENABLE_NLS
6
7 #define NUM_LANGS 3
8 static const char *AvailLang[NUM_LANGS] = {
9         "en_US",
10         "de_DE",
11         "it_IT"
12 };
13
14 locale_t wc_locales[NUM_LANGS];
15
16 typedef struct _lang_pref{
17         char lang[16];
18         char region[16];
19         char *match;
20         double Priority;
21 } LangStruct;
22
23 /* TODO: we skip the language weightening so far. */
24 /* Accept-Language: 'de-de,en-us;q=0.7,en;q=0.3' */
25 /* Accept-Language: de,en-ph;q=0.8,en-us;q=0.5,de-at;q=0.3 */
26 void httplang_to_locale(const char *LocaleString)
27 {
28         char *locale = "C";
29         LangStruct wanted_locales[20];
30         int i = 0;
31         int j = 0;
32         size_t len = strlen(LocaleString);
33         int nFound = 0;
34         int nParts;
35         const int nAvail = 1; /* Number of members in AvailLang */
36         char *search = (char *) malloc(len);
37         // locale_t my_Locale;
38         // locale_t my_Empty_Locale;
39
40         memcpy(search, LocaleString, len);
41         search[len] = '\0';
42         nParts=num_tokens(search,',');
43         for (i=0; ((i<nParts)&&(i<10)); i++)
44         {
45                 char buf[16];
46                 char sbuf[16];
47                 int blen;
48
49                 extract_token(&buf[0],search, 0,',',16);
50                 /* we are searching, if this list item has something like ;q=n*/
51                 if (num_tokens(&buf[0],'=')>1) {
52                         extract_token(&sbuf[0],&buf[0], 1,'=',16);
53                         wanted_locales[i].Priority=atof(&sbuf[0]);
54                 }
55                 else {
56                         wanted_locales[i].Priority=1.0;
57                 }
58                 /* get the locale part */
59                 extract_token(&sbuf[0],&buf[0],0,';',16);
60                 /* get the lang part, which should be allways there */
61                 extract_token(&wanted_locales[i].lang[0],&sbuf[0],0,'-',16);
62                 /* get the area code if any. */
63                 if (num_tokens(&sbuf[0],'-')>1) {
64                         extract_token(&wanted_locales[i].region[0],&sbuf[0],1,'-',16);
65                 }
66                 else { /* no ara code? use lang code */
67                         blen=strlen(&wanted_locales[i].lang[0]);
68                         memcpy(&wanted_locales[i].region[0], wanted_locales[i].lang,blen);
69                         wanted_locales[i].region[blen]='\0';
70                 } /* area codes are uppercase */
71                 blen=strlen(&wanted_locales[i].region[0]);
72                 for (j=0; j<blen; j++)
73                         {
74                                 int chars=toupper(wanted_locales[i].region[j]);
75                                 wanted_locales[i].region[j]=(char)chars;/*todo ?! */
76                         }
77         }
78
79         /* todo: weight  */
80         if (nFound > 0) {
81                 for (i = 0; i <= nFound; i++) {
82                         for (j = 0; j < nAvail; j++) {
83                                 int ret = strncasecmp(&wanted_locales[i].lang[0],
84                                                                           AvailLang[j],
85                                                                           strlen(&wanted_locales[i].lang[0]));
86                                 if (!ret) {
87                                         locale = (char *) AvailLang[j]; //wanted_locales[i];
88                                         i = nFound + 1;
89                                         j = nAvail + 1;
90                                         continue;
91                                 }
92                                 
93                         }
94                 }
95         }
96
97         len = strlen(locale);
98         memcpy(search, locale, len);
99         memcpy(&search[len], ".UTF8", 5);
100         search[len + 5] = '\0';
101
102
103         //      my_Empty_Locale = newlocale(LC_ALL_MASK, NULL, NULL);   /* create default locale */
104         //      my_Locale = newlocale(LC_MESSAGES_MASK /*|LC_TIME_MASK FIXME */ ,
105         //                    search, my_Empty_Locale);
106
107         //      uselocale(my_Locale);
108         //      //      freelocale(my_Locale);
109         //      //      freelocale(my_Empty_Locale);
110         //      free(search);
111 }
112
113
114
115 /*
116         // the web browser sends '-', we need '_' 
117
118                 for (i = 0; i < len; i++)
119                 if (search[i] == '-')
120                         search[i] = '_';
121
122         nFound=i;
123         nParts=num_tokens(search,',');
124         if (nParts>0)
125                 {
126                         extract_token(prefers,search, 1,';',len);
127                         extract_token(langs,search, 0,';',len);
128                 }
129         else
130                 {
131                         free(prefers);
132                         prefers=NULL;
133                         memcpy(search, len);
134                         search[len] = '\0';
135                 }
136         i = 0;
137         while ( !done && (nFound < 10)) {
138                 if ((search[i] == ',') || (search[i] == ';') || (search[i] == '\0'))
139                 {
140                         if ((search[i] == ';') || (search[i] == '\0'))
141                                 done = 1;
142                         search[i] = '\0';
143                         wanted_locales[nFound] = (char *) &search[j];
144                         j = i + 1;
145                         nFound++;
146                 }
147
148                 i++;
149         }
150 */
151
152
153
154 void offer_languages(void) {
155         int i;
156
157         wprintf("<select name=\"language\" size=\"1\">\n");
158
159         for (i=0; i < NUM_LANGS; ++i) {
160                 wprintf("<option value=%s>%s</option>\n", AvailLang[i], AvailLang[i]);
161         }
162
163         wprintf("</select>\n");
164 }
165
166 /*
167  * Set the selected language for this session.
168  */
169 void set_selected_language(char *lang) {
170         int i;
171
172         for (i=0; i<NUM_LANGS; ++i) {
173                 if (!strcasecmp(lang, AvailLang[i])) {
174                         WC->selected_language = i;
175                 }
176         }
177 }
178
179 /*
180  * Activate and deactivate the selected language for this session.
181  */
182 void go_selected_language(void) {
183         uselocale(wc_locales[WC->selected_language]);
184 }
185
186 void stop_selected_language(void) {
187         uselocale(LC_GLOBAL_LOCALE);
188 }
189
190
191 /*
192  * Create a locale_t for each available language
193  */
194 void initialize_locales(void) {
195         int i;
196         locale_t Empty_Locale;
197         char buf[32];
198
199         /* create default locale */
200         Empty_Locale = newlocale(LC_ALL_MASK, NULL, NULL);
201
202         for (i = 0; i < NUM_LANGS; ++i) {
203                 sprintf(buf, "%s.UTF8", AvailLang[i]);
204                 wc_locales[i] = newlocale(LC_MESSAGES_MASK /* |LC_TIME_MASK FIXME */ ,
205                         buf,
206                         Empty_Locale
207                 );
208         }
209 }
210
211
212 #else   /* ENABLE_NLS */
213
214 void offer_languages(void) {
215         wprintf("English (US)");
216 }
217
218 void set_selected_language(char *lang) {
219 }
220
221 void go_selected_language(void) {
222 }
223
224 void stop_selected_language(void) {
225 }
226
227 #endif  /* ENABLE_NLS */