converted comments to get caught by doxygen
[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 4
8 #define SEARCH_LANG 20
9
10 char *AvailLang[NUM_LANGS] = {
11         "C",
12         "en_US",
13         "de_DE",
14         "it_IT"
15 };
16
17 locale_t wc_locales[NUM_LANGS];
18
19 typedef struct _lang_pref{
20         char lang[16];
21         char region[16];
22         long priority;
23         int availability;
24         int selectedlang;
25 } LangStruct;
26
27 /* seems as most browsers just do a one after coma value even if more than 10 locales are available. */
28 /* opera: */
29 /* Accept-Language: sq;q=1.0,de;q=0.9,as;q=0.8,ar;q=0.7,bn;q=0.6,zh-cn;q=0.5,kn;q=0.4,ch;q=0.3,fo;q=0.2,gn;q=0.1,ce;q=0.1,ie;q=0.1 */
30 /* Firefox */
31 /* Accept-Language: 'de-de,en-us;q=0.7,en;q=0.3' */
32 /* Accept-Language: de,en-ph;q=0.8,en-us;q=0.5,de-at;q=0.3 */
33 /* Accept-Language: de,en-us;q=0.9,it;q=0.9,de-de;q=0.8,en-ph;q=0.7,de-at;q=0.7,zh-cn;q=0.6,cy;q=0.5,ar-om;q=0.5,en-tt;q=0.4,xh;q=0.3,nl-be;q=0.3,cs;q=0.2,sv;q=0.1,tk;q=0.1 */
34
35 void httplang_to_locale(char *LocaleString)
36 {
37         LangStruct wanted_locales[SEARCH_LANG];
38         LangStruct *ls;
39
40         int i = 0;
41         int j = 0;
42         size_t len = strlen(LocaleString);
43         long prio;
44         int av;
45         int nBest;
46         int nParts;
47         char *search = (char *) malloc(len);
48         // locale_t my_Locale;
49         // locale_t my_Empty_Locale;
50         
51         memcpy(search, LocaleString, len);
52         search[len] = '\0';
53         nParts=num_tokens(search,',');
54         for (i=0; ((i<nParts)&&(i<SEARCH_LANG)); i++)
55         {
56                         char buf[16];
57                         char sbuf[16];
58                         char lbuf[16];
59                         int blen;
60                         
61                         ls=&wanted_locales[i];
62
63                         extract_token(&buf[0],search, i,',',16);
64                         /* we are searching, if this list item has something like ;q=n*/
65                         if (num_tokens(&buf[0],'=')>1) {
66                                 int sbuflen, k;
67                                 extract_token(&sbuf[0],&buf[0], 1,'=',16);
68                                 sbuflen=strlen(&sbuf[0]);
69                                 for (k=0; k<sbuflen; k++) if (sbuf[k]=='.') sbuf[k]='0';
70                                 ls->priority=atol(&sbuf[0]);
71                         }
72                         else {
73                                 ls->priority=1000;
74                         }
75                         /* get the locale part */
76                         extract_token(&sbuf[0],&buf[0],0,';',16);
77                         /* get the lang part, which should be allways there */
78                         extract_token(&ls->lang[0],&sbuf[0],0,'-',16);
79                         /* get the area code if any. */
80                         if (num_tokens(&sbuf[0],'-')>1) {
81                                 extract_token(&ls->region[0],&sbuf[0],1,'-',16);
82                         }
83                         else { /* no ara code? use lang code */
84                                 blen=strlen(&ls->lang[0]);
85                                 memcpy(&ls->region[0], ls->lang,blen);
86                                 ls->region[blen]='\0';
87                         } /* area codes are uppercase */
88                         blen=strlen(&ls->region[0]);
89                         for (j=0; j<blen; j++)
90                                 {
91                                         int chars=toupper(ls->region[j]);
92                                         ls->region[j]=(char)chars;/* \todo ?! */
93                                 }
94                         sprintf(&lbuf[0],"%s_%s",&ls->lang[0],&ls->region[0]);
95                         
96                         /* check if we have this lang */
97                         ls->availability=1;
98                         ls->selectedlang=-1;
99                         for (j=0; j<NUM_LANGS; j++) {
100                                 int result;
101                                 /* match against the LANG part */
102                                 result=strcasecmp(&ls->lang[0], AvailLang[j]);
103                                 if ((result<0)&&(result<ls->availability)){
104                                         ls->availability=result;
105                                         ls->selectedlang=j;
106                                 }
107                                 /* match against lang and locale */
108                                 if (0==strcasecmp(&lbuf[0], AvailLang[j])){
109                                         ls->availability=0;
110                                         ls->selectedlang=j;
111                                         j=NUM_LANGS;
112                                 }
113                         }
114         }
115         
116         prio=0;
117         av=-1000;
118         nBest=-1;
119         for (i=0; ((i<nParts)&&(i<SEARCH_LANG)); i++)
120                 {
121                         ls=&wanted_locales[i];
122                         if ((ls->availability<=0)&& 
123                                 (av<ls->availability)&&
124                                 (prio<ls->priority)&&
125                                 (ls->selectedlang!=-1)){
126                                 nBest=ls->selectedlang;
127                                 av=ls->availability;
128                                 prio=ls->priority;
129                         }
130                 }
131         if (nBest==-1) /* fall back to C */
132                 nBest=0;
133         WC->selected_language=nBest;
134         lprintf(9, "language found: %s\n", AvailLang[WC->selected_language]);
135         //      set_selected_language(selected_locale);
136 }
137
138 /* TODO: we skip the language weightening so far. */
139 /* Accept-Language: 'de-de,en-us;q=0.7,en;q=0.3' */
140 /* Accept-Language: de,en-ph;q=0.8,en-us;q=0.5,de-at;q=0.3 */
141 //void httplang_to_locale(char *LocaleString)
142 //{
143 //      char selected_locale[16];
144 //      int i, j;
145 //      char lang[64];
146 //      int num_accept = 0;
147 //
148 //      lprintf(9, "languageAccept: %s\n", LocaleString);
149 //
150 //      strcpy(selected_locale, "C");
151 //      num_accept = num_tokens(LocaleString, ',');
152 //
153 //      for (i=num_accept-1; i>=0; --i) {
154 //              extract_token(lang, LocaleString, i, ',', sizeof lang);
155 //
156 //              /* Strip out the weights; we don't use them.  Also convert
157 //               * hyphens to underscores.
158 //               */
159 //              for (j=0; j<strlen(lang); ++j) {
160 //                      if (lang[j] == '-') lang[j] = '_';
161 //                      if (lang[j] == ';') lang[j] = 0;
162 //              }
163 //
164 //              for (j=0; j<NUM_LANGS; ++j) {
165 //                      if (!strncasecmp(lang, AvailLang[j], strlen(lang))) {
166 //                              strcpy(selected_locale, AvailLang[j]);
167 //                      }
168 //              }
169 //      }
170 //
171 //      lprintf(9, "language found: %s\n", selected_locale);
172 //      set_selected_language(selected_locale);
173 //}
174
175
176 void offer_languages(void) {
177         int i;
178
179         wprintf("<select name=\"language\" size=\"1\">\n");
180
181         for (i=0; i < NUM_LANGS; ++i) {
182                 wprintf("<option %s value=%s>%s</option>\n",
183                         ((WC->selected_language == i) ? "selected" : ""),
184                         AvailLang[i],
185                         AvailLang[i]
186                 );
187         }
188
189         wprintf("</select>\n");
190 }
191
192 /*
193  * Set the selected language for this session.
194  */
195 void set_selected_language(char *lang) {
196         int i;
197
198         for (i=0; i<NUM_LANGS; ++i) {
199                 if (!strcasecmp(lang, AvailLang[i])) {
200                         WC->selected_language = i;
201                 }
202         }
203 }
204
205 /*
206  * Activate and deactivate the selected language for this session.
207  */
208 void go_selected_language(void) {
209         if (WC->selected_language < 0) return;
210         uselocale(wc_locales[WC->selected_language]);   /* switch locales */
211         textdomain(textdomain(NULL));                   /* clear the cache */
212 }
213
214 void stop_selected_language(void) {
215         uselocale(LC_GLOBAL_LOCALE);                    /* switch locales */
216         textdomain(textdomain(NULL));                   /* clear the cache */
217 }
218
219
220 /*
221  * Create a locale_t for each available language
222  */
223 void initialize_locales(void) {
224         int i;
225         locale_t Empty_Locale;
226         char buf[32];
227
228         /* create default locale */
229         Empty_Locale = newlocale(LC_ALL_MASK, NULL, NULL);
230
231         for (i = 0; i < NUM_LANGS; ++i) {
232                 sprintf(buf, "%s.UTF8", AvailLang[i]);
233                 wc_locales[i] = newlocale(LC_MESSAGES_MASK /* |LC_TIME_MASK FIXME */ ,
234                         buf,
235                         Empty_Locale
236                 );
237         }
238 }
239
240
241 #else   /* ENABLE_NLS */
242
243 void offer_languages(void) {
244         wprintf("English (US)");
245 }
246
247 void set_selected_language(char *lang) {
248 }
249
250 void go_selected_language(void) {
251 }
252
253 void stop_selected_language(void) {
254 }
255
256 #endif  /* ENABLE_NLS */