From 5db82be74f67c1e49591fd9f18a64d2f90c79a43 Mon Sep 17 00:00:00 2001 From: Damien Picard Date: Thu, 11 Jan 2024 19:49:03 +0100 Subject: [PATCH] Fix #76101: I18n: add new preference to translate reports Translation of the UI is currently split into 3 preferences: interface, tooltips, and new data. The distinction between interface and tooltips is currently unclear as tooltips also include a lot of messages not displayed in the actual tooltips on mouse hover. These include reports to the Info Editor, information in editor headers and footers, and statuses in panels. In order to limit the use of `TIP_()` to actual tooltips, this commit introduces a new preference for this extra information: "Reports". New translation macros are introduced: `RPT_()` and `CTX_RPT_()`, as well as their equivalent for the Python API, `pgettext_rpt_()`, to be imported as `rpt_()`. Pull Request: https://projects.blender.org/blender/blender/pulls/116804 --- .../bl_i18n_utils/bl_extract_messages.py | 1 + scripts/modules/bl_i18n_utils/settings.py | 4 +-- scripts/startup/bl_ui/space_userpref.py | 1 + .../blenloader/intern/versioning_userdef.cc | 4 +-- .../blender/blentranslation/BLT_translation.h | 11 +++++++- .../blentranslation/intern/blt_translation.cc | 24 +++++++++++++++++ source/blender/makesdna/DNA_userdef_types.h | 2 +- source/blender/makesrna/intern/rna_userdef.cc | 10 +++++-- .../python/intern/bpy_app_translations.cc | 27 +++++++++++++++++++ tools/utils_api/bpy_introspect_ui.py | 1 + 10 files changed, 77 insertions(+), 8 deletions(-) diff --git a/scripts/modules/bl_i18n_utils/bl_extract_messages.py b/scripts/modules/bl_i18n_utils/bl_extract_messages.py index 634572d0bdc..b49401c6d53 100644 --- a/scripts/modules/bl_i18n_utils/bl_extract_messages.py +++ b/scripts/modules/bl_i18n_utils/bl_extract_messages.py @@ -573,6 +573,7 @@ def dump_py_messages_from_files(msgs, reports, files, settings): ("pgettext", ("_",)), ("pgettext_iface", ("iface_",)), ("pgettext_tip", ("tip_",)), + ("pgettext_rpt", ("rpt_",)), ("pgettext_data", ("data_",)), ) pgettext_variants_args = {"msgid": (0, {"msgctxt": 1})} diff --git a/scripts/modules/bl_i18n_utils/settings.py b/scripts/modules/bl_i18n_utils/settings.py index bec1240a7ee..1f0515c3e3e 100644 --- a/scripts/modules/bl_i18n_utils/settings.py +++ b/scripts/modules/bl_i18n_utils/settings.py @@ -243,10 +243,10 @@ _ctxt_re = _ctxt_re_gen("") _msg_re = r"(?P" + _str_whole_re.format(_="_msg") + r")" PYGETTEXT_KEYWORDS = (() + tuple((r"{}\(\s*" + _msg_re + r"\s*\)").format(it) - for it in ("IFACE_", "TIP_", "DATA_", "N_")) + + for it in ("IFACE_", "TIP_", "RPT_", "DATA_", "N_")) + tuple((r"{}\(\s*" + _ctxt_re + r"\s*,\s*" + _msg_re + r"\s*\)").format(it) - for it in ("CTX_IFACE_", "CTX_TIP_", "CTX_DATA_", "CTX_N_")) + + for it in ("CTX_IFACE_", "CTX_TIP_", "CTX_RPT_", "CTX_DATA_", "CTX_N_")) + tuple(("{}\\((?:[^\"',]+,){{1,2}}\\s*" + _msg_re + r"\s*(?:\)|,)").format(it) for it in ("BKE_report", "BKE_reportf", "BKE_reports_prepend", "BKE_reports_prependf", diff --git a/scripts/startup/bl_ui/space_userpref.py b/scripts/startup/bl_ui/space_userpref.py index 4dc7e4eb79a..f845cde10f2 100644 --- a/scripts/startup/bl_ui/space_userpref.py +++ b/scripts/startup/bl_ui/space_userpref.py @@ -260,6 +260,7 @@ class USERPREF_PT_interface_translation(InterfacePanel, CenterAlignMixIn, Panel) col.active = (bpy.app.translations.locale != "en_US") col.prop(view, "use_translate_tooltips", text="Tooltips") col.prop(view, "use_translate_interface", text="Interface") + col.prop(view, "use_translate_reports", text="Reports") col.prop(view, "use_translate_new_dataname", text="New Data") diff --git a/source/blender/blenloader/intern/versioning_userdef.cc b/source/blender/blenloader/intern/versioning_userdef.cc index e092fd5a9c7..884b0dce164 100644 --- a/source/blender/blenloader/intern/versioning_userdef.cc +++ b/source/blender/blenloader/intern/versioning_userdef.cc @@ -494,8 +494,8 @@ void blo_do_versions_userdef(UserDef *userdef) USER_FLAG_UNUSED_6 | USER_FLAG_UNUSED_7 | USER_FLAG_UNUSED_9 | USER_DEVELOPER_UI); userdef->uiflag &= ~(USER_HEADER_BOTTOM); - userdef->transopts &= ~(USER_TR_UNUSED_2 | USER_TR_UNUSED_3 | USER_TR_UNUSED_4 | - USER_TR_UNUSED_6 | USER_TR_UNUSED_7); + userdef->transopts &= ~(USER_TR_UNUSED_3 | USER_TR_UNUSED_4 | USER_TR_UNUSED_6 | + USER_TR_UNUSED_7); userdef->uiflag |= USER_LOCK_CURSOR_ADJUST; } diff --git a/source/blender/blentranslation/BLT_translation.h b/source/blender/blentranslation/BLT_translation.h index 6104d0abde9..ccdd69ed278 100644 --- a/source/blender/blentranslation/BLT_translation.h +++ b/source/blender/blentranslation/BLT_translation.h @@ -19,14 +19,21 @@ extern "C" { bool BLT_is_default_context(const char *msgctxt); const char *BLT_pgettext(const char *msgctxt, const char *msgid); -/* translation */ +/* Translation */ +/* - iface includes buttons in the user interface: short labels displayed in windows, panels, + * menus. + * - tooltips only include the popup tooltips when hovering a button. + * - report is for longer, additional information displayed in the UI, such as error messages. + * - new_dataname is the actual user-created data such as objects, meshes, etc. */ bool BLT_translate(void); bool BLT_translate_iface(void); bool BLT_translate_tooltips(void); +bool BLT_translate_reports(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_report(const char *msgctxt, const char *msgid); const char *BLT_translate_do_new_dataname(const char *msgctxt, const char *msgid); /* The "translation-marker" macro. */ @@ -37,9 +44,11 @@ const char *BLT_translate_do_new_dataname(const char *msgctxt, const char *msgid /*# define _(msgid) BLT_gettext(msgid) */ #define IFACE_(msgid) BLT_translate_do_iface(NULL, msgid) #define TIP_(msgid) BLT_translate_do_tooltip(NULL, msgid) +#define RPT_(msgid) BLT_translate_do_report(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_RPT_(context, msgid) BLT_translate_do_report(context, msgid) #define CTX_DATA_(context, msgid) BLT_translate_do_new_dataname(context, msgid) /* Helper macro, when we want to define a same msgid for multiple msgctxt... diff --git a/source/blender/blentranslation/intern/blt_translation.cc b/source/blender/blentranslation/intern/blt_translation.cc index e6779b305e5..b7e9cf38094 100644 --- a/source/blender/blentranslation/intern/blt_translation.cc +++ b/source/blender/blentranslation/intern/blt_translation.cc @@ -90,6 +90,15 @@ bool BLT_translate_tooltips() #endif } +bool BLT_translate_reports() +{ +#ifdef WITH_INTERNATIONAL + return BLT_translate() && (U.transopts & USER_TR_REPORTS); +#else + return false; +#endif +} + bool BLT_translate_new_dataname() { #ifdef WITH_INTERNATIONAL @@ -144,6 +153,21 @@ const char *BLT_translate_do_tooltip(const char *msgctxt, const char *msgid) #endif } +const char *BLT_translate_do_report(const char *msgctxt, const char *msgid) +{ +#ifdef WITH_INTERNATIONAL + if (BLT_translate_reports()) { + return BLT_pgettext(msgctxt, msgid); + } + + return msgid; + +#else + (void)msgctxt; + return msgid; +#endif +} + const char *BLT_translate_do_new_dataname(const char *msgctxt, const char *msgid) { #ifdef WITH_INTERNATIONAL diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 1e13bb3f95c..15eeac0be6e 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -1323,7 +1323,7 @@ typedef enum eUserpref_Anim_Flags { typedef enum eUserpref_Translation_Flags { USER_TR_TOOLTIPS = (1 << 0), USER_TR_IFACE = (1 << 1), - USER_TR_UNUSED_2 = (1 << 2), /* cleared */ + USER_TR_REPORTS = (1 << 2), USER_TR_UNUSED_3 = (1 << 3), /* cleared */ USER_TR_UNUSED_4 = (1 << 4), /* cleared */ USER_DOTRANSLATE_DEPRECATED = (1 << 5), /* Deprecated in 2.83. */ diff --git a/source/blender/makesrna/intern/rna_userdef.cc b/source/blender/makesrna/intern/rna_userdef.cc index b1ae943a097..992a79a6039 100644 --- a/source/blender/makesrna/intern/rna_userdef.cc +++ b/source/blender/makesrna/intern/rna_userdef.cc @@ -330,10 +330,10 @@ static void rna_userdef_language_update(Main * /*bmain*/, Scene * /*scene*/, Poi const char *uilng = BLT_lang_get(); if (STREQ(uilng, "en_US")) { - U.transopts &= ~(USER_TR_IFACE | USER_TR_TOOLTIPS | USER_TR_NEWDATANAME); + U.transopts &= ~(USER_TR_IFACE | USER_TR_TOOLTIPS | USER_TR_REPORTS | USER_TR_NEWDATANAME); } else { - U.transopts |= (USER_TR_IFACE | USER_TR_TOOLTIPS | USER_TR_NEWDATANAME); + U.transopts |= (USER_TR_IFACE | USER_TR_TOOLTIPS | USER_TR_REPORTS | USER_TR_NEWDATANAME); } USERDEF_TAG_DIRTY; @@ -5196,6 +5196,12 @@ static void rna_def_userdef_view(BlenderRNA *brna) "(note that this might make it hard to follow tutorials or the manual)"); RNA_def_property_update(prop, 0, "rna_userdef_update"); + prop = RNA_def_property(srna, "use_translate_reports", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "transopts", USER_TR_REPORTS); + RNA_def_property_ui_text( + prop, "Translate Reports", "Translate additional information, such as error messages"); + 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, nullptr, "transopts", USER_TR_NEWDATANAME); RNA_def_property_ui_text(prop, diff --git a/source/blender/python/intern/bpy_app_translations.cc b/source/blender/python/intern/bpy_app_translations.cc index eb74714d611..5ba843ff8df 100644 --- a/source/blender/python/intern/bpy_app_translations.cc +++ b/source/blender/python/intern/bpy_app_translations.cc @@ -646,6 +646,29 @@ static PyObject *app_translations_pgettext_tip(BlenderAppTranslations * /*self*/ return _py_pgettext(args, kw, BLT_translate_do_tooltip); } +PyDoc_STRVAR( + app_translations_pgettext_rpt_doc, + ".. method:: pgettext_rpt(msgid, msgctxt=None)\n" + "\n" + " Try to translate the given msgid (with optional msgctxt), if reports' translation " + "is enabled.\n" + "\n" + " .. note::\n" + " See :func:`pgettext` notes.\n" + "\n" + " :arg msgid: The string to translate.\n" + " :type msgid: string\n" + " :arg msgctxt: The translation context (defaults to BLT_I18NCONTEXT_DEFAULT).\n" + " :type msgctxt: string or None\n" + " :return: The translated string (or msgid if no translation was found).\n" + "\n"); +static PyObject *app_translations_pgettext_rpt(BlenderAppTranslations * /*self*/, + PyObject *args, + PyObject *kw) +{ + return _py_pgettext(args, kw, BLT_translate_do_report); +} + PyDoc_STRVAR(app_translations_pgettext_data_doc, ".. method:: pgettext_data(msgid, msgctxt=None)\n" "\n" @@ -740,6 +763,10 @@ static PyMethodDef app_translations_methods[] = { (PyCFunction)app_translations_pgettext_tip, METH_VARARGS | METH_KEYWORDS | METH_STATIC, app_translations_pgettext_tip_doc}, + {"pgettext_rpt", + (PyCFunction)app_translations_pgettext_rpt, + METH_VARARGS | METH_KEYWORDS | METH_STATIC, + app_translations_pgettext_rpt_doc}, {"pgettext_data", (PyCFunction)app_translations_pgettext_data, METH_VARARGS | METH_KEYWORDS | METH_STATIC, diff --git a/tools/utils_api/bpy_introspect_ui.py b/tools/utils_api/bpy_introspect_ui.py index db3a5f650bc..df7c89491c3 100644 --- a/tools/utils_api/bpy_introspect_ui.py +++ b/tools/utils_api/bpy_introspect_ui.py @@ -322,6 +322,7 @@ def fake_main(): bpy.app.translations = module_add("bpy.app.translations") bpy.app.translations.pgettext_iface = lambda s, context="": s bpy.app.translations.pgettext_data = lambda s: s + bpy.app.translations.pgettext_report = lambda s: s bpy.app.translations.pgettext_tip = lambda s: s # id's are chosen at random here... bpy.app.translations.contexts = module_add("bpy.app.translations.contexts")