Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2015-08-16 10:32:01 +0300
committerCampbell Barton <ideasman42@gmail.com>2015-08-18 00:01:26 +0300
commit2e2dc9b9e32d104a0f7c3241ea0c11b57a37fd5b (patch)
treea6830032130d13dcbfa522ed6889fe6f141f99f3 /source/blender/blentranslation
parent3047b96eaa962fe45d2333f5ea4be809e02787cd (diff)
Refactor translation code out of blenfont
- Add blentranslation `BLT_*` module. - moved & split `BLF_translation.h` into (`BLT_translation.h`, `BLT_lang.h`). - moved `BLF_*_unifont` functions from `blf_translation.c` to new source file `blf_font_i18n.c`.
Diffstat (limited to 'source/blender/blentranslation')
-rw-r--r--source/blender/blentranslation/BLT_lang.h69
-rw-r--r--source/blender/blentranslation/BLT_translation.h206
-rw-r--r--source/blender/blentranslation/CMakeLists.txt56
-rw-r--r--source/blender/blentranslation/SConscript46
-rw-r--r--source/blender/blentranslation/intern/blt_lang.c356
-rw-r--r--source/blender/blentranslation/intern/blt_translation.c185
6 files changed, 918 insertions, 0 deletions
diff --git a/source/blender/blentranslation/BLT_lang.h b/source/blender/blentranslation/BLT_lang.h
new file mode 100644
index 00000000000..0f9bac936c3
--- /dev/null
+++ b/source/blender/blentranslation/BLT_lang.h
@@ -0,0 +1,69 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenfont/BLT_lang.h
+ * \ingroup blt
+ */
+
+#ifndef __BLT_LANG_H__
+#define __BLT_LANG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Search the path directory to the locale files, this try all
+ * the case for Linux, Win and Mac.
+ * Also dynamically builds locales and locales' menu from "languages" text file.
+ */
+void BLT_lang_init(void);
+
+/* Free languages and locales_menu arrays created by BLT_lang_init. */
+void BLT_lang_free(void);
+
+/* Set the current locale. */
+void BLT_lang_set(const char *);
+/* Get the current locale ([partial] ISO code, e.g. es_ES). */
+const char *BLT_lang_get(void);
+
+/* Get locale's elements (if relevant pointer is not NULL and element actually exists, e.g. if there is no variant,
+ * *variant and *language_variant will always be NULL).
+ * Non-null elements are always MEM_mallocN'ed, it's the caller's responsibility to free them.
+ * NOTE: Always available, even in non-WITH_INTERNATIONAL builds.
+ */
+void BLT_lang_locale_explode(
+ const char *locale, char **language, char **country, char **variant,
+ char **language_country, char **language_variant);
+
+/* Get EnumPropertyItem's for translations menu. */
+struct EnumPropertyItem *BLT_lang_RNA_enum_properties(void);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* __BLT_LANG_H__ */
diff --git a/source/blender/blentranslation/BLT_translation.h b/source/blender/blentranslation/BLT_translation.h
new file mode 100644
index 00000000000..66993d79709
--- /dev/null
+++ b/source/blender/blentranslation/BLT_translation.h
@@ -0,0 +1,206 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenfont/BLT_translation.h
+ * \ingroup blt
+ */
+
+
+#ifndef __BLT_TRANSLATION_H__
+#define __BLT_TRANSLATION_H__
+
+#include "BLI_utildefines.h" /* for bool type */
+
+#define TEXT_DOMAIN_NAME "blender"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool BLT_is_default_context(const char *msgctxt);
+const char *BLT_pgettext(const char *msgctxt, const char *msgid);
+
+/* translation */
+bool BLT_translate(void);
+bool BLT_translate_iface(void);
+bool BLT_translate_tooltips(void);
+bool BLT_translate_new_dataname(void);
+const char *BLT_translate_do(const char *msgctxt, const char *msgid);
+const char *BLT_translate_do_iface(const char *msgctxt, const char *msgid);
+const char *BLT_translate_do_tooltip(const char *msgctxt, const char *msgid);
+const char *BLT_translate_do_new_dataname(const char *msgctxt, const char *msgid);
+
+
+/* The "translation-marker" macro. */
+#define N_(msgid) msgid
+#define CTX_N_(context, msgid) msgid
+
+/* Those macros should be used everywhere in UI code. */
+#ifdef WITH_INTERNATIONAL
+/*# define _(msgid) BLT_gettext(msgid) */
+# define IFACE_(msgid) BLT_translate_do_iface(NULL, msgid)
+# define TIP_(msgid) BLT_translate_do_tooltip(NULL, msgid)
+# define DATA_(msgid) BLT_translate_do_new_dataname(NULL, msgid)
+# define CTX_IFACE_(context, msgid) BLT_translate_do_iface(context, msgid)
+# define CTX_TIP_(context, msgid) BLT_translate_do_tooltip(context, msgid)
+# define CTX_DATA_(context, msgid) BLT_translate_do_new_dataname(context, msgid)
+#else
+/*# define _(msgid) msgid */
+# define IFACE_(msgid) msgid
+# define TIP_(msgid) msgid
+# define DATA_(msgid) msgid
+# define CTX_IFACE_(context, msgid) msgid
+# define CTX_TIP_(context, msgid) msgid
+# define CTX_DATA_(context, msgid) msgid
+#endif
+
+/* Helper macro, when we want to define a same msgid for multiple msgctxt...
+ * Does nothing in C, but is "parsed" by our i18n py tools.
+ * XXX Currently limited to at most 16 contexts at once
+ * (but you can call it several times with the same msgid, should you need more contexts!).
+ */
+#define BLT_I18N_MSGID_MULTI_CTXT(msgid, ...)
+
+/******************************************************************************
+ * All i18n contexts must be defined here.
+ * This is a nice way to be sure not to use a context twice for different
+ * things, and limit the number of existing contexts!
+ * WARNING! Contexts should not be longer than BKE_ST_MAXNAME - 1!
+ */
+
+/* Default, void context.
+ * WARNING! The "" context is not the same as no (NULL) context at mo/boost::locale level!
+ * NOTE: We translate BLT_I18NCONTEXT_DEFAULT as BLT_I18NCONTEXT_DEFAULT_BPY in Python, as we can't use "natural"
+ * None value in rna string properties... :/
+ * The void string "" is also interpreted as BLT_I18NCONTEXT_DEFAULT.
+ * For perf reason, we only use the first char to detect this context, so other contexts should never start
+ * with the same char!
+ */
+#define BLT_I18NCONTEXT_DEFAULT NULL
+#define BLT_I18NCONTEXT_DEFAULT_BPYRNA "*"
+
+/* Default context for operator names/labels. */
+#define BLT_I18NCONTEXT_OPERATOR_DEFAULT "Operator"
+
+/* Mark the msgid applies to several elements (needed in some cases, as english adjectives have no plural mark. :( */
+#define BLT_I18NCONTEXT_PLURAL "Plural"
+
+/* ID-types contexts. */
+/* WARNING! Keep it in sync with idtypes in blenkernel/intern/idcode.c */
+#define BLT_I18NCONTEXT_ID_ACTION "Action"
+#define BLT_I18NCONTEXT_ID_ARMATURE "Armature"
+#define BLT_I18NCONTEXT_ID_BRUSH "Brush"
+#define BLT_I18NCONTEXT_ID_CAMERA "Camera"
+#define BLT_I18NCONTEXT_ID_CURVE "Curve"
+#define BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE "FreestyleLineStyle"
+#define BLT_I18NCONTEXT_ID_GPENCIL "GPencil"
+#define BLT_I18NCONTEXT_ID_GROUP "Group"
+#define BLT_I18NCONTEXT_ID_ID "ID"
+#define BLT_I18NCONTEXT_ID_IMAGE "Image"
+/*#define BLT_I18NCONTEXT_ID_IPO "Ipo"*/ /* Deprecated */
+#define BLT_I18NCONTEXT_ID_SHAPEKEY "Key"
+#define BLT_I18NCONTEXT_ID_LAMP "Lamp"
+#define BLT_I18NCONTEXT_ID_LIBRARY "Library"
+#define BLT_I18NCONTEXT_ID_LATTICE "Lattice"
+#define BLT_I18NCONTEXT_ID_MATERIAL "Material"
+#define BLT_I18NCONTEXT_ID_METABALL "Metaball"
+#define BLT_I18NCONTEXT_ID_MESH "Mesh"
+#define BLT_I18NCONTEXT_ID_NODETREE "NodeTree"
+#define BLT_I18NCONTEXT_ID_OBJECT "Object"
+#define BLT_I18NCONTEXT_ID_PAINTCURVE "PaintCurve"
+#define BLT_I18NCONTEXT_ID_PALETTE "Palette"
+#define BLT_I18NCONTEXT_ID_PARTICLESETTINGS "ParticleSettings"
+#define BLT_I18NCONTEXT_ID_SCENE "Scene"
+#define BLT_I18NCONTEXT_ID_SCREEN "Screen"
+#define BLT_I18NCONTEXT_ID_SEQUENCE "Sequence"
+#define BLT_I18NCONTEXT_ID_SPEAKER "Speaker"
+#define BLT_I18NCONTEXT_ID_SOUND "Sound"
+#define BLT_I18NCONTEXT_ID_TEXTURE "Texture"
+#define BLT_I18NCONTEXT_ID_TEXT "Text"
+#define BLT_I18NCONTEXT_ID_VFONT "VFont"
+#define BLT_I18NCONTEXT_ID_WORLD "World"
+#define BLT_I18NCONTEXT_ID_WINDOWMANAGER "WindowManager"
+#define BLT_I18NCONTEXT_ID_MOVIECLIP "MovieClip"
+#define BLT_I18NCONTEXT_ID_MASK "Mask"
+
+/* Helper for bpy.app.i18n object... */
+typedef struct {
+ const char *c_id;
+ const char *py_id;
+ const char *value;
+} BLT_i18n_contexts_descriptor;
+
+#define BLT_I18NCONTEXTS_ITEM(ctxt_id, py_id) {#ctxt_id, py_id, ctxt_id}
+
+#define BLT_I18NCONTEXTS_DESC { \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_DEFAULT, "default_real"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_DEFAULT_BPYRNA, "default"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "operator_default"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_PLURAL, "plural"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_ACTION, "id_action"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_ARMATURE, "id_armature"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_BRUSH, "id_brush"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CAMERA, "id_camera"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CURVE, "id_curve"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE, "id_fs_linestyle"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_GPENCIL, "id_gpencil"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_GROUP, "id_group"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_ID, "id_id"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_IMAGE, "id_image"), \
+ /*BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_IPO, "id_ipo"),*/ \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SHAPEKEY, "id_shapekey"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_LAMP, "id_lamp"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_LIBRARY, "id_library"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_LATTICE, "id_lattice"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_MASK, "id_mask"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_MATERIAL, "id_material"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_METABALL, "id_metaball"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_MESH, "id_mesh"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_MOVIECLIP, "id_movieclip"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_NODETREE, "id_nodetree"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_OBJECT, "id_object"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_PAINTCURVE, "id_paintcurve"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_PALETTE, "id_palette"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_PARTICLESETTINGS, "id_particlesettings"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SCENE, "id_scene"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SCREEN, "id_screen"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SEQUENCE, "id_sequence"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SPEAKER, "id_speaker"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SOUND, "id_sound"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_TEXTURE, "id_texture"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_TEXT, "id_text"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_VFONT, "id_vfont"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_WORLD, "id_world"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_WINDOWMANAGER, "id_windowmanager"), \
+ {NULL, NULL, NULL} \
+}
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* __BLT_TRANSLATION_H__ */
diff --git a/source/blender/blentranslation/CMakeLists.txt b/source/blender/blentranslation/CMakeLists.txt
new file mode 100644
index 00000000000..59bd7f0adfa
--- /dev/null
+++ b/source/blender/blentranslation/CMakeLists.txt
@@ -0,0 +1,56 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2008, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ ../blenkernel
+ ../blenlib
+ ../makesdna
+ ../makesrna
+ ../../../intern/guardedalloc
+ ../../../intern/locale
+)
+
+set(INC_SYS
+)
+
+set(SRC
+ intern/blt_lang.c
+ intern/blt_translation.c
+
+ BLT_lang.h
+ BLT_translation.h
+)
+
+if(WITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
+if(WITH_PYTHON)
+ add_definitions(-DWITH_PYTHON)
+ list(APPEND INC
+ ../python
+ )
+endif()
+
+blender_add_lib(bf_blentranslation "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/blentranslation/SConscript b/source/blender/blentranslation/SConscript
new file mode 100644
index 00000000000..c7e9853618c
--- /dev/null
+++ b/source/blender/blentranslation/SConscript
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+import sys
+Import ('env')
+
+sources = env.Glob('intern/*.c')
+
+incs = [
+ '.',
+ '#/intern/guardedalloc',
+ '#/intern/locale',
+ '../blenkernel',
+ '../blenlib',
+ '../blentranslation',
+ '../makesdna',
+ '../makesrna',
+ ]
+
+defs = []
+
+if env['WITH_BF_INTERNATIONAL']:
+ defs.append('WITH_INTERNATIONAL')
+
+if env['WITH_BF_PYTHON']:
+ defs.append('WITH_PYTHON')
+ incs.append('../python')
+
+env.BlenderLib('bf_blentranslation', sources, incs, defines=defs, libtype=['core', 'player'], priority=[211, 211])
diff --git a/source/blender/blentranslation/intern/blt_lang.c b/source/blender/blentranslation/intern/blt_lang.c
new file mode 100644
index 00000000000..a0e1fe67268
--- /dev/null
+++ b/source/blender/blentranslation/intern/blt_lang.c
@@ -0,0 +1,356 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenfont/intern/blt_lang.c
+ * \ingroup blt
+ *
+ * Main internationalization functions to set the locale and query available languages.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef _WIN32
+# include <locale.h>
+#endif
+
+#include "RNA_types.h"
+
+#include "BLT_translation.h"
+#include "BLT_lang.h" /* own include */
+
+#include "BLI_fileops.h"
+#include "BLI_linklist.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+
+#include "BKE_appdir.h"
+
+#include "DNA_userdef_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#ifdef WITH_INTERNATIONAL
+
+#include "boost_locale_wrapper.h"
+
+/* Locale options. */
+static const char **locales = NULL;
+static int num_locales = 0;
+static EnumPropertyItem *locales_menu = NULL;
+static int num_locales_menu = 0;
+
+static void free_locales(void)
+{
+ if (locales) {
+ int idx = num_locales_menu - 1; /* Last item does not need to be freed! */
+ while (idx--) {
+ MEM_freeN((void *)locales_menu[idx].identifier);
+ MEM_freeN((void *)locales_menu[idx].name);
+ MEM_freeN((void *)locales_menu[idx].description); /* Also frees locales's relevant value! */
+ }
+
+ MEM_freeN((void *)locales);
+ locales = NULL;
+ }
+ if (locales_menu) {
+ MEM_freeN(locales_menu);
+ locales_menu = NULL;
+ }
+ num_locales = num_locales_menu = 0;
+}
+
+static void fill_locales(void)
+{
+ const char * const languages_path = BKE_appdir_folder_id(BLENDER_DATAFILES, "locale");
+ char languages[FILE_MAX];
+ LinkNode *lines = NULL, *line;
+ char *str;
+ int idx = 0;
+
+ free_locales();
+
+ BLI_join_dirfile(languages, FILE_MAX, languages_path, "languages");
+ line = lines = BLI_file_read_as_lines(languages);
+
+ /* This whole "parsing" code is a bit weak, in that it expects strictly formated input file...
+ * Should not be a problem, though, as this file is script-generated! */
+
+ /* First loop to find highest locale ID */
+ while (line) {
+ int t;
+ str = (char *)line->link;
+ if (str[0] == '#' || str[0] == '\0') {
+ line = line->next;
+ continue; /* Comment or void... */
+ }
+ t = atoi(str);
+ if (t >= num_locales)
+ num_locales = t + 1;
+ num_locales_menu++;
+ line = line->next;
+ }
+ num_locales_menu++; /* The "closing" void item... */
+
+ /* And now, build locales and locale_menu! */
+ locales_menu = MEM_callocN(num_locales_menu * sizeof(EnumPropertyItem), __func__);
+ line = lines;
+ /* Do not allocate locales with zero-sized mem, as LOCALE macro uses NULL locales as invalid marker! */
+ if (num_locales > 0) {
+ locales = MEM_callocN(num_locales * sizeof(char *), __func__);
+ while (line) {
+ int id;
+ char *loc, *sep1, *sep2, *sep3;
+
+ str = (char *)line->link;
+ if (str[0] == '#' || str[0] == '\0') {
+ line = line->next;
+ continue;
+ }
+
+ id = atoi(str);
+ sep1 = strchr(str, ':');
+ if (sep1) {
+ sep1++;
+ sep2 = strchr(sep1, ':');
+ if (sep2) {
+ locales_menu[idx].value = id;
+ locales_menu[idx].icon = 0;
+ locales_menu[idx].name = BLI_strdupn(sep1, sep2 - sep1);
+
+ sep2++;
+ sep3 = strchr(sep2, ':');
+
+ if (sep3) {
+ locales_menu[idx].identifier = loc = BLI_strdupn(sep2, sep3 - sep2);
+ }
+ else {
+ locales_menu[idx].identifier = loc = BLI_strdup(sep2);
+ }
+
+ if (id == 0) {
+ /* The DEFAULT item... */
+ if (BLI_strnlen(loc, 2)) {
+ locales[id] = locales_menu[idx].description = BLI_strdup("");
+ }
+ /* Menu "label", not to be stored in locales! */
+ else {
+ locales_menu[idx].description = BLI_strdup("");
+ }
+ }
+ else {
+ locales[id] = locales_menu[idx].description = BLI_strdup(loc);
+ }
+ idx++;
+ }
+ }
+
+ line = line->next;
+ }
+ }
+
+ /* Add closing item to menu! */
+ locales_menu[idx].identifier = NULL;
+ locales_menu[idx].value = locales_menu[idx].icon = 0;
+ locales_menu[idx].name = locales_menu[idx].description = "";
+
+ BLI_file_free_lines(lines);
+}
+#endif /* WITH_INTERNATIONAL */
+
+EnumPropertyItem *BLT_lang_RNA_enum_properties(void)
+{
+#ifdef WITH_INTERNATIONAL
+ return locales_menu;
+#else
+ return NULL;
+#endif
+}
+
+void BLT_lang_init(void)
+{
+#ifdef WITH_INTERNATIONAL
+ const char * const messagepath = BKE_appdir_folder_id(BLENDER_DATAFILES, "locale");
+#endif
+
+ /* Make sure LANG is correct and wouldn't cause std::rumtime_error. */
+#ifndef _WIN32
+ /* TODO(sergey): This code only ensures LANG is set properly, so later when
+ * Cycles will try to use file system API from boost there'll be no runtime
+ * exception generated by std::locale() which _requires_ having proper LANG
+ * set in the environment.
+ *
+ * Ideally we also need to ensure LC_ALL, LC_MESSAGES and others are also
+ * set to a proper value, but currently it's not a huge deal and doesn't
+ * cause any headache.
+ *
+ * Would also be good to find nicer way to check if LANG is correct.
+ */
+ const char *lang = getenv("LANG");
+ if (lang != NULL) {
+ char *old_locale = setlocale(LC_ALL, NULL);
+ /* Make a copy so subsequenct setlocale() doesn't interfere. */
+ old_locale = BLI_strdup(old_locale);
+ if (setlocale(LC_ALL, lang) == NULL) {
+ setenv("LANG", "C", 1);
+ printf("Warning: Falling back to the standard locale (\"C\")\n");
+ }
+ setlocale(LC_ALL, old_locale);
+ MEM_freeN(old_locale);
+ }
+#endif
+
+#ifdef WITH_INTERNATIONAL
+ if (messagepath) {
+ bl_locale_init(messagepath, TEXT_DOMAIN_NAME);
+ fill_locales();
+ }
+ else {
+ printf("%s: 'locale' data path for translations not found, continuing\n", __func__);
+ }
+#else
+#endif
+}
+
+void BLT_lang_free(void)
+{
+#ifdef WITH_INTERNATIONAL
+ free_locales();
+#else
+#endif
+}
+
+#ifdef WITH_INTERNATIONAL
+# define ULANGUAGE ((U.language >= 0 && U.language < num_locales) ? U.language : 0)
+# define LOCALE(_id) (locales ? locales[(_id)] : "")
+#endif
+
+void BLT_lang_set(const char *str)
+{
+#ifdef WITH_INTERNATIONAL
+ int ulang = ULANGUAGE;
+ const char *short_locale = str ? str : LOCALE(ulang);
+ const char *short_locale_utf8 = NULL;
+
+ if ((U.transopts & USER_DOTRANSLATE) == 0)
+ return;
+
+ /* We want to avoid locales like '.UTF-8'! */
+ if (short_locale[0]) {
+ /* Hurrey! encoding needs to be placed *before* variant! */
+ char *variant = strchr(short_locale, '@');
+ if (variant) {
+ char *locale = BLI_strdupn(short_locale, variant - short_locale);
+ short_locale_utf8 = BLI_sprintfN("%s.UTF-8%s", locale, variant);
+ MEM_freeN(locale);
+ }
+ else {
+ short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale);
+ }
+ bl_locale_set(short_locale_utf8);
+ MEM_freeN((void *)short_locale_utf8);
+ }
+ else {
+ bl_locale_set(short_locale);
+ }
+#else
+ (void)str;
+#endif
+}
+
+/* Get the current locale (short code, e.g. es_ES). */
+const char *BLT_lang_get(void)
+{
+#ifdef WITH_INTERNATIONAL
+ if (BLT_translate()) {
+ const char *locale = LOCALE(ULANGUAGE);
+ if (locale[0] == '\0') {
+ /* Default locale, we have to find which one we are actually using! */
+ locale = bl_locale_get();
+ }
+ return locale;
+ }
+ return "en_US"; /* Kind of default locale in Blender when no translation enabled. */
+#else
+ return "";
+#endif
+}
+
+#undef LOCALE
+#undef ULANGUAGE
+
+/* Get locale's elements (if relevant pointer is not NULL and element actually exists, e.g. if there is no variant,
+ * *variant and *language_variant will always be NULL).
+ * Non-null elements are always MEM_mallocN'ed, it's the caller's responsibility to free them.
+ * NOTE: Keep that one always available, you never know, may become useful even in no-WITH_INTERNATIONAL context...
+ */
+void BLT_lang_locale_explode(
+ const char *locale, char **language, char **country, char **variant,
+ char **language_country, char **language_variant)
+{
+ char *m1, *m2, *_t = NULL;
+
+ m1 = strchr(locale, '_');
+ m2 = strchr(locale, '@');
+
+ if (language || language_variant) {
+ if (m1 || m2) {
+ _t = m1 ? BLI_strdupn(locale, m1 - locale) : BLI_strdupn(locale, m2 - locale);
+ if (language)
+ *language = _t;
+ }
+ else if (language) {
+ *language = BLI_strdup(locale);
+ }
+ }
+ if (country) {
+ if (m1)
+ *country = m2 ? BLI_strdupn(m1 + 1, m2 - (m1 + 1)) : BLI_strdup(m1 + 1);
+ else
+ *country = NULL;
+ }
+ if (variant) {
+ if (m2)
+ *variant = BLI_strdup(m2 + 1);
+ else
+ *variant = NULL;
+ }
+ if (language_country) {
+ if (m1)
+ *language_country = m2 ? BLI_strdupn(locale, m2 - locale) : BLI_strdup(locale);
+ else
+ *language_country = NULL;
+ }
+ if (language_variant) {
+ if (m2)
+ *language_variant = m1 ? BLI_strdupcat(_t, m2) : BLI_strdup(locale);
+ else
+ *language_variant = NULL;
+ }
+ if (_t && !language) {
+ MEM_freeN(_t);
+ }
+}
diff --git a/source/blender/blentranslation/intern/blt_translation.c b/source/blender/blentranslation/intern/blt_translation.c
new file mode 100644
index 00000000000..2651fbbe1f0
--- /dev/null
+++ b/source/blender/blentranslation/intern/blt_translation.c
@@ -0,0 +1,185 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenfont/intern/blt_translation.c
+ * \ingroup blt
+ *
+ * Manages translation files and provides translation functions.
+ * (which are optional and can be disabled as a preference).
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "BLT_translation.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_fileops.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+
+#include "DNA_userdef_types.h" /* For user settings. */
+
+#ifdef WITH_PYTHON
+#include "BPY_extern.h"
+#endif
+
+#ifdef WITH_INTERNATIONAL
+#include "boost_locale_wrapper.h"
+#endif /* WITH_INTERNATIONAL */
+
+bool BLT_is_default_context(const char *msgctxt)
+{
+ /* We use the "short" test, a more complete one could be:
+ * return (!msgctxt || !msgctxt[0] || STREQ(msgctxt, BLT_I18NCONTEXT_DEFAULT_BPYRNA))
+ */
+ /* Note: trying without the void string check for now, it *should* not be necessary... */
+ return (!msgctxt || msgctxt[0] == BLT_I18NCONTEXT_DEFAULT_BPYRNA[0]);
+}
+
+const char *BLT_pgettext(const char *msgctxt, const char *msgid)
+{
+#ifdef WITH_INTERNATIONAL
+ const char *ret = msgid;
+
+ if (msgid && msgid[0]) {
+ if (BLT_is_default_context(msgctxt)) {
+ msgctxt = BLT_I18NCONTEXT_DEFAULT;
+ }
+ ret = bl_locale_pgettext(msgctxt, msgid);
+ /* We assume if the returned string is the same (memory level) as the msgid, no translation was found,
+ * and we can try py scripts' ones!
+ */
+#ifdef WITH_PYTHON
+ if (ret == msgid) {
+ ret = BPY_app_translations_py_pgettext(msgctxt, msgid);
+ }
+#endif
+ }
+
+ return ret;
+#else
+ (void)msgctxt;
+ return msgid;
+#endif
+}
+
+bool BLT_translate(void)
+{
+#ifdef WITH_INTERNATIONAL
+ return (U.transopts & USER_DOTRANSLATE) != 0;
+#else
+ return false;
+#endif
+}
+
+bool BLT_translate_iface(void)
+{
+#ifdef WITH_INTERNATIONAL
+ return (U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_IFACE);
+#else
+ return false;
+#endif
+}
+
+bool BLT_translate_tooltips(void)
+{
+#ifdef WITH_INTERNATIONAL
+ return (U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_TOOLTIPS);
+#else
+ return false;
+#endif
+}
+
+bool BLT_translate_new_dataname(void)
+{
+#ifdef WITH_INTERNATIONAL
+ return (U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_NEWDATANAME);
+#else
+ return false;
+#endif
+}
+
+const char *BLT_translate_do(const char *msgctxt, const char *msgid)
+{
+#ifdef WITH_INTERNATIONAL
+ if (BLT_translate()) {
+ return BLT_pgettext(msgctxt, msgid);
+ }
+ else {
+ return msgid;
+ }
+#else
+ (void)msgctxt;
+ return msgid;
+#endif
+}
+
+const char *BLT_translate_do_iface(const char *msgctxt, const char *msgid)
+{
+#ifdef WITH_INTERNATIONAL
+ if (BLT_translate_iface()) {
+ return BLT_pgettext(msgctxt, msgid);
+ }
+ else {
+ return msgid;
+ }
+#else
+ (void)msgctxt;
+ return msgid;
+#endif
+}
+
+const char *BLT_translate_do_tooltip(const char *msgctxt, const char *msgid)
+{
+#ifdef WITH_INTERNATIONAL
+ if (BLT_translate_tooltips()) {
+ return BLT_pgettext(msgctxt, msgid);
+ }
+ else {
+ return msgid;
+ }
+#else
+ (void)msgctxt;
+ return msgid;
+#endif
+}
+
+const char *BLT_translate_do_new_dataname(const char *msgctxt, const char *msgid)
+{
+#ifdef WITH_INTERNATIONAL
+ if (BLT_translate_new_dataname()) {
+ return BLT_pgettext(msgctxt, msgid);
+ }
+ else {
+ return msgid;
+ }
+#else
+ (void)msgctxt;
+ return msgid;
+#endif
+}