remove dirs to make them external's

This commit is contained in:
Campbell Barton
2011-11-05 12:16:40 +00:00
parent 33accdb725
commit fd6138a26d
9 changed files with 0 additions and 1348 deletions

View File

@@ -1,201 +0,0 @@
release/scripts/modules/rna_prop_ui.py
release/scripts/startup/bl_operators/object.py
release/scripts/startup/bl_operators/object_align.py
release/scripts/startup/bl_operators/object_quick_effects.py
release/scripts/startup/bl_operators/object_randomize_transform.py
release/scripts/startup/bl_operators/presets.py
release/scripts/startup/bl_operators/screen_play_rendered_anim.py
release/scripts/startup/bl_operators/sequencer.py
release/scripts/startup/bl_operators/wm.py
release/scripts/startup/bl_ui/properties_animviz.py
release/scripts/startup/bl_ui/properties_data_armature.py
release/scripts/startup/bl_ui/properties_data_bone.py
release/scripts/startup/bl_ui/properties_data_camera.py
release/scripts/startup/bl_ui/properties_data_curve.py
release/scripts/startup/bl_ui/properties_data_empty.py
release/scripts/startup/bl_ui/properties_data_lamp.py
release/scripts/startup/bl_ui/properties_data_lattice.py
release/scripts/startup/bl_ui/properties_data_mesh.py
release/scripts/startup/bl_ui/properties_data_metaball.py
release/scripts/startup/bl_ui/properties_data_modifier.py
release/scripts/startup/bl_ui/properties_game.py
release/scripts/startup/bl_ui/properties_material.py
release/scripts/startup/bl_ui/properties_object_constraint.py
release/scripts/startup/bl_ui/properties_object.py
release/scripts/startup/bl_ui/properties_particle.py
release/scripts/startup/bl_ui/properties_physics_cloth.py
release/scripts/startup/bl_ui/properties_physics_common.py
release/scripts/startup/bl_ui/properties_physics_field.py
release/scripts/startup/bl_ui/properties_physics_fluid.py
release/scripts/startup/bl_ui/properties_physics_smoke.py
release/scripts/startup/bl_ui/properties_physics_softbody.py
release/scripts/startup/bl_ui/properties_render.py
release/scripts/startup/bl_ui/properties_scene.py
release/scripts/startup/bl_ui/properties_texture.py
release/scripts/startup/bl_ui/properties_world.py
release/scripts/startup/bl_ui/space_console.py
release/scripts/startup/bl_ui/space_dopesheet.py
release/scripts/startup/bl_ui/space_graph.py
release/scripts/startup/bl_ui/space_image.py
release/scripts/startup/bl_ui/space_info.py
release/scripts/startup/bl_ui/space_logic.py
release/scripts/startup/bl_ui/space_nla.py
release/scripts/startup/bl_ui/space_node.py
release/scripts/startup/bl_ui/space_outliner.py
release/scripts/startup/bl_ui/space_sequencer.py
release/scripts/startup/bl_ui/space_text.py
release/scripts/startup/bl_ui/space_time.py
release/scripts/startup/bl_ui/space_userpref.py
release/scripts/startup/bl_ui/space_userpref_keymap.py
release/scripts/startup/bl_ui/space_view3d.py
release/scripts/startup/bl_ui/space_view3d_toolbar.py
source/blender/editors/animation/anim_channels_edit.c
source/blender/editors/animation/anim_markers.c
source/blender/editors/animation/anim_ops.c
source/blender/editors/animation/drivers.c
source/blender/editors/animation/keyframing.c
source/blender/editors/animation/keyingsets.c
source/blender/editors/armature/armature_ops.c
source/blender/editors/armature/editarmature.c
source/blender/editors/armature/editarmature_sketch.c
source/blender/editors/armature/poselib.c
source/blender/editors/armature/poseobject.c
source/blender/editors/armature/poseSlide.c
source/blender/editors/curve/editcurve.c
source/blender/editors/curve/editfont.c
source/blender/editors/gpencil/gpencil_paint.c
source/blender/editors/interface/interface_layout.c
source/blender/editors/interface/interface_ops.c
source/blender/editors/interface/interface_regions.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/interface/interface_utils.c
source/blender/editors/interface/view2d_ops.c
source/blender/editors/mesh/editmesh.c
source/blender/editors/mesh/editmesh_add.c
source/blender/editors/mesh/editmesh_loop.c
source/blender/editors/mesh/editmesh_mods.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/mesh/loopcut.c
source/blender/editors/mesh/mesh_data.c
source/blender/editors/mesh/mesh_ops.c
source/blender/editors/metaball/mball_edit.c
source/blender/editors/object/object_add.c
source/blender/editors/object/object_constraint.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_group.c
source/blender/editors/object/object_lattice.c
source/blender/editors/object/object_modifier.c
source/blender/editors/object/object_ops.c
source/blender/editors/object/object_relations.c
source/blender/editors/object/object_select.c
source/blender/editors/object/object_shapekey.c
source/blender/editors/object/object_transform.c
source/blender/editors/object/object_vgroup.c
source/blender/editors/physics/particle_edit.c
source/blender/editors/physics/particle_object.c
source/blender/editors/physics/physics_pointcache.c
source/blender/editors/render/render_internal.c
source/blender/editors/render/render_opengl.c
source/blender/editors/render/render_shading.c
source/blender/editors/render/render_view.c
source/blender/editors/screen/area.c
source/blender/editors/screen/screendump.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/sculpt_paint/paint_ops.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/paint_utils.c
source/blender/editors/sculpt_paint/paint_vertex.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/sound/sound_ops.c
source/blender/editors/space_action/action_edit.c
source/blender/editors/space_action/action_ops.c
source/blender/editors/space_action/action_select.c
source/blender/editors/space_buttons/buttons_header.c
source/blender/editors/space_buttons/buttons_ops.c
source/blender/editors/space_console/console_ops.c
source/blender/editors/space_file/file_draw.c
source/blender/editors/space_file/file_ops.c
source/blender/editors/space_file/file_panels.c
source/blender/editors/space_graph/graph_buttons.c
source/blender/editors/space_graph/graph_edit.c
source/blender/editors/space_graph/graph_ops.c
source/blender/editors/space_graph/graph_select.c
source/blender/editors/space_image/image_buttons.c
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_info/info_ops.c
source/blender/editors/space_info/info_report.c
source/blender/editors/space_info/space_info.c
source/blender/editors/space_logic/logic_buttons.c
source/blender/editors/space_nla/nla_buttons.c
source/blender/editors/space_nla/nla_channels.c
source/blender/editors/space_nla/nla_edit.c
source/blender/editors/space_nla/nla_select.c
source/blender/editors/space_node/node_buttons.c
source/blender/editors/space_node/node_edit.c
source/blender/editors/space_node/node_header.c
source/blender/editors/space_node/node_ops.c
source/blender/editors/space_node/node_select.c
source/blender/editors/space_node/node_state.c
source/blender/editors/space_script/script_edit.c
source/blender/editors/space_sequencer/sequencer_add.c
source/blender/editors/space_sequencer/sequencer_buttons.c
source/blender/editors/space_sequencer/sequencer_edit.c
source/blender/editors/space_sequencer/sequencer_select.c
source/blender/editors/space_text/text_header.c
source/blender/editors/space_text/text_ops.c
source/blender/editors/space_time/time_ops.c
source/blender/editors/space_view3d/view3d_buttons.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/space_view3d/view3d_edit.c
source/blender/editors/space_view3d/view3d_fly.c
source/blender/editors/space_view3d/view3d_header.c
source/blender/editors/space_view3d/view3d_select.c
source/blender/editors/space_view3d/view3d_view.c
source/blender/editors/space_view3d/view3d_toolbar.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform_ops.c
source/blender/editors/transform/transform_orientations.c
source/blender/editors/util/undo.c
source/blender/editors/uvedit/uvedit_ops.c
source/blender/editors/uvedit/uvedit_unwrap_ops.c
source/blender/makesrna/intern/rna_userdef.c
source/blender/windowmanager/intern/wm_files.c
source/blender/windowmanager/intern/wm_operators.c
source/blender/windowmanager/intern/wm_window.c

View File

@@ -1,81 +0,0 @@
Blender translation HOWTO
=========================
I'll try briefly explain how translation works and how to update translation files.
1. How it works
---------------
This folder contains source files for translation system. These source files have
got .po extension and they've got pretty simple syntax:
msgid "some message id"
msgstr "translation for this message"
This means when string "some message id" is used as operator name, tooltip, menu
and so it'll be displayed on the screen as "translation for this message".
Pretty simple.
This source files are pre-compiled into ../release/datafiles/locale/<language>/LC_MESSAGES/blender.mo,
so they aren't getting compiled every time Blender is compiling to save some time and prevent
failure on systems which don't have needed tools for compiling .po files.
2. How to update translations
-----------------------------
It's also pretty simple. If you can find string you want to translate in <language>.po
file as msgid, just write correct msgstr string for it. If msgid is marked as fuzzy,
i.e.
#, fuzzy
msgid "some message id"
msgstr "translation for this message"
it means translation used to exist for this message, but message was changed, so translation
also have to be updated (it's easier to make new translation based on previous translation).
When translation was updated, remove line with '#, fuzzy' and it'll work.
If there's no message in .po file you want to translate, probably .po file should be updated.
Use the following steps for this:
- With newly compiled blender run:
`blender --background --factory-startup --python update_msg.py`
to update messages.txt file (this file contains strings collected
automatically from RNA system and python UI scripts)
- Run update_pot.py script which will update blender.pot file. This file contains all
strings which should be transated.
- Run update_po.py script to merge all .po files with blender.pot (so all .po files
will contain all msgid-s declared in blender.pot) or update_po.py <language> to
update only needed .po file(s) to save time when you're busy with translation.
But before commit all .po files better be updated.
When you've finished with translation, you should re-compile .po file into .mo file.
It's also pretty simple: just run update_mo.py script to recompile all languages or
just update_mo.py <language> to re-compile only needed language(s).
NOTE: msgfmt, msgmerge and xgettext tools should be available in your PATH.
These steps to update template, translation files and compile them can be made in "batch" mode
using GNUMakefile:
make -f GNUMakefile translations
NOTE: Blender has to be compiled using GNUMakefile first.
3. Note for Windows users
-------------------------
You can find compiled builds of gettext in the lib folder under "binaries\gettext\" for both windows and win64.
In order to run the scripts you will need to replace the location of the GETTEXT_..._EXECUTABLE.
For example in update_pot.py:
-GETTEXT_XGETTEXT_EXECUTABLE = "xgettext"
+GETTEXT_XGETTEXT_EXECUTABLE = "C:\\Blender\\lib\\\windows\\\binaries\\\gettext\\xgettext.exe"
4. Other scripts
----------------
- check_po.py: this script checks if all messages declared in blender.pot exists in.po files
and that no extra messages are declared in .po files
- clean_po.py: this script removes all commented messages which aren't required by .pot file anymore.
- merge_po.py: this script accepts two files as arguments and copies translations from second file
into first file.

View File

@@ -1,92 +0,0 @@
#!/usr/bin/env python
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENSE BLOCK *****
# <pep8 compliant>
# update the pot file according the POTFILES.in
import os
import sys
from codecs import open
CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
FILE_NAME_POT = os.path.join(CURRENT_DIR, "blender.pot")
def read_messages(fname):
def stripeol(s):
return s.rstrip("\n\r")
messages = {}
reading_message = False
message = ""
with open(fname, 'r', "utf-8") as handle:
while True:
line = handle.readline()
if not line:
break
line = stripeol(line)
if line.startswith("msgid"):
reading_message = True
message = line[7:-1]
elif line.startswith("msgstr"):
reading_message = False
messages[message] = True
elif reading_message:
message += line[1:-1]
return messages
def main():
pot_messages = read_messages(FILE_NAME_POT)
if len(sys.argv) > 1:
for lang in sys.argv[1:]:
po = os.path.join(CURRENT_DIR, lang + '.po')
if os.path.exists(po):
po_messages = read_messages(po)
for msgid in po_messages:
if not pot_messages.get(msgid):
print('Unneeded message id \'%s\'' % (msgid))
for msgid in pot_messages:
if not po_messages.get(msgid):
print('Missed message id \'%s\'' % (msgid))
else:
for po in os.listdir(CURRENT_DIR):
if po.endswith('.po'):
print('Processing %s...' % (po))
po_messages = read_messages(po)
for msgid in po_messages:
if not pot_messages.get(msgid):
print(' Unneeded message id \'%s\'' % (msgid))
for msgid in pot_messages:
if not po_messages.get(msgid):
print(' Missed message id \'%s\'' % (msgid))
if __name__ == "__main__":
print("\n\n *** Running %r *** \n" % __file__)
main()

View File

@@ -1,189 +0,0 @@
#!/usr/bin/env python
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENSE BLOCK *****
# <pep8 compliant>
# update the pot file according the POTFILES.in
import os
import sys
import collections
from codecs import open
CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
FILE_NAME_POT = os.path.join(CURRENT_DIR, "blender.pot")
def read_messages(fname):
def stripeol(s):
return s.rstrip("\n\r")
last_message = None
if hasattr(collections, 'OrderedDict'):
messages = collections.OrderedDict()
commented_messages = collections.OrderedDict()
else:
messages = {}
commented_messages = {}
reading_message = False
reading_translation = False
commented = False
message = ""
translation = ""
message_lines = []
translation_lines = []
comment_lines = []
with open(fname, 'r', "utf-8") as handle:
while True:
line = handle.readline()
if not line:
break
line = stripeol(line)
if line.startswith("msgid") or line.startswith("#~ msgid"):
if reading_translation:
last_message['translation'] = translation
translation_lines = []
reading_message = True
reading_translation = False
if line.startswith('#~'):
message = line[10:-1]
commented = True
else:
message = line[7:-1]
commented = False
message_lines.append(message)
elif line.startswith("msgstr") or line.startswith("#~ msgstr"):
reading_message = False
reading_translation = True
last_message = {'comment_lines': comment_lines,
'message_lines': message_lines,
'translation_lines': translation_lines}
if commented:
translation = line[11:-1]
commented_messages[message] = last_message
else:
translation = line[8:-1]
messages[message] = last_message
message_lines = []
comment_lines = []
translation_lines.append(translation)
elif not line.startswith('"') and not line.startswith('#~ "'):
if reading_translation:
last_message['translation'] = translation
else:
comment_lines.append(line)
reading_message = False
reading_translation = False
message_lines = []
translation_lines = []
elif reading_message:
if line.startswith('#~ "'):
m = line[4:-1]
else:
m = line[1:-1]
message += m
message_lines.append(m)
elif reading_translation:
if line.startswith('#~ "'):
t = line[4:-1]
else:
t = line[1:-1]
translation += t
translation_lines.append(t)
return (messages, commented_messages)
def do_clean(po, pot_messages):
po_messages, commented_messages = read_messages(po)
for msgid in commented_messages:
if pot_messages.get(msgid):
t = po_messages.get(msgid)
if not t:
print("Reusing full item from commented "
"lines for msgid '%s'" % msgid)
po_messages[msgid] = commented_messages[msgid]
elif not t['translation']:
print("Reusing translation from commented "
"lines for msgid '%s'" % msgid)
m = commented_messages[msgid]
t['translation'] = m['translation']
t['translation_lines'] = m['translation_lines']
with open(po, 'w', 'utf-8') as handle:
for msgid in po_messages:
item = po_messages[msgid]
for x in item['comment_lines']:
handle.write(x + "\n")
first = True
for x in item['message_lines']:
if first:
handle.write("msgid \"%s\"\n" % x)
else:
handle.write("\"%s\"\n" % x)
first = False
first = True
for x in item['translation_lines']:
if first:
handle.write("msgstr \"%s\"\n" % x)
else:
handle.write("\"%s\"\n" % x)
first = False
handle.write("\n")
def main():
pot_messages, commented_messages = read_messages(FILE_NAME_POT)
if len(sys.argv) > 1:
for lang in sys.argv[1:]:
po = os.path.join(CURRENT_DIR, lang + '.po')
if os.path.exists(po):
do_clean(po, pot_messages)
else:
for po in os.listdir(CURRENT_DIR):
if po.endswith('.po'):
print('Processing %s...' % (po))
do_clean(po, pot_messages)
if __name__ == "__main__":
print("\n\n *** Running %r *** \n" % __file__)
main()

View File

@@ -1,166 +0,0 @@
#!/usr/bin/env python
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENSE BLOCK *****
# <pep8 compliant>
# update the pot file according the POTFILES.in
import sys
import collections
from codecs import open
def read_messages(fname):
def stripeol(s):
return s.rstrip("\n\r")
last_message = None
if hasattr(collections, 'OrderedDict'):
messages = collections.OrderedDict()
commented_messages = collections.OrderedDict()
else:
messages = {}
commented_messages = {}
reading_message = False
reading_translation = False
commented = False
message = ""
translation = ""
message_lines = []
translation_lines = []
comment_lines = []
with open(fname, 'r', "utf-8") as handle:
while True:
line = handle.readline()
if not line:
break
line = stripeol(line)
if line.startswith("msgid") or line.startswith("#~ msgid"):
if reading_translation:
last_message['translation'] = translation
translation_lines = []
reading_message = True
reading_translation = False
if line.startswith('#~'):
message = line[10:-1]
commented = True
else:
message = line[7:-1]
commented = False
message_lines.append(message)
elif line.startswith("msgstr") or line.startswith("#~ msgstr"):
reading_message = False
reading_translation = True
last_message = {'comment_lines': comment_lines,
'message_lines': message_lines,
'translation_lines': translation_lines}
if commented:
translation = line[11:-1]
commented_messages[message] = last_message
else:
translation = line[8:-1]
messages[message] = last_message
message_lines = []
comment_lines = []
translation_lines.append(translation)
elif not line.startswith('"') and not line.startswith('#~ "'):
if reading_translation:
last_message['translation'] = translation
else:
comment_lines.append(line)
reading_message = False
reading_translation = False
message_lines = []
translation_lines = []
elif reading_message:
if line.startswith('#~ "'):
m = line[4:-1]
else:
m = line[1:-1]
message += m
message_lines.append(m)
elif reading_translation:
if line.startswith('#~ "'):
t = line[4:-1]
else:
t = line[1:-1]
translation += t
translation_lines.append(t)
return (messages, commented_messages)
def main():
if len(sys.argv) == 3:
dst_messages, tmp = read_messages(sys.argv[1])
from_messages, tmp = read_messages(sys.argv[2])
for msgid in dst_messages:
msg = dst_messages.get(msgid)
from_msg = from_messages.get(msgid)
if from_msg and from_msg['translation']:
msg['translation'] = from_msg['translation']
msg['translation_lines'] = from_msg['translation_lines']
with open(sys.argv[1], 'w', 'utf-8') as handle:
for msgid in dst_messages:
item = dst_messages[msgid]
for x in item['comment_lines']:
handle.write(x + "\n")
first = True
for x in item['message_lines']:
if first:
handle.write("msgid \"%s\"\n" % x)
else:
handle.write("\"%s\"\n" % x)
first = False
first = True
for x in item['translation_lines']:
if first:
handle.write("msgstr \"%s\"\n" % x)
else:
handle.write("\"%s\"\n" % x)
first = False
handle.write("\n")
else:
print('Usage: %s <destination-po> <source-po>' % (sys.argv[0]))
if __name__ == "__main__":
print("\n\n *** Running %r *** \n" % __file__)
main()

View File

@@ -1,67 +0,0 @@
#!/usr/bin/env python
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENSE BLOCK *****
# <pep8 compliant>
# update all mo files in the LANGS
import subprocess
import os
import sys
GETTEXT_MSGFMT_EXECUTABLE = "msgfmt"
CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
SOURCE_DIR = os.path.normpath(os.path.abspath(os.path.join(CURRENT_DIR, "..")))
LOCALE_DIR = os.path.join(SOURCE_DIR, "release", "datafiles", "locale")
DOMAIN = "blender"
def process_po(po):
lang = os.path.basename(po)[:-3]
# show stats
cmd = (GETTEXT_MSGFMT_EXECUTABLE,
"--statistics",
os.path.join(CURRENT_DIR, "%s.po" % lang),
"-o",
os.path.join(LOCALE_DIR, lang, "LC_MESSAGES", "%s.mo" % DOMAIN),
)
print(" ".join(cmd))
process = subprocess.Popen(cmd)
process.wait()
def main():
if len(sys.argv) > 1:
for lang in sys.argv[1:]:
po = os.path.join(CURRENT_DIR, lang + '.po')
if os.path.exists(po):
process_po(po)
else:
for po in os.listdir(CURRENT_DIR):
if po.endswith(".po"):
process_po(po)
if __name__ == "__main__":
print("\n\n *** Running %r *** \n" % __file__)
main()

View File

@@ -1,380 +0,0 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENSE BLOCK *****
# <pep8-80 compliant>
# Write out messages.txt from blender
# Execite:
# blender --background --python po/update_msg.py
import os
CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
SOURCE_DIR = os.path.normpath(os.path.abspath(os.path.join(CURRENT_DIR, "..")))
FILE_NAME_MESSAGES = os.path.join(CURRENT_DIR, "messages.txt")
COMMENT_PREFIX = "#~ "
def dump_messages_rna(messages):
import bpy
def classBlackList():
blacklist_rna_class = [
# core classes
"Context", "Event", "Function", "UILayout",
"BlendData",
# registerable classes
"Panel", "Menu", "Header", "RenderEngine",
"Operator", "OperatorMacro", "Macro",
"KeyingSetInfo", "UnknownType",
# window classes
"WindowManager", "Window"
]
# ---------------------------------------------------------------------
# Collect internal operators
# extend with all internal operators
# note that this uses internal api introspection functions
# all possible operator names
op_names = list(sorted(set(
[cls.bl_rna.identifier for cls in
bpy.types.OperatorProperties.__subclasses__()] +
[cls.bl_rna.identifier for cls in
bpy.types.Operator.__subclasses__()] +
[cls.bl_rna.identifier for cls in
bpy.types.OperatorMacro.__subclasses__()]
)))
get_inatance = __import__("_bpy").ops.get_instance
path_resolve = type(bpy.context).__base__.path_resolve
for idname in op_names:
op = get_inatance(idname)
if 'INTERNAL' in path_resolve(op, "bl_options"):
blacklist_rna_class.append(idname)
# ---------------------------------------------------------------------
# Collect builtin classes we dont need to doc
blacklist_rna_class.append("Property")
blacklist_rna_class.extend(
[cls.__name__ for cls in
bpy.types.Property.__subclasses__()])
# ---------------------------------------------------------------------
# Collect classes which are attached to collections, these are api
# access only.
collection_props = set()
for cls_id in dir(bpy.types):
cls = getattr(bpy.types, cls_id)
for prop in cls.bl_rna.properties:
if prop.type == 'COLLECTION':
prop_cls = prop.srna
if prop_cls is not None:
collection_props.add(prop_cls.identifier)
blacklist_rna_class.extend(sorted(collection_props))
return blacklist_rna_class
blacklist_rna_class = classBlackList()
def filterRNA(bl_rna):
id = bl_rna.identifier
if id in blacklist_rna_class:
print(" skipping", id)
return True
return False
# -------------------------------------------------------------------------
# Function definitions
def walkProperties(bl_rna):
import bpy
# get our parents properties not to export them multiple times
bl_rna_base = bl_rna.base
if bl_rna_base:
bl_rna_base_props = bl_rna_base.properties.values()
else:
bl_rna_base_props = ()
for prop in bl_rna.properties:
# only write this property is our parent hasn't got it.
if prop in bl_rna_base_props:
continue
if prop.identifier == "rna_type":
continue
msgsrc = "bpy.types.%s.%s" % (bl_rna.identifier, prop.identifier)
if prop.name and prop.name != prop.identifier:
messages.setdefault(prop.name, []).append(msgsrc)
if prop.description:
messages.setdefault(prop.description, []).append(msgsrc)
if isinstance(prop, bpy.types.EnumProperty):
for item in prop.enum_items:
msgsrc = "bpy.types.%s.%s, '%s'" % (bl_rna.identifier,
prop.identifier,
item.identifier,
)
# Here identifier and name can be the same!
if item.name: # and item.name != item.identifier:
messages.setdefault(item.name,
[]).append(msgsrc)
if item.description:
messages.setdefault(item.description,
[]).append(msgsrc)
def walkRNA(bl_rna):
if filterRNA(bl_rna):
return
msgsrc = "bpy.types.%s" % bl_rna.identifier
if bl_rna.name and bl_rna.name != bl_rna.identifier:
messages.setdefault(bl_rna.name, []).append(msgsrc)
if bl_rna.description:
messages.setdefault(bl_rna.description, []).append(msgsrc)
if hasattr(bl_rna, 'bl_label') and bl_rna.bl_label:
messages.setdefault(bl_rna.bl_label, []).append(msgsrc)
walkProperties(bl_rna)
def walkClass(cls):
walkRNA(cls.bl_rna)
def walk_keymap_hierarchy(hier, msgsrc_prev):
for lvl in hier:
msgsrc = "%s.%s" % (msgsrc_prev, lvl[1])
messages.setdefault(lvl[0], []).append(msgsrc)
if lvl[3]:
walk_keymap_hierarchy(lvl[3], msgsrc)
# -------------------------------------------------------------------------
# Dump Messages
def full_class_id(cls):
""" gives us 'ID.Lamp.AreaLamp' which is best for sorting.
"""
cls_id = ""
bl_rna = cls.bl_rna
while bl_rna:
cls_id = "%s.%s" % (bl_rna.identifier, cls_id)
bl_rna = bl_rna.base
return cls_id
cls_list = type(bpy.context).__base__.__subclasses__()
cls_list.sort(key=full_class_id)
for cls in cls_list:
walkClass(cls)
cls_list = bpy.types.Space.__subclasses__()
cls_list.sort(key=full_class_id)
for cls in cls_list:
walkClass(cls)
cls_list = bpy.types.Operator.__subclasses__()
cls_list.sort(key=full_class_id)
for cls in cls_list:
walkClass(cls)
cls_list = bpy.types.OperatorProperties.__subclasses__()
cls_list.sort(key=full_class_id)
for cls in cls_list:
walkClass(cls)
cls_list = bpy.types.Menu.__subclasses__()
cls_list.sort(key=full_class_id)
for cls in cls_list:
walkClass(cls)
from bpy_extras.keyconfig_utils import KM_HIERARCHY
walk_keymap_hierarchy(KM_HIERARCHY, "KM_HIERARCHY")
def dump_messages_pytext(messages):
""" dumps text inlined in the python user interface: eg.
layout.prop("someprop", text="My Name")
"""
import ast
# -------------------------------------------------------------------------
# Gather function names
import bpy
# key: func_id
# val: [(arg_kw, arg_pos), (arg_kw, arg_pos), ...]
func_translate_args = {}
# so far only 'text' keywords, but we may want others translated later
translate_kw = ("text", )
for func_id, func in bpy.types.UILayout.bl_rna.functions.items():
# check it has a 'text' argument
for (arg_pos, (arg_kw, arg)) in enumerate(func.parameters.items()):
if ((arg_kw in translate_kw) and
(arg.is_output == False) and
(arg.type == 'STRING')):
func_translate_args.setdefault(func_id, []).append((arg_kw,
arg_pos))
# print(func_translate_args)
# -------------------------------------------------------------------------
# Function definitions
def extract_strings(fp_rel, node_container):
""" Recursively get strings, needed incase we have "Blah" + "Blah",
passed as an argument in that case it wont evaluate to a string.
"""
for node in ast.walk(node_container):
if type(node) == ast.Str:
eval_str = ast.literal_eval(node)
if eval_str:
# print("%s:%d: %s" % (fp, node.lineno, eval_str))
msgsrc = "%s:%s" % (fp_rel, node.lineno)
messages.setdefault(eval_str, []).append(msgsrc)
def extract_strings_from_file(fp):
filedata = open(fp, 'r', encoding="utf8")
root_node = ast.parse(filedata.read(), fp, 'exec')
filedata.close()
fp_rel = os.path.relpath(fp, SOURCE_DIR)
for node in ast.walk(root_node):
if type(node) == ast.Call:
# print("found function at")
# print("%s:%d" % (fp, node.lineno))
# lambda's
if type(node.func) == ast.Name:
continue
# getattr(self, con.type)(context, box, con)
if not hasattr(node.func, "attr"):
continue
translate_args = func_translate_args.get(node.func.attr, ())
# do nothing if not found
for arg_kw, arg_pos in translate_args:
if arg_pos < len(node.args):
extract_strings(fp_rel, node.args[arg_pos])
else:
for kw in node.keywords:
if kw.arg == arg_kw:
extract_strings(fp_rel, kw.value)
# -------------------------------------------------------------------------
# Dump Messages
mod_dir = os.path.join(SOURCE_DIR,
"release",
"scripts",
"startup",
"bl_ui")
files = [os.path.join(mod_dir, fn)
for fn in sorted(os.listdir(mod_dir))
if not fn.startswith("_")
if fn.endswith("py")
]
for fp in files:
extract_strings_from_file(fp)
def dump_messages():
def filter_message(msg):
# check for strings like ": %d"
msg_test = msg
for ignore in ("%d", "%s", "%r", # string formatting
"*", ".", "(", ")", "-", "/", "\\", "+", ":", "#", "%"
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"x", # used on its own eg: 100x200
"X", "Y", "Z", # used alone. no need to include
):
msg_test = msg_test.replace(ignore, "")
msg_test = msg_test.strip()
if not msg_test:
# print("Skipping: '%s'" % msg)
return True
# we could filter out different strings here
return False
if 1:
import collections
messages = collections.OrderedDict()
else:
messages = {}
messages[""] = []
# get strings from RNA
dump_messages_rna(messages)
# get strings from UI layout definitions text="..." args
dump_messages_pytext(messages)
del messages[""]
message_file = open(FILE_NAME_MESSAGES, 'w', encoding="utf8")
# message_file.writelines("\n".join(sorted(messages)))
for key, value in messages.items():
# filter out junk values
if filter_message(key):
continue
for msgsrc in value:
message_file.write("%s%s\n" % (COMMENT_PREFIX, msgsrc))
message_file.write("%s\n" % key)
message_file.close()
print("Written %d messages to: %r" % (len(messages), FILE_NAME_MESSAGES))
def main():
try:
import bpy
except ImportError:
print("This script must run from inside blender")
return
dump_messages()
if __name__ == "__main__":
print("\n\n *** Running %r *** \n" % __file__)
main()

View File

@@ -1,66 +0,0 @@
#!/usr/bin/env python
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENSE BLOCK *****
# <pep8 compliant>
# update all po files in the LANGS
import subprocess
import os
import sys
GETTEXT_MSGMERGE_EXECUTABLE = "msgmerge"
CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
DOMAIN = "blender"
def process_po(po):
lang = os.path.basename(po)[:-3]
# update po file
cmd = (GETTEXT_MSGMERGE_EXECUTABLE,
"--update",
"--backup=none",
"--lang=%s" % lang,
os.path.join(CURRENT_DIR, "%s.po" % lang),
os.path.join(CURRENT_DIR, "%s.pot" % DOMAIN),
)
print(" ".join(cmd))
process = subprocess.Popen(cmd)
process.wait()
def main():
if len(sys.argv) > 1:
for lang in sys.argv[1:]:
po = os.path.join(CURRENT_DIR, lang + '.po')
if os.path.exists(po):
process_po(po)
else:
for po in os.listdir(CURRENT_DIR):
if po.endswith(".po"):
process_po(po)
if __name__ == "__main__":
print("\n\n *** Running %r *** \n" % __file__)
main()

View File

@@ -1,106 +0,0 @@
#!/usr/bin/env python
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENSE BLOCK *****
# <pep8 compliant>
# update the pot file according the POTFILES.in
import subprocess
import os
from codecs import open
GETTEXT_XGETTEXT_EXECUTABLE = "xgettext"
CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
SOURCE_DIR = os.path.normpath(os.path.abspath(os.path.join(CURRENT_DIR, "..")))
DOMAIN = "blender"
COMMENT_PREFIX = "#~ " # from update_msg.py
FILE_NAME_POT = os.path.join(CURRENT_DIR, "blender.pot")
FILE_NAME_MESSAGES = os.path.join(CURRENT_DIR, "messages.txt")
def main():
cmd = (GETTEXT_XGETTEXT_EXECUTABLE,
"--files-from=%s" % os.path.join(SOURCE_DIR, "po", "POTFILES.in"),
"--keyword=_",
"--keyword=N_",
"--directory=%s" % SOURCE_DIR,
"--output=%s" % os.path.join(SOURCE_DIR, "po", "%s.pot" % DOMAIN),
"--from-code=utf-8",
)
print(" ".join(cmd))
process = subprocess.Popen(cmd)
process.wait()
def stripeol(s):
return s.rstrip("\n\r")
pot_messages = {}
reading_message = False
message = ""
with open(FILE_NAME_POT, 'r', "utf-8") as handle:
while True:
line = handle.readline()
if not line:
break
line = stripeol(line)
if line.startswith("msgid"):
reading_message = True
message = line[7:-1]
elif line.startswith("msgstr"):
reading_message = False
pot_messages[message] = True
elif reading_message:
message += line[1:-1]
# add messages collected automatically from RNA
with open(FILE_NAME_POT, "a", "utf-8") as pot_handle:
with open(FILE_NAME_MESSAGES, 'r', "utf-8") as handle:
msgsrc_ls = []
while True:
line = handle.readline()
if not line:
break
line = stripeol(line)
# COMMENT_PREFIX
if line.startswith(COMMENT_PREFIX):
msgsrc_ls.append(line[len(COMMENT_PREFIX):].strip())
else:
line = line.replace("\\", "\\\\")
line = line.replace("\"", "\\\"")
line = line.replace("\t", "\\t")
if not pot_messages.get(line):
for msgsrc in msgsrc_ls:
pot_handle.write("#: %s\n" % msgsrc)
pot_handle.write("msgid \"%s\"\n" % line)
pot_handle.write("msgstr \"\"\n\n")
msgsrc_ls[:] = []
if __name__ == "__main__":
print("\n\n *** Running %r *** \n" % __file__)
main()