diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2013-02-24 12:52:19 +0400 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2013-02-24 12:52:19 +0400 |
commit | b39c8c2650111a4dcd3417baf1742b6fac81a08b (patch) | |
tree | 6f51372386c91509b57e93589632890da8e56bdf /ui_translate/edit_translation.py | |
parent | 5b6e54f7d1ff8f2ea13511e023387457b66aa263 (diff) |
Big i18n tools update, II/II.
Now everything should be done with ui_translate addon (which is also now fully functional again, in theory ;) ).
Notes:
* Everything is still a bit raw and sometimes hackish.
* Not every feature implemented yet.
* A bunch of cleanup is still needed.
* Doc needs to be updated too!
Diffstat (limited to 'ui_translate/edit_translation.py')
-rw-r--r-- | ui_translate/edit_translation.py | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/ui_translate/edit_translation.py b/ui_translate/edit_translation.py new file mode 100644 index 00000000..02cde75b --- /dev/null +++ b/ui_translate/edit_translation.py @@ -0,0 +1,309 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# <pep8 compliant> + +if "bpy" in locals(): + import imp + imp.reload(settings) + imp.reload(i18n_utils) +else: + import bpy + from bpy.props import (BoolProperty, + CollectionProperty, + EnumProperty, + FloatProperty, + FloatVectorProperty, + IntProperty, + PointerProperty, + StringProperty, + ) + from . import settings + from bl_i18n_utils import utils as i18n_utils + + +import os +import shutil + + +# A global cache for I18nMessages objects, as parsing po files takes a few seconds. +PO_CACHE = {} + + +def _get_messages(lang, fname): + if fname not in PO_CACHE: + PO_CACHE[fname] = i18n_utils.I18nMessages(uid=lang, kind='PO', key=fname, src=fname, settings=settings.settings) + return PO_CACHE[fname] + + +class UI_OT_i18n_edittranslation_update_mo(bpy.types.Operator): + """Try to "compile" given po file into relevant blender.mo file """ \ + """(WARNING: it will replace the official mo file in your user dir!)""" + bl_idname = "ui.i18n_edittranslation_update_mo" + bl_label = "Edit Translation Update Mo" + + # "Parameters" + lang = StringProperty(description="Current (translated) language", + options={'SKIP_SAVE'}) + po_file = StringProperty(description="Path to the matching po file", + subtype='FILE_PATH', options={'SKIP_SAVE'}) + clean_mo = BoolProperty(description="Clean up (remove) all local " + "translation files, to be able to use " + "all system's ones again", + default=False, options={'SKIP_SAVE'}) + + def execute(self, context): + if self.clean_mo: + root = bpy.utils.user_resource('DATAFILES', settings.settings.MO_PATH_ROOT_RELATIVE) + if root: + shutil.rmtree(root) + elif not (self.lang and self.po_file): + return {'CANCELLED'} + else: + mo_dir = bpy.utils.user_resource('DATAFILES', settings.settings.MO_PATH_TEMPLATE_RELATIVE.format(self.lang), + create=True) + mo_file = os.path.join(mo_dir, settings.settings.MO_FILE_NAME) + _get_messages(self.lang, self.po_file).write(kind='MO', dest=mo_file) + + bpy.ops.ui.reloadtranslation() + return {'FINISHED'} + + +class UI_OT_i18n_edittranslation(bpy.types.Operator): + """Translate the label and tool tip of the property defined by given 'parameters'""" + bl_idname = "ui.edittranslation" + bl_label = "Edit Translation" + + # "Parameters" + but_label = StringProperty(description="Label of the control", options={'SKIP_SAVE'}) + rna_label = StringProperty(description="RNA-defined label of the control, if any", options={'SKIP_SAVE'}) + enum_label = StringProperty(description="Label of the enum item of the control, if any", options={'SKIP_SAVE'}) + but_tip = StringProperty(description="Tip of the control", options={'SKIP_SAVE'}) + rna_tip = StringProperty(description="RNA-defined tip of the control, if any", options={'SKIP_SAVE'}) + enum_tip = StringProperty(description="Tip of the enum item of the control, if any", options={'SKIP_SAVE'}) + rna_struct = StringProperty(description="Identifier of the RNA struct, if any", options={'SKIP_SAVE'}) + rna_prop = StringProperty(description="Identifier of the RNA property, if any", options={'SKIP_SAVE'}) + rna_enum = StringProperty(description="Identifier of the RNA enum item, if any", options={'SKIP_SAVE'}) + rna_ctxt = StringProperty(description="RNA context for label", options={'SKIP_SAVE'}) + + lang = StringProperty(description="Current (translated) language", options={'SKIP_SAVE'}) + po_file = StringProperty(description="Path to the matching po file", subtype='FILE_PATH', options={'SKIP_SAVE'}) + + # Found in po file. + org_but_label = StringProperty(description="Original label of the control", options={'SKIP_SAVE'}) + org_rna_label = StringProperty(description="Original RNA-defined label of the control, if any", + options={'SKIP_SAVE'}) + org_enum_label = StringProperty(description="Original label of the enum item of the control, if any", + options={'SKIP_SAVE'}) + org_but_tip = StringProperty(description="Original tip of the control", options={'SKIP_SAVE'}) + org_rna_tip = StringProperty(description="Original RNA-defined tip of the control, if any", options={'SKIP_SAVE'}) + org_enum_tip = StringProperty(description="Original tip of the enum item of the control, if any", + options={'SKIP_SAVE'}) + + flag_items = (('FUZZY', "Fuzzy", "Message is marked as fuzzy in po file"), + ('ERROR', "Error", "Some error occurred with this message"), + ) + but_label_flags = EnumProperty(items=flag_items, description="Flags about the label of the button", + options={'SKIP_SAVE', 'ENUM_FLAG'}) + rna_label_flags = EnumProperty(items=flag_items, description="Flags about the RNA-defined label of the button", + options={'SKIP_SAVE', 'ENUM_FLAG'}) + enum_label_flags = EnumProperty(items=flag_items, description="Flags about the RNA enum item label of the button", + options={'SKIP_SAVE', 'ENUM_FLAG'}) + but_tip_flags = EnumProperty(items=flag_items, description="Flags about the tip of the button", + options={'SKIP_SAVE', 'ENUM_FLAG'}) + rna_tip_flags = EnumProperty(items=flag_items, description="Flags about the RNA-defined tip of the button", + options={'SKIP_SAVE', 'ENUM_FLAG'}) + enum_tip_flags = EnumProperty(items=flag_items, description="Flags about the RNA enum item tip of the button", + options={'SKIP_SAVE', 'ENUM_FLAG'}) + + stats_str = StringProperty(description="Stats from opened po", options={'SKIP_SAVE'}) + update_po = BoolProperty(description="Update po file, try to rebuild mo file, and refresh Blender UI", + default=False, options={'SKIP_SAVE'}) + update_mo = BoolProperty(description="Try to rebuild mo file, and refresh Blender UI", + default=False, options={'SKIP_SAVE'}) + clean_mo = BoolProperty(description="Clean up (remove) all local translation files, to be able to use " + "all system's ones again", + default=False, options={'SKIP_SAVE'}) + + def execute(self, context): + if not hasattr(self, "msgmap"): + self.report('ERROR', "Looks like you did not invoke this operator first!") + return {'CANCELLED'} + + msgs = _get_messages(self.lang, self.po_file) + done_keys = set() + for mmap in self.msgmap.values(): + if 'ERROR' in getattr(self, mmap["msg_flags"]): + continue + k = mmap["key"] +# print(k) + if k not in done_keys and len(k) == 1: + k = tuple(k)[0] + msgs.msgs[k].msgstr = getattr(self, mmap["msgstr"]) + msgs.msgs[k].is_fuzzy = 'FUZZY' in getattr(self, mmap["msg_flags"]) + done_keys.add(k) + + if self.update_po: + # Try to overwrite po file, may fail if we have no good rights... + try: + msgs.write(kind='PO', dest=self.po_file) + except Exception as e: + self.report('ERROR', "Could not write to po file ({})".format(str(e))) + # Always invalidate reverse messages cache afterward! + msgs.invalidate_reverse_cache() + if self.update_mo: + lang = os.path.splitext(os.path.basename(self.po_file))[0] + bpy.ops.ui.i18n_edittranslation_update_mo(po_file=self.po_file, lang=lang) + elif self.clean_mo: + bpy.ops.ui.i18n_edittranslation_update_mo(clean_mo=True) + return {'FINISHED'} + + def invoke(self, context, event): + self.msgmap = {"but_label": {"msgstr": "but_label", "msgid": "org_but_label", + "msg_flags": "but_label_flags", "key": set()}, + "rna_label": {"msgstr": "rna_label", "msgid": "org_rna_label", + "msg_flags": "rna_label_flags", "key": set()}, + "enum_label": {"msgstr": "enum_label", "msgid": "org_enum_label", + "msg_flags": "enum_label_flags", "key": set()}, + "but_tip": {"msgstr": "but_tip", "msgid": "org_but_tip", + "msg_flags": "but_tip_flags", "key": set()}, + "rna_tip": {"msgstr": "rna_tip", "msgid": "org_rna_tip", + "msg_flags": "rna_tip_flags", "key": set()}, + "enum_tip": {"msgstr": "enum_tip", "msgid": "org_enum_tip", + "msg_flags": "enum_tip_flags", "key": set()}, + } + + msgs = _get_messages(self.lang, self.po_file) + msgs.find_best_messages_matches(self, self.msgmap, self.rna_ctxt, self.rna_struct, self.rna_prop, self.rna_enum) + msgs.update_info() + self.stats_str = "{}: {} messages, {} translated.".format(os.path.basename(self.po_file), msgs.nbr_msgs, + msgs.nbr_trans_msgs) + + for mmap in self.msgmap.values(): + k = tuple(mmap["key"]) + if k: + if len(k) == 1: + k = k[0] + ctxt, msgid = k + setattr(self, mmap["msgstr"], msgs.msgs[k].msgstr) + setattr(self, mmap["msgid"], msgid) + if msgs.msgs[k].is_fuzzy: + setattr(self, mmap["msg_flags"], {'FUZZY'}) + else: + setattr(self, mmap["msgid"], + "ERROR: Button label “{}” matches several messages in po file ({})!" + "".format(self.but_label, k)) + setattr(self, mmap["msg_flags"], {'ERROR'}) + else: + setattr(self, mmap["msgstr"], "") + setattr(self, mmap["msgid"], "") + + wm = context.window_manager + return wm.invoke_props_dialog(self, width=600) + + def draw(self, context): + layout = self.layout + layout.label(text=self.stats_str) + src, _a, _b = bpy.utils.make_rna_paths(self.rna_struct, self.rna_prop, self.rna_enum) + if src: + layout.label(text=" RNA Path: bpy.types." + src) + if self.rna_ctxt: + layout.label(text=" RNA Context: " + self.rna_ctxt) + + if self.org_but_label or self.org_rna_label or self.org_enum_label: + # XXX Can't use box, labels are not enough readable in them :/ + box = layout.box() + #box = layout + box.label(text="Labels:") + split = box.split(percentage=0.15) + col1 = split.column() + col2 = split.column() + if self.org_but_label: + col1.label(text="Button Label:") + row = col2.row() + row.enabled = False + if 'ERROR' in self.but_label_flags: + row.alert = True + else: + col1.prop_enum(self, "but_label_flags", 'FUZZY', text="Fuzzy") + col2.prop(self, "but_label", text="") + row.prop(self, "org_but_label", text="") + if self.org_rna_label: + col1.label(text="RNA Label:") + row = col2.row() + row.enabled = False + if 'ERROR' in self.rna_label_flags: + row.alert = True + else: + col1.prop_enum(self, "rna_label_flags", 'FUZZY', text="Fuzzy") + col2.prop(self, "rna_label", text="") + row.prop(self, "org_rna_label", text="") + if self.org_enum_label: + col1.label(text="Enum Item Label:") + row = col2.row() + row.enabled = False + if 'ERROR' in self.enum_label_flags: + row.alert = True + else: + col1.prop_enum(self, "enum_label_flags", 'FUZZY', text="Fuzzy") + col2.prop(self, "enum_label", text="") + row.prop(self, "org_enum_label", text="") + + if self.org_but_tip or self.org_rna_tip or self.org_enum_tip: + # XXX Can't use box, labels are not enough readable in them :/ + box = layout.box() + #box = layout + box.label(text="Tool Tips:") + split = box.split(percentage=0.15) + col1 = split.column() + col2 = split.column() + if self.org_but_tip: + col1.label(text="Button Tip:") + row = col2.row() + row.enabled = False + if 'ERROR' in self.but_tip_flags: + row.alert = True + else: + col1.prop_enum(self, "but_tip_flags", 'FUZZY', text="Fuzzy") + col2.prop(self, "but_tip", text="") + row.prop(self, "org_but_tip", text="") + if self.org_rna_tip: + col1.label(text="RNA Tip:") + row = col2.row() + row.enabled = False + if 'ERROR' in self.rna_tip_flags: + row.alert = True + else: + col1.prop_enum(self, "rna_tip_flags", 'FUZZY', text="Fuzzy") + col2.prop(self, "rna_tip", text="") + row.prop(self, "org_rna_tip", text="") + if self.org_enum_tip: + col1.label(text="Enum Item Tip:") + row = col2.row() + row.enabled = False + if 'ERROR' in self.enum_tip_flags: + row.alert = True + else: + col1.prop_enum(self, "enum_tip_flags", 'FUZZY', text="Fuzzy") + col2.prop(self, "enum_tip", text="") + row.prop(self, "org_enum_tip", text="") + + row = layout.row() + row.prop(self, "update_po", text="Save to PO File", toggle=True) + row.prop(self, "update_mo", text="Rebuild MO File", toggle=True) + row.prop(self, "clean_mo", text="Erase Local MO files", toggle=True) |