Actually, UI scripts should not use directly pgettext, but rather the iface or toolti...
authorBastien Montagne <montagne29@wanadoo.fr>
Sun, 10 Feb 2013 10:29:38 +0000 (10:29 +0000)
committerBastien Montagne <montagne29@wanadoo.fr>
Sun, 10 Feb 2013 10:29:38 +0000 (10:29 +0000)
(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!.

release/scripts/startup/bl_ui/properties_data_modifier.py
release/scripts/startup/bl_ui/properties_material.py
release/scripts/startup/bl_ui/properties_particle.py
release/scripts/startup/bl_ui/properties_physics_fluid.py
release/scripts/startup/bl_ui/space_clip.py
release/scripts/startup/bl_ui/space_image.py
release/scripts/startup/bl_ui/space_sequencer.py
release/scripts/startup/bl_ui/space_text.py
release/scripts/startup/bl_ui/space_userpref.py
release/scripts/startup/bl_ui/space_userpref_keymap.py
source/blender/python/intern/bpy_app_translations.c

index 303015e..7be0019 100644 (file)
@@ -19,8 +19,7 @@
 # <pep8 compliant>
 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)
index f3a83d2..273b245 100644 (file)
@@ -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 <none>")
                 else:
index fb930e9..0aa2c14 100644 (file)
@@ -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()
index c9eaa7a..2164b86 100644 (file)
@@ -19,8 +19,7 @@
 # <pep8 compliant>
 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()
 
index e26f446..bc5d89f 100644 (file)
@@ -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'
index ed4b28a..01b6766 100644 (file)
@@ -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()
 
index c8d7d1e..7841acf 100644 (file)
@@ -19,8 +19,7 @@
 # <pep8 compliant>
 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):
index 089bffd..4264fc9 100644 (file)
@@ -19,8 +19,7 @@
 # <pep8-80 compliant>
 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"
index 239597d..017f75b 100644 (file)
@@ -19,8 +19,7 @@
 # <pep8 compliant>
 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()
 
index 1c0e54c..e9eb2aa 100644 (file)
@@ -19,8 +19,7 @@
 # <pep8 compliant>
 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
 
index b6d2f62..6839c0b 100644 (file)
@@ -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}