From d0f4a2396b38c122b7e56de83532515ae8fa4381 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 10 Feb 2013 10:29:38 +0000 Subject: [PATCH] Actually, UI scripts should not use directly pgettext, but rather the iface or tooltip variants. Added those to bpy.app.translations, and used pgettext_iface. (Did not add those when I created that module, because I did not thought we would actually need them in usual UI code, but turned out I was wrong). Also made some optimizations in those py gettext funcs, when i18n is disabled at build time, no need to do pyobject -> cstring -> pyobject conversions!. --- .../startup/bl_ui/properties_data_modifier.py | 5 +- .../startup/bl_ui/properties_material.py | 5 +- .../startup/bl_ui/properties_particle.py | 5 +- .../startup/bl_ui/properties_physics_fluid.py | 5 +- release/scripts/startup/bl_ui/space_clip.py | 9 +- release/scripts/startup/bl_ui/space_image.py | 5 +- .../scripts/startup/bl_ui/space_sequencer.py | 19 ++-- release/scripts/startup/bl_ui/space_text.py | 7 +- .../scripts/startup/bl_ui/space_userpref.py | 5 +- .../startup/bl_ui/space_userpref_keymap.py | 5 +- .../python/intern/bpy_app_translations.c | 93 +++++++++++++++---- 11 files changed, 106 insertions(+), 57 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index 303015ebac2..7be00193fb4 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -19,8 +19,7 @@ # import bpy from bpy.types import Panel - -from bpy.app.translations import pgettext as _ +from bpy.app.translations import pgettext_iface as iface_ class ModifierButtonsPanel(): @@ -267,7 +266,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): layout.prop(md, "angle_limit") layout.prop(md, "use_dissolve_boundaries") - layout.label(text=_("Face Count: %d") % md.face_count, translate=False) + layout.label(text=iface_("Face Count: %d") % md.face_count, translate=False) def DISPLACE(self, layout, ob, md): has_texture = (md.texture is not None) diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py index f3a83d225b9..273b2450200 100644 --- a/release/scripts/startup/bl_ui/properties_material.py +++ b/release/scripts/startup/bl_ui/properties_material.py @@ -20,8 +20,7 @@ import bpy from bpy.types import Menu, Panel, UIList from rna_prop_ui import PropertyPanel - -from bpy.app.translations import pgettext as _ +from bpy.app.translations import pgettext_iface as iface_ def active_node_mat(mat): @@ -82,7 +81,7 @@ class MATERIAL_UL_matslots(UIList): if ma and not context.scene.render.use_shading_nodes: manode = ma.active_node_material if manode: - layout.label(text=_("Node %s") % manode.name, translate=False, icon_value=layout.icon(manode)) + layout.label(text=iface_("Node %s") % manode.name, translate=False, icon_value=layout.icon(manode)) elif ma.use_nodes: layout.label(text="Node ") else: diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index fb930e9de5b..0aa2c14a0c7 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -20,8 +20,7 @@ import bpy from bpy.types import Panel from rna_prop_ui import PropertyPanel - -from bpy.app.translations import pgettext as _ +from bpy.app.translations import pgettext_iface as iface_ from bl_ui.properties_physics_common import (point_cache_ui, effector_weights_ui, @@ -150,7 +149,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel): #row.label(text="Render") if part.is_fluid: - layout.label(text=_("%d fluid particles for this frame") % part.count, translate=False) + layout.label(text=iface_("%d fluid particles for this frame") % part.count, translate=False) return row = col.row() diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py index c9eaa7a4acc..2164b86f486 100644 --- a/release/scripts/startup/bl_ui/properties_physics_fluid.py +++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py @@ -19,8 +19,7 @@ # import bpy from bpy.types import Panel, Menu - -from bpy.app.translations import pgettext as _ +from bpy.app.translations import pgettext_iface as iface_ class FLUID_MT_presets(Menu): @@ -66,7 +65,7 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel): if fluid.type == 'DOMAIN': # odd formatting here so translation script can extract string - layout.operator("fluid.bake", text=_("Bake (Req. Memory: %s)") % fluid.memory_estimate, + layout.operator("fluid.bake", text=iface_("Bake (Req. Memory: %s)") % fluid.memory_estimate, translate=False, icon='MOD_FLUIDSIM') split = layout.split() diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index e26f44675fb..bc5d89fd45b 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -20,8 +20,7 @@ import bpy from bpy.types import Panel, Header, Menu, UIList - -from bpy.app.translations import pgettext as _ +from bpy.app.translations import pgettext_iface as iface_ class CLIP_UL_tracking_objects(UIList): @@ -913,9 +912,11 @@ class CLIP_MT_view(Menu): ratios = ((1, 8), (1, 4), (1, 2), (1, 1), (2, 1), (4, 1), (8, 1)) - text = _("Zoom %d:%d") + text = iface_("Zoom %d:%d") for a, b in ratios: - layout.operator("clip.view_zoom_ratio", text=text % (a, b), translate=False).ratio = a / b + layout.operator("clip.view_zoom_ratio", + text=text % (a, b), + translate=False).ratio = a / b else: if sc.view == 'GRAPH': layout.operator_context = 'INVOKE_REGION_PREVIEW' diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index ed4b28a62d7..01b67667cfb 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -20,8 +20,7 @@ import bpy from bpy.types import Header, Menu, Panel from bl_ui.properties_paint_common import UnifiedPaintPanel, brush_texture_settings - -from bpy.app.translations import pgettext as _ +from bpy.app.translations import pgettext_iface as iface_ class ImagePaintPanel(UnifiedPaintPanel): @@ -73,7 +72,7 @@ class IMAGE_MT_view(Menu): ratios = ((1, 8), (1, 4), (1, 2), (1, 1), (2, 1), (4, 1), (8, 1)) for a, b in ratios: - layout.operator("image.view_zoom_ratio", text=_("Zoom %d:%d") % (a, b), translate=False).ratio = a / b + layout.operator("image.view_zoom_ratio", text=iface_("Zoom %d:%d") % (a, b), translate=False).ratio = a / b layout.separator() diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index c8d7d1e60c1..7841acf01b3 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -19,8 +19,7 @@ # import bpy from bpy.types import Header, Menu, Panel - -from bpy.app.translations import pgettext as _ +from bpy.app.translations import pgettext_iface as iface_ def act_strip(context): @@ -424,13 +423,15 @@ class SEQUENCER_PT_edit(SequencerButtonsPanel, Panel): col = layout.column(align=True) row = col.row() - row.label(text=_("Final Length: %s") % bpy.utils.smpte_from_frame(strip.frame_final_duration), translate=False) + row.label(text=iface_("Final Length: %s") % bpy.utils.smpte_from_frame(strip.frame_final_duration), + translate=False) row = col.row() row.active = (frame_current >= strip.frame_start and frame_current <= strip.frame_start + strip.frame_duration) - row.label(text=_("Playhead: %d") % (frame_current - strip.frame_start), translate=False) + row.label(text=iface_("Playhead: %d") % (frame_current - strip.frame_start), translate=False) - col.label(text=_("Frame Offset %d:%d") % (strip.frame_offset_start, strip.frame_offset_end), translate=False) - col.label(text=_("Frame Still %d:%d") % (strip.frame_still_start, strip.frame_still_end), translate=False) + col.label(text=iface_("Frame Offset %d:%d") % (strip.frame_offset_start, strip.frame_offset_end), + translate=False) + col.label(text=iface_("Frame Still %d:%d") % (strip.frame_still_start, strip.frame_still_end), translate=False) elem = False @@ -440,7 +441,7 @@ class SEQUENCER_PT_edit(SequencerButtonsPanel, Panel): elem = strip.elements[0] if elem and elem.orig_width > 0 and elem.orig_height > 0: - col.label(text=_("Original Dimension: %dx%d") % (elem.orig_width, elem.orig_height), translate=False) + col.label(text=iface_("Original Dimension: %dx%d") % (elem.orig_width, elem.orig_height), translate=False) else: col.label(text="Original Dimension: None") @@ -717,7 +718,7 @@ class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel): if scene: sta = scene.frame_start end = scene.frame_end - layout.label(text=_("Original frame range: %d-%d (%d)") % (sta, end, end - sta + 1), translate=False) + layout.label(text=iface_("Original frame range: %d-%d (%d)") % (sta, end, end - sta + 1), translate=False) class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel): @@ -746,7 +747,7 @@ class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel): if mask: sta = mask.frame_start end = mask.frame_end - layout.label(text=_("Original frame range: %d-%d (%d)") % (sta, end, end - sta + 1), translate=False) + layout.label(text=iface_("Original frame range: %d-%d (%d)") % (sta, end, end - sta + 1), translate=False) class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel): diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py index 089bffd7e75..4264fc95cea 100644 --- a/release/scripts/startup/bl_ui/space_text.py +++ b/release/scripts/startup/bl_ui/space_text.py @@ -19,8 +19,7 @@ # import bpy from bpy.types import Header, Menu, Panel - -from bpy.app.translations import pgettext as _ +from bpy.app.translations import pgettext_iface as iface_ class TEXT_HT_header(Header): @@ -74,10 +73,10 @@ class TEXT_HT_header(Header): row = layout.row() if text.filepath: if text.is_dirty: - row.label(text=_("File: *%r (unsaved)") % + row.label(text=iface_("File: *%r (unsaved)") % text.filepath, translate=False) else: - row.label(text=pgettext("File: %r") % + row.label(text=iface_("File: %r") % text.filepath, translate=False) else: row.label(text="Text: External" diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 239597d54f9..017f75b7583 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -19,8 +19,7 @@ # import bpy from bpy.types import Header, Menu, Panel - -from bpy.app.translations import pgettext as _ +from bpy.app.translations import pgettext_iface as iface_ def ui_style_items(col, context): @@ -782,7 +781,7 @@ class USERPREF_PT_theme(Panel): col = split.column() for i, ui in enumerate(theme.bone_color_sets): - col.label(text=_("Color Set %d:") % (i + 1), translate=False) # i starts from 0 + col.label(text=iface_("Color Set %d:") % (i + 1), translate=False) # i starts from 0 row = col.row() diff --git a/release/scripts/startup/bl_ui/space_userpref_keymap.py b/release/scripts/startup/bl_ui/space_userpref_keymap.py index 1c0e54c2c47..e9eb2aa8b8f 100644 --- a/release/scripts/startup/bl_ui/space_userpref_keymap.py +++ b/release/scripts/startup/bl_ui/space_userpref_keymap.py @@ -19,8 +19,7 @@ # import bpy from bpy.types import Menu - -from bpy.app.translations import pgettext as _ +from bpy.app.translations import pgettext_iface as iface_ class USERPREF_MT_keyconfigs(Menu): @@ -99,7 +98,7 @@ class InputKeyMapPanel: subcol = self.indented_layout(col, level + 1) subrow = subcol.row() subrow.prop(km, "show_expanded_items", text="", emboss=False) - subrow.label(text=_("%s (Global)") % km.name, translate=False) + subrow.label(text=iface_("%s (Global)") % km.name, translate=False) else: km.show_expanded_items = True diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c index b6d2f624229..6839c0b12a6 100644 --- a/source/blender/python/intern/bpy_app_translations.c +++ b/source/blender/python/intern/bpy_app_translations.c @@ -495,6 +495,37 @@ PyGetSetDef app_translations_getseters[] = { {NULL} }; +/* pgettext helper. */ +static PyObject *_py_pgettext(PyObject *args, PyObject *kw, const char *(*_pgettext)(const char *, const char *)) +{ + static const char *kwlist[] = {"msgid", "msgctxt", NULL}; + +#ifdef WITH_INTERNATIONAL + char *msgid, *msgctxt = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "s|z:bpy.app.translations.pgettext", (char **)kwlist, + &msgid, &msgctxt)) + { + return NULL; + } + + return PyUnicode_FromString((*_pgettext)(msgctxt ? msgctxt : BLF_I18NCONTEXT_DEFAULT, msgid)); +#else + PyObject *msgid, *msgctxt; + (void)_pgettext; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "O|O:bpy.app.translations.pgettext", (char **)kwlist, + &msgid, &msgctxt)) + { + return NULL; + } + + Py_INCREF(msgid); + + return msgid; +#endif +} + PyDoc_STRVAR(app_translations_pgettext_doc, ".. method:: pgettext(msgid, msgctxt)\n" "\n" @@ -502,7 +533,8 @@ PyDoc_STRVAR(app_translations_pgettext_doc, " NOTE: The (msgid, msgctxt) parameter orders has been switched compared to gettext function, to allow\n" " single-parameter calls (context then defaults to BLF_I18NCONTEXT_DEFAULT).\n" " NOTE: You should really rarely need to use this function in regular addon code, as all translation should be\n" -" handled by Blender internal code.\n" +" handled by Blender internal code. The only exception are string containing formatting (like \"File: %r\"),\n" +" but you should rather use pgettext_iface/_tip in those cases!\n" " Note: Does nothing when Blender is built without internationalization support (hence always returns msgid).\n" "\n" " :arg msgid: The string to translate.\n" @@ -515,26 +547,45 @@ PyDoc_STRVAR(app_translations_pgettext_doc, ); static PyObject *app_translations_pgettext(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw) { - /* Note we could optimize this a bit when WITH_INTERNATIONAL is not defined, but don't think "code complexity" would - * be worth it, as this func should not often be used! - */ - /* XXX This code fails with scons when WITH_INTERNATIONAL is not defined, at link time, stating that BLF_pgettext - * is undefined... So using #ifdef after all, rather than removing scons from blender trunk! - */ - static const char *kwlist[] = {"msgid", "msgctxt", NULL}; - char *msgid, *msgctxt = NULL; + return _py_pgettext(args, kw, BLF_pgettext); +} - if (!PyArg_ParseTupleAndKeywords(args, kw, "s|z:bpy.app.translations.pgettext", (char **)kwlist, - &msgid, &msgctxt)) - { - return NULL; - } +PyDoc_STRVAR(app_translations_pgettext_iface_doc, +".. method:: pgettext_iface(msgid, msgctxt)\n" +"\n" +" Try to translate the given msgid (with optional msgctxt), if labels' 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_iface(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw) +{ + return _py_pgettext(args, kw, BLF_translate_do_iface); +} -#ifdef WITH_INTERNATIONAL - return PyUnicode_FromString(BLF_pgettext(msgctxt ? msgctxt : BLF_I18NCONTEXT_DEFAULT, msgid)); -#else - return PyUnicode_FromString(msgid); -#endif +PyDoc_STRVAR(app_translations_pgettext_tip_doc, +".. method:: pgettext(msgid, msgctxt)\n" +"\n" +" Try to translate the given msgid (with optional msgctxt), if tooltips' 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_tip(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw) +{ + return _py_pgettext(args, kw, BLF_translate_do_tooltip); } PyDoc_STRVAR(app_translations_locale_explode_doc, @@ -575,6 +626,10 @@ PyMethodDef app_translations_methods[] = { 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}, {NULL}