1 # SPDX-License-Identifier: GPL-2.0-or-later
7 importlib
.reload(settings
)
8 importlib
.reload(utils_i18n
)
11 from bpy
.types
import (
17 from bpy
.props
import (
23 from . import settings
24 from bl_i18n_utils
import utils
as utils_i18n
26 from bpy
.app
.translations
import pgettext_iface
as iface_
29 # Data ########################################################################
31 class I18nUpdateTranslationLanguage(PropertyGroup
):
32 """Settings/info about a language"""
36 description
="ISO code (eg. \"fr_FR\")",
42 description
="Numeric ID (read only!)",
48 description
="Language label (eg. \"French (Français)\")",
54 description
="If this language should be used in the current operator",
58 po_path
: StringProperty(
60 description
="Path to the relevant po file in branches",
65 po_path_trunk
: StringProperty(
66 name
="PO Trunk File Path",
67 description
="Path to the relevant po file in trunk",
72 mo_path_trunk
: StringProperty(
74 description
="Path to the relevant mo file",
79 po_path_git
: StringProperty(
80 name
="PO Git Master File Path",
81 description
="Path to the relevant po file in Blender's translations git repository",
87 class I18nUpdateTranslationSettings(PropertyGroup
):
88 """Settings/info about a language"""
90 langs
: CollectionProperty(
92 type=I18nUpdateTranslationLanguage
,
93 description
="Languages to update in branches",
96 active_lang
: IntProperty(
97 name
="Active Language",
99 description
="Index of active language in langs collection",
102 pot_path
: StringProperty(
103 name
="POT File Path",
104 description
="Path to the pot template file",
109 is_init
: BoolProperty(
110 description
="Whether these settings have already been auto-set or not",
116 # UI ##########################################################################
118 class UI_UL_i18n_languages(UIList
):
121 def draw_item(self
, context
, layout
, data
, item
, icon
, active_data
, active_propname
, index
):
122 if self
.layout_type
in {'DEFAULT', 'COMPACT'}:
123 layout
.label(text
=item
.name
, icon_value
=icon
)
124 layout
.prop(item
, "use", text
="")
125 elif self
.layout_type
in {'GRID'}:
126 layout
.alignment
= 'CENTER'
127 layout
.label(text
=item
.uid
)
128 layout
.prop(item
, "use", text
="")
131 class UI_PT_i18n_update_translations_settings(Panel
):
134 bl_label
= "I18n Update Translation"
135 bl_space_type
= "PROPERTIES"
136 bl_region_type
= "WINDOW"
137 bl_context
= "render"
139 def draw(self
, context
):
141 i18n_sett
= context
.window_manager
.i18n_update_svn_settings
143 if not i18n_sett
.is_init
and bpy
.ops
.ui
.i18n_updatetranslation_svn_init_settings
.poll():
144 # Cannot call the operator from here, this code might run while `pyrna_write_check()` returns False
145 # (which prevents any operator call from Python), during initialization of Blender.
146 UI_OT_i18n_updatetranslation_svn_init_settings
.execute_static(context
, settings
.settings
)
148 if not i18n_sett
.is_init
:
149 layout
.label(text
="Could not init languages data!")
150 layout
.label(text
="Please edit the preferences of the UI Translate add-on")
151 layout
.operator("ui.i18n_updatetranslation_svn_init_settings", text
="Init Settings")
153 split
= layout
.split(factor
=0.75)
154 split
.template_list("UI_UL_i18n_languages", "", i18n_sett
, "langs", i18n_sett
, "active_lang", rows
=8)
156 col
.operator("ui.i18n_updatetranslation_svn_init_settings", text
="Reset Settings")
157 deselect
= any(l
.use
for l
in i18n_sett
.langs
)
158 op
= col
.operator("ui.i18n_updatetranslation_svn_settings_select",
159 text
="Deselect All" if deselect
else "Select All")
160 op
.use_invert
= False
161 op
.use_select
= not deselect
162 col
.operator("ui.i18n_updatetranslation_svn_settings_select", text
="Invert Selection").use_invert
= True
164 col
.operator("ui.i18n_updatetranslation_svn_branches", text
="Update Branches")
165 col
.operator("ui.i18n_updatetranslation_svn_trunk", text
="Update Trunk")
167 col
.operator("ui.i18n_cleanuptranslation_svn_branches", text
="Clean up Branches")
168 col
.operator("ui.i18n_updatetranslation_svn_statistics", text
="Statistics")
170 if i18n_sett
.active_lang
>= 0 and i18n_sett
.active_lang
< len(i18n_sett
.langs
):
171 lng
= i18n_sett
.langs
[i18n_sett
.active_lang
]
172 col
= layout
.column()
175 row
.label(text
="[{}]: \"{}\" ({})".format(lng
.uid
, iface_(lng
.name
), lng
.num_id
), translate
=False)
176 row
.prop(lng
, "use", text
="")
177 col
.prop(lng
, "po_path")
178 col
.prop(lng
, "po_path_trunk")
179 col
.prop(lng
, "mo_path_trunk")
180 col
.prop(lng
, "po_path_git")
182 layout
.prop(i18n_sett
, "pot_path")
185 layout
.label(text
="Add-ons:")
187 op
= row
.operator("ui.i18n_addon_translation_invoke", text
="Refresh I18n Data...")
188 op
.op_id
= "ui.i18n_addon_translation_update"
189 op
= row
.operator("ui.i18n_addon_translation_invoke", text
="Export PO...")
190 op
.op_id
= "ui.i18n_addon_translation_export"
191 op
= row
.operator("ui.i18n_addon_translation_invoke", text
="Import PO...")
192 op
.op_id
= "ui.i18n_addon_translation_import"
195 # Operators ###################################################################
197 class UI_OT_i18n_updatetranslation_svn_init_settings(Operator
):
198 """Init settings for i18n svn's update operators"""
200 bl_idname
= "ui.i18n_updatetranslation_svn_init_settings"
201 bl_label
= "Init I18n Update Settings"
202 bl_option
= {'REGISTER'}
205 def poll(cls
, context
):
206 return context
.window_manager
is not None
209 def execute_static(context
, self_settings
):
210 i18n_sett
= context
.window_manager
.i18n_update_svn_settings
212 # First, create the list of languages from settings.
213 i18n_sett
.langs
.clear()
214 root_br
= self_settings
.BRANCHES_DIR
215 root_tr_po
= self_settings
.TRUNK_PO_DIR
216 root_git_po
= self_settings
.GIT_I18N_PO_DIR
217 root_tr_mo
= os
.path
.join(self_settings
.TRUNK_DIR
, self_settings
.MO_PATH_TEMPLATE
, self_settings
.MO_FILE_NAME
)
218 if not (os
.path
.isdir(root_br
) and os
.path
.isdir(root_tr_po
)):
219 i18n_sett
.is_init
= False
221 for can_use
, uid
, num_id
, name
, isocode
, po_path_branch
in utils_i18n
.list_po_dir(root_br
, self_settings
):
222 lng
= i18n_sett
.langs
.add()
228 lng
.po_path
= po_path_branch
229 lng
.po_path_trunk
= os
.path
.join(root_tr_po
, isocode
+ ".po")
230 lng
.mo_path_trunk
= root_tr_mo
.format(isocode
)
231 lng
.po_path_git
= os
.path
.join(root_git_po
, isocode
+ ".po")
233 i18n_sett
.pot_path
= self_settings
.FILE_NAME_POT
234 i18n_sett
.is_init
= True
236 def execute(self
, context
):
237 if not hasattr(self
, "settings"):
238 self
.settings
= settings
.settings
240 self
.execute_static(context
, self
.settings
)
242 if context
.window_manager
.i18n_update_svn_settings
.is_init
is False:
247 class UI_OT_i18n_updatetranslation_svn_settings_select(Operator
):
248 """(De)select (or invert selection of) all languages for i18n svn's update operators"""
250 bl_idname
= "ui.i18n_updatetranslation_svn_settings_select"
251 bl_label
= "Init I18n Update Select Languages"
254 use_select
: BoolProperty(
256 description
="Select all if True, else deselect all",
260 use_invert
: BoolProperty(
261 name
="Invert Selection",
262 description
="Inverse selection (overrides 'Select All' when True)",
265 # /End Operator Arguments
268 def poll(cls
, context
):
269 return context
.window_manager
is not None
271 def execute(self
, context
):
273 for lng
in context
.window_manager
.i18n_update_svn_settings
.langs
:
274 lng
.use
= not lng
.use
276 for lng
in context
.window_manager
.i18n_update_svn_settings
.langs
:
277 lng
.use
= self
.use_select
282 I18nUpdateTranslationLanguage
,
283 I18nUpdateTranslationSettings
,
284 UI_UL_i18n_languages
,
285 UI_PT_i18n_update_translations_settings
,
286 UI_OT_i18n_updatetranslation_svn_init_settings
,
287 UI_OT_i18n_updatetranslation_svn_settings_select
,