Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSayamindu Dasgupta <sayamindu@gmail.com>2010-02-10 15:26:32 (GMT)
committer Sayamindu Dasgupta <sayamindu@gmail.com>2010-02-10 15:26:32 (GMT)
commite6aa91ba3fd63bb886d41d51f5b52c36d017bdb4 (patch)
tree1e1af37988e721dc0c188fbefb390895532bc956
parentd250407ba6dee268a36539d749609ac30333d39f (diff)
parentd00d9b64316eb0ed647621286a708ffc68bc8656 (diff)
Merge branch 'master' of git://git.sugarlabs.org/sugar-toolkit/gettext-enhancements
-rw-r--r--src/sugar/activity/Makefile.am1
-rw-r--r--src/sugar/activity/i18n.py144
-rw-r--r--src/sugar/activity/main.py5
3 files changed, 147 insertions, 3 deletions
diff --git a/src/sugar/activity/Makefile.am b/src/sugar/activity/Makefile.am
index e2e6fdc..2c2eff1 100644
--- a/src/sugar/activity/Makefile.am
+++ b/src/sugar/activity/Makefile.am
@@ -6,6 +6,7 @@ sugar_PYTHON = \
activityhandle.py \
activityservice.py \
bundlebuilder.py \
+ i18n.py \
main.py \
namingalert.py \
widgets.py
diff --git a/src/sugar/activity/i18n.py b/src/sugar/activity/i18n.py
new file mode 100644
index 0000000..1c3c893
--- /dev/null
+++ b/src/sugar/activity/i18n.py
@@ -0,0 +1,144 @@
+# Copyright (C) 2010 One Laptop Per Child
+#
+# Author: Sayamindu Dasgupta <sayamindu@laptop.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+import gconf
+
+import locale
+import os
+import struct
+import sys
+
+import dateutil.parser
+import time
+
+_MO_BIG_ENDIAN = 0xde120495
+_MO_LITTLE_ENDIAN = 0x950412de
+
+
+def _read_bin(handle, format_string, byte_count):
+ read_bytes = handle.read(byte_count)
+ return_value = struct.unpack(format_string, read_bytes)
+ if len(return_value) == 1:
+ return return_value[0]
+ else:
+ return return_value
+
+
+def _extract_header(file_path):
+ header = ''
+ handle = open(file_path, 'rb')
+ magic_number = _read_bin(handle, '<I', 4)
+
+ if magic_number == _MO_BIG_ENDIAN:
+ format_string = '>II'
+ elif magic_number == _MO_LITTLE_ENDIAN:
+ format_string = '<II'
+ else:
+ raise IOError('File does not seem to be a valid MO file')
+
+ version_, num_of_strings = _read_bin(handle, format_string, 8)
+
+ msgids_hash_offset, msgstrs_hash_offset = _read_bin(handle, \
+ format_string, 8)
+ handle.seek(msgids_hash_offset)
+
+ msgids_index = []
+ for i in range(num_of_strings):
+ msgids_index.append(_read_bin(handle, format_string, 8))
+ handle.seek(msgstrs_hash_offset)
+
+ msgstrs_index = []
+ for i in range(num_of_strings):
+ msgstrs_index.append(_read_bin(handle, format_string, 8))
+
+ for i in range(num_of_strings):
+ handle.seek(msgids_index[i][1])
+ msgid = handle.read(msgids_index[i][0])
+ if msgid == '':
+ handle.seek(msgstrs_index[i][1])
+ msgstr = handle.read(msgstrs_index[i][0])
+ header = msgstr
+ break
+ else:
+ continue
+
+ handle.close()
+ return header
+
+
+def _extract_modification_time(file_path):
+ header = _extract_header(file_path)
+ items = header.split('\n')
+ for item in items:
+ if item.startswith('PO-Revision-Date:'):
+ time_str = item.split(': ')[1]
+ parsed_time = dateutil.parser.parse(time_str)
+ return time.mktime(parsed_time.timetuple())
+
+ raise ValueError('Could not find a revision date')
+
+
+def get_locale_path(bundle_id):
+ """ Returns the locale path, which is the directory where the preferred
+ MO file is located.
+
+ The preferred MO file is the one with the latest translation.
+
+ @type bundle_id: string
+ @param bundle_id: The bundle id of the activity in question
+ @rtype: string
+ @return: the preferred locale path
+ """
+
+ # Note: We pre-assign weights to the directories so that if no translations
+ # exist, the appropriate fallbacks (eg: bn for bn_BD) can be loaded
+ # The directory with the highest weight is returned, and if a MO file is
+ # found, the weight of the directory is set to the MO's modification time
+ # (as described in the MO header, and _not_ the filesystem mtime)
+
+ candidate_dirs = {}
+
+ if 'SUGAR_LOCALEDIR' in os.environ:
+ candidate_dirs[os.environ['SUGAR_LOCALEDIR']] = 2
+
+ gconf_client = gconf.client_get_default()
+ package_dir = gconf_client.get_string("/desktop/sugar/i18n/langpackdir")
+ if package_dir is not None and package_dir is not '':
+ candidate_dirs[package_dir] = 1
+
+ candidate_dirs[os.path.join(sys.prefix, 'share', 'locale')] = 0
+
+ for candidate_dir in candidate_dirs.keys():
+ if os.path.exists(candidate_dir):
+ full_path = os.path.join(candidate_dir, \
+ locale.getdefaultlocale()[0], 'LC_MESSAGES', \
+ bundle_id + '.mo')
+ if os.path.exists(full_path):
+ try:
+ candidate_dirs[candidate_dir] = \
+ _extract_modification_time(full_path)
+ except (IOError, ValueError):
+ # The mo file is damaged or has not been initialized
+ # Set lowest priority
+ candidate_dirs[candidate_dir] = -1
+
+ available_paths = sorted(candidate_dirs.iteritems(), key=lambda (k, v): \
+ (v, k), reverse=True)
+ preferred_path = available_paths[0][0]
+ return preferred_path
diff --git a/src/sugar/activity/main.py b/src/sugar/activity/main.py
index ef4d001..0647e81 100644
--- a/src/sugar/activity/main.py
+++ b/src/sugar/activity/main.py
@@ -27,6 +27,7 @@ import dbus.glib
import sugar
from sugar.activity import activityhandle
+from sugar.activity import i18n
from sugar.bundle.activitybundle import ActivityBundle
from sugar.graphics import style
from sugar import logger
@@ -103,9 +104,7 @@ def main():
settings.set_property('gtk-font-name',
'%s %f' % (style.FONT_FACE, style.FONT_SIZE))
- locale_path = None
- if 'SUGAR_LOCALEDIR' in os.environ:
- locale_path = os.environ['SUGAR_LOCALEDIR']
+ locale_path = i18n.get_locale_path(bundle.get_bundle_id())
gettext.bindtextdomain(bundle.get_bundle_id(), locale_path)
gettext.bindtextdomain('sugar-toolkit', sugar.locale_path)