Commits

Takayuki Shimizukawa committed 0986d4e

checking whether the number of references is equal in both the translated form and the untranslated form? If they're not equal, emit a warning and don't bother trying to transfer the references.

Comments (0)

Files changed (5)

sphinx/environment.py

     def _collect_ref_nodes(cls, nodelist):
         return cls._collect_nodes(nodelist, nodes.reference)
 
+    def _is_ref_inconsistency(self, node1, node2):
+        """
+        check equality of the number of reference in both the translated
+        form and the untranslated form.
+        """
+        env = self.document.settings.env
+        for f in [self._collect_footnote_ref_nodes,
+                  self._collect_ref_nodes,
+                  ]:
+            if len(f(node1.children)) != len(f(node2.children)):
+                env.warn_node('The number of reference are inconsistent '
+                              'in both the translated form and the '
+                              'untranslated form. skip translation.', node1)
+                return True
+
+        return False
+
     def apply(self):
         env = self.document.settings.env
         settings, source = self.document.settings, self.document['source']
             if not isinstance(patch, nodes.paragraph):
                 continue # skip for now
 
+            if self._is_ref_inconsistency(node, patch):
+                continue #skip translation.
+
             footnote_refs = self._collect_footnote_ref_nodes(node.children)
             refs = self._collect_ref_nodes(node.children)
 
                     # use original 'footnote_reference' object.
                     # this object is already registered in self.document.autofootnote_refs
                     patch.children[i] = footnote_refs.pop(0)
-                    # Some duplicated footnote_reference in msgstr cause
-                    # IndexError in .pop(0). That is invalid msgstr.
 
                 elif isinstance(child, nodes.reference):
                     # reference should use original 'refname'.

tests/root/contents.txt

    only
    i18n_footnote
    i18n_external_links
+   i18n_refs_inconsistency
 
    Python <http://python.org/>
 

tests/root/i18n_refs_inconsistency.po

+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2012, foof
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-12-05 08:28\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n with refs inconsistency"
+msgstr "I18N WITH REFS INCONSISTENCY"
+
+msgid "[100]_ for [#]_ footnote [ref2]_."
+msgstr "FOR FOOTNOTE [ref2]_."
+
+msgid "for reference_."
+msgstr "reference_ FOR reference_."
+
+msgid "This is a auto numbered footnote."
+msgstr "THIS IS A AUTO NUMBERED FOOTNOTE."
+
+msgid "This is a named footnote."
+msgstr "THIS IS A NAMED FOOTNOTE."
+
+msgid "This is a numbered footnote."
+msgstr "THIS IS A NUMBERED FOOTNOTE."
+

tests/root/i18n_refs_inconsistency.txt

+:tocdepth: 2
+
+i18n with refs inconsistency
+=============================
+
+* [100]_ for [#]_ footnote [ref2]_.
+* for reference_.
+
+.. [#] This is a auto numbered footnote.
+.. [ref2] This is a named footnote.
+.. [100] This is a numbered footnote.
+.. _reference: http://www.example.com

tests/test_intl.py

 
 from subprocess import Popen, PIPE
 import re
+import os
+from StringIO import StringIO
 
 from util import *
 from util import SkipTest
 
 
+warnfile = StringIO()
+
+
 def setup_module():
     (test_root / 'xx' / 'LC_MESSAGES').makedirs()
     # Compile all required catalogs into binary format (*.mo).
-    for catalog in 'bom', 'subdir', 'i18n_footnote', 'i18n_external_links':
+    for catalog in ('bom', 'subdir', 'i18n_footnote', 'i18n_external_links',
+            'i18n_refs_inconsistency'):
         try:
             p = Popen(['msgfmt', test_root / '%s.po' % catalog, '-o',
                 test_root / 'xx' / 'LC_MESSAGES' / '%s.mo' % catalog],
     assert result == expect
 
 
+@with_app(buildername='text', warning=warnfile,
+          confoverrides={'language': 'xx', 'locale_dirs': ['.']})
+def test_i18n_warn_for_number_of_references_inconsistency(app):
+    app.builddir.rmtree(True)
+    app.builder.build(['i18n_refs_inconsistency'])
+    result = (app.outdir / 'i18n_refs_inconsistency.txt').text(encoding='utf-8')
+    expect = (u"\nI18N WITH REFS INCONSISTENCY"
+              u"\n****************************\n"
+              u"\n* [100] for [1] footnote [ref2].\n"
+              u"\n* for reference.\n"
+              u"\n[1] THIS IS A AUTO NUMBERED FOOTNOTE.\n"
+              u"\n[ref2] THIS IS A NAMED FOOTNOTE.\n"
+              u"\n[100] THIS IS A NUMBERED FOOTNOTE.\n")
+    assert result == expect
+
+    warnings = warnfile.getvalue().replace(os.sep, '/')
+    expected_warning_expr = "i18n_refs_inconsistency.txt:\d+: WARNING: The number of reference are inconsistent in both the translated form and the untranslated form. skip translation."
+    assert len(re.findall(expected_warning_expr, warnings)) == 2
+
+
 @with_app(buildername='html',
           confoverrides={'language': 'xx', 'locale_dirs': ['.']})
 def test_i18n_keep_external_links(app):