Merge branch 'blender2.8' of git.blender.org:blender-addons into blender2.8

This commit is contained in:
Kalle-Samuli Riihikoski 2018-11-12 13:00:21 +02:00
commit d3fddc7d32
7 changed files with 488 additions and 232 deletions

View File

@ -62,7 +62,7 @@ def face_inset_fillet(bme, face_index_list, inset_amount, distance,
bme.faces.ensure_lookup_table()
# loops through the faces...
f = bme.faces[faceindex]
f.select_set(0)
f.select_set(False)
list_del.append(f)
f.normal_update()
vertex_index_list = [v.index for v in f.verts]

View File

@ -21,11 +21,11 @@
bl_info = {
"name": "Manage UI translations",
"author": "Bastien Montagne",
"version": (1, 1, 4),
"blender": (2, 79, 0),
"version": (1, 1, 5),
"blender": (2, 80, 0),
"location": "Main \"File\" menu, text editor, any UI control",
"description": "Allow to manage UI translations directly from Blender "
"(update main po files, update scripts' translations, etc.)",
"description": "Allows managing UI translations directly from Blender "
"(update main .po files, update scripts' translations, etc.)",
"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",
"support": 'OFFICIAL',
@ -42,15 +42,12 @@ if "bpy" in locals():
else:
import bpy
from . import (
settings,
edit_translation,
update_svn,
update_addon,
update_ui,
)
import os
settings,
edit_translation,
update_svn,
update_addon,
update_ui,
)
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
def register():
for cls in classes:
bpy.utils.register_class(cls)
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,
# the load/save user preferences process has no effect on them :( ).
if __name__ in bpy.context.user_preferences.addons:
pref = bpy.context.user_preferences.addons[__name__].preferences
import os
if os.path.isfile(pref.persistent_data_path):
pref._settings.load(pref.persistent_data_path, reset=True)
def unregister():
del bpy.types.WindowManager.i18n_update_svn_settings
for cls in classes:
bpy.utils.unregister_class(cls)
del bpy.types.WindowManager.i18n_update_svn_settings

View File

@ -18,30 +18,24 @@
# <pep8 compliant>
import os
import shutil
if "bpy" in locals():
import importlib
importlib.reload(settings)
importlib.reload(utils_i18n)
else:
import bpy
from bpy.types import Operator
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
BoolProperty,
EnumProperty,
StringProperty,
)
from . import settings
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.
PO_CACHE = {}
@ -52,21 +46,30 @@ def _get_messages(lang, fname):
return PO_CACHE[fname]
class UI_OT_i18n_edittranslation_update_mo(bpy.types.Operator):
"""Try to "compile" given po file into relevant blender.mo file """ \
"""(WARNING: it will replace the official mo file in your user dir!)"""
class UI_OT_i18n_edittranslation_update_mo(Operator):
"""Try to "compile" given po file into relevant blender.mo file
(WARNING: it will replace the official mo file in your user dir!)"""
bl_idname = "ui.i18n_edittranslation_update_mo"
bl_label = "Edit Translation Update Mo"
# "Parameters"
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'})
clean_mo = BoolProperty(description="Clean up (remove) all local "
"translation files, to be able to use "
"all system's ones again",
default=False, options={'SKIP_SAVE'})
# Operator Arguments
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'},
)
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):
if self.clean_mo:
@ -85,65 +88,169 @@ class UI_OT_i18n_edittranslation_update_mo(bpy.types.Operator):
return {'FINISHED'}
class UI_OT_i18n_edittranslation(bpy.types.Operator):
"""Translate the label and tooltip of the property defined by given 'parameters'"""
class UI_OT_i18n_edittranslation(Operator):
"""Translate the label and tooltip of the given property"""
bl_idname = "ui.edittranslation"
bl_label = "Edit Translation"
# "Parameters"
but_label = StringProperty(description="Label of the control", options={'SKIP_SAVE'})
rna_label = StringProperty(description="RNA-defined label of the control, if any", options={'SKIP_SAVE'})
enum_label = StringProperty(description="Label of the enum item of the control, if any", 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'})
# Operator Arguments
but_label: StringProperty(
description="Label of the control",
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'})
rna_label: StringProperty(
description="RNA-defined label of the control, if any",
options={'SKIP_SAVE'},
)
enum_label: StringProperty(
description="Label of the enum item of the control, if any",
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.
org_but_label = StringProperty(description="Original label of the control", options={'SKIP_SAVE'})
org_rna_label = StringProperty(description="Original RNA-defined label of the control, if any",
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_tip = StringProperty(description="Original RNA-defined tip of the control, if any", options={'SKIP_SAVE'})
org_enum_tip = StringProperty(description="Original tip of the enum item of the control, if any",
options={'SKIP_SAVE'})
org_but_label: StringProperty(
description="Original label of the control",
options={'SKIP_SAVE'},
)
flag_items = (('FUZZY', "Fuzzy", "Message is marked as fuzzy in po file"),
('ERROR', "Error", "Some error occurred with this message"),
)
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",
options={'SKIP_SAVE', 'ENUM_FLAG'})
enum_label_flags = EnumProperty(items=flag_items, description="Flags about the RNA enum item label of the button",
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'})
rna_tip_flags = EnumProperty(items=flag_items, description="Flags about the RNA-defined tip of the button",
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_rna_label: StringProperty(
description="Original RNA-defined label of the control, if any",
options={'SKIP_SAVE'},
)
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 UI",
default=False, options={'SKIP_SAVE'})
update_mo = BoolProperty(description="Try to rebuild mo file, and refresh Blender UI",
default=False, options={'SKIP_SAVE'})
clean_mo = BoolProperty(description="Clean up (remove) all local translation files, to be able to use "
"all system's ones again",
default=False, 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_tip: StringProperty(
description="Original RNA-defined tip of the control, if any", options={'SKIP_SAVE'}
)
org_enum_tip: StringProperty(
description="Original tip of the enum item of the control, if any",
options={'SKIP_SAVE'},
)
flag_items = (
('FUZZY', "Fuzzy", "Message is marked as fuzzy in po file"),
('ERROR', "Error", "Some error occurred with this message"),
)
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):
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'}
msgs = _get_messages(self.lang, self.po_file)
@ -152,7 +259,6 @@ class UI_OT_i18n_edittranslation(bpy.types.Operator):
if 'ERROR' in getattr(self, mmap["msg_flags"]):
continue
k = mmap["key"]
# print(k)
if k not in done_keys and len(k) == 1:
k = tuple(k)[0]
msgs.msgs[k].msgstr = getattr(self, mmap["msgstr"])
@ -160,7 +266,7 @@ class UI_OT_i18n_edittranslation(bpy.types.Operator):
done_keys.add(k)
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:
msgs.write(kind='PO', dest=self.po_file)
except Exception as e:
@ -175,19 +281,20 @@ class UI_OT_i18n_edittranslation(bpy.types.Operator):
return {'FINISHED'}
def invoke(self, context, event):
self.msgmap = {"but_label": {"msgstr": "but_label", "msgid": "org_but_label",
"msg_flags": "but_label_flags", "key": set()},
"rna_label": {"msgstr": "rna_label", "msgid": "org_rna_label",
"msg_flags": "rna_label_flags", "key": set()},
"enum_label": {"msgstr": "enum_label", "msgid": "org_enum_label",
"msg_flags": "enum_label_flags", "key": set()},
"but_tip": {"msgstr": "but_tip", "msgid": "org_but_tip",
"msg_flags": "but_tip_flags", "key": set()},
"rna_tip": {"msgstr": "rna_tip", "msgid": "org_rna_tip",
"msg_flags": "rna_tip_flags", "key": set()},
"enum_tip": {"msgstr": "enum_tip", "msgid": "org_enum_tip",
"msg_flags": "enum_tip_flags", "key": set()},
}
self.msgmap = {
"but_label": {
"msgstr": "but_label", "msgid": "org_but_label", "msg_flags": "but_label_flags", "key": set()},
"rna_label": {
"msgstr": "rna_label", "msgid": "org_rna_label", "msg_flags": "rna_label_flags", "key": set()},
"enum_label": {
"msgstr": "enum_label", "msgid": "org_enum_label", "msg_flags": "enum_label_flags", "key": set()},
"but_tip": {
"msgstr": "but_tip", "msgid": "org_but_tip", "msg_flags": "but_tip_flags", "key": set()},
"rna_tip": {
"msgstr": "rna_tip", "msgid": "org_rna_tip", "msg_flags": "rna_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.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):
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 :/
box = layout.box()
#box = layout
box.label(text="Labels:")
split = box.split(percentage=0.15)
split = box.split(factor=0.15)
col1 = split.column()
col2 = split.column()
if self.org_but_label:
@ -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:
# XXX Can't use box, labels are not enough readable in them :/
box = layout.box()
#box = layout
box.label(text="Tool Tips:")
split = box.split(percentage=0.15)
split = box.split(factor=0.15)
col1 = split.column()
col2 = split.column()
if self.org_but_tip:

View File

@ -18,40 +18,46 @@
# <pep8 compliant>
import os
if "bpy" in locals():
import importlib
importlib.reload(settings_i18n)
else:
import bpy
from bpy.types import (
Operator,
AddonPreferences,
)
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
BoolProperty,
StringProperty,
)
from bl_i18n_utils import settings as settings_i18n
import os
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"""
bl_idname = "ui.i18n_settings_load"
bl_label = "I18n Load Settings"
bl_option = {'REGISTER'}
# "Parameters"
filepath = StringProperty(description="Path to the saved settings file",
subtype='FILE_PATH')
filter_glob = StringProperty(default="*.json", options={'HIDDEN'})
# Operator Arguments
filepath: StringProperty(
subtype='FILE_PATH',
description="Path to the saved settings file",
)
filter_glob: StringProperty(
default="*.json",
options={'HIDDEN'}
)
# /End Operator Arguments
def invoke(self, context, event):
if not self.properties.is_property_set("filepath"):
@ -67,16 +73,23 @@ class UI_OT_i18n_settings_load(bpy.types.Operator):
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"""
bl_idname = "ui.i18n_settings_save"
bl_label = "I18n Save Settings"
bl_option = {'REGISTER'}
# "Parameters"
filepath = StringProperty(description="Path to the saved settings file",
subtype='FILE_PATH')
filter_glob = StringProperty(default="*.json", options={'HIDDEN'})
# Operator Arguments
filepath: StringProperty(
description="Path to the saved settings file",
subtype='FILE_PATH',
)
filter_glob: StringProperty(
default="*.json",
options={'HIDDEN'},
)
# /End Operator Arguments
def invoke(self, context, event):
if not self.properties.is_property_set("filepath"):
@ -92,18 +105,20 @@ class UI_OT_i18n_settings_save(bpy.types.Operator):
return {'FINISHED'}
# Addon Preferences ###########################################################
def _setattr(self, name, val):
print(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_option = {'REGISTER'}
_settings = settings
WARN_MSGID_NOT_CAPITALIZED = BoolProperty(
WARN_MSGID_NOT_CAPITALIZED: BoolProperty(
name="Warn Msgid Not Capitalized",
description="Warn about messages not starting by a capitalized letter (with a few allowed exceptions!)",
default=True,
@ -111,7 +126,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences):
set=lambda self, val: _setattr(self._settings, "WARN_MSGID_NOT_CAPITALIZED", val),
)
GETTEXT_MSGFMT_EXECUTABLE = StringProperty(
GETTEXT_MSGFMT_EXECUTABLE: StringProperty(
name="Gettext 'msgfmt' executable",
description="The gettext msgfmt 'compiler'. Youll likely have to edit it if youre under Windows",
subtype='FILE_PATH',
@ -120,7 +135,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences):
set=lambda self, val: setattr(self._settings, "GETTEXT_MSGFMT_EXECUTABLE", val),
)
FRIBIDI_LIB = StringProperty(
FRIBIDI_LIB: StringProperty(
name="Fribidi Library",
description="The FriBidi C compiled library (.so under Linux, .dll under windows...), youll likely have "
"to edit it if youre 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):
set=lambda self, val: setattr(self._settings, "FRIBIDI_LIB", val),
)
SOURCE_DIR = StringProperty(
SOURCE_DIR: StringProperty(
name="Source Root",
description="The Blender source root path",
subtype='FILE_PATH',
@ -139,7 +154,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences):
set=lambda self, val: setattr(self._settings, "SOURCE_DIR", val),
)
I18N_DIR = StringProperty(
I18N_DIR: StringProperty(
name="Translation Root",
description="The bf-translation repository",
subtype='FILE_PATH',
@ -148,7 +163,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences):
set=lambda self, val: setattr(self._settings, "I18N_DIR", val),
)
SPELL_CACHE = StringProperty(
SPELL_CACHE: StringProperty(
name="Spell Cache",
description="A cache storing validated msgids, to avoid re-spellchecking them",
subtype='FILE_PATH',
@ -157,7 +172,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences):
set=lambda self, val: setattr(self._settings, "SPELL_CACHE", val),
)
PY_SYS_PATHS = StringProperty(
PY_SYS_PATHS: StringProperty(
name="Import Paths",
description="Additional paths to add to sys.path (';' separated)",
default="",
@ -165,7 +180,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences):
set=lambda self, val: setattr(self._settings, "PY_SYS_PATHS", val),
)
persistent_data_path = StringProperty(
persistent_data_path: StringProperty(
name="Persistent Data Path",
description="The name of a json file storing those settings (unfortunately, Blender's system "
"does not work here)",
@ -187,7 +202,7 @@ class UI_AP_i18n_settings(bpy.types.AddonPreferences):
layout.prop(self, "PY_SYS_PATHS")
layout.separator()
split = layout.split(0.75)
split = layout.split(factor=0.75)
col = split.column()
col.prop(self, "persistent_data_path")
row = col.row()

View File

@ -25,16 +25,12 @@ if "bpy" in locals():
importlib.reload(bl_extract_messages)
else:
import bpy
from bpy.types import Operator
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
BoolProperty,
EnumProperty,
StringProperty,
)
from . import settings
from bl_i18n_utils import utils as utils_i18n
from bl_i18n_utils import bl_extract_messages
@ -49,7 +45,8 @@ import subprocess
import tempfile
##### Helpers #####
# Helpers ###################################################################
def validate_module(op, context):
module_name = op.module_name
addon = getattr(context, "active_addon", None)
@ -91,16 +88,27 @@ def enum_addons(self, context):
return _cached_enum_addons
##### Operators #####
# Operators ###################################################################
# 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"""
bl_idname = "ui.i18n_addon_translation_invoke"
bl_label = "Update I18n Add-on"
bl_property = "module_name"
module_name = EnumProperty(items=enum_addons, name="Add-on", description="Add-on to process", options=set())
op_id = StringProperty(name="Operator Name", description="Name (id) of the operator to invoke")
# Operator Arguments
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):
global _cached_enum_addons
@ -116,17 +124,24 @@ class UI_OT_i18n_addon_translation_invoke(bpy.types.Operator):
op = bpy.ops
for item in self.op_id.split('.'):
op = getattr(op, item, None)
#print(self.op_id, item, op)
if op is None:
return {'CANCELLED'}
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)"""
bl_idname = "ui.i18n_addon_translation_update"
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):
global _cached_enum_addons
@ -174,13 +189,23 @@ class UI_OT_i18n_addon_translation_update(bpy.types.Operator):
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"""
bl_idname = "ui.i18n_addon_translation_import"
bl_label = "I18n Add-on Import"
module_name = EnumProperty(items=enum_addons, name="Add-on", description="Add-on to process", options=set())
directory = StringProperty(maxlen=1024, subtype='FILE_PATH', options={'HIDDEN', 'SKIP_SAVE'})
# Operator Arguments
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):
if kind == 'PO':
@ -253,16 +278,37 @@ class UI_OT_i18n_addon_translation_import(bpy.types.Operator):
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"""
bl_idname = "ui.i18n_addon_translation_export"
bl_label = "I18n Add-on Export"
module_name = EnumProperty(items=enum_addons, name="Add-on", description="Add-on to process", options=set())
use_export_pot = BoolProperty(name="Export POT", default=True, description="Export (generate) a POT file too")
use_update_existing = BoolProperty(name="Update Existing", default=True,
description="Update existing po files, if any, instead of overwriting them")
directory = StringProperty(maxlen=1024, subtype='FILE_PATH', options={'HIDDEN', 'SKIP_SAVE'})
# Operator Arguments
module_name: EnumProperty(
name="Add-on",
description="Add-on to process",
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):
if kind == 'PO':

View File

@ -25,16 +25,11 @@ if "bpy" in locals():
importlib.reload(utils_languages_menu)
else:
import bpy
from bpy.types import Operator
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
BoolProperty,
EnumProperty,
)
from . import settings
from bl_i18n_utils import utils as utils_i18n
from bl_i18n_utils import utils_languages_menu
@ -46,13 +41,20 @@ import subprocess
import tempfile
##### Operators #####
class UI_OT_i18n_updatetranslation_svn_branches(bpy.types.Operator):
# Operators ###################################################################
class UI_OT_i18n_updatetranslation_svn_branches(Operator):
"""Update i18n svn's branches (po files)"""
bl_idname = "ui.i18n_updatetranslation_svn_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):
if not hasattr(self, "settings"):
@ -108,7 +110,7 @@ class UI_OT_i18n_updatetranslation_svn_branches(bpy.types.Operator):
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)"""
bl_idname = "ui.i18n_updatetranslation_svn_trunk"
bl_label = "Update I18n Trunk"
@ -166,14 +168,27 @@ class UI_OT_i18n_updatetranslation_svn_trunk(bpy.types.Operator):
return {'FINISHED'}
class UI_OT_i18n_updatetranslation_svn_statistics(bpy.types.Operator):
"""Create or extend a 'i18n_info.txt' Text datablock containing statistics and checks about """
"""current branches and/or trunk"""
class UI_OT_i18n_updatetranslation_svn_statistics(Operator):
"""Create or extend a 'i18n_info.txt' Text datablock
It will contain statistics and checks about current branches and/or trunk.
"""
bl_idname = "ui.i18n_updatetranslation_svn_statistics"
bl_label = "Update I18n Statistics"
use_branches = BoolProperty(name="Check Branches", default=True, description="Check po files in branches")
use_trunk = BoolProperty(name="Check Trunk", default=False, description="Check po files in trunk")
# Operator Arguments
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"
@ -220,7 +235,6 @@ class UI_OT_i18n_updatetranslation_svn_statistics(bpy.types.Operator):
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)

View File

@ -18,64 +18,125 @@
# <pep8 compliant>
import os
if "bpy" in locals():
import importlib
importlib.reload(settings)
importlib.reload(utils_i18n)
else:
import bpy
from bpy.types import (
Operator,
Panel,
PropertyGroup,
UIList,
)
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
BoolProperty,
IntProperty,
StringProperty,
CollectionProperty,
)
from . import settings
from bl_i18n_utils import utils as utils_i18n
from bpy.app.translations import pgettext_iface as iface_
import os
# Data ########################################################################
class I18nUpdateTranslationLanguage(PropertyGroup):
"""Settings/info about a language."""
uid: StringProperty(
name="Language ID",
description="ISO code (eg. \"fr_FR\")",
default="",
)
num_id: IntProperty(
name="Numeric ID",
description="Numeric ID (read only!)",
default=0, min=0,
)
name: StringProperty(
name="Language Name",
description="Language label (eg. \"French (Français)\")",
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="",
)
##### Data #####
class I18nUpdateTranslationLanguage(bpy.types.PropertyGroup):
class I18nUpdateTranslationSettings(PropertyGroup):
"""Settings/info about a language"""
uid = StringProperty(name="Language ID", default="", description="ISO code, like fr_FR")
num_id = IntProperty(name="Numeric ID", default=0, min=0, description="Numeric ID (readonly!)")
name = StringProperty(name="Language Name", default="",
description="English language name/label (like \"French (Français)\")")
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")
po_path_trunk = StringProperty(name="PO Trunk File Path", default="", subtype='FILE_PATH',
description="Path to the relevant po file in trunk")
mo_path_trunk = StringProperty(name="MO File Path", default="", subtype='FILE_PATH',
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")
langs: CollectionProperty(
name="Languages",
type=I18nUpdateTranslationLanguage,
description="Languages to update in branches",
)
active_lang: IntProperty(
name="Active Language",
default=0,
description="Index of active language in langs collection",
)
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'},
)
class I18nUpdateTranslationSettings(bpy.types.PropertyGroup):
"""Settings/info about a language"""
langs = CollectionProperty(name="Languages", type=I18nUpdateTranslationLanguage,
description="Languages to update in branches")
active_lang = IntProperty(name="Active Language", default=0,
description="Index of active language in langs collection")
pot_path = StringProperty(name="POT File Path", default="", subtype='FILE_PATH',
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")
# UI ##########################################################################
class UI_UL_i18n_languages(UIList):
""" """
##### UI #####
class UI_UL_i18n_languages(bpy.types.UIList):
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'}:
layout.label(item.name, icon_value=icon)
layout.prop(item, "use", text="")
@ -85,7 +146,9 @@ class UI_UL_i18n_languages(bpy.types.UIList):
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_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
@ -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="Please edit the preferences of the UI Translate add-on")
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)
col = split.column()
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):
layout.prop(i18n_sett, "pot_path")
layout.separator()
layout.label("Add-ons:")
layout.label(text="Add-ons:")
row = layout.row()
op = row.operator("ui.i18n_addon_translation_invoke", text="Refresh I18n Data...")
op.op_id = "ui.i18n_addon_translation_update"
@ -142,9 +205,11 @@ class UI_PT_i18n_update_translations_settings(bpy.types.Panel):
op.op_id = "ui.i18n_addon_translation_import"
##### Operators #####
class UI_OT_i18n_updatetranslation_svn_init_settings(bpy.types.Operator):
# Operators ###################################################################
class UI_OT_i18n_updatetranslation_svn_init_settings(Operator):
"""Init settings for i18n svn's update operators"""
bl_idname = "ui.i18n_updatetranslation_svn_init_settings"
bl_label = "Init I18n Update Settings"
bl_option = {'REGISTER'}
@ -200,14 +265,25 @@ class UI_OT_i18n_updatetranslation_svn_init_settings(bpy.types.Operator):
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"""
bl_idname = "ui.i18n_updatetranslation_svn_settings_select"
bl_label = "Init I18n Update Select Languages"
use_select = BoolProperty(name="Select All", default=True, description="Select all if True, else deselect all")
use_invert = BoolProperty(name="Invert Selection", default=False,
description="Inverse selection (overrides 'Select All' when True)")
# Operator Arguments
use_select: BoolProperty(
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
def poll(cls, context):