2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2008 Blender Foundation.
19 * All rights reserved.
21 * Contributor(s): Blender Foundation.
23 * ***** END GPL LICENSE BLOCK *****
26 /** \file blender/blenfont/intern/blf_lang.c
35 #include "BKE_global.h"
38 #include "BLF_translation.h" /* own include */
40 #ifdef WITH_INTERNATIONAL
46 #include "DNA_userdef_types.h"
48 #include "RNA_types.h"
50 #include "MEM_guardedalloc.h"
52 #include "BLI_string.h"
53 #include "BLI_utildefines.h"
54 #include "BLI_path_util.h"
55 #include "BLI_fileops.h"
56 #include "BLI_linklist.h"
57 #include "BLI_string.h"
59 #define SYSTEM_ENCODING_DEFAULT "UTF-8"
60 #define FONT_SIZE_DEFAULT 12
63 static char global_messagepath[1024];
64 static char global_language[32];
65 static char global_encoding_name[32];
67 static const char **locales = NULL;
68 static int num_locales = 0;
69 static EnumPropertyItem *locales_menu = NULL;
70 static int num_locales_menu = 0;
72 #define ULANGUAGE ((U.language >= 0 && U.language < num_locales) ? U.language : 0)
73 #define LOCALE(_id) (locales ? locales[_id] : "")
75 static void free_locales(void)
78 int idx = num_locales_menu - 1; /* Last item does not need to be freed! */
80 MEM_freeN((void*)locales_menu[idx].identifier);
81 MEM_freeN((void*)locales_menu[idx].name);
82 MEM_freeN((void*)locales_menu[idx].description); /* Also frees locales's relevant value! */
88 MEM_freeN(locales_menu);
91 num_locales = num_locales_menu = 0;
94 static void fill_locales(void)
96 char *languages_path = BLI_get_folder(BLENDER_DATAFILES, "locale");
97 LinkNode *lines = NULL, *line;
103 BLI_join_dirfile(languages_path, FILE_MAX, languages_path, "languages");
104 line = lines = BLI_file_read_as_lines(languages_path);
106 /* This whole "parsing" code is a bit weak, in that it expects strictly formated input file...
107 * Should not be a problem, though, as this file is script-generated! */
109 /* First loop to find highest locale ID */
112 str = (char*) line->link;
113 if (str[0] == '#' || str[0] == '\0') {
115 continue; /* Comment or void... */
118 if (t >= num_locales)
123 num_locales_menu++; /* The "closing" void item... */
125 /* And now, buil locales and locale_menu! */
126 locales_menu = MEM_callocN(num_locales_menu * sizeof(EnumPropertyItem), __func__);
128 /* Do not allocate locales with zero-sized mem, as LOCALE macro uses NULL locales as invalid marker! */
129 if (num_locales > 0) {
130 locales = MEM_callocN(num_locales * sizeof(char*), __func__);
133 char *loc, *sep1, *sep2;
135 str = (char*) line->link;
136 if (str[0] == '#' || str[0] == '\0') {
142 sep1 = strchr(str, ':');
145 sep2 = strchr(sep1, ':');
148 locales_menu[idx].value = id;
149 locales_menu[idx].icon = 0;
150 locales_menu[idx].name = BLI_strdupn(sep1, sep2 - sep1);
151 locales_menu[idx].identifier = loc = BLI_strdup(sep2 + 1);
153 /* The DEFAULT item... */
154 if (BLI_strnlen(loc, 2))
155 locales[id] = locales_menu[idx].description = BLI_strdup("");
156 /* Menu "label", not to be stored in locales! */
158 locales_menu[idx].description = BLI_strdup("");
161 locales[id] = locales_menu[idx].description = BLI_strdup(loc);
171 /* Add closing item to menu! */
172 locales_menu[idx].identifier = NULL;
173 locales_menu[idx].value = locales_menu[idx].icon = 0;
174 locales_menu[idx].name = locales_menu[idx].description = "";
176 BLI_file_free_lines(lines);
179 EnumPropertyItem *BLF_RNA_lang_enum_properties(void)
184 void BLF_lang_init(void)
186 char *messagepath = BLI_get_folder(BLENDER_DATAFILES, "locale");
188 BLI_strncpy(global_encoding_name, SYSTEM_ENCODING_DEFAULT, sizeof(global_encoding_name));
191 BLI_strncpy(global_messagepath, messagepath, sizeof(global_messagepath));
195 printf("%s: 'locale' data path for translations not found, continuing\n", __func__);
196 global_messagepath[0] = '\0';
200 void BLF_lang_free(void)
205 /* Get LANG/LANGUAGE environment variable. */
206 static void get_language_variable(const char *varname, char *var, const size_t maxlen)
208 char *env = getenv(varname);
213 /* Store defaul locale. */
214 BLI_strncpy(var, env, maxlen);
216 /* Use first language as default. */
217 s = strchr(var, ':');
223 /* Get language to be used based on locale (which might be empty when using default language) and
224 * LANG environment variable.
226 static void get_language(const char *locale, const char *lang, char *language, const size_t maxlen)
229 BLI_strncpy(language, locale, maxlen);
234 BLI_strncpy(language, lang, maxlen);
236 s = strchr(language, '.');
242 /* XXX WARNING!!! In osx somehow the previous function call jumps in this one??? (ton, ppc) */
243 void BLF_lang_set(const char *str)
246 const char *short_locale;
248 int ulang = ULANGUAGE;
250 if ((U.transopts & USER_DOTRANSLATE) == 0)
256 short_locale = LOCALE(ulang);
258 #if defined(_WIN32) && !defined(FREE_WINDOWS)
263 if (ulang) /* Use system setting. */
264 envStr = BLI_sprintfN("LANG=%s", getenv("LANG"));
266 envStr = BLI_sprintfN("LANG=%s", short_locale);
268 gettext_putenv(envStr);
272 locreturn = setlocale(LC_ALL, short_locale);
274 if (locreturn == NULL) {
275 if (G.debug & G_DEBUG)
276 printf("Could not change locale to %s\n", short_locale);
283 static char default_lang[64] = "\0";
284 static char default_language[64] = "\0";
286 if (default_lang[0] == 0)
287 get_language_variable("LANG", default_lang, sizeof(default_lang));
289 if (default_language[0] == 0)
290 get_language_variable("LANGUAGE", default_language, sizeof(default_language));
292 if (short_locale[0]) {
293 char *short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale);
295 if (G.debug & G_DEBUG)
296 printf("Setting LANG and LANGUAGE to %s\n", short_locale_utf8);
298 locreturn = setlocale(LC_ALL, short_locale_utf8);
300 if (locreturn != NULL) {
301 BLI_setenv("LANG", short_locale_utf8);
302 BLI_setenv("LANGUAGE", short_locale_utf8);
305 if (G.debug & G_DEBUG)
306 printf("Setting LANG and LANGUAGE to %s\n", short_locale);
308 locreturn = setlocale(LC_ALL, short_locale);
310 if (locreturn != NULL) {
311 BLI_setenv("LANG", short_locale);
312 BLI_setenv("LANGUAGE", short_locale);
316 if (G.debug & G_DEBUG && locreturn == NULL)
317 printf("Could not change locale to %s nor %s\n", short_locale, short_locale_utf8);
319 MEM_freeN(short_locale_utf8);
322 if (G.debug & G_DEBUG)
323 printf("Setting LANG=%s and LANGUAGE=%s\n", default_lang, default_language);
325 BLI_setenv("LANG", default_lang);
326 BLI_setenv("LANGUAGE", default_language);
327 locreturn = setlocale(LC_ALL, "");
329 if (G.debug & G_DEBUG && locreturn == NULL)
330 printf("Could not reset locale\n");
333 if (locreturn == NULL) {
336 get_language(short_locale, default_lang, language, sizeof(language));
338 if (G.debug & G_DEBUG)
339 printf("Fallback to LANG=%s and LANGUAGE=%s\n", default_lang, language);
341 /* Fallback to default settings. */
342 BLI_setenv("LANG", default_lang);
343 BLI_setenv("LANGUAGE", language);
345 locreturn = setlocale(LC_ALL, "");
353 /*printf("Change locale to %s\n", locreturn ); */
354 BLI_strncpy(global_language, locreturn, sizeof(global_language));
357 setlocale(LC_NUMERIC, "C");
359 textdomain(TEXT_DOMAIN_NAME);
360 bindtextdomain(TEXT_DOMAIN_NAME, global_messagepath);
361 bind_textdomain_codeset(TEXT_DOMAIN_NAME, global_encoding_name);
364 const char *BLF_lang_get(void)
366 int uilang = ULANGUAGE;
367 return LOCALE(uilang);
370 void BLF_lang_encoding(const char *str)
372 BLI_strncpy(global_encoding_name, str, sizeof(global_encoding_name));
373 /* bind_textdomain_codeset(TEXT_DOMAIN_NAME, encoding_name); */
379 #else /* ! WITH_INTERNATIONAL */
381 void BLF_lang_init(void)
386 void BLF_lang_free(void)
391 void BLF_lang_encoding(const char *str)
397 void BLF_lang_set(const char *str)
403 const char *BLF_lang_get(void)
408 #endif /* WITH_INTERNATIONAL */