1 # SPDX-FileCopyrightText: 2013-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
9 importlib
.reload(settings
)
10 importlib
.reload(utils_i18n
)
13 from bpy
.types
import (
19 from bpy
.props
import (
25 from . import settings
26 from bl_i18n_utils
import utils
as utils_i18n
28 from bpy
.app
.translations
import pgettext_iface
as iface_
31 # Data ########################################################################
33 class I18nUpdateTranslationLanguage(PropertyGroup
):
34 """Settings/info about a language"""
38 description
="ISO code (eg. \"fr_FR\")",
44 description
="Numeric ID (read only!)",
50 description
="Language label (eg. \"French (Français)\")",
56 description
="If this language should be used in the current operator",
60 po_path
: StringProperty(
61 name
="PO Work File Path",
62 description
="Path to the relevant po file in the work repository",
67 po_path_blender
: StringProperty(
68 name
="PO Blender File Path",
69 description
="Path to the relevant po file in Blender's source repository",
75 class I18nUpdateTranslationSettings(PropertyGroup
):
76 """Settings/info about a language"""
78 langs
: CollectionProperty(
80 type=I18nUpdateTranslationLanguage
,
81 description
="Languages to update in work repository",
84 active_lang
: IntProperty(
85 name
="Active Language",
87 description
="Index of active language in langs collection",
90 pot_path
: StringProperty(
92 description
="Path to the pot template file",
97 is_init
: BoolProperty(
98 description
="Whether these settings have already been auto-set or not",
104 # UI ##########################################################################
106 class UI_UL_i18n_languages(UIList
):
109 def draw_item(self
, context
, layout
, data
, item
, icon
, active_data
, active_propname
, index
):
110 if self
.layout_type
in {'DEFAULT', 'COMPACT'}:
111 layout
.label(text
=item
.name
, icon_value
=icon
)
112 layout
.prop(item
, "use", text
="")
113 elif self
.layout_type
in {'GRID'}:
114 layout
.alignment
= 'CENTER'
115 layout
.label(text
=item
.uid
)
116 layout
.prop(item
, "use", text
="")
119 class UI_PT_i18n_update_translations_settings(Panel
):
122 bl_label
= "I18n Update Translation"
123 bl_space_type
= "PROPERTIES"
124 bl_region_type
= "WINDOW"
125 bl_context
= "render"
127 def draw(self
, context
):
129 i18n_sett
= context
.window_manager
.i18n_update_settings
131 if not i18n_sett
.is_init
and bpy
.ops
.ui
.i18n_updatetranslation_init_settings
.poll():
132 # Cannot call the operator from here, this code might run while `pyrna_write_check()` returns False
133 # (which prevents any operator call from Python), during initialization of Blender.
134 UI_OT_i18n_updatetranslation_init_settings
.execute_static(context
, settings
.settings
)
136 if not i18n_sett
.is_init
:
137 layout
.label(text
="Could not init languages data!")
138 layout
.label(text
="Please edit the preferences of the UI Translate add-on")
139 layout
.operator("ui.i18n_updatetranslation_init_settings", text
="Init Settings")
141 split
= layout
.split(factor
=0.75)
142 split
.template_list("UI_UL_i18n_languages", "", i18n_sett
, "langs", i18n_sett
, "active_lang", rows
=8)
144 col
.operator("ui.i18n_updatetranslation_init_settings", text
="Reset Settings")
145 deselect
= any(l
.use
for l
in i18n_sett
.langs
)
146 op
= col
.operator("ui.i18n_updatetranslation_settings_select",
147 text
="Deselect All" if deselect
else "Select All")
148 op
.use_invert
= False
149 op
.use_select
= not deselect
150 col
.operator("ui.i18n_updatetranslation_settings_select", text
="Invert Selection").use_invert
= True
152 col
.operator("ui.i18n_updatetranslation_work_repo", text
="Update Work Repo")
153 col
.operator("ui.i18n_cleanuptranslation_work_repo", text
="Clean up Work Repo")
155 col
.operator("ui.i18n_updatetranslation_blender_repo", text
="Update Blender Repo")
157 col
.operator("ui.i18n_updatetranslation_statistics", text
="Statistics")
159 if i18n_sett
.active_lang
>= 0 and i18n_sett
.active_lang
< len(i18n_sett
.langs
):
160 lng
= i18n_sett
.langs
[i18n_sett
.active_lang
]
161 col
= layout
.column()
164 row
.label(text
="[{}]: \"{}\" ({})".format(lng
.uid
, iface_(lng
.name
), lng
.num_id
), translate
=False)
165 row
.prop(lng
, "use", text
="")
166 col
.prop(lng
, "po_path")
167 col
.prop(lng
, "po_path_blender")
169 layout
.prop(i18n_sett
, "pot_path")
172 layout
.label(text
="Add-ons:")
174 op
= row
.operator("ui.i18n_addon_translation_invoke", text
="Refresh I18n Data...")
175 op
.op_id
= "ui.i18n_addon_translation_update"
176 op
= row
.operator("ui.i18n_addon_translation_invoke", text
="Export PO...")
177 op
.op_id
= "ui.i18n_addon_translation_export"
178 op
= row
.operator("ui.i18n_addon_translation_invoke", text
="Import PO...")
179 op
.op_id
= "ui.i18n_addon_translation_import"
182 # Operators ###################################################################
184 class UI_OT_i18n_updatetranslation_init_settings(Operator
):
185 """Init settings for i18n files update operators"""
187 bl_idname
= "ui.i18n_updatetranslation_init_settings"
188 bl_label
= "Init I18n Update Settings"
189 bl_option
= {'REGISTER'}
192 def poll(cls
, context
):
193 return context
.window_manager
is not None
196 def execute_static(context
, self_settings
):
197 i18n_sett
= context
.window_manager
.i18n_update_settings
199 # First, create the list of languages from settings.
200 i18n_sett
.langs
.clear()
201 root_work
= self_settings
.WORK_DIR
202 root_blender_po
= self_settings
.BLENDER_I18N_PO_DIR
204 print(root_blender_po
)
205 print(self_settings
.FILE_NAME_POT
)
206 if not (os
.path
.isdir(root_work
) and os
.path
.isdir(root_blender_po
)):
207 i18n_sett
.is_init
= False
209 for can_use
, uid
, num_id
, name
, isocode
, po_path_work
in utils_i18n
.list_po_dir(root_work
, self_settings
):
210 lng
= i18n_sett
.langs
.add()
216 lng
.po_path
= po_path_work
217 lng
.po_path_blender
= os
.path
.join(root_blender_po
, isocode
+ ".po")
219 i18n_sett
.pot_path
= self_settings
.FILE_NAME_POT
220 i18n_sett
.is_init
= True
222 def execute(self
, context
):
223 if not hasattr(self
, "settings"):
224 self
.settings
= settings
.settings
226 self
.execute_static(context
, self
.settings
)
228 if context
.window_manager
.i18n_update_settings
.is_init
is False:
233 class UI_OT_i18n_updatetranslation_settings_select(Operator
):
234 """(De)select (or invert selection of) all languages for i18n files update operators"""
236 bl_idname
= "ui.i18n_updatetranslation_settings_select"
237 bl_label
= "Init I18n Update Select Languages"
239 use_select
: BoolProperty(
241 description
="Select all if True, else deselect all",
245 use_invert
: BoolProperty(
246 name
="Invert Selection",
247 description
="Inverse selection (overrides 'Select All' when True)",
252 def poll(cls
, context
):
253 return context
.window_manager
is not None
255 def execute(self
, context
):
257 for lng
in context
.window_manager
.i18n_update_settings
.langs
:
258 lng
.use
= not lng
.use
260 for lng
in context
.window_manager
.i18n_update_settings
.langs
:
261 lng
.use
= self
.use_select
266 I18nUpdateTranslationLanguage
,
267 I18nUpdateTranslationSettings
,
268 UI_UL_i18n_languages
,
269 UI_PT_i18n_update_translations_settings
,
270 UI_OT_i18n_updatetranslation_init_settings
,
271 UI_OT_i18n_updatetranslation_settings_select
,