Merge branch 'blender-v5.0-release'

This commit is contained in:
Bastien Montagne
2025-10-10 16:02:20 +02:00
6 changed files with 83 additions and 59 deletions

View File

@@ -820,10 +820,6 @@ def dump_src_messages(msgs, reports, settings):
return {k: getattr(bpy.app.translations.contexts, n) for k, n in bpy.app.translations.contexts_C_to_py.items()}
contexts = get_contexts()
# Build regexes to extract messages (with optional contexts) from C source.
pygettexts = tuple(re.compile(r).search for r in settings.PYGETTEXT_KEYWORDS)
_clean_str = re.compile(settings.str_clean_re).finditer
def clean_str(s):
@@ -867,8 +863,9 @@ def dump_src_messages(msgs, reports, settings):
data = ""
with open(path, encoding="utf8") as f:
data = f.read()
for srch in pygettexts:
m = srch(data)
for keyword in settings.PYGETTEXT_KEYWORDS:
m = keyword.search(data)
line = pos = 0
while m:
d = m.groupdict()
@@ -887,14 +884,14 @@ def dump_src_messages(msgs, reports, settings):
process_msg(msgs, msgctxt, msgid, msgsrc, reports, check_ctxt_src, settings)
reports["src_messages"].append((msgctxt, msgid, msgsrc))
else:
_msgctxt = d.get("ctxt_raw")
_msgctxt = d.get("ctxt_raw", keyword.context_override)
msgctxt, msgid = process_entry(_msgctxt, _msgid)
process_msg(msgs, msgctxt, msgid, msgsrc, reports, check_ctxt_src, settings)
reports["src_messages"].append((msgctxt, msgid, msgsrc))
pos = m.end()
line += data[m.start():pos].count('\n')
m = srch(data, pos)
m = keyword.search(data, pos)
forbidden = set()
forced = set()

View File

@@ -11,6 +11,7 @@
import json
import os
import re
import sys
import types
@@ -247,77 +248,96 @@ _ctxt_re_gen = lambda uid: (
)
_ctxt_re = _ctxt_re_gen("")
_msg_re = r"(?P<msg_raw>" + _str_whole_re.format(_="_msg") + r")"
PYGETTEXT_KEYWORDS = (() +
tuple((r"{}\(\s*" + _msg_re + r"\s*\)").format(it)
for it in ("IFACE_", "TIP_", "RPT_", "DATA_", "N_")) +
tuple((r"{}\(\s*" + _ctxt_re + r"\s*,\s*" + _msg_re + r"\s*\)").format(it)
class PyGettextKeyword:
def __init__(self, re_expr, context_override=None):
self.re_expr = re_expr
self.context_override = context_override
self.re = re.compile(re_expr)
self.search = self.re.search
PYGETTEXT_KEYWORDS = (() +
tuple(PyGettextKeyword((r"{}\(\s*" + _msg_re + r"\s*\)").format(it))
for it in ("IFACE_", "TIP_", "RPT_", "DATA_", "N_")) +
tuple(PyGettextKeyword((r"{}\(\s*" + _ctxt_re + r"\s*,\s*" + _msg_re + r"\s*\)").format(it))
for it in ("CTX_IFACE_", "CTX_TIP_", "CTX_RPT_", "CTX_DATA_", "CTX_N_")) +
tuple(("{}\\((?:[^\"',]+,){{1,2}}\\s*" + _msg_re + r"\s*(?:\)|,)").format(it)
tuple(PyGettextKeyword(("{}\\((?:[^\"',]+,){{1,2}}\\s*" + _msg_re + r"\s*(?:\)|,)").format(it))
for it in ("BKE_report", "BKE_reportf", "BKE_reports_prepend", "BKE_reports_prependf",
"CTX_wm_operator_poll_msg_set", "WM_global_report", "WM_global_reportf",
"UI_but_disable")) +
# ED_undo_push() is used in Undo History menu and has the "Operator" context, same as operators.
tuple(PyGettextKeyword(("{}\\((?:[^\"',]+,)\\s*" + _msg_re + r"\s*(?:\))").format(it),
context_override='BLT_I18NCONTEXT_OPERATOR_DEFAULT')
for it in ("ED_undo_push", "ED_undo_grouped_push")) +
# bmesh operator errors
tuple(("{}\\((?:[^\"',]+,){{3}}\\s*" + _msg_re + r"\s*\)").format(it)
tuple(PyGettextKeyword(("{}\\((?:[^\"',]+,){{3}}\\s*" + _msg_re + r"\s*\)").format(it))
for it in ("BMO_error_raise",)) +
# Modifier errors
tuple(("{}\\((?:[^\"',]+,){{2}}\\s*" + _msg_re + r"\s*(?:\)|,)").format(it)
tuple(PyGettextKeyword(("{}\\((?:[^\"',]+,){{2}}\\s*" + _msg_re + r"\s*(?:\)|,)").format(it))
for it in ("BKE_modifier_set_error",)) +
# Window manager job names.
tuple(("{}\\((?:[^\"',]+,){{3}}\\s*" + _msg_re + r"\s*,").format(it)
tuple(PyGettextKeyword(("{}\\((?:[^\"',]+,){{3}}\\s*" + _msg_re + r"\s*,").format(it))
for it in ("WM_jobs_get",)) +
# Compositor and EEVEE messages.
# Ends either with `)` (function call close), or `,` when there are extra formatting parameters.
tuple((r"{}\(\s*" + _msg_re + r"\s*(?:\)|,)").format(it)
tuple(PyGettextKeyword((r"{}\(\s*" + _msg_re + r"\s*(?:\)|,)").format(it))
for it in ("set_info_message", "info_append_i18n")) +
# This one is a tad more risky, but in practice would not expect a name/uid string parameter
# (the second one in those functions) to ever have a comma in it, so think this is fine.
tuple(("{}\\((?:[^,]+,){{2}}\\s*" + _msg_re + r"\s*(?:\)|,)").format(it)
tuple(PyGettextKeyword(("{}\\((?:[^,]+,){{2}}\\s*" + _msg_re + r"\s*(?:\)|,)").format(it))
for it in ("modifier_subpanel_register", "gpencil_modifier_subpanel_register")) +
# Node socket declarations: context-less names.
tuple((r"\.{}(?:<decl::.*?>\(|[^,]+,)\s*" + _msg_re + r"(?:,[^),]+)*\s*\)"
r"(?![^;]*\.translation_context\()").format(it)
tuple(PyGettextKeyword((r"\.{}(?:<decl::.*?>\(|[^,]+,)\s*" + _msg_re + r"(?:,[^),]+)*\s*\)"
r"(?![^;]*\.translation_context\()").format(it))
for it in ("add_input", "add_output")) +
# Node socket declarations: names with contexts
tuple((r"\.{}(?:<decl::.*?>\(|[^,]+,)\s*" + _msg_re +
r"[^;]*\.translation_context\(\s*" + _ctxt_re + r"\s*\)").format(it)
tuple(PyGettextKeyword((r"\.{}(?:<decl::.*?>\(|[^,]+,)\s*" + _msg_re +
r"[^;]*\.translation_context\(\s*" + _ctxt_re + r"\s*\)").format(it))
for it in ("add_input", "add_output")) +
# Node socket declarations: description and error messages
tuple((r"\.{}\(\s*" + _msg_re + r"\s*\)").format(it)
tuple(PyGettextKeyword((r"\.{}\(\s*" + _msg_re + r"\s*\)").format(it))
for it in ("description", "error_message_add")) +
# Node socket panels and labels from declarations: context-less names
tuple((r"\.{}\(\s*" + _msg_re +
r"\s*\)(?![^;]*\.translation_context\()[^;]*;").format(it)
tuple(PyGettextKeyword((r"\.{}\(\s*" + _msg_re +
r"\s*\)(?![^;]*\.translation_context\()[^;]*;").format(it))
for it in ("short_label", "add_panel",)) +
# Node socket panels and labels from declarations: names with contexts
tuple((r"\.{}\(\s*" + _msg_re + r"[^;]*\.translation_context\(\s*" +
_ctxt_re + r"\s*\)").format(it)
tuple(PyGettextKeyword((r"\.{}\(\s*" + _msg_re + r"[^;]*\.translation_context\(\s*" +
_ctxt_re + r"\s*\)").format(it))
for it in ("short_label", "add_panel",)) +
# Dynamic node socket labels
tuple((r"{}\(\s*[^,]+,\s*" + _msg_re + r"\s*\)").format(it)
tuple(PyGettextKeyword((r"{}\(\s*[^,]+,\s*" + _msg_re + r"\s*\)").format(it))
for it in ("node_sock_label",)) +
# Geometry Nodes field inputs
((r"FieldInput\(CPPType::get<.*?>\(\),\s*" + _msg_re + r"\s*\)"),) +
(PyGettextKeyword(r"FieldInput\(CPPType::get<.*?>\(\),\s*" + _msg_re + r"\s*\)"),) +
# bUnitDef unit names
((r"/\*name_display\*/\s*" + _msg_re + r"\s*,"),) +
(PyGettextKeyword(r"/\*name_display\*/\s*" + _msg_re + r"\s*,"),) +
tuple((r"{}\(\s*" + _msg_re + r"\s*,\s*(?:" +
r"\s*,\s*)?(?:".join(_ctxt_re_gen(i) for i in range(PYGETTEXT_MAX_MULTI_CTXT)) + r")?\s*,?\s*\)").format(it)
for it in ("BLT_I18N_MSGID_MULTI_CTXT",))
tuple(PyGettextKeyword(
(r"{}\(\s*"
+ _msg_re
+ r"\s*,\s*(?:"
+ r"\s*,\s*)?(?:".join(_ctxt_re_gen(i) for i in range(PYGETTEXT_MAX_MULTI_CTXT))
+ r")?\s*,?\s*\)"
).format(it)
) for it in ("BLT_I18N_MSGID_MULTI_CTXT",))
)
# autopep8: on

View File

@@ -58,7 +58,11 @@ static void colorband_distribute(bContext *C, ColorBand *coba, bool evenly)
coba->data[a].pos = pos;
pos += gap;
}
ED_undo_push(C, evenly ? "Distribute Stops Evenly" : "Distribute Stops from Left");
const char *undo_str = evenly ? CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT,
"Distribute Stops Evenly") :
CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT,
"Distribute Stops from Left");
ED_undo_push(C, undo_str);
}
}

View File

@@ -678,7 +678,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
break;
case UI_ID_RENAME:
/* Only for the undo push. */
undo_push_label = "Rename Data-Block";
undo_push_label = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Rename Data-Block");
break;
case UI_ID_BROWSE:
case UI_ID_PIN:
@@ -698,10 +698,10 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
id_us_clear_real(id);
id_fake_user_clear(id);
id->us = 0;
undo_push_label = "Delete Data-Block";
undo_push_label = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Data-Block");
}
else {
undo_push_label = "Unlink Data-Block";
undo_push_label = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Unlink Data-Block");
}
break;
@@ -713,7 +713,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
else {
id_us_min(id);
}
undo_push_label = "Fake User";
undo_push_label = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Fake User");
}
else {
return;
@@ -731,7 +731,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
/* Reassign to get proper updates/notifiers. */
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
undo_push_label = "Make Local";
undo_push_label = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Make Local");
}
}
if (undo_push_label != nullptr) {
@@ -752,7 +752,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, nullptr);
RNA_property_update(C, &template_ui->ptr, template_ui->prop);
undo_push_label = "Make Local";
undo_push_label = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Make Local");
}
}
break;
@@ -776,7 +776,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
DEG_relations_tag_update(bmain);
}
BKE_main_ensure_invariants(*CTX_data_main(C));
undo_push_label = "Make Single User";
undo_push_label = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Make Single User");
}
break;
#if 0

View File

@@ -730,7 +730,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
if (ELEM(tselem->type, TSE_SOME_ID, TSE_LINKED_NODE_TREE)) {
if (id_rename_helper()) {
undo_str = "Rename Data-Block";
undo_str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Rename Data-Block");
}
WM_msg_publish_rna_prop(mbus, tselem->id, tselem->id, ID, name);
@@ -787,13 +787,13 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
BKE_object_defgroup_unique_name(vg, ob);
WM_msg_publish_rna_prop(mbus, &ob->id, vg, VertexGroup, name);
DEG_id_tag_update(tselem->id, ID_RECALC_SYNC_TO_EVAL);
undo_str = "Rename Vertex Group";
undo_str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Rename Vertex Group");
break;
}
case TSE_NLA_ACTION: {
/* The #tselem->id is a #bAction. */
if (id_rename_helper()) {
undo_str = "Rename Data-Block";
undo_str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Rename Data-Block");
}
WM_msg_publish_rna_prop(mbus, tselem->id, tselem->id, ID, name);
DEG_id_tag_update(tselem->id, ID_RECALC_SYNC_TO_EVAL);
@@ -801,13 +801,14 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
}
case TSE_NLA_TRACK: {
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, nullptr);
undo_str = "Rename NLA Track";
undo_str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Rename NLA Track");
break;
}
case TSE_MODIFIER: {
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER | NA_RENAME, nullptr);
DEG_relations_tag_update(bmain);
undo_str = "Rename Modifier";
undo_str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Rename Modifier");
break;
}
case TSE_EBONE: {
@@ -823,7 +824,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
WM_msg_publish_rna_prop(mbus, &arm->id, ebone, EditBone, name);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, nullptr);
DEG_id_tag_update(tselem->id, ID_RECALC_SYNC_TO_EVAL);
undo_str = "Rename Edit Bone";
undo_str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Rename Edit Bone");
}
break;
}
@@ -846,7 +847,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
WM_msg_publish_rna_prop(mbus, &arm->id, bone, Bone, name);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, nullptr);
DEG_id_tag_update(tselem->id, ID_RECALC_SYNC_TO_EVAL);
undo_str = "Rename Bone";
undo_str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Rename Bone");
break;
}
case TSE_POSE_CHANNEL: {
@@ -871,7 +872,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, nullptr);
DEG_id_tag_update(tselem->id, ID_RECALC_SYNC_TO_EVAL);
DEG_id_tag_update(&arm->id, ID_RECALC_SYNC_TO_EVAL);
undo_str = "Rename Pose Bone";
undo_str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Rename Pose Bone");
break;
}
case TSE_GP_LAYER: {
@@ -889,7 +890,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, gpd);
DEG_id_tag_update(tselem->id, ID_RECALC_SYNC_TO_EVAL);
undo_str = "Rename Annotation Layer";
undo_str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Rename Annotation Layer");
break;
}
case TSE_GREASE_PENCIL_NODE: {
@@ -905,7 +906,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
grease_pencil.rename_node(*bmain, node, new_name);
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_SYNC_TO_EVAL);
WM_event_add_notifier(C, NC_ID | NA_RENAME, nullptr);
undo_str = "Rename Grease Pencil Drawing";
undo_str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Rename Grease Pencil Drawing");
break;
}
case TSE_R_LAYER: {
@@ -922,13 +923,13 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, ViewLayer, name);
WM_event_add_notifier(C, NC_ID | NA_RENAME, nullptr);
DEG_id_tag_update(tselem->id, ID_RECALC_SYNC_TO_EVAL);
undo_str = "Rename View Layer";
undo_str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Rename View Layer");
break;
}
case TSE_LAYER_COLLECTION: {
/* The #tselem->id is a #Collection, not a #LayerCollection */
if (id_rename_helper()) {
undo_str = "Rename Data-Block";
undo_str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Rename Data-Block");
}
WM_msg_publish_rna_prop(mbus, tselem->id, tselem->id, ID, name);
WM_event_add_notifier(C, NC_ID | NA_RENAME, nullptr);
@@ -944,13 +945,13 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
WM_msg_publish_rna_prop(mbus, &arm->id, bcoll, BoneCollection, name);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_COLLECTION, arm);
DEG_id_tag_update(&arm->id, ID_RECALC_SYNC_TO_EVAL);
undo_str = "Rename Bone Collection";
undo_str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Rename Bone Collection");
break;
}
case TSE_ACTION_SLOT: {
WM_event_add_notifier(C, NC_ID | NA_RENAME, nullptr);
undo_str = "Rename Action Slot";
undo_str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Rename Action Slot");
break;
}
}

View File

@@ -36,6 +36,8 @@
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
#include "BLT_translation.hh"
#include "BKE_anim_data.hh"
#include "BKE_animsys.h"
#include "BKE_armature.hh"
@@ -2513,7 +2515,7 @@ static wmOperatorStatus outliner_object_operation_exec(bContext *C, wmOperator *
WM_window_set_active_scene(bmain, C, win, sce);
}
str = "Select Objects";
str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Select Objects");
selection_changed = true;
break;
}
@@ -2531,14 +2533,14 @@ static wmOperatorStatus outliner_object_operation_exec(bContext *C, wmOperator *
if (scene != sce) {
WM_window_set_active_scene(bmain, C, win, sce);
}
str = "Select Object Hierarchy";
str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Select Object Hierarchy");
selection_changed = true;
break;
}
case OL_OP_DESELECT:
outliner_do_object_operation(
C, op->reports, scene, space_outliner, &space_outliner->tree, object_deselect_fn);
str = "Deselect Objects";
str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Deselect Objects");
selection_changed = true;
break;
case OL_OP_REMAP:
@@ -2549,7 +2551,7 @@ static wmOperatorStatus outliner_object_operation_exec(bContext *C, wmOperator *
case OL_OP_RENAME:
outliner_do_object_operation(
C, op->reports, scene, space_outliner, &space_outliner->tree, item_rename_fn);
str = "Rename Object";
str = CTX_N_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Rename Object");
break;
default:
BLI_assert_unreachable();