I18n users request: add the ability to use a translated name for newly added/created objects or other datablocks.

This simply adds a third "translation type" (in addition to iface and tip), "new data", with relevant user settings flag and helper funcs/macros (and py api).

Currently implemented name translation when adding new objects, as well as modifiers and constraints, will add the others (cd layers, scenes, perhaps nodes [though I think they do not need this], etc.) later.
This commit is contained in:
Bastien Montagne 2013-03-20 18:42:09 +00:00
parent e9b0b402cc
commit 885441e758
13 changed files with 144 additions and 75 deletions

@ -528,9 +528,11 @@ class USERPREF_PT_system(Panel):
if system.use_international_fonts:
column.prop(system, "language")
row = column.row()
row.label(text="Translate:")
row.prop(system, "use_translate_interface", text="Interface")
row.prop(system, "use_translate_tooltips", text="Tooltips")
row.label(text="Translate:", text_ctxt=bpy.app.translations.contexts.id_windowmanager)
row = column.row(True)
row.prop(system, "use_translate_interface", text="Interface", toggle=True)
row.prop(system, "use_translate_tooltips", text="Tooltips", toggle=True)
row.prop(system, "use_translate_new_dataname", text="New Data", toggle=True)
class USERPREF_MT_interface_theme_presets(Menu):

@ -77,8 +77,10 @@ const char *BLF_pgettext(const char *msgctxt, const char *msgid);
/* translation */
bool BLF_translate_iface(void);
bool BLF_translate_tooltips(void);
bool BLF_translate_new_dataname(void);
const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid);
const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid);
const char *BLF_translate_do_new_dataname(const char *msgctxt, const char *msgid);
/* The "translation-marker" macro. */
@ -90,14 +92,18 @@ const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid);
/*# define _(msgid) BLF_gettext(msgid) */
# define IFACE_(msgid) BLF_translate_do_iface(NULL, msgid)
# define TIP_(msgid) BLF_translate_do_tooltip(NULL, msgid)
# define DATA_(msgid) BLF_translate_do_new_dataname(NULL, msgid)
# define CTX_IFACE_(context, msgid) BLF_translate_do_iface(context, msgid)
# define CTX_TIP_(context, msgid) BLF_translate_do_tooltip(context, msgid)
# define CTX_DATA_(context, msgid) BLF_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...

@ -177,6 +177,15 @@ bool BLF_translate_tooltips(void)
#endif
}
bool BLF_translate_new_dataname(void)
{
#ifdef WITH_INTERNATIONAL
return (U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_NEWDATANAME);
#else
return false;
#endif
}
const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid)
{
#ifdef WITH_INTERNATIONAL
@ -206,3 +215,18 @@ const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid)
return msgid;
#endif
}
const char *BLF_translate_do_new_dataname(const char *msgctxt, const char *msgid)
{
#ifdef WITH_INTERNATIONAL
if (BLF_translate_new_dataname()) {
return BLF_pgettext(msgctxt, msgid);
}
else {
return msgid;
}
#else
(void)msgctxt;
return msgid;
#endif
}

@ -43,6 +43,8 @@
#include "BLI_kdopbvh.h"
#include "BLI_utildefines.h"
#include "BLF_translation.h"
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
#include "DNA_constraint_types.h"
@ -4353,12 +4355,12 @@ static bConstraint *add_new_constraint_internal(const char *name, short type)
cti->new_data(con->data);
/* if no name is provided, use the type of the constraint as the name */
newName = (name && name[0]) ? name : cti->name;
newName = (name && name[0]) ? name : DATA_(cti->name);
}
else {
/* if no name is provided, use the generic "Const" name */
/* NOTE: any constraint type that gets here really shouldn't get added... */
newName = (name && name[0]) ? name : "Const";
newName = (name && name[0]) ? name : DATA_("Const");
}
/* copy the name */

@ -95,7 +95,7 @@ ModifierData *modifier_new(int type)
ModifierData *md = MEM_callocN(mti->structSize, mti->structName);
/* note, this name must be made unique later */
BLI_strncpy(md->name, mti->name, sizeof(md->name));
BLI_strncpy(md->name, DATA_(mti->name), sizeof(md->name));
md->type = type;
md->mode = eModifierMode_Realtime | eModifierMode_Render | eModifierMode_Expanded;

@ -65,6 +65,8 @@
#include "BLI_utildefines.h"
#include "BLI_linklist.h"
#include "BLF_translation.h"
#include "BKE_pbvh.h"
#include "BKE_main.h"
#include "BKE_global.h"
@ -855,20 +857,20 @@ void *BKE_object_obdata_add_from_type(int type)
static const char *get_obdata_defname(int type)
{
switch (type) {
case OB_MESH: return "Mesh";
case OB_CURVE: return "Curve";
case OB_SURF: return "Surf";
case OB_FONT: return "Text";
case OB_MBALL: return "Mball";
case OB_CAMERA: return "Camera";
case OB_LAMP: return "Lamp";
case OB_LATTICE: return "Lattice";
case OB_ARMATURE: return "Armature";
case OB_SPEAKER: return "Speaker";
case OB_EMPTY: return "Empty";
case OB_MESH: return DATA_("Mesh");
case OB_CURVE: return DATA_("Curve");
case OB_SURF: return DATA_("Surf");
case OB_FONT: return DATA_("Text");
case OB_MBALL: return DATA_("Mball");
case OB_CAMERA: return DATA_("Camera");
case OB_LAMP: return DATA_("Lamp");
case OB_LATTICE: return DATA_("Lattice");
case OB_ARMATURE: return DATA_("Armature");
case OB_SPEAKER: return DATA_("Speaker");
case OB_EMPTY: return DATA_("Empty");
default:
printf("get_obdata_defname: Internal error, bad type: %d\n", type);
return "Empty";
return DATA_("Empty");
}
}

@ -56,6 +56,8 @@
#include "BLI_threads.h"
#include "BLI_linklist.h"
#include "BLF_translation.h"
#include "BKE_anim.h"
#include "BKE_animsys.h"
@ -3488,17 +3490,19 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n
psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
BLI_addtail(&ob->particlesystem, psys);
psys->part = psys_new_settings("ParticleSettings", NULL);
psys->part = psys_new_settings(DATA_("ParticleSettings"), NULL);
if (BLI_countlist(&ob->particlesystem) > 1)
BLI_snprintf(psys->name, sizeof(psys->name), "ParticleSystem %i", BLI_countlist(&ob->particlesystem));
BLI_snprintf(psys->name, sizeof(psys->name), DATA_("ParticleSystem %i"), BLI_countlist(&ob->particlesystem));
else
strcpy(psys->name, "ParticleSystem");
strcpy(psys->name, DATA_("ParticleSystem"));
md = modifier_new(eModifierType_ParticleSystem);
if (name) BLI_strncpy_utf8(md->name, name, sizeof(md->name));
else BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", BLI_countlist(&ob->particlesystem));
if (name)
BLI_strncpy_utf8(md->name, name, sizeof(md->name));
else
BLI_snprintf(md->name, sizeof(md->name), DATA_("ParticleSystem %i"), BLI_countlist(&ob->particlesystem));
modifier_unique_name(&ob->modifiers, md);
psmd = (ParticleSystemModifierData *) md;

@ -6150,20 +6150,20 @@ static const char *get_curve_defname(int type)
if ((type & CU_TYPE) == CU_BEZIER) {
switch (stype) {
case CU_PRIM_CURVE: return "BezierCurve";
case CU_PRIM_CIRCLE: return "BezierCircle";
case CU_PRIM_PATH: return "CurvePath";
case CU_PRIM_CURVE: return DATA_("BezierCurve");
case CU_PRIM_CIRCLE: return DATA_("BezierCircle");
case CU_PRIM_PATH: return DATA_("CurvePath");
default:
return "Curve";
return DATA_("Curve");
}
}
else {
switch (stype) {
case CU_PRIM_CURVE: return "NurbsCurve";
case CU_PRIM_CIRCLE: return "NurbsCircle";
case CU_PRIM_PATH: return "NurbsPath";
case CU_PRIM_CURVE: return DATA_("NurbsCurve");
case CU_PRIM_CIRCLE: return DATA_("NurbsCircle");
case CU_PRIM_PATH: return DATA_("NurbsPath");
default:
return "Curve";
return DATA_("Curve");
}
}
}
@ -6173,13 +6173,13 @@ static const char *get_surf_defname(int type)
int stype = type & CU_PRIMITIVE;
switch (stype) {
case CU_PRIM_CURVE: return "SurfCurve";
case CU_PRIM_CIRCLE: return "SurfCircle";
case CU_PRIM_PATCH: return "SurfPatch";
case CU_PRIM_SPHERE: return "SurfSphere";
case CU_PRIM_DONUT: return "SurfTorus";
case CU_PRIM_CURVE: return DATA_("SurfCurve");
case CU_PRIM_CIRCLE: return DATA_("SurfCircle");
case CU_PRIM_PATCH: return DATA_("SurfPatch");
case CU_PRIM_SPHERE: return DATA_("SurfSphere");
case CU_PRIM_DONUT: return DATA_("SurfTorus");
default:
return "Surface";
return DATA_("Surface");
}
}

@ -34,6 +34,8 @@
#include "BLI_math.h"
#include "BLF_translation.h"
#include "BKE_context.h"
#include "BKE_library.h"
#include "BKE_tessmesh.h"
@ -106,7 +108,7 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op)
unsigned int layer;
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, "Plane", &dia, mat, &state, loc, rot, layer);
obedit = make_prim_init(C, DATA_("Plane"), &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(em, op, "verts.out",
@ -147,7 +149,7 @@ static int add_primitive_cube_exec(bContext *C, wmOperator *op)
unsigned int layer;
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, "Cube", &dia, mat, &state, loc, rot, layer);
obedit = make_prim_init(C, DATA_("Cube"), &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(em, op, "verts.out", "create_cube matrix=%m4 size=%f", mat, dia * 2.0f)) {
@ -196,7 +198,7 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op)
cap_tri = (cap_end == 2);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, "Circle", &dia, mat, &state, loc, rot, layer);
obedit = make_prim_init(C, DATA_("Circle"), &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(em, op, "verts.out",
@ -251,7 +253,7 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
cap_tri = (cap_end == 2);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, "Cylinder", &dia, mat, &state, loc, rot, layer);
obedit = make_prim_init(C, DATA_("Cylinder"), &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(
@ -312,7 +314,7 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op)
cap_tri = (cap_end == 2);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, "Cone", &dia, mat, &state, loc, rot, layer);
obedit = make_prim_init(C, DATA_("Cone"), &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(
@ -369,7 +371,7 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op)
unsigned int layer;
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, "Grid", &dia, mat, &state, loc, rot, layer);
obedit = make_prim_init(C, DATA_("Grid"), &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(em, op, "verts.out",
@ -425,7 +427,7 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
if (!view_aligned)
rot[0] += (float)M_PI / 2.0f;
obedit = make_prim_init(C, "Suzanne", &dia, mat, &state, loc, rot, layer);
obedit = make_prim_init(C, DATA_("Suzanne"), &dia, mat, &state, loc, rot, layer);
mat[0][0] *= dia;
mat[1][1] *= dia;
mat[2][2] *= dia;
@ -468,7 +470,7 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
unsigned int layer;
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, "Sphere", &dia, mat, &state, loc, rot, layer);
obedit = make_prim_init(C, DATA_("Sphere"), &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(em, op, "verts.out",
@ -520,7 +522,7 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
unsigned int layer;
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, "Icosphere", &dia, mat, &state, loc, rot, layer);
obedit = make_prim_init(C, DATA_("Icosphere"), &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(

@ -452,7 +452,7 @@ static int effector_add_exec(bContext *C, wmOperator *op)
if (!ob)
return OPERATOR_CANCELLED;
rename_id(&ob->id, "CurveGuide");
rename_id(&ob->id, DATA_("CurveGuide"));
((Curve *)ob->data)->flag |= CU_PATH | CU_3D;
ED_object_enter_editmode(C, 0);
ED_object_new_primitive_matrix(C, ob, loc, rot, mat, FALSE);
@ -465,7 +465,7 @@ static int effector_add_exec(bContext *C, wmOperator *op)
if (!ob)
return OPERATOR_CANCELLED;
rename_id(&ob->id, "Field");
rename_id(&ob->id, DATA_("Field"));
if (ELEM(type, PFIELD_WIND, PFIELD_VORTEX))
ob->empty_drawtype = OB_SINGLE_ARROW;
}
@ -822,13 +822,13 @@ void OBJECT_OT_drop_named_image(wmOperatorType *ot)
static const char *get_lamp_defname(int type)
{
switch (type) {
case LA_LOCAL: return "Point";
case LA_SUN: return "Sun";
case LA_SPOT: return "Spot";
case LA_HEMI: return "Hemi";
case LA_AREA: return "Area";
case LA_LOCAL: return DATA_("Point");
case LA_SUN: return DATA_("Sun");
case LA_SPOT: return DATA_("Spot");
case LA_HEMI: return DATA_("Hemi");
case LA_AREA: return DATA_("Area");
default:
return "Lamp";
return DATA_("Lamp");
}
}
@ -980,7 +980,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op)
BKE_nlatrack_add_strip(nlt, strip);
/* auto-name the strip, and give the track an interesting name */
strcpy(nlt->name, "SoundTrack");
strcpy(nlt->name, DATA_("SoundTrack"));
BKE_nlastrip_validate_name(adt, strip);
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);

@ -606,12 +606,13 @@ typedef enum eAutokey_Flag {
typedef enum eUserpref_Translation_Flags {
USER_TR_TOOLTIPS = (1 << 0),
USER_TR_IFACE = (1 << 1),
/* USER_TR_MENUS = (1 << 2) deprecated */
/* USER_TR_FILESELECT = (1 << 3) deprecated */
/* USER_TR_TEXTEDIT = (1 << 4) deprecated */
/* USER_TR_MENUS = (1 << 2), deprecated */
/* USER_TR_FILESELECT = (1 << 3), deprecated */
/* USER_TR_TEXTEDIT = (1 << 4), deprecated */
USER_DOTRANSLATE = (1 << 5),
USER_USETEXTUREFONT = (1 << 6),
/* CONVERT_TO_UTF8 = (1 << 7) deprecated */
/* CONVERT_TO_UTF8 = (1 << 7), deprecated */
USER_TR_NEWDATANAME = (1 << 8),
} eUserpref_Translation_Flags;
/* dupflag */

@ -3366,12 +3366,17 @@ static void rna_def_userdef_system(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_translate_tooltips", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_TR_TOOLTIPS);
RNA_def_property_ui_text(prop, "Translate Tooltips", "Translate Tooltips");
RNA_def_property_ui_text(prop, "Translate Tooltips", "Translate tooltips");
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "use_translate_interface", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_TR_IFACE);
RNA_def_property_ui_text(prop, "Translate Interface", "Translate Interface");
RNA_def_property_ui_text(prop, "Translate Interface", "Translate interface");
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "use_translate_new_dataname", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_TR_NEWDATANAME);
RNA_def_property_ui_text(prop, "Translate New Names", "Translate new data names (when adding/creating some)");
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "use_textured_fonts", PROP_BOOLEAN, PROP_NONE);

@ -570,7 +570,7 @@ static PyObject *app_translations_pgettext_iface(BlenderAppTranslations *UNUSED(
}
PyDoc_STRVAR(app_translations_pgettext_tip_doc,
".. method:: pgettext(msgid, msgctxt)\n"
".. method:: pgettext_tip(msgid, msgctxt)\n"
"\n"
" Try to translate the given msgid (with optional msgctxt), if tooltips' translation is enabled.\n"
" NOTE: See pgettext notes.\n"
@ -588,6 +588,25 @@ static PyObject *app_translations_pgettext_tip(BlenderAppTranslations *UNUSED(se
return _py_pgettext(args, kw, BLF_translate_do_tooltip);
}
PyDoc_STRVAR(app_translations_pgettext_data_doc,
".. method:: pgettext_data(msgid, msgctxt)\n"
"\n"
" Try to translate the given msgid (with optional msgctxt), if new data name's translation is enabled.\n"
" NOTE: See pgettext notes.\n"
"\n"
" :arg msgid: The string to translate.\n"
" :type msgid: string\n"
" :arg msgctxt: The translation context.\n"
" :type msgctxt: string or None\n"
" :default msgctxt: BLF_I18NCONTEXT_DEFAULT value.\n"
" :return: The translated string (or msgid if no translation was found).\n"
"\n"
);
static PyObject *app_translations_pgettext_data(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw)
{
return _py_pgettext(args, kw, BLF_translate_do_new_dataname);
}
PyDoc_STRVAR(app_translations_locale_explode_doc,
".. method:: locale_explode(locale)\n"
"\n"
@ -620,18 +639,20 @@ static PyObject *app_translations_locale_explode(BlenderAppTranslations *UNUSED(
PyMethodDef app_translations_methods[] = {
/* Can't use METH_KEYWORDS alone, see http://bugs.python.org/issue11587 */
{(char *)"register", (PyCFunction)app_translations_py_messages_register, METH_VARARGS | METH_KEYWORDS,
app_translations_py_messages_register_doc},
{(char *)"unregister", (PyCFunction)app_translations_py_messages_unregister, METH_VARARGS | METH_KEYWORDS,
app_translations_py_messages_unregister_doc},
{(char *)"pgettext", (PyCFunction)app_translations_pgettext, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
app_translations_pgettext_doc},
{(char *)"pgettext_iface", (PyCFunction)app_translations_pgettext_iface, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
app_translations_pgettext_iface_doc},
{(char *)"pgettext_tip", (PyCFunction)app_translations_pgettext_tip, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
app_translations_pgettext_tip_doc},
{(char *)"locale_explode", (PyCFunction)app_translations_locale_explode, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
app_translations_locale_explode_doc},
{"register", (PyCFunction)app_translations_py_messages_register, METH_VARARGS | METH_KEYWORDS,
app_translations_py_messages_register_doc},
{"unregister", (PyCFunction)app_translations_py_messages_unregister, METH_VARARGS | METH_KEYWORDS,
app_translations_py_messages_unregister_doc},
{"pgettext", (PyCFunction)app_translations_pgettext, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
app_translations_pgettext_doc},
{"pgettext_iface", (PyCFunction)app_translations_pgettext_iface, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
app_translations_pgettext_iface_doc},
{"pgettext_tip", (PyCFunction)app_translations_pgettext_tip, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
app_translations_pgettext_tip_doc},
{"pgettext_data", (PyCFunction)app_translations_pgettext_data, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
app_translations_pgettext_data_doc},
{"locale_explode", (PyCFunction)app_translations_locale_explode, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
app_translations_locale_explode_doc},
{NULL}
};
@ -697,7 +718,7 @@ PyDoc_STRVAR(app_translations_doc,
static PyTypeObject BlenderAppTranslationsType = {
PyVarObject_HEAD_INIT(NULL, 0)
/* tp_name */
(char *)"bpy.app._translations_type",
"bpy.app._translations_type",
/* tp_basicsize */
sizeof(BlenderAppTranslations),
0, /* tp_itemsize */