remove dirs to make them external's
This commit is contained in:
201
po/POTFILES.in
201
po/POTFILES.in
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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()
|
||||
189
po/clean_po.py
189
po/clean_po.py
@@ -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()
|
||||
166
po/merge_po.py
166
po/merge_po.py
@@ -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()
|
||||
@@ -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()
|
||||
380
po/update_msg.py
380
po/update_msg.py
@@ -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()
|
||||
@@ -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()
|
||||
106
po/update_pot.py
106
po/update_pot.py
@@ -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()
|
||||
Reference in New Issue
Block a user