1 # SPDX-License-Identifier: GPL-2.0-or-later
5 importlib
.reload(settings
)
6 importlib
.reload(utils_i18n
)
7 importlib
.reload(utils_languages_menu
)
10 from bpy
.types
import Operator
11 from bpy
.props
import (
15 from . import settings
16 from bl_i18n_utils
import utils
as utils_i18n
17 from bl_i18n_utils
import utils_languages_menu
19 import concurrent
.futures
27 # Operators ###################################################################
29 def i18n_updatetranslation_svn_branches_callback(pot
, lng
, settings
):
32 if os
.path
.isfile(lng
['po_path']):
33 po
= utils_i18n
.I18nMessages(uid
=lng
['uid'], kind
='PO', src
=lng
['po_path'], settings
=settings
)
37 po
.write(kind
="PO", dest
=lng
['po_path'])
38 print("{} PO written!".format(lng
['uid']))
41 class UI_OT_i18n_updatetranslation_svn_branches(Operator
):
42 """Update i18n svn's branches (po files)"""
43 bl_idname
= "ui.i18n_updatetranslation_svn_branches"
44 bl_label
= "Update I18n Branches"
46 use_skip_pot_gen
: BoolProperty(
48 description
="Skip POT file generation",
52 def execute(self
, context
):
53 if not hasattr(self
, "settings"):
54 self
.settings
= settings
.settings
55 i18n_sett
= context
.window_manager
.i18n_update_svn_settings
56 self
.settings
.FILE_NAME_POT
= i18n_sett
.pot_path
58 context
.window_manager
.progress_begin(0, len(i18n_sett
.langs
) + 1)
59 context
.window_manager
.progress_update(0)
60 if not self
.use_skip_pot_gen
:
61 env
= os
.environ
.copy()
62 env
["ASAN_OPTIONS"] = "exitcode=0:" + os
.environ
.get("ASAN_OPTIONS", "")
63 # Generate base pot from RNA messages (we use another blender instance here, to be able to perfectly
64 # control our environment (factory startup, specific addons enabled/disabled...)).
65 # However, we need to export current user settings about this addon!
71 os
.path
.join(os
.path
.dirname(utils_i18n
.__file
__), "bl_extract_messages.py"),
74 self
.settings
.to_json(),
76 # Not working (UI is not refreshed...).
77 #self.report({'INFO'}, "Extracting messages, this will take some time...")
78 context
.window_manager
.progress_update(1)
79 ret
= subprocess
.run(cmmd
, env
=env
)
80 if ret
.returncode
!= 0:
81 self
.report({'ERROR'}, "Message extraction process failed!")
82 context
.window_manager
.progress_end()
85 # Now we should have a valid POT file, we have to merge it in all languages po's...
86 with concurrent
.futures
.ProcessPoolExecutor() as exctr
:
87 pot
= utils_i18n
.I18nMessages(kind
='PO', src
=self
.settings
.FILE_NAME_POT
, settings
=self
.settings
)
88 num_langs
= len(i18n_sett
.langs
)
89 for progress
, _
in enumerate(exctr
.map(i18n_updatetranslation_svn_branches_callback
,
91 [dict(lng
.items()) for lng
in i18n_sett
.langs
],
92 (self
.settings
,) * num_langs
,
94 context
.window_manager
.progress_update(progress
+ 2)
95 context
.window_manager
.progress_end()
98 def invoke(self
, context
, event
):
99 wm
= context
.window_manager
100 return wm
.invoke_props_dialog(self
)
103 def i18n_cleanuptranslation_svn_branches_callback(lng
, settings
):
105 print("Skipping {} language ({}).".format(lng
['name'], lng
['uid']))
107 po
= utils_i18n
.I18nMessages(uid
=lng
['uid'], kind
='PO', src
=lng
['po_path'], settings
=settings
)
108 errs
= po
.check(fix
=True)
109 cleanedup_commented
= po
.clean_commented()
110 po
.write(kind
="PO", dest
=lng
['po_path'])
111 print("Processing {} language ({}).\n"
112 "Cleaned up {} commented messages.\n".format(lng
['name'], lng
['uid'], cleanedup_commented
) +
113 ("Errors in this po, solved as best as possible!\n\t" + "\n\t".join(errs
) if errs
else "") + "\n")
116 class UI_OT_i18n_cleanuptranslation_svn_branches(Operator
):
117 """Clean up i18n svn's branches (po files)"""
118 bl_idname
= "ui.i18n_cleanuptranslation_svn_branches"
119 bl_label
= "Clean up I18n Branches"
121 def execute(self
, context
):
122 if not hasattr(self
, "settings"):
123 self
.settings
= settings
.settings
124 i18n_sett
= context
.window_manager
.i18n_update_svn_settings
125 # 'DEFAULT' and en_US are always valid, fully-translated "languages"!
126 stats
= {"DEFAULT": 1.0, "en_US": 1.0}
128 context
.window_manager
.progress_begin(0, len(i18n_sett
.langs
) + 1)
129 context
.window_manager
.progress_update(0)
130 with concurrent
.futures
.ProcessPoolExecutor() as exctr
:
131 num_langs
= len(i18n_sett
.langs
)
132 for progress
, _
in enumerate(exctr
.map(i18n_cleanuptranslation_svn_branches_callback
,
133 [dict(lng
.items()) for lng
in i18n_sett
.langs
],
134 (self
.settings
,) * num_langs
,
136 context
.window_manager
.progress_update(progress
+ 1)
138 context
.window_manager
.progress_end()
143 def i18n_updatetranslation_svn_trunk_callback(lng
, settings
):
145 if lng
['uid'] in settings
.IMPORT_LANGUAGES_SKIP
:
146 reports
.append("Skipping {} language ({}), edit settings if you want to enable it.".format(lng
['name'], lng
['uid']))
147 return lng
['uid'], 0.0, reports
149 reports
.append("Skipping {} language ({}).".format(lng
['name'], lng
['uid']))
150 return lng
['uid'], 0.0, reports
151 po
= utils_i18n
.I18nMessages(uid
=lng
['uid'], kind
='PO', src
=lng
['po_path'], settings
=settings
)
152 errs
= po
.check(fix
=True)
153 reports
.append("Processing {} language ({}).\n"
154 "Cleaned up {} commented messages.\n".format(lng
['name'], lng
['uid'], po
.clean_commented()) +
155 ("Errors in this po, solved as best as possible!\n\t" + "\n\t".join(errs
) if errs
else ""))
156 if lng
['uid'] in settings
.IMPORT_LANGUAGES_RTL
:
157 po
.write(kind
="PO", dest
=lng
['po_path_trunk'][:-3] + "_raw.po")
159 po
.write(kind
="PO", dest
=lng
['po_path_trunk'])
160 po
.write(kind
="PO_COMPACT", dest
=lng
['po_path_git'])
161 ret
= po
.write(kind
="MO", dest
=lng
['mo_path_trunk'])
163 reports
.append(ret
.stdout
.decode().rstrip("\n"))
165 stderr_str
= ret
.stderr
.decode().rstrip("\n")
166 if ret
.returncode
!= 0:
167 reports
.append("ERROR: " + stderr_str
)
169 reports
.append(stderr_str
)
171 return lng
['uid'], po
.nbr_trans_msgs
/ po
.nbr_msgs
, reports
174 class UI_OT_i18n_updatetranslation_svn_trunk(Operator
):
175 """Update i18n svn's branches (po files)"""
176 bl_idname
= "ui.i18n_updatetranslation_svn_trunk"
177 bl_label
= "Update I18n Trunk"
179 def execute(self
, context
):
180 if not hasattr(self
, "settings"):
181 self
.settings
= settings
.settings
182 i18n_sett
= context
.window_manager
.i18n_update_svn_settings
183 # 'DEFAULT' and en_US are always valid, fully-translated "languages"!
184 stats
= {"DEFAULT": 1.0, "en_US": 1.0}
186 context
.window_manager
.progress_begin(0, len(i18n_sett
.langs
) + 1)
187 context
.window_manager
.progress_update(0)
188 with concurrent
.futures
.ProcessPoolExecutor() as exctr
:
189 num_langs
= len(i18n_sett
.langs
)
190 for progress
, (lng_uid
, stats_val
, reports
) in enumerate(exctr
.map(i18n_updatetranslation_svn_trunk_callback
,
191 [dict(lng
.items()) for lng
in i18n_sett
.langs
],
192 (self
.settings
,) * num_langs
,
194 context
.window_manager
.progress_update(progress
+ 1)
195 stats
[lng_uid
] = stats_val
196 print("".join(reports
) + "\n")
198 # Copy pot file from branches to trunk.
199 shutil
.copy2(self
.settings
.FILE_NAME_POT
, self
.settings
.TRUNK_PO_DIR
)
201 print("Generating languages' menu...")
202 context
.window_manager
.progress_update(progress
+ 2)
203 # First complete our statistics by checking po files we did not touch this time!
204 po_to_uid
= {os
.path
.basename(lng
.po_path
): lng
.uid
for lng
in i18n_sett
.langs
}
205 for po_path
in os
.listdir(self
.settings
.TRUNK_PO_DIR
):
206 uid
= po_to_uid
.get(po_path
, None)
207 po_path
= os
.path
.join(self
.settings
.TRUNK_PO_DIR
, po_path
)
208 if uid
and uid
not in stats
:
209 po
= utils_i18n
.I18nMessages(uid
=uid
, kind
='PO', src
=po_path
, settings
=self
.settings
)
210 stats
[uid
] = po
.nbr_trans_msgs
/ po
.nbr_msgs
if po
.nbr_msgs
> 0 else 0
211 utils_languages_menu
.gen_menu_file(stats
, self
.settings
)
212 context
.window_manager
.progress_end()
217 class UI_OT_i18n_updatetranslation_svn_statistics(Operator
):
218 """Create or extend a 'i18n_info.txt' Text datablock"""
219 """(it will contain statistics and checks about current branches and/or trunk)"""
220 bl_idname
= "ui.i18n_updatetranslation_svn_statistics"
221 bl_label
= "Update I18n Statistics"
223 use_branches
: BoolProperty(
224 name
="Check Branches",
225 description
="Check po files in branches",
229 use_trunk
: BoolProperty(
231 description
="Check po files in trunk",
235 report_name
= "i18n_info.txt"
237 def execute(self
, context
):
238 if not hasattr(self
, "settings"):
239 self
.settings
= settings
.settings
240 i18n_sett
= context
.window_manager
.i18n_update_svn_settings
244 if self
.use_branches
:
245 lst
+= [(lng
, lng
.po_path
) for lng
in i18n_sett
.langs
]
247 lst
+= [(lng
, lng
.po_path_trunk
) for lng
in i18n_sett
.langs
248 if lng
.uid
not in self
.settings
.IMPORT_LANGUAGES_SKIP
]
250 context
.window_manager
.progress_begin(0, len(lst
))
251 context
.window_manager
.progress_update(0)
252 for progress
, (lng
, path
) in enumerate(lst
):
253 context
.window_manager
.progress_update(progress
+ 1)
255 print("Skipping {} language ({}).".format(lng
.name
, lng
.uid
))
257 buff
.write("Processing {} language ({}, {}).\n".format(lng
.name
, lng
.uid
, path
))
258 po
= utils_i18n
.I18nMessages(uid
=lng
.uid
, kind
='PO', src
=path
, settings
=self
.settings
)
259 po
.print_info(prefix
=" ", output
=buff
.write
)
260 errs
= po
.check(fix
=False)
262 buff
.write(" WARNING! Po contains following errors:\n")
263 buff
.write(" " + "\n ".join(errs
))
268 if self
.report_name
not in bpy
.data
.texts
:
269 text
= bpy
.data
.texts
.new(self
.report_name
)
271 text
= bpy
.data
.texts
[self
.report_name
]
272 data
= text
.as_string()
273 data
= data
+ "\n" + buff
.getvalue()
274 text
.from_string(data
)
275 self
.report({'INFO'}, "Info written to {} text datablock!".format(self
.report_name
))
276 context
.window_manager
.progress_end()
280 def invoke(self
, context
, event
):
281 wm
= context
.window_manager
282 return wm
.invoke_props_dialog(self
)
286 UI_OT_i18n_updatetranslation_svn_branches
,
287 UI_OT_i18n_cleanuptranslation_svn_branches
,
288 UI_OT_i18n_updatetranslation_svn_trunk
,
289 UI_OT_i18n_updatetranslation_svn_statistics
,