[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [54415] trunk/blender/release/scripts/ modules/bl_i18n_utils/bl_process_msg.py: Updated py ui message extraction, to find out contexts as much as possible...
Bastien Montagne
montagne29 at wanadoo.fr
Sat Feb 9 19:32:00 CET 2013
Revision: 54415
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=54415
Author: mont29
Date: 2013-02-09 18:32:00 +0000 (Sat, 09 Feb 2013)
Log Message:
-----------
Updated py ui message extraction, to find out contexts as much as possible...
Modified Paths:
--------------
trunk/blender/release/scripts/modules/bl_i18n_utils/bl_process_msg.py
Modified: trunk/blender/release/scripts/modules/bl_i18n_utils/bl_process_msg.py
===================================================================
--- trunk/blender/release/scripts/modules/bl_i18n_utils/bl_process_msg.py 2013-02-09 18:26:40 UTC (rev 54414)
+++ trunk/blender/release/scripts/modules/bl_i18n_utils/bl_process_msg.py 2013-02-09 18:32:00 UTC (rev 54415)
@@ -358,16 +358,69 @@
"""
import ast
+ bpy_struct = bpy.types.ID.__base__
+
+ # Helper function
+ def extract_strings(node):
+ """
+ Recursively get strings, needed in case we have "Blah" + "Blah", passed as an argument in that case it won't
+ evaluate to a string. However, break on some kind of stopper nodes, like e.g. Subscript.
+ """
+ if type(node) == ast.Str:
+ eval_str = ast.literal_eval(node)
+ if eval_str:
+ return eval_str, (node,)
+ return None, ()
+
+ eval_str = []
+ nodes = []
+ for nd in ast.iter_child_nodes(node):
+ if type(nd) not in stopper_nodes:
+ estr, nds = extract_strings(nd)
+ eval_str.append(estr)
+ nodes += nds
+ if eval_str:
+ return "".join(s for s in eval_str if s is not None), tuple(n for n in nodes if n is not None)
+ return None, ()
+
+ def _ctxt_to_ctxt(node):
+ return extract_strings(node)[0]
+
+ def _op_to_ctxt(node):
+ opname, _ = extract_strings(node)
+ if not opname:
+ return ""
+ op = bpy.ops
+ for n in opname.split('.'):
+ op = getattr(op, n)
+ try:
+ return op.get_rna().bl_rna.translation_context
+ except Exception as e:
+ print("ERROR: ", str(e))
+
# -------------------------------------------------------------------------
# Gather function names
+ # so far only 'text' keywords, but we may want others translated later
+ translate_kw = ("text", )
+
# key: func_id
# val: [(arg_kw, arg_pos), (arg_kw, arg_pos), ...]
func_translate_args = {}
- # so far only 'text' keywords, but we may want others translated later
- translate_kw = ("text", )
+ # as we only have one translate keyword, no need for complex context extraction setup for now...
+ # And it's already enough complex like that!
+ # Note: order is important, first one wins!
+ context_kw = ((("text_ctxt",), _ctxt_to_ctxt),
+ (("operator",), _op_to_ctxt),
+ )
+ context_kw_set = set()
+ for c, _ in context_kw:
+ context_kw_set |= set(c)
+ # Like func_translate_args.
+ func_context_args = {}
+
# Break recursive nodes look up on some kind of nodes.
# E.g. we don’t want to get strings inside subscripts (blah["foo"])!
stopper_nodes = {ast.Subscript, }
@@ -376,9 +429,11 @@
for func_id, func in bpy.types.UILayout.bl_rna.functions.items():
# check it has one or more arguments as defined in translate_kw
for (arg_pos, (arg_kw, arg)) in enumerate(func.parameters.items()):
- if ((arg_kw in translate_kw) and (arg.is_output is False) and (arg.type == 'STRING')):
+ if ((arg_kw in translate_kw) and (not arg.is_output) and (arg.type == 'STRING')):
func_translate_args.setdefault(func_id, []).append((arg_kw, arg_pos))
- # print(func_translate_args)
+ elif ((arg_kw in context_kw_set) and (not arg.is_output) and (arg.type == 'STRING')):
+ func_context_args.setdefault(func_id, []).append((arg_kw, arg_pos))
+ #print(func_context_args)
check_ctxt_py = None
if check_ctxt:
@@ -387,32 +442,6 @@
"not_capitalized": check_ctxt["not_capitalized"],
"end_point": check_ctxt["end_point"]}
- # Helper function
- def extract_strings(fp_rel, node):
- """
- Recursively get strings, needed in case we have "Blah" + "Blah", passed as an argument in that case it won't
- evaluate to a string. However, break on some kind of stopper nodes, like e.g. Subscript.
- """
- if type(node) == ast.Str:
- eval_str = ast.literal_eval(node)
- if eval_str:
- # Parse optional context included in string!
- # XXX Not yet!
- #if bpy.app.i18n.context_sep in eval_str:
- #key = eval_str.split(bpy.app.i18n.context_sep, 1)
- if 0:
- pass
- else:
- key = (CONTEXT_DEFAULT, eval_str)
- msgsrc = "{}:{}".format(fp_rel, node.lineno)
- check(check_ctxt_py, messages, key, msgsrc)
- messages.setdefault(key, []).append(msgsrc)
- return
-
- for nd in ast.iter_child_nodes(node):
- if type(nd) not in stopper_nodes:
- extract_strings(fp_rel, nd)
-
for fp in files:
with open(fp, 'r', encoding="utf8") as filedata:
root_node = ast.parse(filedata.read(), fp, 'exec')
@@ -432,16 +461,50 @@
if not hasattr(node.func, "attr"):
continue
+ # First try to get i18n context.
+ context_args = func_context_args.get(node.func.attr, ())
+ context = ""
+ context_elements = {}
+ for arg_kw, arg_pos in context_args:
+ if arg_pos < len(node.args):
+ context_elements[arg_kw] = node.args[arg_pos]
+ else:
+ for kw in node.keywords:
+ if kw.arg == arg_kw:
+ context_elements[arg_kw] = kw.value
+ break
+ #print(context_elements)
+ for kws, proc in context_kw:
+ if set(kws) <= context_elements.keys():
+ args = tuple(context_elements[k] for k in kws)
+ #print("running ", proc, " with ", args)
+ ctxt = proc(*args)
+ if ctxt:
+ context = ctxt
+ break
+
translate_args = func_translate_args.get(node.func.attr, ())
-
+ #print(translate_args)
# do nothing if not found
for arg_kw, arg_pos in translate_args:
+ estr, nds = None, ()
if arg_pos < len(node.args):
- extract_strings(fp_rel, node.args[arg_pos])
+ estr, nds = extract_strings(node.args[arg_pos])
+ #print(estr, nds)
else:
for kw in node.keywords:
if kw.arg == arg_kw:
- extract_strings(fp_rel, kw.value)
+ estr, nds = extract_strings(kw.value)
+ break
+ #print(estr, nds)
+ if estr:
+ key = (context, estr)
+ if nds:
+ msgsrc = ["{}:{}".format(fp_rel, sorted({nd.lineno for nd in nds})[0])]
+ else:
+ msgsrc = ["{}:???".format(fp_rel)]
+ check(check_ctxt_py, messages, key, msgsrc)
+ messages.setdefault(key, []).extend(msgsrc)
def dump_py_messages(messages, check_ctxt, addons):
More information about the Bf-blender-cvs
mailing list