00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00103 token = Com_EParse(text, errhead, name);
00104 if (!*text || *token == '}')
00105 break;
00106
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
00114 token = Com_EParse(text, errhead, name);
00115
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
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
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
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
00199 do {
00200
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
00247 if (!CL_LanguageTest(language->localeID))
00248 continue;
00249 #endif
00250
00251
00252 if (CL_LanguageTest(language->localeID) || !strcmp(language->localeID, "none")) {
00253 UI_AddOption(&languageOption, "", language->localeString, language->localeID);
00254 }
00255 }
00256
00257
00258 UI_SortOptions(&languageOption);
00259 UI_RegisterOption(OPTION_LANGUAGES, languageOption);
00260
00261
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
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 }