[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [61205] trunk/blender: Be ready for changes in bf-translations repository
Sergey Sharybin
sergey.vfx at gmail.com
Fri Nov 8 21:44:49 CET 2013
Revision: 61205
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=61205
Author: nazgul
Date: 2013-11-08 20:44:48 +0000 (Fri, 08 Nov 2013)
Log Message:
-----------
Be ready for changes in bf-translations repository
Made it so if there's release/datafiles/locale/po
folder, then all the .po files will be converted
to .mo at blender compile time and installed to
an appropriate location.
Uses small own implementation msgfmt which is
based on msgfmt.py from Python project, but also
supports contexts.
There's no functional changes for until we've
switched to use source .po files instead of
pre-compiled .mo.
P.S. Well, there's one change which is msgfmt.cc
being compiled even if it's not used, but
would rather not clutter code with checks
since pretty soon we'll use this program
anyway.
Modified Paths:
--------------
trunk/blender/SConstruct
trunk/blender/build_files/cmake/macros.cmake
trunk/blender/intern/locale/CMakeLists.txt
trunk/blender/intern/locale/SConscript
trunk/blender/source/creator/CMakeLists.txt
Added Paths:
-----------
trunk/blender/intern/locale/msgfmt.cc
Modified: trunk/blender/SConstruct
===================================================================
--- trunk/blender/SConstruct 2013-11-08 18:01:07 UTC (rev 61204)
+++ trunk/blender/SConstruct 2013-11-08 20:44:48 UTC (rev 61205)
@@ -944,6 +944,9 @@
def check_path(path, member):
return (member in path.split(os.sep))
+ po_dir = os.path.join("release", "datafiles", "locale", "po")
+ need_compile_mo = os.path.exists(po_dir)
+
for intpath in internationalpaths:
for dp, dn, df in os.walk(intpath):
if '.svn' in dn:
@@ -952,7 +955,10 @@
dn.remove('_svn')
# we only care about release/datafiles/fonts, release/datafiles/locales
- if check_path(dp, "fonts") or check_path(dp, "locale"):
+ if check_path(dp, "locale"):
+ if need_compile_mo and check_path(dp, "po"):
+ continue
+ elif check_path(dp, "fonts"):
pass
else:
continue
@@ -966,6 +972,19 @@
env.Execute(Mkdir(dir))
scriptinstall.append(env.Install(dir=dir,source=source))
+ if need_compile_mo:
+ for f in os.listdir(po_dir):
+ if not f.endswith(".po"):
+ continue
+
+ locale_name = os.path.splitext(f)[0]
+
+ mo_file = os.path.join(B.root_build_dir, "locale", locale_name + ".mo")
+
+ dir = os.path.join(env['BF_INSTALLDIR'], VERSION)
+ dir = os.path.join(dir, "datafiles", "locale", locale_name, "LC_MESSAGES")
+ scriptinstall.append(env.InstallAs(os.path.join(dir, "blender.mo"), mo_file))
+
#-- icons
if env['OURPLATFORM']=='linux':
iconlist = []
Modified: trunk/blender/build_files/cmake/macros.cmake
===================================================================
--- trunk/blender/build_files/cmake/macros.cmake 2013-11-08 18:01:07 UTC (rev 61204)
+++ trunk/blender/build_files/cmake/macros.cmake 2013-11-08 20:44:48 UTC (rev 61205)
@@ -870,3 +870,33 @@
unset(_file_to)
endmacro()
+
+macro(msgfmt_simple
+ file_from
+ list_to_add)
+
+ # remove ../'s
+ get_filename_component(_file_from_we ${file_from} NAME_WE)
+
+ get_filename_component(_file_from ${file_from} REALPATH)
+ get_filename_component(_file_to ${CMAKE_CURRENT_BINARY_DIR}/${_file_from_we}.mo REALPATH)
+
+ list(APPEND ${list_to_add} ${_file_to})
+
+ get_filename_component(_file_to_path ${_file_to} PATH)
+
+ add_custom_command(
+ OUTPUT ${_file_to}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${_file_to_path}
+ COMMAND ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/msgfmt ${_file_from} ${_file_to}
+ DEPENDS msgfmt)
+
+ message("${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/msgfmt ${_file_from} ${_file_to}")
+
+ set_source_files_properties(${_file_to} PROPERTIES GENERATED TRUE)
+
+ unset(_file_from_we)
+ unset(_file_from)
+ unset(_file_to)
+ unset(_file_to_path)
+endmacro()
Modified: trunk/blender/intern/locale/CMakeLists.txt
===================================================================
--- trunk/blender/intern/locale/CMakeLists.txt 2013-11-08 18:01:07 UTC (rev 61204)
+++ trunk/blender/intern/locale/CMakeLists.txt 2013-11-08 20:44:48 UTC (rev 61205)
@@ -45,3 +45,11 @@
endif()
blender_add_lib(bf_intern_locale "${SRC}" "${INC}" "${INC_SYS}")
+
+# -----------------------------------------------------------------------------
+# Build msgfmt executable
+set(MSFFMT_SRC
+ msgfmt.cc
+)
+
+add_executable(msgfmt ${MSFFMT_SRC})
Modified: trunk/blender/intern/locale/SConscript
===================================================================
--- trunk/blender/intern/locale/SConscript 2013-11-08 18:01:07 UTC (rev 61204)
+++ trunk/blender/intern/locale/SConscript 2013-11-08 20:44:48 UTC (rev 61205)
@@ -37,3 +37,49 @@
incs += ' ' + env['BF_BOOST_INC']
env.BlenderLib( 'bf_intern_locale', sources, Split(incs), defs, libtype=['intern','player'], priority=[10, 185])
+
+if env['WITH_BF_INTERNATIONAL']:
+ import os
+ from os.path import dirname
+
+ def normpath(path):
+ return os.path.abspath(os.path.normpath(path))
+
+ # build directory
+ source_dir = Dir('.').srcnode().path
+ root_build_dir = normpath(env['BF_BUILDDIR'])
+ root_source_dir = dirname(dirname(normpath(source_dir)))
+ po_dir = os.path.join(root_source_dir, "release", "datafiles", "locale", "po")
+ build_dir = os.path.join(root_build_dir, 'locale')
+
+ if os.path.exists(po_dir):
+ # create directory if needed
+ if not os.path.exists(build_dir):
+ os.makedirs(build_dir)
+
+ msgfmt_tool = env.Clone()
+ targetpath = root_build_dir + '/msgfmt'
+ msgfmt_target = msgfmt_tool.Program(target = targetpath, source = ['msgfmt.cc'])
+
+ locale = env.Clone()
+
+ # dependencies
+ dependencies = [targetpath]
+
+ # add command for each locale
+ all_mo_files = []
+ for f in os.listdir(po_dir):
+ if not f.endswith(".po"):
+ continue
+
+ po_file = os.path.join(po_dir, f)
+ mo_file = os.path.join(build_dir, os.path.splitext(f)[0] + ".mo")
+
+ command = "\"%s\" \"%s\" \"%s\"" % (targetpath, po_file, mo_file)
+
+ locale.Command(mo_file, po_file, command)
+ locale.Depends(mo_file, dependencies)
+
+ all_mo_files.append(mo_file)
+
+ env.Depends("boost_locale_wrapper.cpp", all_mo_files)
Added: trunk/blender/intern/locale/msgfmt.cc
===================================================================
--- trunk/blender/intern/locale/msgfmt.cc (rev 0)
+++ trunk/blender/intern/locale/msgfmt.cc 2013-11-08 20:44:48 UTC (rev 61205)
@@ -0,0 +1,366 @@
+// Written by Sergey Sharybin <sergey.vfx at gmail.com>
+// Added support for contexts
+//
+// Based on Python script msgfmt.py from Python source
+// code tree, which wes weitten by Written by
+// Martin v. Löwis <loewis at informatik.hu-berlin.de>
+//
+// Generate binary message catalog from textual translation description.
+//
+// This program converts a textual Uniforum-style message catalog (.po file) into
+// a binary GNU catalog (.mo file). This is essentially the same function as the
+// GNU msgfmt program, however, it is a simpler implementation.
+//
+// Usage: msgfmt input.po output.po
+
+#include <algorithm>
+#include <fstream>
+#include <iostream>
+#include <map>
+#include <stdlib.h>
+#include <string>
+#include <vector>
+
+namespace {
+
+std::map<std::string, std::string> MESSAGES;
+
+bool starts_with(const std::string &string,
+ const std::string &prefix) {
+ return prefix.size() <= string.size() &&
+ string.compare(0, prefix.size(), prefix) == 0;
+}
+
+std::string ltrim(const std::string &s) {
+ std::string result = s;
+ result.erase(result.begin(),
+ std::find_if(result.begin(),
+ result.end(),
+ std::not1(std::ptr_fun<int, int>(std::isspace))));
+ return result;
+}
+
+std::string rtrim(const std::string &s) {
+ std::string result = s;
+ result.erase(
+ std::find_if(result.rbegin(),
+ result.rend(),
+ std::not1(std::ptr_fun<int, int>(std::isspace))).base(),
+ result.end());
+ return result;
+}
+
+std::string trim(const std::string &s) {
+ return ltrim(rtrim(s));
+}
+
+std::string unescape(const std::string &s) {
+ std::string result;
+ std::string::const_iterator it = s.begin();
+ while (it != s.end()) {
+ char current_char = *it++;
+ if (current_char == '\\' && it != s.end()) {
+ char next_char = *it++;
+ if (next_char == '\\') {
+ current_char = '\\';
+ } else if (next_char == 'n') {
+ current_char = '\n';
+ } else if (next_char == 't') {
+ current_char = '\t';
+ } else {
+ current_char = next_char;
+ }
+ }
+ result += current_char;
+ }
+
+ if (result[0] == '"' && result[result.size() - 1] == '"') {
+ result = result.substr(1, result.size() - 2);
+ }
+
+ return result;
+}
+
+// Add a non-fuzzy translation to the dictionary.
+void add(const std::string &msgctxt,
+ const std::string &msgid,
+ const std::string &msgstr,
+ bool fuzzy) {
+ if (fuzzy == false && msgstr.empty() == false) {
+ if (msgctxt.empty()) {
+ MESSAGES[msgid] = msgstr;
+ } else {
+ MESSAGES[msgctxt + (char)0x04 + msgid] = msgstr;
+ }
+ }
+}
+
+template<typename TKey, typename TValue>
+void get_keys(std::map<TKey, TValue> map,
+ std::vector<TKey> *keys) {
+ for (typename std::map<TKey, TValue>::iterator it = map.begin();
+ it != map.end();
+ it++) {
+ keys->push_back(it->first);
+ }
+}
+
+std::string intToBytes(int value) {
+ std::string result;
+ for (unsigned int i = 0; i < sizeof(value); i++) {
+ result += (unsigned char) ((value >> (i * 8)) & 0xff);
+ }
+ return result;
+}
+
+typedef enum {
+ SECTION_NONE = 0,
+ SECTION_CTX = 1,
+ SECTION_ID = 2,
+ SECTION_STR = 3
+} eSectionType;
+
+struct Offset {
+ unsigned int o1, l1, o2, l2;
+};
+
+// Return the generated output.
+std::string generate(void) {
+ // The keys are sorted in the .mo file
+ std::vector<std::string> keys;
+
+ // Get list of sorted keys.
+ get_keys(MESSAGES, &keys);
+ std::sort(keys.begin(), keys.end());
+
+ std::vector<Offset> offsets;
+ std::string ids = "", strs = "";
+ for (std::vector<std::string>::iterator it = keys.begin();
+ it != keys.end();
+ it++) {
+ std::string &id = *it;
+ // For each string, we need size and file offset. Each string is NUL
+ // terminated; the NUL does not count into the size.
+ Offset offset = {(unsigned int) ids.size(),
+ (unsigned int) id.size(),
+ (unsigned int) strs.size(),
+ (unsigned int) MESSAGES[id].size()};
+ offsets.push_back(offset);
+ ids += id + '\0';
+ strs += MESSAGES[id] + '\0';
+ }
+
+ // The header is 7 32-bit unsigned integers. We don't use hash tables, so
+ // the keys start right after the index tables.
+ // translated string.
+ int keystart = 7 * 4 + 16 * keys.size();
+ // and the values start after the keys
+ int valuestart = keystart + ids.size();
+ std::vector<int> koffsets;
+ std::vector<int> voffsets;
+ // The string table first has the list of keys, then the list of values.
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list