diff options
Diffstat (limited to 'source/blender/blentranslation')
-rw-r--r-- | source/blender/blentranslation/BLT_lang.h | 69 | ||||
-rw-r--r-- | source/blender/blentranslation/BLT_translation.h | 206 | ||||
-rw-r--r-- | source/blender/blentranslation/CMakeLists.txt | 56 | ||||
-rw-r--r-- | source/blender/blentranslation/SConscript | 46 | ||||
-rw-r--r-- | source/blender/blentranslation/intern/blt_lang.c | 356 | ||||
-rw-r--r-- | source/blender/blentranslation/intern/blt_translation.c | 185 |
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 +} |