[Checkins] SVN: zope.i18n/trunk/ Feature: Added optional automatic compilation of mo files from po files. You need to depend on the `zope.i18n [compile]` extra and set an environment variable called `zope.i18n.compile_mo_files` to any True value to enable this option. Bumped the package version to 3.5dev, as we added features and this is not a maintenance release anymore.

Hanno Schlichting plone at hannosch.info
Sat Apr 26 06:53:04 EDT 2008


Log message for revision 85758:
  Feature: Added optional automatic compilation of mo files from po files. You need to depend on the `zope.i18n [compile]` extra and set an environment variable called `zope.i18n.compile_mo_files` to any True value to enable this option. Bumped the package version to 3.5dev, as we added features and this is not a maintenance release anymore.
  

Changed:
  U   zope.i18n/trunk/CHANGES.txt
  U   zope.i18n/trunk/buildout.cfg
  U   zope.i18n/trunk/setup.py
  A   zope.i18n/trunk/src/zope/i18n/compile.py
  U   zope.i18n/trunk/src/zope/i18n/tests/locale2/en/LC_MESSAGES/zope-i18n.mo
  A   zope.i18n/trunk/src/zope/i18n/tests/locale3/
  D   zope.i18n/trunk/src/zope/i18n/tests/locale3/__init__.py
  D   zope.i18n/trunk/src/zope/i18n/tests/locale3/en/
  A   zope.i18n/trunk/src/zope/i18n/tests/locale3/en/
  _U  zope.i18n/trunk/src/zope/i18n/tests/locale3/en/LC_MESSAGES/
  A   zope.i18n/trunk/src/zope/i18n/tests/locale3/en/LC_MESSAGES/zope-i18n.in
  U   zope.i18n/trunk/src/zope/i18n/tests/locale3/en/LC_MESSAGES/zope-i18n.mo
  U   zope.i18n/trunk/src/zope/i18n/tests/locale3/en/LC_MESSAGES/zope-i18n.po
  A   zope.i18n/trunk/src/zope/i18n/tests/locale3/en/LC_MESSAGES/zope-i18n2.po
  U   zope.i18n/trunk/src/zope/i18n/tests/test_zcml.py
  U   zope.i18n/trunk/src/zope/i18n/zcml.py

-=-
Modified: zope.i18n/trunk/CHANGES.txt
===================================================================
--- zope.i18n/trunk/CHANGES.txt	2008-04-26 10:36:13 UTC (rev 85757)
+++ zope.i18n/trunk/CHANGES.txt	2008-04-26 10:52:59 UTC (rev 85758)
@@ -2,9 +2,14 @@
 CHANGES
 =======
 
-3.4.1 (unreleased)
+3.5 (unreleased)
 ------------------
 
+- Feature: Added optional automatic compilation of mo files from po files.
+  You need to depend on the `zope.i18n [compile]` extra and set an environment
+  variable called `zope.i18n.compile_mo_files` to any True value to enable
+  this option.
+
 - Feature: Re-use existing translation domains when registering new ones.
   This allows multiple packages to register translations in the same domain.
   If the same message exists in multiple catalogs the one registered first

Modified: zope.i18n/trunk/buildout.cfg
===================================================================
--- zope.i18n/trunk/buildout.cfg	2008-04-26 10:36:13 UTC (rev 85757)
+++ zope.i18n/trunk/buildout.cfg	2008-04-26 10:52:59 UTC (rev 85758)
@@ -1,8 +1,15 @@
 [buildout]
 develop = . 
-parts = test
+parts = test test-compile
 find-links = http://download.zope.org/distribution/
 
 [test]
 recipe = zc.recipe.testrunner
-eggs = zope.i18n
+eggs =
+    zope.i18n
+
+[test-compile]
+recipe = zc.recipe.testrunner
+eggs =
+    zope.i18n
+    python-gettext

Modified: zope.i18n/trunk/setup.py
===================================================================
--- zope.i18n/trunk/setup.py	2008-04-26 10:36:13 UTC (rev 85757)
+++ zope.i18n/trunk/setup.py	2008-04-26 10:52:59 UTC (rev 85758)
@@ -24,7 +24,7 @@
 
 setup(
     name='zope.i18n',
-    version = '3.4.1dev',
+    version = '3.5dev',
     author='Zope Corporation and Contributors',
     author_email='zope3-dev at zope.org',
     description='Zope3 Internationalization Support',
@@ -58,4 +58,7 @@
                       ],
     include_package_data = True,
     zip_safe = False,
+    extras_require = dict(
+        compile = ['pythongettext'],
+        ),
     )

Added: zope.i18n/trunk/src/zope/i18n/compile.py
===================================================================
--- zope.i18n/trunk/src/zope/i18n/compile.py	                        (rev 0)
+++ zope.i18n/trunk/src/zope/i18n/compile.py	2008-04-26 10:52:59 UTC (rev 85758)
@@ -0,0 +1,46 @@
+import logging
+import os
+from os.path import join
+from stat import ST_MTIME
+
+HAS_PYTHON_GETTEXT = True
+try:
+    from pythongettext.msgfmt import Msgfmt
+    from pythongettext.msgfmt import PoSyntaxError
+except ImportError:
+    HAS_PYTHON_GETTEXT = False
+
+logger = logging.getLogger('zope.i18n')
+
+
+def compile_mo_file(domain, lc_messages_path):
+    """Creates or updates a mo file in the locales folder."""
+    if not HAS_PYTHON_GETTEXT:
+        return
+
+    base = join(lc_messages_path, domain)
+    pofile = str(base + '.po')
+    mofile = str(base + '.mo')
+
+    po_mtime = 0
+    try:
+        po_mtime = os.stat(pofile)[ST_MTIME]
+    except (IOError, OSError):
+        return
+
+    mo_mtime = 0
+    if os.path.exists(mofile):
+        # Update mo file?
+        try:
+            mo_mtime = os.stat(mofile)[ST_MTIME]
+        except (IOError, OSError):
+            return
+
+    if po_mtime > mo_mtime:
+        try:
+            mo = Msgfmt(pofile, domain).getAsFile()
+            fd = open(mofile, 'wb')
+            fd.write(mo.read())
+            fd.close()
+        except (IOError, OSError, PoSyntaxError):
+            logger.warn('Error while compiling %s' % pofile)


Property changes on: zope.i18n/trunk/src/zope/i18n/compile.py
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: zope.i18n/trunk/src/zope/i18n/tests/locale2/en/LC_MESSAGES/zope-i18n.mo
===================================================================
(Binary files differ)

Copied: zope.i18n/trunk/src/zope/i18n/tests/locale3 (from rev 85741, zope.i18n/trunk/src/zope/i18n/tests/locale)

Deleted: zope.i18n/trunk/src/zope/i18n/tests/locale3/__init__.py
===================================================================
--- zope.i18n/trunk/src/zope/i18n/tests/locale/__init__.py	2008-04-26 07:46:02 UTC (rev 85741)
+++ zope.i18n/trunk/src/zope/i18n/tests/locale3/__init__.py	2008-04-26 10:52:59 UTC (rev 85758)
@@ -1,2 +0,0 @@
-#
-# This file is necessary to make this directory a package.

Copied: zope.i18n/trunk/src/zope/i18n/tests/locale3/en (from rev 85757, zope.i18n/trunk/src/zope/i18n/tests/locale/en)


Property changes on: zope.i18n/trunk/src/zope/i18n/tests/locale3/en/LC_MESSAGES
___________________________________________________________________
Name: svn:ignore
   + zope-i18n2.mo


Added: zope.i18n/trunk/src/zope/i18n/tests/locale3/en/LC_MESSAGES/zope-i18n.in
===================================================================
(Binary files differ)


Property changes on: zope.i18n/trunk/src/zope/i18n/tests/locale3/en/LC_MESSAGES/zope-i18n.in
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: zope.i18n/trunk/src/zope/i18n/tests/locale3/en/LC_MESSAGES/zope-i18n.mo
===================================================================
(Binary files differ)

Modified: zope.i18n/trunk/src/zope/i18n/tests/locale3/en/LC_MESSAGES/zope-i18n.po
===================================================================
--- zope.i18n/trunk/src/zope/i18n/tests/locale/en/LC_MESSAGES/zope-i18n.po	2008-04-26 10:36:13 UTC (rev 85757)
+++ zope.i18n/trunk/src/zope/i18n/tests/locale3/en/LC_MESSAGES/zope-i18n.po	2008-04-26 10:52:59 UTC (rev 85758)
@@ -1,14 +1,11 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: Zope 3\n"
-"PO-Revision-Date: 2002/06/13\n"
+"PO-Revision-Date: 2008/04/26\n"
 "Last-Translator: Zope 3 contributors\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=ISO-8859-1\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-msgid "New Domain"
-msgstr "New Domain translated"
-
-msgid "New Language"
-msgstr "New Language translated"
+msgid "I'm a newer file"
+msgstr "I'm a newer file translated"

Added: zope.i18n/trunk/src/zope/i18n/tests/locale3/en/LC_MESSAGES/zope-i18n2.po
===================================================================
--- zope.i18n/trunk/src/zope/i18n/tests/locale3/en/LC_MESSAGES/zope-i18n2.po	                        (rev 0)
+++ zope.i18n/trunk/src/zope/i18n/tests/locale3/en/LC_MESSAGES/zope-i18n2.po	2008-04-26 10:52:59 UTC (rev 85758)
@@ -0,0 +1,11 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Zope 3\n"
+"PO-Revision-Date: 2008/04/26\n"
+"Last-Translator: Zope 3 contributors\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "I'm a new file"
+msgstr "I'm a new file translated"


Property changes on: zope.i18n/trunk/src/zope/i18n/tests/locale3/en/LC_MESSAGES/zope-i18n2.po
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: zope.i18n/trunk/src/zope/i18n/tests/test_zcml.py
===================================================================
--- zope.i18n/trunk/src/zope/i18n/tests/test_zcml.py	2008-04-26 10:36:13 UTC (rev 85757)
+++ zope.i18n/trunk/src/zope/i18n/tests/test_zcml.py	2008-04-26 10:52:59 UTC (rev 85758)
@@ -16,13 +16,18 @@
 $Id$
 """
 import os
+import shutil
 import unittest
 
-import zope.component
-import zope.i18n.tests
+from zope.component import getUtility
+from zope.component import queryUtility
 from zope.component.testing import PlacelessSetup
 from zope.configuration import xmlconfig
+
+import zope.i18n.tests
 from zope.i18n.interfaces import ITranslationDomain
+from zope.i18n.compile import HAS_PYTHON_GETTEXT
+from zope.i18n import zcml
 
 template = """\
 <configure
@@ -38,7 +43,7 @@
         self.context = xmlconfig.file('meta.zcml', zope.i18n)
 
     def testRegisterTranslations(self):
-        self.assert_(zope.component.queryUtility(ITranslationDomain) is None)
+        self.assert_(queryUtility(ITranslationDomain) is None)
         xmlconfig.string(
             template % '''
             <configure package="zope.i18n.tests">
@@ -47,12 +52,12 @@
             ''', self.context)
         path = os.path.join(os.path.dirname(zope.i18n.tests.__file__),
                             'locale', 'en', 'LC_MESSAGES', 'zope-i18n.mo')
-        util = zope.component.getUtility(ITranslationDomain, 'zope-i18n')
+        util = getUtility(ITranslationDomain, 'zope-i18n')
         self.assertEquals(util._catalogs,
                           {'test': ['test'], 'en': [unicode(path)]})
 
     def testRegisterDistributedTranslations(self):
-        self.assert_(zope.component.queryUtility(ITranslationDomain) is None)
+        self.assert_(queryUtility(ITranslationDomain) is None)
         xmlconfig.string(
             template % '''
             <configure package="zope.i18n.tests">
@@ -69,7 +74,7 @@
                              'locale', 'en', 'LC_MESSAGES', 'zope-i18n.mo')
         path2 = os.path.join(os.path.dirname(zope.i18n.tests.__file__),
                              'locale2', 'en', 'LC_MESSAGES', 'zope-i18n.mo')
-        util = zope.component.getUtility(ITranslationDomain, 'zope-i18n')
+        util = getUtility(ITranslationDomain, 'zope-i18n')
         self.assertEquals(util._catalogs,
                           {'test': ['test', 'test'],
                                    'en': [unicode(path1), unicode(path2)]})
@@ -83,7 +88,37 @@
         msg = util.translate(u'New Language', target_language='en')
         self.assertEquals(msg, u'New Language translated')
 
+    if HAS_PYTHON_GETTEXT:
+        def testRegisterAndCompileTranslations(self):
+            zcml.COMPILE_MO_FILES = True
+            self.assert_(queryUtility(ITranslationDomain) is None)
 
+            # Copy an old and outdated file over, so we can test if the
+            # newer file check works
+            testpath = os.path.join(os.path.dirname(zope.i18n.tests.__file__))
+            basepath = os.path.join(testpath, 'locale3', 'en', 'LC_MESSAGES')
+            in_ = os.path.join(basepath, 'zope-i18n.in')
+            path = os.path.join(basepath, 'zope-i18n.mo')
+            shutil.copy2(in_, path)
+
+            xmlconfig.string(
+                template % '''
+                <configure package="zope.i18n.tests">
+                <i18n:registerTranslations directory="locale3" />
+                </configure>
+                ''', self.context)
+            util = getUtility(ITranslationDomain, 'zope-i18n')
+            self.assertEquals(util._catalogs,
+                              {'test': ['test'], 'en': [unicode(path)]})
+
+            msg = util.translate(u"I'm a newer file", target_language='en')
+            self.assertEquals(msg, u"I'm a newer file translated")
+
+            util = getUtility(ITranslationDomain, 'zope-i18n2')
+            msg = util.translate(u"I'm a new file", target_language='en')
+            self.assertEquals(msg, u"I'm a new file translated")
+
+
 def test_suite():
     return unittest.makeSuite(DirectivesTest)
 

Modified: zope.i18n/trunk/src/zope/i18n/zcml.py
===================================================================
--- zope.i18n/trunk/src/zope/i18n/zcml.py	2008-04-26 10:36:13 UTC (rev 85757)
+++ zope.i18n/trunk/src/zope/i18n/zcml.py	2008-04-26 10:52:59 UTC (rev 85758)
@@ -1,4 +1,5 @@
-##############################################################################
+
+# ##############################################################################
 #
 # Copyright (c) 2001, 2002 Zope Corporation and Contributors.
 # All Rights Reserved.
@@ -21,6 +22,7 @@
 
 from zope.interface import Interface
 from zope.configuration.fields import Path
+from zope.i18n.compile import compile_mo_file
 from zope.i18n.gettextmessagecatalog import GettextMessageCatalog
 from zope.i18n.testmessagecatalog import TestMessageCatalog
 from zope.i18n.translationdomain import TranslationDomain
@@ -28,6 +30,10 @@
 from zope.component import queryUtility
 from zope.component.zcml import utility
 
+COMPILE_MO_FILES_KEY = 'zope.i18n.compile_mo_files'
+COMPILE_MO_FILES = os.environ.get(COMPILE_MO_FILES_KEY, False)
+
+
 class IRegisterTranslationsDirective(Interface):
     """Register translations with the global site manager."""
 
@@ -47,6 +53,12 @@
     for language in os.listdir(path):
         lc_messages_path = os.path.join(path, language, 'LC_MESSAGES')
         if os.path.isdir(lc_messages_path):
+            # Preprocess files and update or compile the mo files
+            if COMPILE_MO_FILES:
+                for domain_file in os.listdir(lc_messages_path):
+                    if domain_file.endswith('.po'):
+                        domain = domain_file[:-3]
+                        compile_mo_file(domain, lc_messages_path)
             for domain_file in os.listdir(lc_messages_path):
                 if domain_file.endswith('.mo'):
                     domain_path = os.path.join(lc_messages_path, domain_file)



More information about the Checkins mailing list