1 # ##### BEGIN GPL LICENSE BLOCK #####
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.
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.
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.
17 # ##### END GPL LICENSE BLOCK #####
23 importlib
.reload(settings
)
24 importlib
.reload(utils_i18n
)
27 from bpy
.props
import (
37 from . import settings
38 from bl_i18n_utils
import utils
as utils_i18n
45 # A global cache for I18nMessages objects, as parsing po files takes a few seconds.
49 def _get_messages(lang
, fname
):
50 if fname
not in PO_CACHE
:
51 PO_CACHE
[fname
] = utils_i18n
.I18nMessages(uid
=lang
, kind
='PO', key
=fname
, src
=fname
, settings
=settings
.settings
)
52 return PO_CACHE
[fname
]
55 class UI_OT_i18n_edittranslation_update_mo(bpy
.types
.Operator
):
56 """Try to "compile" given po file into relevant blender.mo file """ \
57 """(WARNING: it will replace the official mo file in your user dir!)"""
58 bl_idname
= "ui.i18n_edittranslation_update_mo"
59 bl_label
= "Edit Translation Update Mo"
62 lang
= StringProperty(description
="Current (translated) language",
63 options
={'SKIP_SAVE'})
64 po_file
= StringProperty(description
="Path to the matching po file",
65 subtype
='FILE_PATH', options
={'SKIP_SAVE'})
66 clean_mo
= BoolProperty(description
="Clean up (remove) all local "
67 "translation files, to be able to use "
68 "all system's ones again",
69 default
=False, options
={'SKIP_SAVE'})
71 def execute(self
, context
):
73 root
= bpy
.utils
.user_resource('DATAFILES', settings
.settings
.MO_PATH_ROOT_RELATIVE
)
76 elif not (self
.lang
and self
.po_file
):
79 mo_dir
= bpy
.utils
.user_resource('DATAFILES', settings
.settings
.MO_PATH_TEMPLATE_RELATIVE
.format(self
.lang
),
81 mo_file
= os
.path
.join(mo_dir
, settings
.settings
.MO_FILE_NAME
)
82 _get_messages(self
.lang
, self
.po_file
).write(kind
='MO', dest
=mo_file
)
84 bpy
.ops
.ui
.reloadtranslation()
88 class UI_OT_i18n_edittranslation(bpy
.types
.Operator
):
89 """Translate the label and tooltip of the property defined by given 'parameters'"""
90 bl_idname
= "ui.edittranslation"
91 bl_label
= "Edit Translation"
94 but_label
= StringProperty(description
="Label of the control", options
={'SKIP_SAVE'})
95 rna_label
= StringProperty(description
="RNA-defined label of the control, if any", options
={'SKIP_SAVE'})
96 enum_label
= StringProperty(description
="Label of the enum item of the control, if any", options
={'SKIP_SAVE'})
97 but_tip
= StringProperty(description
="Tip of the control", options
={'SKIP_SAVE'})
98 rna_tip
= StringProperty(description
="RNA-defined tip of the control, if any", options
={'SKIP_SAVE'})
99 enum_tip
= StringProperty(description
="Tip of the enum item of the control, if any", options
={'SKIP_SAVE'})
100 rna_struct
= StringProperty(description
="Identifier of the RNA struct, if any", options
={'SKIP_SAVE'})
101 rna_prop
= StringProperty(description
="Identifier of the RNA property, if any", options
={'SKIP_SAVE'})
102 rna_enum
= StringProperty(description
="Identifier of the RNA enum item, if any", options
={'SKIP_SAVE'})
103 rna_ctxt
= StringProperty(description
="RNA context for label", options
={'SKIP_SAVE'})
105 lang
= StringProperty(description
="Current (translated) language", options
={'SKIP_SAVE'})
106 po_file
= StringProperty(description
="Path to the matching po file", subtype
='FILE_PATH', options
={'SKIP_SAVE'})
109 org_but_label
= StringProperty(description
="Original label of the control", options
={'SKIP_SAVE'})
110 org_rna_label
= StringProperty(description
="Original RNA-defined label of the control, if any",
111 options
={'SKIP_SAVE'})
112 org_enum_label
= StringProperty(description
="Original label of the enum item of the control, if any",
113 options
={'SKIP_SAVE'})
114 org_but_tip
= StringProperty(description
="Original tip of the control", options
={'SKIP_SAVE'})
115 org_rna_tip
= StringProperty(description
="Original RNA-defined tip of the control, if any", options
={'SKIP_SAVE'})
116 org_enum_tip
= StringProperty(description
="Original tip of the enum item of the control, if any",
117 options
={'SKIP_SAVE'})
119 flag_items
= (('FUZZY', "Fuzzy", "Message is marked as fuzzy in po file"),
120 ('ERROR', "Error", "Some error occurred with this message"),
122 but_label_flags
= EnumProperty(items
=flag_items
, description
="Flags about the label of the button",
123 options
={'SKIP_SAVE', 'ENUM_FLAG'})
124 rna_label_flags
= EnumProperty(items
=flag_items
, description
="Flags about the RNA-defined label of the button",
125 options
={'SKIP_SAVE', 'ENUM_FLAG'})
126 enum_label_flags
= EnumProperty(items
=flag_items
, description
="Flags about the RNA enum item label of the button",
127 options
={'SKIP_SAVE', 'ENUM_FLAG'})
128 but_tip_flags
= EnumProperty(items
=flag_items
, description
="Flags about the tip of the button",
129 options
={'SKIP_SAVE', 'ENUM_FLAG'})
130 rna_tip_flags
= EnumProperty(items
=flag_items
, description
="Flags about the RNA-defined tip of the button",
131 options
={'SKIP_SAVE', 'ENUM_FLAG'})
132 enum_tip_flags
= EnumProperty(items
=flag_items
, description
="Flags about the RNA enum item tip of the button",
133 options
={'SKIP_SAVE', 'ENUM_FLAG'})
135 stats_str
= StringProperty(description
="Stats from opened po", options
={'SKIP_SAVE'})
136 update_po
= BoolProperty(description
="Update po file, try to rebuild mo file, and refresh Blender UI",
137 default
=False, options
={'SKIP_SAVE'})
138 update_mo
= BoolProperty(description
="Try to rebuild mo file, and refresh Blender UI",
139 default
=False, options
={'SKIP_SAVE'})
140 clean_mo
= BoolProperty(description
="Clean up (remove) all local translation files, to be able to use "
141 "all system's ones again",
142 default
=False, options
={'SKIP_SAVE'})
144 def execute(self
, context
):
145 if not hasattr(self
, "msgmap"):
146 self
.report('ERROR', "Looks like you did not invoke this operator first!")
149 msgs
= _get_messages(self
.lang
, self
.po_file
)
151 for mmap
in self
.msgmap
.values():
152 if 'ERROR' in getattr(self
, mmap
["msg_flags"]):
156 if k
not in done_keys
and len(k
) == 1:
158 msgs
.msgs
[k
].msgstr
= getattr(self
, mmap
["msgstr"])
159 msgs
.msgs
[k
].is_fuzzy
= 'FUZZY' in getattr(self
, mmap
["msg_flags"])
163 # Try to overwrite po file, may fail if we have no good rights...
165 msgs
.write(kind
='PO', dest
=self
.po_file
)
166 except Exception as e
:
167 self
.report('ERROR', "Could not write to po file ({})".format(str(e
)))
168 # Always invalidate reverse messages cache afterward!
169 msgs
.invalidate_reverse_cache()
171 lang
= os
.path
.splitext(os
.path
.basename(self
.po_file
))[0]
172 bpy
.ops
.ui
.i18n_edittranslation_update_mo(po_file
=self
.po_file
, lang
=lang
)
174 bpy
.ops
.ui
.i18n_edittranslation_update_mo(clean_mo
=True)
177 def invoke(self
, context
, event
):
178 self
.msgmap
= {"but_label": {"msgstr": "but_label", "msgid": "org_but_label",
179 "msg_flags": "but_label_flags", "key": set()},
180 "rna_label": {"msgstr": "rna_label", "msgid": "org_rna_label",
181 "msg_flags": "rna_label_flags", "key": set()},
182 "enum_label": {"msgstr": "enum_label", "msgid": "org_enum_label",
183 "msg_flags": "enum_label_flags", "key": set()},
184 "but_tip": {"msgstr": "but_tip", "msgid": "org_but_tip",
185 "msg_flags": "but_tip_flags", "key": set()},
186 "rna_tip": {"msgstr": "rna_tip", "msgid": "org_rna_tip",
187 "msg_flags": "rna_tip_flags", "key": set()},
188 "enum_tip": {"msgstr": "enum_tip", "msgid": "org_enum_tip",
189 "msg_flags": "enum_tip_flags", "key": set()},
192 msgs
= _get_messages(self
.lang
, self
.po_file
)
193 msgs
.find_best_messages_matches(self
, self
.msgmap
, self
.rna_ctxt
, self
.rna_struct
, self
.rna_prop
, self
.rna_enum
)
195 self
.stats_str
= "{}: {} messages, {} translated.".format(os
.path
.basename(self
.po_file
), msgs
.nbr_msgs
,
198 for mmap
in self
.msgmap
.values():
199 k
= tuple(mmap
["key"])
204 setattr(self
, mmap
["msgstr"], msgs
.msgs
[k
].msgstr
)
205 setattr(self
, mmap
["msgid"], msgid
)
206 if msgs
.msgs
[k
].is_fuzzy
:
207 setattr(self
, mmap
["msg_flags"], {'FUZZY'})
209 setattr(self
, mmap
["msgid"],
210 "ERROR: Button label “{}” matches several messages in po file ({})!"
211 "".format(self
.but_label
, k
))
212 setattr(self
, mmap
["msg_flags"], {'ERROR'})
214 setattr(self
, mmap
["msgstr"], "")
215 setattr(self
, mmap
["msgid"], "")
217 wm
= context
.window_manager
218 return wm
.invoke_props_dialog(self
, width
=600)
220 def draw(self
, context
):
222 layout
.label(text
=self
.stats_str
)
223 src
, _a
, _b
= bpy
.utils
.make_rna_paths(self
.rna_struct
, self
.rna_prop
, self
.rna_enum
)
225 layout
.label(text
=" RNA Path: bpy.types." + src
)
227 layout
.label(text
=" RNA Context: " + self
.rna_ctxt
)
229 if self
.org_but_label
or self
.org_rna_label
or self
.org_enum_label
:
230 # XXX Can't use box, labels are not enough readable in them :/
233 box
.label(text
="Labels:")
234 split
= box
.split(percentage
=0.15)
235 col1
= split
.column()
236 col2
= split
.column()
237 if self
.org_but_label
:
238 col1
.label(text
="Button Label:")
241 if 'ERROR' in self
.but_label_flags
:
244 col1
.prop_enum(self
, "but_label_flags", 'FUZZY', text
="Fuzzy")
245 col2
.prop(self
, "but_label", text
="")
246 row
.prop(self
, "org_but_label", text
="")
247 if self
.org_rna_label
:
248 col1
.label(text
="RNA Label:")
251 if 'ERROR' in self
.rna_label_flags
:
254 col1
.prop_enum(self
, "rna_label_flags", 'FUZZY', text
="Fuzzy")
255 col2
.prop(self
, "rna_label", text
="")
256 row
.prop(self
, "org_rna_label", text
="")
257 if self
.org_enum_label
:
258 col1
.label(text
="Enum Item Label:")
261 if 'ERROR' in self
.enum_label_flags
:
264 col1
.prop_enum(self
, "enum_label_flags", 'FUZZY', text
="Fuzzy")
265 col2
.prop(self
, "enum_label", text
="")
266 row
.prop(self
, "org_enum_label", text
="")
268 if self
.org_but_tip
or self
.org_rna_tip
or self
.org_enum_tip
:
269 # XXX Can't use box, labels are not enough readable in them :/
272 box
.label(text
="Tool Tips:")
273 split
= box
.split(percentage
=0.15)
274 col1
= split
.column()
275 col2
= split
.column()
277 col1
.label(text
="Button Tip:")
280 if 'ERROR' in self
.but_tip_flags
:
283 col1
.prop_enum(self
, "but_tip_flags", 'FUZZY', text
="Fuzzy")
284 col2
.prop(self
, "but_tip", text
="")
285 row
.prop(self
, "org_but_tip", text
="")
287 col1
.label(text
="RNA Tip:")
290 if 'ERROR' in self
.rna_tip_flags
:
293 col1
.prop_enum(self
, "rna_tip_flags", 'FUZZY', text
="Fuzzy")
294 col2
.prop(self
, "rna_tip", text
="")
295 row
.prop(self
, "org_rna_tip", text
="")
296 if self
.org_enum_tip
:
297 col1
.label(text
="Enum Item Tip:")
300 if 'ERROR' in self
.enum_tip_flags
:
303 col1
.prop_enum(self
, "enum_tip_flags", 'FUZZY', text
="Fuzzy")
304 col2
.prop(self
, "enum_tip", text
="")
305 row
.prop(self
, "org_enum_tip", text
="")
308 row
.prop(self
, "update_po", text
="Save to PO File", toggle
=True)
309 row
.prop(self
, "update_mo", text
="Rebuild MO File", toggle
=True)
310 row
.prop(self
, "clean_mo", text
="Erase Local MO files", toggle
=True)
314 UI_OT_i18n_edittranslation_update_mo
,
315 UI_OT_i18n_edittranslation
,