gettext.c

00001 /*
00002  * $Id
00003  */
00009 #include "webcit.h"
00010 #include "webserver.h"
00011 
00012 #ifdef ENABLE_NLS
00013 
00014 #define NUM_LANGS 9 
00015 #define SEARCH_LANG 20 
00018 char *AvailLang[NUM_LANGS] = {
00019         "C",
00020         "en_US",
00021         "de_DE",
00022         "it_IT",
00023         "es_ES",
00024         "en_GB",
00025         "da_DK",
00026         "fr_FR",
00027         "nl_NL"
00028 };
00029 
00030 locale_t wc_locales[NUM_LANGS]; 
00033 typedef struct _lang_pref{
00034         char lang[16];          
00035         char region[16];        
00036         long priority;          
00037         int availability;       
00038         int selectedlang;       
00039 } LangStruct;
00040 
00041 /* \brief parse browser locale header 
00042  * seems as most browsers just do a one after coma value even if more than 10 locales are available. Sample strings:
00043  * opera: 
00044  * 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 
00045  * Firefox 
00046  * Accept-Language: 'de-de,en-us;q=0.7,en;q=0.3' 
00047  * Accept-Language: de,en-ph;q=0.8,en-us;q=0.5,de-at;q=0.3 
00048  * 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 
00049  * \param LocaleString the string from the browser http headers
00050  */
00051 
00052 void httplang_to_locale(char *LocaleString)
00053 {
00054         LangStruct wanted_locales[SEARCH_LANG];
00055         LangStruct *ls;
00056 
00057         int i = 0;
00058         int j = 0;
00059         /* size_t len = strlen(LocaleString); */
00060         long prio;
00061         int av;
00062         int nBest;
00063         int nParts;
00064         char search[1024];
00065         
00066         safestrncpy(search, LocaleString, sizeof search);
00067         nParts=num_tokens(search,',');
00068         for (i=0; ((i<nParts)&&(i<SEARCH_LANG)); i++)
00069         {
00070                         char buf[16];
00071                         char sbuf[16];
00072                         char lbuf[16];
00073                         int blen;
00074                         
00075                         ls=&wanted_locales[i];
00076 
00077                         extract_token(&buf[0],search, i,',',16);
00079                         if (num_tokens(&buf[0],'=')>1) {
00080                                 int sbuflen, k;
00081                                 extract_token(&sbuf[0],&buf[0], 1,'=',16);
00082                                 sbuflen=strlen(&sbuf[0]);
00083                                 for (k=0; k<sbuflen; k++) if (sbuf[k]=='.') sbuf[k]='0';
00084                                 ls->priority=atol(&sbuf[0]);
00085                         }
00086                         else {
00087                                 ls->priority=1000;
00088                         }
00090                         extract_token(&sbuf[0],&buf[0],0,';',16);
00092                         extract_token(&ls->lang[0],&sbuf[0],0,'-',16);
00094                         if (num_tokens(&sbuf[0],'-')>1) {
00095                                 extract_token(&ls->region[0],&sbuf[0],1,'-',16);
00096                         }
00097                         else { 
00098                                 blen=strlen(&ls->lang[0]);
00099                                 memcpy(&ls->region[0], ls->lang,blen);
00100                                 ls->region[blen]='\0';
00101                         } 
00102                         blen=strlen(&ls->region[0]);
00103                         for (j=0; j<blen; j++)
00104                                 {
00105                                         int chars=toupper(ls->region[j]);
00106                                         ls->region[j]=(char)chars;
00107                                 }
00108                         sprintf(&lbuf[0],"%s_%s",&ls->lang[0],&ls->region[0]);
00109                         
00111                         ls->availability=1;
00112                         ls->selectedlang=-1;
00113                         for (j=0; j<NUM_LANGS; j++) {
00114                                 int result;
00116                                 result=strcasecmp(&ls->lang[0], AvailLang[j]);
00117                                 if ((result<0)&&(result<ls->availability)){
00118                                         ls->availability=result;
00119                                         ls->selectedlang=j;
00120                                 }
00122                                 if (0==strcasecmp(&lbuf[0], AvailLang[j])){
00123                                         ls->availability=0;
00124                                         ls->selectedlang=j;
00125                                         j=NUM_LANGS;
00126                                 }
00127                         }
00128         }
00129         
00130         prio=0;
00131         av=-1000;
00132         nBest=-1;
00133         for (i=0; ((i<nParts)&&(i<SEARCH_LANG)); i++) {
00134                 ls=&wanted_locales[i];
00135                 if ((ls->availability<=0)&& 
00136                    (av<ls->availability)&&
00137                    (prio<ls->priority)&&
00138                    (ls->selectedlang!=-1)) {
00139                         nBest=ls->selectedlang;
00140                         av=ls->availability;
00141                         prio=ls->priority;
00142                 }
00143         }
00144         if (nBest == -1) {
00146                 nBest=0;
00147         }
00148         WC->selected_language=nBest;
00149         lprintf(9, "language found: %s\n", AvailLang[WC->selected_language]);
00150 }
00151 
00152 /* TODO: we skip the language weighting so far. */
00153 /* Accept-Language: 'de-de,en-us;q=0.7,en;q=0.3' */
00154 /* Accept-Language: de,en-ph;q=0.8,en-us;q=0.5,de-at;q=0.3 */
00155 //void httplang_to_locale(char *LocaleString)
00156 //{
00157 //      char selected_locale[16];
00158 //      int i, j;
00159 //      char lang[64];
00160 //      int num_accept = 0;
00161 //
00162 //      lprintf(9, "languageAccept: %s\n", LocaleString);
00163 //
00164 //      strcpy(selected_locale, "C");
00165 //      num_accept = num_tokens(LocaleString, ',');
00166 //
00167 //      for (i=num_accept-1; i>=0; --i) {
00168 //              extract_token(lang, LocaleString, i, ',', sizeof lang);
00169 //
00170 //              /* Strip out the weights; we don't use them.  Also convert
00171 //               * hyphens to underscores.
00172 //               */
00173 //              for (j=0; j<strlen(lang); ++j) {
00174 //                      if (lang[j] == '-') lang[j] = '_';
00175 //                      if (lang[j] == ';') lang[j] = 0;
00176 //              }
00177 //
00178 //              for (j=0; j<NUM_LANGS; ++j) {
00179 //                      if (!strncasecmp(lang, AvailLang[j], strlen(lang))) {
00180 //                              strcpy(selected_locale, AvailLang[j]);
00181 //                      }
00182 //              }
00183 //      }
00184 //
00185 //      lprintf(9, "language found: %s\n", selected_locale);
00186 //      set_selected_language(selected_locale);
00187 //}
00188 
00189 
00195 void offer_languages(void) {
00196         int i;
00197 
00198         wprintf("<select name=\"language\" id=\"lname\" size=\"1\">\n");
00199 
00200         for (i=0; i < NUM_LANGS; ++i) {
00201                 wprintf("<option %s value=%s>%s</option>\n",
00202                         ((WC->selected_language == i) ? "selected" : ""),
00203                         AvailLang[i],
00204                         AvailLang[i]
00205                 );
00206         }
00207 
00208         wprintf("</select>\n");
00209 }
00210 
00215 void set_selected_language(char *lang) {
00216         int i;
00217 
00218         for (i=0; i<NUM_LANGS; ++i) {
00219                 if (!strcasecmp(lang, AvailLang[i])) {
00220                         WC->selected_language = i;
00221                 }
00222         }
00223 }
00224 
00228 void go_selected_language(void) {
00229         if (WC->selected_language < 0) return;
00230         uselocale(wc_locales[WC->selected_language]);   
00231         textdomain(textdomain(NULL));                   
00232 }
00233 
00237 void stop_selected_language(void) {
00238         uselocale(LC_GLOBAL_LOCALE);                    
00239         textdomain(textdomain(NULL));                   
00240 }
00241 
00242 
00246 void initialize_locales(void) {
00247         int i;
00248         locale_t Empty_Locale;
00249         char buf[32];
00250 
00251         /* create default locale */
00252         Empty_Locale = newlocale(LC_ALL_MASK, NULL, NULL);
00253 
00254         for (i = 0; i < NUM_LANGS; ++i) {
00255                 if (i == 0) {
00256                         sprintf(buf, "%s", AvailLang[i]);       // locale 0 (C) is ascii, not utf-8
00257                 }
00258                 else {
00259                         sprintf(buf, "%s.UTF8", AvailLang[i]);
00260                 }
00261                 wc_locales[i] = newlocale(
00262                         (LC_MESSAGES_MASK|LC_TIME_MASK),
00263                         buf,
00264                         (((i > 0) && (wc_locales[0] != NULL)) ? wc_locales[0] : Empty_Locale)
00265                 );
00266                 if (wc_locales[i] == NULL) {
00267                         lprintf(1, "Error configuring locale for %s: %s\n",
00268                                 buf,
00269                                 strerror(errno)
00270                         );
00271                 }
00272                 else {
00273                         lprintf(3, "Configured available locale: %s\n", buf);
00274                 }
00275         }
00276 }
00277 
00278 
00279 #else   /* ENABLE_NLS */
00280 
00281 void offer_languages(void) {
00282         wprintf("English (US)");
00283 }
00284 
00286 void set_selected_language(char *lang) {
00287 }
00288 
00290 void go_selected_language(void) {
00291 }
00292 
00294 void stop_selected_language(void) {
00295 }
00296 
00297 #endif  /* ENABLE_NLS */
00298 
00299 

Generated on Wed Jun 20 23:13:08 2007 for webcit by  doxygen 1.5.2