cl_language.c

Go to the documentation of this file.
00001 
00006 /*
00007 All original material Copyright (C) 2002-2010 UFO: Alien Invasion.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018 See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 */
00025 
00026 #include "client.h"
00027 #include "cl_language.h"
00028 #include "../shared/parse.h"
00029 #include "../ports/system.h"
00030 
00031 #include "ui/ui_main.h"
00032 #include "ui/ui_font.h"
00033 #include "ui/node/ui_node_abstractoption.h"
00034 
00038 typedef struct localeMapping_s {
00039     char *localeMapping;    
00040     struct localeMapping_s *next;   
00041 } localeMapping_t;
00042 
00047 typedef struct language_s {
00048     char *localeID;         
00049     char *localeString;     
00050     localeMapping_t *localeMapping; 
00051     struct language_s *next;    
00052 } language_t;
00053 
00054 static language_t *languageList;    
00055 static int languageCount; 
00061 static const char *CL_GetLocaleID (const char *fullLocale)
00062 {
00063     int i;
00064     language_t *language;
00065 
00066     for (i = 0, language = languageList; i < languageCount; language = language->next, i++) {
00067         localeMapping_t *mapping = language->localeMapping;
00068 
00069         while (mapping) {
00070             if (!strcmp(fullLocale, mapping->localeMapping))
00071                 return language->localeID;
00072             mapping = mapping->next;
00073         }
00074     }
00075     Com_DPrintf(DEBUG_CLIENT, "CL_GetLocaleID: Could not find your system locale '%s'. "
00076         "Add it to the languages script file and send a patch please.\n", fullLocale);
00077     return NULL;
00078 }
00079 
00083 void CL_ParseLanguages (const char *name, const char **text)
00084 {
00085     const char *errhead = "CL_ParseLanguages: unexpected end of file (language ";
00086     const char  *token;
00087     language_t *language = NULL;
00088     localeMapping_t *mapping = NULL;
00089 
00090     if (!*text) {
00091         Com_Printf("CL_ParseLanguages: language without body ignored (%s)\n", name);
00092         return;
00093     }
00094 
00095     token = Com_EParse(text, errhead, name);
00096     if (!*text || *token != '{') {
00097         Com_Printf("CL_ParseLanguages: language without body ignored (%s)\n", name);
00098         return;
00099     }
00100 
00101     do {
00102         /* get the name type */
00103         token = Com_EParse(text, errhead, name);
00104         if (!*text || *token == '}')
00105             break;
00106         /* inner locale id definition */
00107         if (*token == '{') {
00108             if (!language) {
00109                 Com_Printf("CL_ParseLanguages: language: '%s' - found mappings with language string - ignore it\n", name);
00110                 return;
00111             }
00112             do {
00113                 /* get the locale mappings now type */
00114                 token = Com_EParse(text, errhead, name);
00115                 /* end of locale mappings reached */
00116                 if (!*text || *token == '}')
00117                     break;
00118                 mapping = Mem_PoolAlloc(sizeof(*mapping), cl_genericPool, 0);
00119                 mapping->localeMapping = Mem_PoolStrDup(token, cl_genericPool, 0);
00120                 /* link it in */
00121                 mapping->next = language->localeMapping;
00122                 language->localeMapping = mapping;
00123             } while (*text);
00124             language = NULL;
00125         } else {
00126             if (*token != '_') {
00127                 Com_Printf("CL_ParseLanguages: language: '%s' - not marked translatable (%s) - ignore it\n", name, token);
00128                 continue;
00129             }
00130             language = Mem_PoolAlloc(sizeof(*language), cl_genericPool, 0);
00131             language->localeID = Mem_PoolStrDup(name, cl_genericPool, 0);
00132             language->localeString = Mem_PoolStrDup(token + 1, cl_genericPool, 0);
00133             language->localeMapping = NULL;
00134             language->next = languageList;
00135             languageList = language;
00136             languageCount++;
00137         }
00138     } while (*text);
00139 }
00140 
00146 static qboolean CL_LanguageTest (const char *localeID)
00147 {
00148 #ifndef _WIN32
00149     int i;
00150     language_t* language;
00151     localeMapping_t* mapping;
00152 #endif
00153     char languagePath[MAX_OSPATH];
00154     cvar_t *fs_i18ndir;
00155 
00156     assert(localeID);
00157 
00158     /* Find the proper *.mo file. */
00159     fs_i18ndir = Cvar_Get("fs_i18ndir", "", 0, "System path to language files");
00160     if (fs_i18ndir->string[0] != '\0')
00161         Q_strncpyz(languagePath, fs_i18ndir->string, sizeof(languagePath));
00162     else
00163 #ifdef LOCALEDIR
00164         Com_sprintf(languagePath, sizeof(languagePath), LOCALEDIR);
00165 #else
00166         Com_sprintf(languagePath, sizeof(languagePath), "%s/"BASEDIRNAME"/i18n/", FS_GetCwd());
00167 #endif
00168     Com_DPrintf(DEBUG_CLIENT, "CL_LanguageTest: using mo files from '%s'\n", languagePath);
00169     Q_strcat(languagePath, localeID, sizeof(languagePath));
00170     Q_strcat(languagePath, "/LC_MESSAGES/ufoai.mo", sizeof(languagePath));
00171 
00172     /* No *.mo file -> no language. */
00173     if (!FS_FileExists(languagePath)) {
00174         Com_DPrintf(DEBUG_CLIENT, "CL_LanguageTest: locale '%s' not found.\n", localeID);
00175         return qfalse;
00176     }
00177 
00178 #ifdef _WIN32
00179     if (Sys_Setenv("LANGUAGE=%s", localeID) == 0) {
00180         Com_DPrintf(DEBUG_CLIENT, "CL_LanguageTest: locale '%s' found.\n", localeID);
00181         return qtrue;
00182     }
00183 #else
00184     for (i = 0, language = languageList; i < languageCount; language = language->next, i++) {
00185         if (!strcmp(localeID, language->localeID))
00186             break;
00187     }
00188     if (i == languageCount) {
00189         Com_DPrintf(DEBUG_CLIENT, "CL_LanguageTest: Could not find locale with id '%s'\n", localeID);
00190         return qfalse;
00191     }
00192 
00193     mapping = language->localeMapping;
00194     if (!mapping) {
00195         Com_DPrintf(DEBUG_CLIENT, "No locale mappings for locale with id '%s'\n", localeID);
00196         return qfalse;
00197     }
00198     /* Cycle through all mappings, but stop at first locale possible to set. */
00199     do {
00200         /* setlocale() will return NULL if no setting possible. */
00201         if (setlocale(LC_MESSAGES, mapping->localeMapping)) {
00202             Com_DPrintf(DEBUG_CLIENT, "CL_LanguageTest: language '%s' with locale '%s' found.\n", localeID, mapping->localeMapping);
00203             return qtrue;
00204         } else
00205             Com_DPrintf(DEBUG_CLIENT, "CL_LanguageTest: language '%s' with locale '%s' not found on your system.\n", localeID, mapping->localeMapping);
00206         mapping = mapping->next;
00207     } while (mapping);
00208     Com_DPrintf(DEBUG_CLIENT, "CL_LanguageTest: not possible to use language '%s'.\n", localeID);
00209 #endif
00210 
00211     return qfalse;
00212 }
00213 
00219 void CL_LanguageInit (void)
00220 {
00221     int i;
00222     language_t* language;
00223     uiNode_t *languageOption = NULL;
00224     char systemLanguage[MAX_VAR];
00225 
00226     if (s_language->string[0] != '\0') {
00227         Com_Printf("CL_LanguageInit: language settings are stored in configuration: %s\n", s_language->string);
00228         Q_strncpyz(systemLanguage, s_language->string, sizeof(systemLanguage));
00229     } else {
00230         const char *currentLocale = Sys_GetLocale();
00231 
00232         if (currentLocale) {
00233             const char *localeID = CL_GetLocaleID(currentLocale);
00234             if (localeID)
00235                 Q_strncpyz(systemLanguage, localeID, sizeof(systemLanguage));
00236             else
00237                 systemLanguage[0] = '\0';
00238         } else
00239             systemLanguage[0] = '\0';
00240     }
00241 
00242     Com_DPrintf(DEBUG_CLIENT, "CL_LanguageInit: system language is: '%s'\n", systemLanguage);
00243 
00244     for (i = 0, language = languageList; i < languageCount; language = language->next, i++) {
00245 #ifndef DEBUG
00246         /* No language option available only for DEBUG. */
00247         if (!CL_LanguageTest(language->localeID))
00248             continue;
00249 #endif
00250 
00251         /* Test the locale first, add to list if setting given locale possible. */
00252         if (CL_LanguageTest(language->localeID) || !strcmp(language->localeID, "none")) {
00253             UI_AddOption(&languageOption, "", language->localeString, language->localeID);
00254         }
00255     }
00256 
00257     /* sort the list, and register it to the menu */
00258     UI_SortOptions(&languageOption);
00259     UI_RegisterOption(OPTION_LANGUAGES, languageOption);
00260 
00261     /* Set to the locale remembered previously. */
00262     CL_LanguageTryToSet(systemLanguage);
00263 }
00264 
00268 static void CL_NewLanguage (void)
00269 {
00270     R_FontShutdown();
00271     R_FontInit();
00272     UI_InitFonts();
00273     R_FontSetTruncationMarker(_("..."));
00274 }
00275 
00281 qboolean CL_LanguageTryToSet (const char *localeID)
00282 {
00283     int i;
00284     language_t* language;
00285     localeMapping_t* mapping;
00286 
00287     assert(localeID);
00288 
00289     /* in case of an error we really don't want a flooded console */
00290     s_language->modified = qfalse;
00291 
00292     for (i = 0, language = languageList; i < languageCount; language = language->next, i++) {
00293         if (!strcmp(localeID, language->localeID))
00294             break;
00295     }
00296 
00297     if (i == languageCount) {
00298         Com_Printf("Could not find locale with id '%s'\n", localeID);
00299         return qfalse;
00300     }
00301 
00302     mapping = language->localeMapping;
00303     if (!mapping) {
00304         Com_Printf("No locale mappings for locale with id '%s'\n", localeID);
00305         return qfalse;
00306     }
00307 
00308     Cvar_Set("s_language", localeID);
00309     s_language->modified = qfalse;
00310 
00311     do {
00312         Com_DPrintf(DEBUG_CLIENT, "CL_LanguageTryToSet: %s (%s)\n", mapping->localeMapping, localeID);
00313         if (Sys_SetLocale(mapping->localeMapping)) {
00314             CL_NewLanguage();
00315             return qtrue;
00316         }
00317         mapping = mapping->next;
00318     } while (mapping);
00319 
00320 #ifndef _WIN32
00321     Com_DPrintf(DEBUG_CLIENT, "CL_LanguageTryToSet: Finally try: '%s'\n", localeID);
00322     Sys_SetLocale(localeID);
00323     CL_NewLanguage();
00324 #endif
00325 
00326     return qfalse;
00327 }

Generated by  doxygen 1.6.2