Skip to content
Snippets Groups Projects
Commit b3f7398f authored by Ines Almeida's avatar Ines Almeida
Browse files

UI Translate: update to 2.8

Make operator properties into variable annotations.
Cleanup includes and descriptions.
PEP-8 compliance pass.
parent 70d1e306
No related branches found
No related tags found
No related merge requests found
...@@ -21,11 +21,11 @@ ...@@ -21,11 +21,11 @@
bl_info = { bl_info = {
"name": "Manage UI translations", "name": "Manage UI translations",
"author": "Bastien Montagne", "author": "Bastien Montagne",
"version": (1, 1, 4), "version": (1, 1, 5),
"blender": (2, 79, 0), "blender": (2, 80, 0),
"location": "Main \"File\" menu, text editor, any UI control", "location": "Main \"File\" menu, text editor, any UI control",
"description": "Allow to manage UI translations directly from Blender " "description": "Allows managing UI translations directly from Blender "
"(update main po files, update scripts' translations, etc.)", "(update main .po files, update scripts' translations, etc.)",
"warning": "Still in development, not all features are fully implemented yet!", "warning": "Still in development, not all features are fully implemented yet!",
"wiki_url": "http://wiki.blender.org/index.php/Dev:Doc/How_to/Translate_Blender", "wiki_url": "http://wiki.blender.org/index.php/Dev:Doc/How_to/Translate_Blender",
"support": 'OFFICIAL', "support": 'OFFICIAL',
...@@ -42,15 +42,12 @@ if "bpy" in locals(): ...@@ -42,15 +42,12 @@ if "bpy" in locals():
else: else:
import bpy import bpy
from . import ( from . import (
settings, settings,
edit_translation, edit_translation,
update_svn, update_svn,
update_addon, update_addon,
update_ui, update_ui,
) )
import os
classes = settings.classes + edit_translation.classes + update_svn.classes + update_addon.classes + update_ui.classes classes = settings.classes + edit_translation.classes + update_svn.classes + update_addon.classes + update_ui.classes
...@@ -59,18 +56,21 @@ classes = settings.classes + edit_translation.classes + update_svn.classes + upd ...@@ -59,18 +56,21 @@ classes = settings.classes + edit_translation.classes + update_svn.classes + upd
def register(): def register():
for cls in classes: for cls in classes:
bpy.utils.register_class(cls) bpy.utils.register_class(cls)
bpy.types.WindowManager.i18n_update_svn_settings = \ bpy.types.WindowManager.i18n_update_svn_settings = \
bpy.props.PointerProperty(type=update_ui.I18nUpdateTranslationSettings) bpy.props.PointerProperty(type=update_ui.I18nUpdateTranslationSettings)
# Init addon's preferences (unfortunately, as we are using an external storage for the properties, # Init addon's preferences (unfortunately, as we are using an external storage for the properties,
# the load/save user preferences process has no effect on them :( ). # the load/save user preferences process has no effect on them :( ).
if __name__ in bpy.context.user_preferences.addons: if __name__ in bpy.context.user_preferences.addons:
pref = bpy.context.user_preferences.addons[__name__].preferences pref = bpy.context.user_preferences.addons[__name__].preferences
import os
if os.path.isfile(pref.persistent_data_path): if os.path.isfile(pref.persistent_data_path):
pref._settings.load(pref.persistent_data_path, reset=True) pref._settings.load(pref.persistent_data_path, reset=True)
def unregister(): def unregister():
del bpy.types.WindowManager.i18n_update_svn_settings
for cls in classes: for cls in classes:
bpy.utils.unregister_class(cls) bpy.utils.unregister_class(cls)
del bpy.types.WindowManager.i18n_update_svn_settings
...@@ -18,30 +18,24 @@ ...@@ -18,30 +18,24 @@
# <pep8 compliant> # <pep8 compliant>
import os
import shutil
if "bpy" in locals(): if "bpy" in locals():
import importlib import importlib
importlib.reload(settings) importlib.reload(settings)
importlib.reload(utils_i18n) importlib.reload(utils_i18n)
else: else:
import bpy import bpy
from bpy.types import Operator
from bpy.props import ( from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, EnumProperty,
EnumProperty, StringProperty,
FloatProperty, )
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from . import settings from . import settings
from bl_i18n_utils import utils as utils_i18n from bl_i18n_utils import utils as utils_i18n
import os
import shutil
# A global cache for I18nMessages objects, as parsing po files takes a few seconds. # A global cache for I18nMessages objects, as parsing po files takes a few seconds.
PO_CACHE = {} PO_CACHE = {}
...@@ -52,21 +46,30 @@ def _get_messages(lang, fname): ...@@ -52,21 +46,30 @@ def _get_messages(lang, fname):
return PO_CACHE[fname] return PO_CACHE[fname]
class UI_OT_i18n_edittranslation_update_mo(bpy.types.Operator): class UI_OT_i18n_edittranslation_update_mo(Operator):
"""Try to "compile" given po file into relevant blender.mo file """ \ """Try to "compile" given po file into relevant blender.mo file
"""(WARNING: it will replace the official mo file in your user dir!)""" (WARNING: it will replace the official mo file in your user dir!)"""
bl_idname = "ui.i18n_edittranslation_update_mo" bl_idname = "ui.i18n_edittranslation_update_mo"
bl_label = "Edit Translation Update Mo" bl_label = "Edit Translation Update Mo"
# "Parameters" # Operator Arguments
lang = StringProperty(description="Current (translated) language", lang: StringProperty(
options={'SKIP_SAVE'}) description="Current (translated) language",
po_file = StringProperty(description="Path to the matching po file", options={'SKIP_SAVE'},
subtype='FILE_PATH', options={'SKIP_SAVE'}) )
clean_mo = BoolProperty(description="Clean up (remove) all local "
"translation files, to be able to use " po_file: StringProperty(
"all system's ones again", description="Path to the matching po file",
default=False, options={'SKIP_SAVE'}) subtype='FILE_PATH',
options={'SKIP_SAVE'},
)
clean_mo: BoolProperty(
description="Remove all local translation files, to be able to use the system ones again",
default=False,
options={'SKIP_SAVE'}
)
# /End Operator Arguments
def execute(self, context): def execute(self, context):
if self.clean_mo: if self.clean_mo:
...@@ -85,65 +88,169 @@ class UI_OT_i18n_edittranslation_update_mo(bpy.types.Operator): ...@@ -85,65 +88,169 @@ class UI_OT_i18n_edittranslation_update_mo(bpy.types.Operator):
return {'FINISHED'} return {'FINISHED'}
class UI_OT_i18n_edittranslation(bpy.types.Operator): class UI_OT_i18n_edittranslation(Operator):
"""Translate the label and tooltip of the property defined by given 'parameters'""" """Translate the label and tooltip of the given property"""
bl_idname = "ui.edittranslation" bl_idname = "ui.edittranslation"
bl_label = "Edit Translation" bl_label = "Edit Translation"
# "Parameters" # Operator Arguments
but_label = StringProperty(description="Label of the control", options={'SKIP_SAVE'}) but_label: StringProperty(
rna_label = StringProperty(description="RNA-defined label of the control, if any", options={'SKIP_SAVE'}) description="Label of the control",
enum_label = StringProperty(description="Label of the enum item of the control, if any", options={'SKIP_SAVE'}) options={'SKIP_SAVE'},
but_tip = StringProperty(description="Tip of the control", options={'SKIP_SAVE'}) )
rna_tip = StringProperty(description="RNA-defined tip of the control, if any", options={'SKIP_SAVE'})
enum_tip = StringProperty(description="Tip of the enum item of the control, if any", options={'SKIP_SAVE'}) rna_label: StringProperty(
rna_struct = StringProperty(description="Identifier of the RNA struct, if any", options={'SKIP_SAVE'}) description="RNA-defined label of the control, if any",
rna_prop = StringProperty(description="Identifier of the RNA property, if any", options={'SKIP_SAVE'}) options={'SKIP_SAVE'},
rna_enum = StringProperty(description="Identifier of the RNA enum item, if any", options={'SKIP_SAVE'}) )
rna_ctxt = StringProperty(description="RNA context for label", options={'SKIP_SAVE'})
enum_label: StringProperty(
lang = StringProperty(description="Current (translated) language", options={'SKIP_SAVE'}) description="Label of the enum item of the control, if any",
po_file = StringProperty(description="Path to the matching po file", subtype='FILE_PATH', options={'SKIP_SAVE'}) options={'SKIP_SAVE'},
)
but_tip: StringProperty(
description="Tip of the control",
options={'SKIP_SAVE'},
)
rna_tip: StringProperty(
description="RNA-defined tip of the control, if any",
options={'SKIP_SAVE'},
)
enum_tip: StringProperty(
description="Tip of the enum item of the control, if any",
options={'SKIP_SAVE'},
)
rna_struct: StringProperty(
description="Identifier of the RNA struct, if any",
options={'SKIP_SAVE'},
)
rna_prop: StringProperty(
description="Identifier of the RNA property, if any",
options={'SKIP_SAVE'},
)
rna_enum: StringProperty(
description="Identifier of the RNA enum item, if any",
options={'SKIP_SAVE'},
)
rna_ctxt: StringProperty(
description="RNA context for label",
options={'SKIP_SAVE'},
)
lang: StringProperty(
description="Current (translated) language",
options={'SKIP_SAVE'},
)
po_file: StringProperty(
description="Path to the matching po file",
subtype='FILE_PATH',
options={'SKIP_SAVE'},
)
# Found in po file. # Found in po file.
org_but_label = StringProperty(description="Original label of the control", options={'SKIP_SAVE'}) org_but_label: StringProperty(
org_rna_label = StringProperty(description="Original RNA-defined label of the control, if any", description="Original label of the control",
options={'SKIP_SAVE'}) options={'SKIP_SAVE'},
org_enum_label = StringProperty(description="Original label of the enum item of the control, if any", )
options={'SKIP_SAVE'})
org_but_tip = StringProperty(description="Original tip of the control", options={'SKIP_SAVE'}) org_rna_label: StringProperty(
org_rna_tip = StringProperty(description="Original RNA-defined tip of the control, if any", options={'SKIP_SAVE'}) description="Original RNA-defined label of the control, if any",
org_enum_tip = StringProperty(description="Original tip of the enum item of the control, if any", options={'SKIP_SAVE'},
options={'SKIP_SAVE'}) )
flag_items = (('FUZZY', "Fuzzy", "Message is marked as fuzzy in po file"), org_enum_label: StringProperty(
('ERROR', "Error", "Some error occurred with this message"), description="Original label of the enum item of the control, if any",
) options={'SKIP_SAVE'},
but_label_flags = EnumProperty(items=flag_items, description="Flags about the label of the button", )
options={'SKIP_SAVE', 'ENUM_FLAG'})
rna_label_flags = EnumProperty(items=flag_items, description="Flags about the RNA-defined label of the button", org_but_tip: StringProperty(
options={'SKIP_SAVE', 'ENUM_FLAG'}) description="Original tip of the control",
enum_label_flags = EnumProperty(items=flag_items, description="Flags about the RNA enum item label of the button", options={'SKIP_SAVE'},
options={'SKIP_SAVE', 'ENUM_FLAG'}) )
but_tip_flags = EnumProperty(items=flag_items, description="Flags about the tip of the button",
options={'SKIP_SAVE', 'ENUM_FLAG'}) org_rna_tip: StringProperty(
rna_tip_flags = EnumProperty(items=flag_items, description="Flags about the RNA-defined tip of the button", description="Original RNA-defined tip of the control, if any", options={'SKIP_SAVE'}
options={'SKIP_SAVE', 'ENUM_FLAG'}) )
enum_tip_flags = EnumProperty(items=flag_items, description="Flags about the RNA enum item tip of the button",
options={'SKIP_SAVE', 'ENUM_FLAG'}) org_enum_tip: StringProperty(
description="Original tip of the enum item of the control, if any",
stats_str = StringProperty(description="Stats from opened po", options={'SKIP_SAVE'}) options={'SKIP_SAVE'},
update_po = BoolProperty(description="Update po file, try to rebuild mo file, and refresh Blender UI", )
default=False, options={'SKIP_SAVE'})
update_mo = BoolProperty(description="Try to rebuild mo file, and refresh Blender UI", flag_items = (
default=False, options={'SKIP_SAVE'}) ('FUZZY', "Fuzzy", "Message is marked as fuzzy in po file"),
clean_mo = BoolProperty(description="Clean up (remove) all local translation files, to be able to use " ('ERROR', "Error", "Some error occurred with this message"),
"all system's ones again", )
default=False, options={'SKIP_SAVE'})
but_label_flags: EnumProperty(
description="Flags about the label of the button",
items=flag_items,
options={'SKIP_SAVE', 'ENUM_FLAG'},
)
rna_label_flags: EnumProperty(
description="Flags about the RNA-defined label of the button",
items=flag_items,
options={'SKIP_SAVE', 'ENUM_FLAG'},
)
enum_label_flags: EnumProperty(
description="Flags about the RNA enum item label of the button",
items=flag_items,
options={'SKIP_SAVE', 'ENUM_FLAG'},
)
but_tip_flags: EnumProperty(
description="Flags about the tip of the button",
items=flag_items,
options={'SKIP_SAVE', 'ENUM_FLAG'},
)
rna_tip_flags: EnumProperty(
description="Flags about the RNA-defined tip of the button",
items=flag_items,
options={'SKIP_SAVE', 'ENUM_FLAG'},
)
enum_tip_flags: EnumProperty(
description="Flags about the RNA enum item tip of the button",
items=flag_items,
options={'SKIP_SAVE', 'ENUM_FLAG'},
)
stats_str: StringProperty(
description="Stats from opened po", options={'SKIP_SAVE'})
update_po: BoolProperty(
description="Update po file, try to rebuild mo file, and refresh Blender's UI",
default=False,
options={'SKIP_SAVE'},
)
update_mo: BoolProperty(
description="Try to rebuild mo file, and refresh Blender's UI",
default=False,
options={'SKIP_SAVE'},
)
clean_mo: BoolProperty(
description="Remove all local translation files, to be able to use the system ones again",
default=False,
options={'SKIP_SAVE'},
)
# /End Operator Arguments
def execute(self, context): def execute(self, context):
if not hasattr(self, "msgmap"): if not hasattr(self, "msgmap"):
self.report('ERROR', "Looks like you did not invoke this operator first!") self.report('ERROR', "invoke() needs to be called before execute()")
return {'CANCELLED'} return {'CANCELLED'}
msgs = _get_messages(self.lang, self.po_file) msgs = _get_messages(self.lang, self.po_file)
...@@ -152,7 +259,6 @@ class UI_OT_i18n_edittranslation(bpy.types.Operator): ...@@ -152,7 +259,6 @@ class UI_OT_i18n_edittranslation(bpy.types.Operator):
if 'ERROR' in getattr(self, mmap["msg_flags"]): if 'ERROR' in getattr(self, mmap["msg_flags"]):
continue continue
k = mmap["key"] k = mmap["key"]
# print(k)
if k not in done_keys and len(k) == 1: if k not in done_keys and len(k) == 1:
k = tuple(k)[0] k = tuple(k)[0]
msgs.msgs[k].msgstr = getattr(self, mmap["msgstr"]) msgs.msgs[k].msgstr = getattr(self, mmap["msgstr"])
...@@ -160,7 +266,7 @@ class UI_OT_i18n_edittranslation(bpy.types.Operator): ...@@ -160,7 +266,7 @@ class UI_OT_i18n_edittranslation(bpy.types.Operator):
done_keys.add(k) done_keys.add(k)
if self.update_po: if self.update_po:
# Try to overwrite po file, may fail if we have no good rights... # Try to overwrite .po file, may fail if there are no permissions.
try: try:
msgs.write(kind='PO', dest=self.po_file) msgs.write(kind='PO', dest=self.po_file)
except Exception as e: except Exception as e:
...@@ -175,19 +281,20 @@ class UI_OT_i18n_edittranslation(bpy.types.Operator): ...@@ -175,19 +281,20 @@ class UI_OT_i18n_edittranslation(bpy.types.Operator):
return {'FINISHED'} return {'FINISHED'}
def invoke(self, context, event): def invoke(self, context, event):
self.msgmap = {"but_label": {"msgstr": "but_label", "msgid": "org_but_label", self.msgmap = {
"msg_flags": "but_label_flags", "key": set()}, "but_label": {
"rna_label": {"msgstr": "rna_label", "msgid": "org_rna_label", "msgstr": "but_label", "msgid": "org_but_label", "msg_flags": "but_label_flags", "key": set()},
"msg_flags": "rna_label_flags", "key": set()}, "rna_label": {
"enum_label": {"msgstr": "enum_label", "msgid": "org_enum_label", "msgstr": "rna_label", "msgid": "org_rna_label", "msg_flags": "rna_label_flags", "key": set()},
"msg_flags": "enum_label_flags", "key": set()}, "enum_label": {
"but_tip": {"msgstr": "but_tip", "msgid": "org_but_tip", "msgstr": "enum_label", "msgid": "org_enum_label", "msg_flags": "enum_label_flags", "key": set()},
"msg_flags": "but_tip_flags", "key": set()}, "but_tip": {
"rna_tip": {"msgstr": "rna_tip", "msgid": "org_rna_tip", "msgstr": "but_tip", "msgid": "org_but_tip", "msg_flags": "but_tip_flags", "key": set()},
"msg_flags": "rna_tip_flags", "key": set()}, "rna_tip": {
"enum_tip": {"msgstr": "enum_tip", "msgid": "org_enum_tip", "msgstr": "rna_tip", "msgid": "org_rna_tip", "msg_flags": "rna_tip_flags", "key": set()},
"msg_flags": "enum_tip_flags", "key": set()}, "enum_tip": {
} "msgstr": "enum_tip", "msgid": "org_enum_tip", "msg_flags": "enum_tip_flags", "key": set()},
}
msgs = _get_messages(self.lang, self.po_file) msgs = _get_messages(self.lang, self.po_file)
msgs.find_best_messages_matches(self, self.msgmap, self.rna_ctxt, self.rna_struct, self.rna_prop, self.rna_enum) msgs.find_best_messages_matches(self, self.msgmap, self.rna_ctxt, self.rna_struct, self.rna_prop, self.rna_enum)
...@@ -229,9 +336,8 @@ class UI_OT_i18n_edittranslation(bpy.types.Operator): ...@@ -229,9 +336,8 @@ class UI_OT_i18n_edittranslation(bpy.types.Operator):
if self.org_but_label or self.org_rna_label or self.org_enum_label: if self.org_but_label or self.org_rna_label or self.org_enum_label:
# XXX Can't use box, labels are not enough readable in them :/ # XXX Can't use box, labels are not enough readable in them :/
box = layout.box() box = layout.box()
#box = layout
box.label(text="Labels:") box.label(text="Labels:")
split = box.split(percentage=0.15) split = box.split(factor=0.15)
col1 = split.column() col1 = split.column()
col2 = split.column() col2 = split.column()
if self.org_but_label: if self.org_but_label:
...@@ -268,9 +374,8 @@ class UI_OT_i18n_edittranslation(bpy.types.Operator): ...@@ -268,9 +374,8 @@ class UI_OT_i18n_edittranslation(bpy.types.Operator):
if self.org_but_tip or self.org_rna_tip or self.org_enum_tip: if self.org_but_tip or self.org_rna_tip or self.org_enum_tip:
# XXX Can't use box, labels are not enough readable in them :/ # XXX Can't use box, labels are not enough readable in them :/
box = layout.box() box = layout.box()
#box = layout
box.label(text="Tool Tips:") box.label(text="Tool Tips:")
split = box.split(percentage=0.15) split = box.split(factor=0.15)
col1 = split.column() col1 = split.column()
col2 = split.column() col2 = split.column()
if self.org_but_tip: if self.org_but_tip:
......
...@@ -18,40 +18,46 @@ ...@@ -18,40 +18,46 @@
# <pep8 compliant> # <pep8 compliant>
import os
if "bpy" in locals(): if "bpy" in locals():
import importlib import importlib
importlib.reload(settings_i18n) importlib.reload(settings_i18n)
else: else:
import bpy import bpy
from bpy.types import (
Operator,
AddonPreferences,
)
from bpy.props import ( from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, StringProperty,
EnumProperty, )
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bl_i18n_utils import settings as settings_i18n from bl_i18n_utils import settings as settings_i18n
import os
settings = settings_i18n.I18nSettings() settings = settings_i18n.I18nSettings()
class UI_OT_i18n_settings_load(bpy.types.Operator): # Operators ###################################################################
class UI_OT_i18n_settings_load(Operator):
"""Load translations' settings from a persistent JSon file""" """Load translations' settings from a persistent JSon file"""
bl_idname = "ui.i18n_settings_load" bl_idname = "ui.i18n_settings_load"
bl_label = "I18n Load Settings" bl_label = "I18n Load Settings"
bl_option = {'REGISTER'} bl_option = {'REGISTER'}
# "Parameters" # Operator Arguments
filepath = StringProperty(description="Path to the saved settings file", filepath: StringProperty(
subtype='FILE_PATH') subtype='FILE_PATH',
filter_glob = StringProperty(default="*.json", options={'HIDDEN'}) description="Path to the saved settings file",
)
filter_glob: StringProperty(
default="*.json",
options={'HIDDEN'}
)
# /End Operator Arguments
def invoke(self, context, event): def invoke(self, context, event):
if not self.properties.is_property_set("filepath"): if not self.properties.is_property_set("filepath"):
...@@ -67,16 +73,23 @@ class UI_OT_i18n_settings_load(bpy.types.Operator): ...@@ -67,16 +73,23 @@ class UI_OT_i18n_settings_load(bpy.types.Operator):
return {'FINISHED'} return {'FINISHED'}
class UI_OT_i18n_settings_save(bpy.types.Operator): class UI_OT_i18n_settings_save(Operator):
"""Save translations' settings in a persistent JSon file""" """Save translations' settings in a persistent JSon file"""
bl_idname = "ui.i18n_settings_save" bl_idname = "ui.i18n_settings_save"
bl_label = "I18n Save Settings" bl_label = "I18n Save Settings"
bl_option = {'REGISTER'} bl_option = {'REGISTER'}
# "Parameters" # Operator Arguments
filepath = StringProperty(description="Path to the saved settings file", filepath: StringProperty(
subtype='FILE_PATH') description="Path to the saved settings file",
filter_glob = StringProperty(default="*.json", options={'HIDDEN'}) subtype='FILE_PATH',
)
filter_glob: StringProperty(
default="*.json",
options={'HIDDEN'},
)
# /End Operator Arguments
def invoke(self, context, event): def invoke(self, context, event):
if not self.properties.is_property_set("filepath"): if not self.properties.is_property_set("filepath"):
...@@ -92,18 +105,20 @@ class UI_OT_i18n_settings_save(bpy.types.Operator): ...@@ -92,18 +105,20 @@ class UI_OT_i18n_settings_save(bpy.types.Operator):
return {'FINISHED'} return {'FINISHED'}
# Addon Preferences ###########################################################
def _setattr(self, name, val): def _setattr(self, name, val):
print(self, name, val) print(self, name, val)
setattr(self, name, val) setattr(self, name, val)
class UI_AP_i18n_settings(bpy.types.AddonPreferences): class UI_AP_i18n_settings(AddonPreferences):
bl_idname = __name__.split(".")[0] # We want "top" module name! bl_idname = __name__.split(".")[0] # We want "top" module name!
bl_option = {'REGISTER'} bl_option = {'REGISTER'}
_settings = settings _settings = settings
WARN_MSGID_NOT_CAPITALIZED = BoolProperty( WARN_MSGID_NOT_CAPITALIZED: BoolProperty(
name="Warn Msgid Not Capitalized", name="Warn Msgid Not Capitalized",
description="Warn about messages not starting by a capitalized letter (with a few allowed exceptions!)", description="Warn about messages not starting by a capitalized letter (with a few allowed exceptions!)",
default=True, default=True,
...@@ -111,7 +126,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences): ...@@ -111,7 +126,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences):
set=lambda self, val: _setattr(self._settings, "WARN_MSGID_NOT_CAPITALIZED", val), set=lambda self, val: _setattr(self._settings, "WARN_MSGID_NOT_CAPITALIZED", val),
) )
GETTEXT_MSGFMT_EXECUTABLE = StringProperty( GETTEXT_MSGFMT_EXECUTABLE: StringProperty(
name="Gettext 'msgfmt' executable", name="Gettext 'msgfmt' executable",
description="The gettext msgfmt 'compiler'. You’ll likely have to edit it if you’re under Windows", description="The gettext msgfmt 'compiler'. You’ll likely have to edit it if you’re under Windows",
subtype='FILE_PATH', subtype='FILE_PATH',
...@@ -120,7 +135,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences): ...@@ -120,7 +135,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences):
set=lambda self, val: setattr(self._settings, "GETTEXT_MSGFMT_EXECUTABLE", val), set=lambda self, val: setattr(self._settings, "GETTEXT_MSGFMT_EXECUTABLE", val),
) )
FRIBIDI_LIB = StringProperty( FRIBIDI_LIB: StringProperty(
name="Fribidi Library", name="Fribidi Library",
description="The FriBidi C compiled library (.so under Linux, .dll under windows...), you’ll likely have " description="The FriBidi C compiled library (.so under Linux, .dll under windows...), you’ll likely have "
"to edit it if you’re under Windows, e.g. using the one included in svn's libraries repository", "to edit it if you’re under Windows, e.g. using the one included in svn's libraries repository",
...@@ -130,7 +145,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences): ...@@ -130,7 +145,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences):
set=lambda self, val: setattr(self._settings, "FRIBIDI_LIB", val), set=lambda self, val: setattr(self._settings, "FRIBIDI_LIB", val),
) )
SOURCE_DIR = StringProperty( SOURCE_DIR: StringProperty(
name="Source Root", name="Source Root",
description="The Blender source root path", description="The Blender source root path",
subtype='FILE_PATH', subtype='FILE_PATH',
...@@ -139,7 +154,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences): ...@@ -139,7 +154,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences):
set=lambda self, val: setattr(self._settings, "SOURCE_DIR", val), set=lambda self, val: setattr(self._settings, "SOURCE_DIR", val),
) )
I18N_DIR = StringProperty( I18N_DIR: StringProperty(
name="Translation Root", name="Translation Root",
description="The bf-translation repository", description="The bf-translation repository",
subtype='FILE_PATH', subtype='FILE_PATH',
...@@ -148,7 +163,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences): ...@@ -148,7 +163,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences):
set=lambda self, val: setattr(self._settings, "I18N_DIR", val), set=lambda self, val: setattr(self._settings, "I18N_DIR", val),
) )
SPELL_CACHE = StringProperty( SPELL_CACHE: StringProperty(
name="Spell Cache", name="Spell Cache",
description="A cache storing validated msgids, to avoid re-spellchecking them", description="A cache storing validated msgids, to avoid re-spellchecking them",
subtype='FILE_PATH', subtype='FILE_PATH',
...@@ -157,7 +172,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences): ...@@ -157,7 +172,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences):
set=lambda self, val: setattr(self._settings, "SPELL_CACHE", val), set=lambda self, val: setattr(self._settings, "SPELL_CACHE", val),
) )
PY_SYS_PATHS = StringProperty( PY_SYS_PATHS: StringProperty(
name="Import Paths", name="Import Paths",
description="Additional paths to add to sys.path (';' separated)", description="Additional paths to add to sys.path (';' separated)",
default="", default="",
...@@ -165,7 +180,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences): ...@@ -165,7 +180,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences):
set=lambda self, val: setattr(self._settings, "PY_SYS_PATHS", val), set=lambda self, val: setattr(self._settings, "PY_SYS_PATHS", val),
) )
persistent_data_path = StringProperty( persistent_data_path: StringProperty(
name="Persistent Data Path", name="Persistent Data Path",
description="The name of a json file storing those settings (unfortunately, Blender's system " description="The name of a json file storing those settings (unfortunately, Blender's system "
"does not work here)", "does not work here)",
...@@ -187,7 +202,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences): ...@@ -187,7 +202,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences):
layout.prop(self, "PY_SYS_PATHS") layout.prop(self, "PY_SYS_PATHS")
layout.separator() layout.separator()
split = layout.split(0.75) split = layout.split(factor=0.75)
col = split.column() col = split.column()
col.prop(self, "persistent_data_path") col.prop(self, "persistent_data_path")
row = col.row() row = col.row()
......
...@@ -25,16 +25,12 @@ if "bpy" in locals(): ...@@ -25,16 +25,12 @@ if "bpy" in locals():
importlib.reload(bl_extract_messages) importlib.reload(bl_extract_messages)
else: else:
import bpy import bpy
from bpy.types import Operator
from bpy.props import ( from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, EnumProperty,
EnumProperty, StringProperty,
FloatProperty, )
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from . import settings from . import settings
from bl_i18n_utils import utils as utils_i18n from bl_i18n_utils import utils as utils_i18n
from bl_i18n_utils import bl_extract_messages from bl_i18n_utils import bl_extract_messages
...@@ -49,7 +45,8 @@ import subprocess ...@@ -49,7 +45,8 @@ import subprocess
import tempfile import tempfile
##### Helpers ##### # Helpers ###################################################################
def validate_module(op, context): def validate_module(op, context):
module_name = op.module_name module_name = op.module_name
addon = getattr(context, "active_addon", None) addon = getattr(context, "active_addon", None)
...@@ -91,16 +88,27 @@ def enum_addons(self, context): ...@@ -91,16 +88,27 @@ def enum_addons(self, context):
return _cached_enum_addons return _cached_enum_addons
##### Operators ##### # Operators ###################################################################
# This one is a helper one, as we sometimes need another invoke function (like e.g. file selection)... # This one is a helper one, as we sometimes need another invoke function (like e.g. file selection)...
class UI_OT_i18n_addon_translation_invoke(bpy.types.Operator): class UI_OT_i18n_addon_translation_invoke(Operator):
"""Wrapper operator which will invoke given op after setting its module_name""" """Wrapper operator which will invoke given op after setting its module_name"""
bl_idname = "ui.i18n_addon_translation_invoke" bl_idname = "ui.i18n_addon_translation_invoke"
bl_label = "Update I18n Add-on" bl_label = "Update I18n Add-on"
bl_property = "module_name" bl_property = "module_name"
module_name = EnumProperty(items=enum_addons, name="Add-on", description="Add-on to process", options=set()) # Operator Arguments
op_id = StringProperty(name="Operator Name", description="Name (id) of the operator to invoke") module_name: EnumProperty(
name="Add-on",
description="Add-on to process",
items=enum_addons,
options=set(),
)
op_id: StringProperty(
name="Operator Name",
description="Name (id) of the operator to invoke",
)
# /End Operator Arguments
def invoke(self, context, event): def invoke(self, context, event):
global _cached_enum_addons global _cached_enum_addons
...@@ -116,17 +124,24 @@ class UI_OT_i18n_addon_translation_invoke(bpy.types.Operator): ...@@ -116,17 +124,24 @@ class UI_OT_i18n_addon_translation_invoke(bpy.types.Operator):
op = bpy.ops op = bpy.ops
for item in self.op_id.split('.'): for item in self.op_id.split('.'):
op = getattr(op, item, None) op = getattr(op, item, None)
#print(self.op_id, item, op)
if op is None: if op is None:
return {'CANCELLED'} return {'CANCELLED'}
return op('INVOKE_DEFAULT', module_name=self.module_name) return op('INVOKE_DEFAULT', module_name=self.module_name)
class UI_OT_i18n_addon_translation_update(bpy.types.Operator):
class UI_OT_i18n_addon_translation_update(Operator):
"""Update given add-on's translation data (found as a py tuple in the add-on's source code)""" """Update given add-on's translation data (found as a py tuple in the add-on's source code)"""
bl_idname = "ui.i18n_addon_translation_update" bl_idname = "ui.i18n_addon_translation_update"
bl_label = "Update I18n Add-on" bl_label = "Update I18n Add-on"
module_name = EnumProperty(items=enum_addons, name="Add-on", description="Add-on to process", options=set()) # Operator Arguments
module_name: EnumProperty(
name="Add-on",
description="Add-on to process",
items=enum_addons,
options=set()
)
# /End Operator Arguments
def execute(self, context): def execute(self, context):
global _cached_enum_addons global _cached_enum_addons
...@@ -174,13 +189,23 @@ class UI_OT_i18n_addon_translation_update(bpy.types.Operator): ...@@ -174,13 +189,23 @@ class UI_OT_i18n_addon_translation_update(bpy.types.Operator):
return {'FINISHED'} return {'FINISHED'}
class UI_OT_i18n_addon_translation_import(bpy.types.Operator): class UI_OT_i18n_addon_translation_import(Operator):
"""Import given add-on's translation data from PO files""" """Import given add-on's translation data from PO files"""
bl_idname = "ui.i18n_addon_translation_import" bl_idname = "ui.i18n_addon_translation_import"
bl_label = "I18n Add-on Import" bl_label = "I18n Add-on Import"
module_name = EnumProperty(items=enum_addons, name="Add-on", description="Add-on to process", options=set()) # Operator Arguments
directory = StringProperty(maxlen=1024, subtype='FILE_PATH', options={'HIDDEN', 'SKIP_SAVE'}) module_name: EnumProperty(
name="Add-on",
description="Add-on to process", options=set(),
items=enum_addons,
)
directory: StringProperty(
subtype='FILE_PATH', maxlen=1024,
options={'HIDDEN', 'SKIP_SAVE'}
)
# /End Operator Arguments
def _dst(self, trans, path, uid, kind): def _dst(self, trans, path, uid, kind):
if kind == 'PO': if kind == 'PO':
...@@ -253,16 +278,37 @@ class UI_OT_i18n_addon_translation_import(bpy.types.Operator): ...@@ -253,16 +278,37 @@ class UI_OT_i18n_addon_translation_import(bpy.types.Operator):
return {'FINISHED'} return {'FINISHED'}
class UI_OT_i18n_addon_translation_export(bpy.types.Operator): class UI_OT_i18n_addon_translation_export(Operator):
"""Export given add-on's translation data as PO files""" """Export given add-on's translation data as PO files"""
bl_idname = "ui.i18n_addon_translation_export" bl_idname = "ui.i18n_addon_translation_export"
bl_label = "I18n Add-on Export" bl_label = "I18n Add-on Export"
module_name = EnumProperty(items=enum_addons, name="Add-on", description="Add-on to process", options=set()) # Operator Arguments
use_export_pot = BoolProperty(name="Export POT", default=True, description="Export (generate) a POT file too") module_name: EnumProperty(
use_update_existing = BoolProperty(name="Update Existing", default=True, name="Add-on",
description="Update existing po files, if any, instead of overwriting them") description="Add-on to process",
directory = StringProperty(maxlen=1024, subtype='FILE_PATH', options={'HIDDEN', 'SKIP_SAVE'}) items=enum_addons,
options=set()
)
use_export_pot: BoolProperty(
name="Export POT",
description="Export (generate) a POT file too",
default=True,
)
use_update_existing: BoolProperty(
name="Update Existing",
description="Update existing po files, if any, instead of overwriting them",
default=True,
)
directory: StringProperty(
subtype='FILE_PATH', maxlen=1024,
options={'HIDDEN', 'SKIP_SAVE'}
)
# /End Operator Arguments
def _dst(self, trans, path, uid, kind): def _dst(self, trans, path, uid, kind):
if kind == 'PO': if kind == 'PO':
......
...@@ -25,16 +25,11 @@ if "bpy" in locals(): ...@@ -25,16 +25,11 @@ if "bpy" in locals():
importlib.reload(utils_languages_menu) importlib.reload(utils_languages_menu)
else: else:
import bpy import bpy
from bpy.types import Operator
from bpy.props import ( from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, EnumProperty,
EnumProperty, )
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from . import settings from . import settings
from bl_i18n_utils import utils as utils_i18n from bl_i18n_utils import utils as utils_i18n
from bl_i18n_utils import utils_languages_menu from bl_i18n_utils import utils_languages_menu
...@@ -46,13 +41,20 @@ import subprocess ...@@ -46,13 +41,20 @@ import subprocess
import tempfile import tempfile
##### Operators ##### # Operators ###################################################################
class UI_OT_i18n_updatetranslation_svn_branches(bpy.types.Operator):
class UI_OT_i18n_updatetranslation_svn_branches(Operator):
"""Update i18n svn's branches (po files)""" """Update i18n svn's branches (po files)"""
bl_idname = "ui.i18n_updatetranslation_svn_branches" bl_idname = "ui.i18n_updatetranslation_svn_branches"
bl_label = "Update I18n Branches" bl_label = "Update I18n Branches"
use_skip_pot_gen = BoolProperty(name="Skip POT", default=False, description="Skip POT file generation") # Operator Arguments
use_skip_pot_gen: BoolProperty(
name="Skip POT",
description="Skip POT file generation",
default=False,
)
# /End Operator Arguments
def execute(self, context): def execute(self, context):
if not hasattr(self, "settings"): if not hasattr(self, "settings"):
...@@ -108,7 +110,7 @@ class UI_OT_i18n_updatetranslation_svn_branches(bpy.types.Operator): ...@@ -108,7 +110,7 @@ class UI_OT_i18n_updatetranslation_svn_branches(bpy.types.Operator):
return wm.invoke_props_dialog(self) return wm.invoke_props_dialog(self)
class UI_OT_i18n_updatetranslation_svn_trunk(bpy.types.Operator): class UI_OT_i18n_updatetranslation_svn_trunk(Operator):
"""Update i18n svn's branches (po files)""" """Update i18n svn's branches (po files)"""
bl_idname = "ui.i18n_updatetranslation_svn_trunk" bl_idname = "ui.i18n_updatetranslation_svn_trunk"
bl_label = "Update I18n Trunk" bl_label = "Update I18n Trunk"
...@@ -166,14 +168,27 @@ class UI_OT_i18n_updatetranslation_svn_trunk(bpy.types.Operator): ...@@ -166,14 +168,27 @@ class UI_OT_i18n_updatetranslation_svn_trunk(bpy.types.Operator):
return {'FINISHED'} return {'FINISHED'}
class UI_OT_i18n_updatetranslation_svn_statistics(bpy.types.Operator): class UI_OT_i18n_updatetranslation_svn_statistics(Operator):
"""Create or extend a 'i18n_info.txt' Text datablock containing statistics and checks about """ """Create or extend a 'i18n_info.txt' Text datablock
"""current branches and/or trunk"""
It will contain statistics and checks about current branches and/or trunk.
"""
bl_idname = "ui.i18n_updatetranslation_svn_statistics" bl_idname = "ui.i18n_updatetranslation_svn_statistics"
bl_label = "Update I18n Statistics" bl_label = "Update I18n Statistics"
use_branches = BoolProperty(name="Check Branches", default=True, description="Check po files in branches") # Operator Arguments
use_trunk = BoolProperty(name="Check Trunk", default=False, description="Check po files in trunk") use_branches: BoolProperty(
name="Check Branches",
description="Check po files in branches",
default=True,
)
use_trunk: BoolProperty(
name="Check Trunk",
description="Check po files in trunk",
default=False,
)
# /End Operator Arguments
report_name = "i18n_info.txt" report_name = "i18n_info.txt"
...@@ -220,7 +235,6 @@ class UI_OT_i18n_updatetranslation_svn_statistics(bpy.types.Operator): ...@@ -220,7 +235,6 @@ class UI_OT_i18n_updatetranslation_svn_statistics(bpy.types.Operator):
return {'FINISHED'} return {'FINISHED'}
def invoke(self, context, event): def invoke(self, context, event):
wm = context.window_manager wm = context.window_manager
return wm.invoke_props_dialog(self) return wm.invoke_props_dialog(self)
......
...@@ -18,64 +18,125 @@ ...@@ -18,64 +18,125 @@
# <pep8 compliant> # <pep8 compliant>
import os
if "bpy" in locals(): if "bpy" in locals():
import importlib import importlib
importlib.reload(settings) importlib.reload(settings)
importlib.reload(utils_i18n) importlib.reload(utils_i18n)
else: else:
import bpy import bpy
from bpy.types import (
Operator,
Panel,
PropertyGroup,
UIList,
)
from bpy.props import ( from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, IntProperty,
EnumProperty, StringProperty,
FloatProperty, CollectionProperty,
FloatVectorProperty, )
IntProperty,
PointerProperty,
StringProperty,
)
from . import settings from . import settings
from bl_i18n_utils import utils as utils_i18n from bl_i18n_utils import utils as utils_i18n
from bpy.app.translations import pgettext_iface as iface_ from bpy.app.translations import pgettext_iface as iface_
import os
# Data ########################################################################
##### Data ##### class I18nUpdateTranslationLanguage(PropertyGroup):
class I18nUpdateTranslationLanguage(bpy.types.PropertyGroup): """Settings/info about a language."""
"""Settings/info about a language"""
uid = StringProperty(name="Language ID", default="", description="ISO code, like fr_FR") uid: StringProperty(
num_id = IntProperty(name="Numeric ID", default=0, min=0, description="Numeric ID (readonly!)") name="Language ID",
name = StringProperty(name="Language Name", default="", description="ISO code (eg. \"fr_FR\")",
description="English language name/label (like \"French (Français)\")") default="",
use = BoolProperty(name="Use", default=True, description="Use this language in current operator") )
po_path = StringProperty(name="PO File Path", default="", subtype='FILE_PATH',
description="Path to the relevant po file in branches") num_id: IntProperty(
po_path_trunk = StringProperty(name="PO Trunk File Path", default="", subtype='FILE_PATH', name="Numeric ID",
description="Path to the relevant po file in trunk") description="Numeric ID (read only!)",
mo_path_trunk = StringProperty(name="MO File Path", default="", subtype='FILE_PATH', default=0, min=0,
description="Path to the relevant mo file") )
po_path_git = StringProperty(name="PO Git Master File Path", default="", subtype='FILE_PATH',
description="Path to the relevant po file in Blender's translations git repository") name: StringProperty(
name="Language Name",
description="Language label (eg. \"French (Français)\")",
class I18nUpdateTranslationSettings(bpy.types.PropertyGroup): default="",
)
use: BoolProperty(
name="Use",
description="If this language should be used in the current operator",
default=True,
)
po_path: StringProperty(
name="PO File Path",
description="Path to the relevant po file in branches",
subtype='FILE_PATH',
default="",
)
po_path_trunk: StringProperty(
name="PO Trunk File Path",
description="Path to the relevant po file in trunk",
subtype='FILE_PATH',
default="",
)
mo_path_trunk: StringProperty(
name="MO File Path",
description="Path to the relevant mo file",
subtype='FILE_PATH',
default="",
)
po_path_git: StringProperty(
name="PO Git Master File Path",
description="Path to the relevant po file in Blender's translations git repository",
subtype='FILE_PATH',
default="",
)
class I18nUpdateTranslationSettings(PropertyGroup):
"""Settings/info about a language""" """Settings/info about a language"""
langs = CollectionProperty(name="Languages", type=I18nUpdateTranslationLanguage,
description="Languages to update in branches") langs: CollectionProperty(
active_lang = IntProperty(name="Active Language", default=0, name="Languages",
description="Index of active language in langs collection") type=I18nUpdateTranslationLanguage,
pot_path = StringProperty(name="POT File Path", default="", subtype='FILE_PATH', description="Languages to update in branches",
description="Path to the pot template file") )
is_init = BoolProperty(default=False, options={'HIDDEN'},
description="Whether these settings have already been auto-set or not") active_lang: IntProperty(
name="Active Language",
default=0,
##### UI ##### description="Index of active language in langs collection",
class UI_UL_i18n_languages(bpy.types.UIList): )
pot_path: StringProperty(
name="POT File Path",
description="Path to the pot template file",
subtype='FILE_PATH',
default="",
)
is_init: BoolProperty(
description="Whether these settings have already been auto-set or not",
default=False,
options={'HIDDEN'},
)
# UI ##########################################################################
class UI_UL_i18n_languages(UIList):
""" """
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
#assert(isinstance(item, bpy.types.I18nUpdateTranslationLanguage))
if self.layout_type in {'DEFAULT', 'COMPACT'}: if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.label(item.name, icon_value=icon) layout.label(item.name, icon_value=icon)
layout.prop(item, "use", text="") layout.prop(item, "use", text="")
...@@ -85,7 +146,9 @@ class UI_UL_i18n_languages(bpy.types.UIList): ...@@ -85,7 +146,9 @@ class UI_UL_i18n_languages(bpy.types.UIList):
layout.prop(item, "use", text="") layout.prop(item, "use", text="")
class UI_PT_i18n_update_translations_settings(bpy.types.Panel): class UI_PT_i18n_update_translations_settings(Panel):
""" """
bl_label = "I18n Update Translation" bl_label = "I18n Update Translation"
bl_space_type = "PROPERTIES" bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW" bl_region_type = "WINDOW"
...@@ -102,7 +165,7 @@ class UI_PT_i18n_update_translations_settings(bpy.types.Panel): ...@@ -102,7 +165,7 @@ class UI_PT_i18n_update_translations_settings(bpy.types.Panel):
layout.label(text="Could not init languages data!") layout.label(text="Could not init languages data!")
layout.label(text="Please edit the preferences of the UI Translate add-on") layout.label(text="Please edit the preferences of the UI Translate add-on")
else: else:
split = layout.split(0.75) split = layout.split(factor=0.75)
split.template_list("UI_UL_i18n_languages", "", i18n_sett, "langs", i18n_sett, "active_lang", rows=8) split.template_list("UI_UL_i18n_languages", "", i18n_sett, "langs", i18n_sett, "active_lang", rows=8)
col = split.column() col = split.column()
col.operator("ui.i18n_updatetranslation_svn_init_settings", text="Reset Settings") col.operator("ui.i18n_updatetranslation_svn_init_settings", text="Reset Settings")
...@@ -132,7 +195,7 @@ class UI_PT_i18n_update_translations_settings(bpy.types.Panel): ...@@ -132,7 +195,7 @@ class UI_PT_i18n_update_translations_settings(bpy.types.Panel):
layout.prop(i18n_sett, "pot_path") layout.prop(i18n_sett, "pot_path")
layout.separator() layout.separator()
layout.label("Add-ons:") layout.label(text="Add-ons:")
row = layout.row() row = layout.row()
op = row.operator("ui.i18n_addon_translation_invoke", text="Refresh I18n Data...") op = row.operator("ui.i18n_addon_translation_invoke", text="Refresh I18n Data...")
op.op_id = "ui.i18n_addon_translation_update" op.op_id = "ui.i18n_addon_translation_update"
...@@ -142,9 +205,11 @@ class UI_PT_i18n_update_translations_settings(bpy.types.Panel): ...@@ -142,9 +205,11 @@ class UI_PT_i18n_update_translations_settings(bpy.types.Panel):
op.op_id = "ui.i18n_addon_translation_import" op.op_id = "ui.i18n_addon_translation_import"
##### Operators ##### # Operators ###################################################################
class UI_OT_i18n_updatetranslation_svn_init_settings(bpy.types.Operator):
class UI_OT_i18n_updatetranslation_svn_init_settings(Operator):
"""Init settings for i18n svn's update operators""" """Init settings for i18n svn's update operators"""
bl_idname = "ui.i18n_updatetranslation_svn_init_settings" bl_idname = "ui.i18n_updatetranslation_svn_init_settings"
bl_label = "Init I18n Update Settings" bl_label = "Init I18n Update Settings"
bl_option = {'REGISTER'} bl_option = {'REGISTER'}
...@@ -200,14 +265,25 @@ class UI_OT_i18n_updatetranslation_svn_init_settings(bpy.types.Operator): ...@@ -200,14 +265,25 @@ class UI_OT_i18n_updatetranslation_svn_init_settings(bpy.types.Operator):
return {'FINISHED'} return {'FINISHED'}
class UI_OT_i18n_updatetranslation_svn_settings_select(bpy.types.Operator): class UI_OT_i18n_updatetranslation_svn_settings_select(Operator):
"""(De)select (or invert selection of) all languages for i18n svn's update operators""" """(De)select (or invert selection of) all languages for i18n svn's update operators"""
bl_idname = "ui.i18n_updatetranslation_svn_settings_select" bl_idname = "ui.i18n_updatetranslation_svn_settings_select"
bl_label = "Init I18n Update Select Languages" bl_label = "Init I18n Update Select Languages"
use_select = BoolProperty(name="Select All", default=True, description="Select all if True, else deselect all") # Operator Arguments
use_invert = BoolProperty(name="Invert Selection", default=False, use_select: BoolProperty(
description="Inverse selection (overrides 'Select All' when True)") name="Select All",
description="Select all if True, else deselect all",
default=True,
)
use_invert: BoolProperty(
name="Invert Selection",
description="Inverse selection (overrides 'Select All' when True)",
default=False,
)
# /End Operator Arguments
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment