~ubuntu-branches/ubuntu/trusty/blender/trusty-proposed

« back to all changes in this revision

Viewing changes to release/scripts/addons/ui_translate/edit_translation.py

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2013-08-14 10:43:49 UTC
  • mfrom: (14.2.19 sid)
  • Revision ID: package-import@ubuntu.com-20130814104349-t1d5mtwkphp12dyj
Tags: 2.68a-3
* Upload to unstable
* debian/: python3.3 Depends simplified
  - debian/control: python3.3 Depends dropped
    for blender-data package
  - 0001-blender_thumbnailer.patch refreshed
* debian/control: libavcodec b-dep versioning dropped

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# ##### BEGIN GPL LICENSE BLOCK #####
 
2
#
 
3
#  This program is free software; you can redistribute it and/or
 
4
#  modify it under the terms of the GNU General Public License
 
5
#  as published by the Free Software Foundation; either version 2
 
6
#  of the License, or (at your option) any later version.
 
7
#
 
8
#  This program is distributed in the hope that it will be useful,
 
9
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
#  GNU General Public License for more details.
 
12
#
 
13
#  You should have received a copy of the GNU General Public License
 
14
#  along with this program; if not, write to the Free Software Foundation,
 
15
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
16
#
 
17
# ##### END GPL LICENSE BLOCK #####
 
18
 
 
19
# <pep8 compliant>
 
20
 
 
21
if "bpy" in locals():
 
22
    import imp
 
23
    imp.reload(settings)
 
24
    imp.reload(utils_i18n)
 
25
else:
 
26
    import bpy
 
27
    from bpy.props import (BoolProperty,
 
28
                           CollectionProperty,
 
29
                           EnumProperty,
 
30
                           FloatProperty,
 
31
                           FloatVectorProperty,
 
32
                           IntProperty,
 
33
                           PointerProperty,
 
34
                           StringProperty,
 
35
                           )
 
36
    from . import settings
 
37
    from bl_i18n_utils import utils as utils_i18n
 
38
 
 
39
 
 
40
import os
 
41
import shutil
 
42
 
 
43
 
 
44
# A global cache for I18nMessages objects, as parsing po files takes a few seconds.
 
45
PO_CACHE = {}
 
46
 
 
47
 
 
48
def _get_messages(lang, fname):
 
49
    if fname not in PO_CACHE:
 
50
        PO_CACHE[fname] = utils_i18n.I18nMessages(uid=lang, kind='PO', key=fname, src=fname, settings=settings.settings)
 
51
    return PO_CACHE[fname]
 
52
 
 
53
 
 
54
class UI_OT_i18n_edittranslation_update_mo(bpy.types.Operator):
 
55
    """Try to "compile" given po file into relevant blender.mo file """ \
 
56
    """(WARNING: it will replace the official mo file in your user dir!)"""
 
57
    bl_idname = "ui.i18n_edittranslation_update_mo"
 
58
    bl_label = "Edit Translation Update Mo"
 
59
 
 
60
    # "Parameters"
 
61
    lang = StringProperty(description="Current (translated) language",
 
62
                          options={'SKIP_SAVE'})
 
63
    po_file = StringProperty(description="Path to the matching po file",
 
64
                             subtype='FILE_PATH', options={'SKIP_SAVE'})
 
65
    clean_mo = BoolProperty(description="Clean up (remove) all local "
 
66
                                        "translation files, to be able to use "
 
67
                                        "all system's ones again",
 
68
                            default=False, options={'SKIP_SAVE'})
 
69
 
 
70
    def execute(self, context):
 
71
        if self.clean_mo:
 
72
            root = bpy.utils.user_resource('DATAFILES', settings.settings.MO_PATH_ROOT_RELATIVE)
 
73
            if root:
 
74
                shutil.rmtree(root)
 
75
        elif not (self.lang and self.po_file):
 
76
            return {'CANCELLED'}
 
77
        else:
 
78
            mo_dir = bpy.utils.user_resource('DATAFILES', settings.settings.MO_PATH_TEMPLATE_RELATIVE.format(self.lang),
 
79
                                             create=True)
 
80
            mo_file = os.path.join(mo_dir, settings.settings.MO_FILE_NAME)
 
81
            _get_messages(self.lang, self.po_file).write(kind='MO', dest=mo_file)
 
82
 
 
83
        bpy.ops.ui.reloadtranslation()
 
84
        return {'FINISHED'}
 
85
 
 
86
 
 
87
class UI_OT_i18n_edittranslation(bpy.types.Operator):
 
88
    """Translate the label and tool tip of the property defined by given 'parameters'"""
 
89
    bl_idname = "ui.edittranslation"
 
90
    bl_label = "Edit Translation"
 
91
 
 
92
    # "Parameters"
 
93
    but_label = StringProperty(description="Label of the control", options={'SKIP_SAVE'})
 
94
    rna_label = StringProperty(description="RNA-defined label of the control, if any", options={'SKIP_SAVE'})
 
95
    enum_label = StringProperty(description="Label of the enum item of the control, if any", options={'SKIP_SAVE'})
 
96
    but_tip = StringProperty(description="Tip of the control", options={'SKIP_SAVE'})
 
97
    rna_tip = StringProperty(description="RNA-defined tip of the control, if any", options={'SKIP_SAVE'})
 
98
    enum_tip = StringProperty(description="Tip of the enum item of the control, if any", options={'SKIP_SAVE'})
 
99
    rna_struct = StringProperty(description="Identifier of the RNA struct, if any", options={'SKIP_SAVE'})
 
100
    rna_prop = StringProperty(description="Identifier of the RNA property, if any", options={'SKIP_SAVE'})
 
101
    rna_enum = StringProperty(description="Identifier of the RNA enum item, if any", options={'SKIP_SAVE'})
 
102
    rna_ctxt = StringProperty(description="RNA context for label", options={'SKIP_SAVE'})
 
103
 
 
104
    lang = StringProperty(description="Current (translated) language", options={'SKIP_SAVE'})
 
105
    po_file = StringProperty(description="Path to the matching po file", subtype='FILE_PATH', options={'SKIP_SAVE'})
 
106
 
 
107
    # Found in po file.
 
108
    org_but_label = StringProperty(description="Original label of the control", options={'SKIP_SAVE'})
 
109
    org_rna_label = StringProperty(description="Original RNA-defined label of the control, if any",
 
110
                                   options={'SKIP_SAVE'})
 
111
    org_enum_label = StringProperty(description="Original label of the enum item of the control, if any",
 
112
                                    options={'SKIP_SAVE'})
 
113
    org_but_tip = StringProperty(description="Original tip of the control", options={'SKIP_SAVE'})
 
114
    org_rna_tip = StringProperty(description="Original RNA-defined tip of the control, if any", options={'SKIP_SAVE'})
 
115
    org_enum_tip = StringProperty(description="Original tip of the enum item of the control, if any",
 
116
                                  options={'SKIP_SAVE'})
 
117
 
 
118
    flag_items = (('FUZZY', "Fuzzy", "Message is marked as fuzzy in po file"),
 
119
                  ('ERROR', "Error", "Some error occurred with this message"),
 
120
                 )
 
121
    but_label_flags = EnumProperty(items=flag_items, description="Flags about the label of the button",
 
122
                                   options={'SKIP_SAVE', 'ENUM_FLAG'})
 
123
    rna_label_flags = EnumProperty(items=flag_items, description="Flags about the RNA-defined label of the button",
 
124
                                   options={'SKIP_SAVE', 'ENUM_FLAG'})
 
125
    enum_label_flags = EnumProperty(items=flag_items, description="Flags about the RNA enum item label of the button",
 
126
                                    options={'SKIP_SAVE', 'ENUM_FLAG'})
 
127
    but_tip_flags = EnumProperty(items=flag_items, description="Flags about the tip of the button",
 
128
                                 options={'SKIP_SAVE', 'ENUM_FLAG'})
 
129
    rna_tip_flags = EnumProperty(items=flag_items, description="Flags about the RNA-defined tip of the button",
 
130
                                 options={'SKIP_SAVE', 'ENUM_FLAG'})
 
131
    enum_tip_flags = EnumProperty(items=flag_items, description="Flags about the RNA enum item tip of the button",
 
132
                                  options={'SKIP_SAVE', 'ENUM_FLAG'})
 
133
 
 
134
    stats_str = StringProperty(description="Stats from opened po", options={'SKIP_SAVE'})
 
135
    update_po = BoolProperty(description="Update po file, try to rebuild mo file, and refresh Blender UI",
 
136
                             default=False, options={'SKIP_SAVE'})
 
137
    update_mo = BoolProperty(description="Try to rebuild mo file, and refresh Blender UI",
 
138
                             default=False, options={'SKIP_SAVE'})
 
139
    clean_mo = BoolProperty(description="Clean up (remove) all local translation files, to be able to use "
 
140
                                        "all system's ones again",
 
141
                            default=False, options={'SKIP_SAVE'})
 
142
 
 
143
    def execute(self, context):
 
144
        if not hasattr(self, "msgmap"):
 
145
            self.report('ERROR', "Looks like you did not invoke this operator first!")
 
146
            return {'CANCELLED'}
 
147
 
 
148
        msgs = _get_messages(self.lang, self.po_file)
 
149
        done_keys = set()
 
150
        for mmap in self.msgmap.values():
 
151
            if 'ERROR' in getattr(self, mmap["msg_flags"]):
 
152
                continue
 
153
            k = mmap["key"]
 
154
#            print(k)
 
155
            if k not in done_keys and len(k) == 1:
 
156
                k = tuple(k)[0]
 
157
                msgs.msgs[k].msgstr = getattr(self, mmap["msgstr"])
 
158
                msgs.msgs[k].is_fuzzy = 'FUZZY' in getattr(self, mmap["msg_flags"])
 
159
                done_keys.add(k)
 
160
 
 
161
        if self.update_po:
 
162
            # Try to overwrite po file, may fail if we have no good rights...
 
163
            try:
 
164
                msgs.write(kind='PO', dest=self.po_file)
 
165
            except Exception as e:
 
166
                self.report('ERROR', "Could not write to po file ({})".format(str(e)))
 
167
            # Always invalidate reverse messages cache afterward!
 
168
            msgs.invalidate_reverse_cache()
 
169
        if self.update_mo:
 
170
            lang = os.path.splitext(os.path.basename(self.po_file))[0]
 
171
            bpy.ops.ui.i18n_edittranslation_update_mo(po_file=self.po_file, lang=lang)
 
172
        elif self.clean_mo:
 
173
            bpy.ops.ui.i18n_edittranslation_update_mo(clean_mo=True)
 
174
        return {'FINISHED'}
 
175
 
 
176
    def invoke(self, context, event):
 
177
        self.msgmap = {"but_label": {"msgstr": "but_label", "msgid": "org_but_label",
 
178
                                     "msg_flags": "but_label_flags", "key": set()},
 
179
                       "rna_label": {"msgstr": "rna_label", "msgid": "org_rna_label",
 
180
                                     "msg_flags": "rna_label_flags", "key": set()},
 
181
                       "enum_label": {"msgstr": "enum_label", "msgid": "org_enum_label",
 
182
                                      "msg_flags": "enum_label_flags", "key": set()},
 
183
                       "but_tip": {"msgstr": "but_tip", "msgid": "org_but_tip",
 
184
                                   "msg_flags": "but_tip_flags", "key": set()},
 
185
                       "rna_tip": {"msgstr": "rna_tip", "msgid": "org_rna_tip",
 
186
                                   "msg_flags": "rna_tip_flags", "key": set()},
 
187
                       "enum_tip": {"msgstr": "enum_tip", "msgid": "org_enum_tip",
 
188
                                    "msg_flags": "enum_tip_flags", "key": set()},
 
189
                      }
 
190
 
 
191
        msgs = _get_messages(self.lang, self.po_file)
 
192
        msgs.find_best_messages_matches(self, self.msgmap, self.rna_ctxt, self.rna_struct, self.rna_prop, self.rna_enum)
 
193
        msgs.update_info()
 
194
        self.stats_str = "{}: {} messages, {} translated.".format(os.path.basename(self.po_file), msgs.nbr_msgs,
 
195
                                                                  msgs.nbr_trans_msgs)
 
196
 
 
197
        for mmap in self.msgmap.values():
 
198
            k = tuple(mmap["key"])
 
199
            if k:
 
200
                if len(k) == 1:
 
201
                    k = k[0]
 
202
                    ctxt, msgid = k
 
203
                    setattr(self, mmap["msgstr"], msgs.msgs[k].msgstr)
 
204
                    setattr(self, mmap["msgid"], msgid)
 
205
                    if msgs.msgs[k].is_fuzzy:
 
206
                        setattr(self, mmap["msg_flags"], {'FUZZY'})
 
207
                else:
 
208
                    setattr(self, mmap["msgid"],
 
209
                            "ERROR: Button label “{}” matches several messages in po file ({})!"
 
210
                            "".format(self.but_label, k))
 
211
                    setattr(self, mmap["msg_flags"], {'ERROR'})
 
212
            else:
 
213
                setattr(self, mmap["msgstr"], "")
 
214
                setattr(self, mmap["msgid"], "")
 
215
 
 
216
        wm = context.window_manager
 
217
        return wm.invoke_props_dialog(self, width=600)
 
218
 
 
219
    def draw(self, context):
 
220
        layout = self.layout
 
221
        layout.label(text=self.stats_str)
 
222
        src, _a, _b = bpy.utils.make_rna_paths(self.rna_struct, self.rna_prop, self.rna_enum)
 
223
        if src:
 
224
            layout.label(text="    RNA Path: bpy.types." + src)
 
225
        if self.rna_ctxt:
 
226
            layout.label(text="    RNA Context: " + self.rna_ctxt)
 
227
 
 
228
        if self.org_but_label or self.org_rna_label or self.org_enum_label:
 
229
            # XXX Can't use box, labels are not enough readable in them :/
 
230
            box = layout.box()
 
231
            #box = layout
 
232
            box.label(text="Labels:")
 
233
            split = box.split(percentage=0.15)
 
234
            col1 = split.column()
 
235
            col2 = split.column()
 
236
            if self.org_but_label:
 
237
                col1.label(text="Button Label:")
 
238
                row = col2.row()
 
239
                row.enabled = False
 
240
                if 'ERROR' in self.but_label_flags:
 
241
                    row.alert = True
 
242
                else:
 
243
                    col1.prop_enum(self, "but_label_flags", 'FUZZY', text="Fuzzy")
 
244
                    col2.prop(self, "but_label", text="")
 
245
                row.prop(self, "org_but_label", text="")
 
246
            if self.org_rna_label:
 
247
                col1.label(text="RNA Label:")
 
248
                row = col2.row()
 
249
                row.enabled = False
 
250
                if 'ERROR' in self.rna_label_flags:
 
251
                    row.alert = True
 
252
                else:
 
253
                    col1.prop_enum(self, "rna_label_flags", 'FUZZY', text="Fuzzy")
 
254
                    col2.prop(self, "rna_label", text="")
 
255
                row.prop(self, "org_rna_label", text="")
 
256
            if self.org_enum_label:
 
257
                col1.label(text="Enum Item Label:")
 
258
                row = col2.row()
 
259
                row.enabled = False
 
260
                if 'ERROR' in self.enum_label_flags:
 
261
                    row.alert = True
 
262
                else:
 
263
                    col1.prop_enum(self, "enum_label_flags", 'FUZZY', text="Fuzzy")
 
264
                    col2.prop(self, "enum_label", text="")
 
265
                row.prop(self, "org_enum_label", text="")
 
266
 
 
267
        if self.org_but_tip or self.org_rna_tip or self.org_enum_tip:
 
268
            # XXX Can't use box, labels are not enough readable in them :/
 
269
            box = layout.box()
 
270
            #box = layout
 
271
            box.label(text="Tool Tips:")
 
272
            split = box.split(percentage=0.15)
 
273
            col1 = split.column()
 
274
            col2 = split.column()
 
275
            if self.org_but_tip:
 
276
                col1.label(text="Button Tip:")
 
277
                row = col2.row()
 
278
                row.enabled = False
 
279
                if 'ERROR' in self.but_tip_flags:
 
280
                    row.alert = True
 
281
                else:
 
282
                    col1.prop_enum(self, "but_tip_flags", 'FUZZY', text="Fuzzy")
 
283
                    col2.prop(self, "but_tip", text="")
 
284
                row.prop(self, "org_but_tip", text="")
 
285
            if self.org_rna_tip:
 
286
                col1.label(text="RNA Tip:")
 
287
                row = col2.row()
 
288
                row.enabled = False
 
289
                if 'ERROR' in self.rna_tip_flags:
 
290
                    row.alert = True
 
291
                else:
 
292
                    col1.prop_enum(self, "rna_tip_flags", 'FUZZY', text="Fuzzy")
 
293
                    col2.prop(self, "rna_tip", text="")
 
294
                row.prop(self, "org_rna_tip", text="")
 
295
            if self.org_enum_tip:
 
296
                col1.label(text="Enum Item Tip:")
 
297
                row = col2.row()
 
298
                row.enabled = False
 
299
                if 'ERROR' in self.enum_tip_flags:
 
300
                    row.alert = True
 
301
                else:
 
302
                    col1.prop_enum(self, "enum_tip_flags", 'FUZZY', text="Fuzzy")
 
303
                    col2.prop(self, "enum_tip", text="")
 
304
                row.prop(self, "org_enum_tip", text="")
 
305
 
 
306
        row = layout.row()
 
307
        row.prop(self, "update_po", text="Save to PO File", toggle=True)
 
308
        row.prop(self, "update_mo", text="Rebuild MO File", toggle=True)
 
309
        row.prop(self, "clean_mo", text="Erase Local MO files", toggle=True)