Commits

Anonymous committed 32b377b

Added versioning support to i18n builder

  • Participants
  • Parent commits c14f7bc

Comments (0)

Files changed (1)

File sphinx/builders/intl.py

 from datetime import datetime
 from os import path
 from codecs import open
+import os
+import pickle
 
 from docutils import nodes
+from docutils.utils import Reporter
 
 from sphinx.builders import Builder
 from sphinx.util.nodes import extract_messages
-from sphinx.util.osutil import SEP
+from sphinx.util.osutil import SEP, copyfile
 from sphinx.util.console import darkgreen
+from sphinx.environment import WarningStream
+from sphinx.versioning import add_uids, merge_doctrees
 
 POHEADER = ur"""
 # SOME DESCRIPTIVE TITLE.
 
     def init(self):
         Builder.init(self)
-        self.catalogs = defaultdict(list)
+        self.catalogs = defaultdict(dict)
+        for root, dirs, files in os.walk(self.doctreedir):
+            for fn in files:
+                fp = path.join(root, fn)
+                if fp.endswith('.doctree'):
+                    copyfile(fp, fp + '.old')
+
+    def get_old_doctree(self, docname):
+        fp = self.env.doc2path(docname, self.doctreedir, '.doctree.old')
+        try:
+            f = open(fp, 'rb')
+            try:
+                doctree = pickle.load(f)
+            finally:
+                f.close()
+        except IOError:
+            return None
+        doctree.settings.env = self.env
+        doctree.reporter = Reporter(self.env.doc2path(docname), 2, 5,
+                                    stream=WarningStream(self.env._warnfunc))
+
+    def resave_doctree(self, docname, doctree):
+        reporter = doctree.reporter
+        doctree.reporter = None
+        doctree.settings.warning_stream = None
+        doctree.settings.env = None
+        doctree.settings.record_dependencies = None
+
+        fp = self.env.doc2path(docname, self.doctreedir, '.doctree')
+        f = open(fp, 'wb')
+        try:
+            pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
+        finally:
+            f.close()
+
+        doctree.reporter = reporter
 
     def get_target_uri(self, docname, typ=None):
         return ''
 
     def write_doc(self, docname, doctree):
         catalog = self.catalogs[docname.split(SEP, 1)[0]]
-        for _, msg in extract_messages(doctree):
-            if msg not in catalog:
-                catalog.append(msg)
+        old_doctree = self.get_old_doctree(docname)
+
+        if old_doctree:
+            list(merge_doctrees(old_doctree, doctree, nodes.TextElement))
+        else:
+            list(add_uids(doctree, nodes.TextElement))
+        self.resave_doctree(docname, doctree)
+
+        for node, msg in extract_messages(doctree):
+            catalog.setdefault(node.uid, msg)
+
+    def finish(self):
+        Builder.finish(self)
+        for root, dirs, files in os.walk(self.doctreedir):
+            for fn in files:
+                fp = path.join(root, fn)
+                if fp.endswith('.doctree.old'):
+                    os.remove(fp)
 
 class MessageCatalogBuilder(I18NBuilder):
     """
     name = 'gettext'
 
     def finish(self):
+        I18NBuilder.finish(self)
         data = dict(
             version = self.config.version,
             copyright = self.config.copyright,
             pofile = open(pofp, 'w', encoding='utf-8')
             try:
                 pofile.write(POHEADER % data)
-                for message in messages:
+                for message in messages.itervalues():
                     # message contains *one* line of text ready for translation
                     message = message.replace(u'\\', ur'\\'). \
                                       replace(u'"', ur'\"')