merge with DasIch/sphinx-i18n

This commit is contained in:
Georg Brandl
2010-08-21 19:34:05 +02:00
5 changed files with 52 additions and 30 deletions

View File

@@ -6,9 +6,8 @@ Internationalization
.. versionadded:: 1.1
Complementary to translations provided for Sphinx-generated messages such as
navigation bars Sphinx provides mechanisms facilitating *document* translations
navigation bars, Sphinx provides mechanisms facilitating *document* translations
in itself. It relies on the existing configuration values :confval:`language`
and :confval:`locale_dirs`.
.. XXX write more!

View File

@@ -5,17 +5,19 @@
The MessageCatalogBuilder class.
:copyright: Copyright 2010 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import collections
from datetime import datetime
from os import path
from codecs import open
from datetime import datetime
from collections import defaultdict
from sphinx.builders import Builder
from sphinx.builders.versioning import VersioningBuilderMixin
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
POHEADER = ur"""
@@ -39,14 +41,17 @@ msgstr ""
"""[1:]
class MessageCatalogBuilder(Builder):
class I18nBuilder(Builder, VersioningBuilderMixin):
"""
Builds gettext-style message catalogs (.pot files).
General i18n builder.
"""
name = 'gettext'
name = 'i18n'
def init(self):
self.catalogs = collections.defaultdict(list)
Builder.init(self)
VersioningBuilderMixin.init(self)
self.catalogs = defaultdict(dict)
def get_target_uri(self, docname, typ=None):
return ''
@@ -58,18 +63,26 @@ class MessageCatalogBuilder(Builder):
return
def write_doc(self, docname, doctree):
"""
Store a document's translatable strings in the message catalog of its
section. For this purpose a document's *top-level directory* -- or
otherwise its *name* -- is considered its section.
"""
catalog = self.catalogs[docname.split(SEP, 1)[0]]
for _, msg in extract_messages(doctree):
# XXX msgctxt for duplicate messages
if msg not in catalog:
catalog.append(msg)
self.handle_versioning(docname, doctree, nodes.TextElement)
for node, msg in extract_messages(doctree):
catalog.setdefault(node.uid, msg)
def finish(self):
Builder.finish(self)
VersioningBuilderMixin.finish(self)
class MessageCatalogBuilder(I18nBuilder):
"""
Builds gettext-style message catalogs (.pot files).
"""
name = 'gettext'
def finish(self):
I18nBuilder.finish(self)
data = dict(
version = self.config.version,
copyright = self.config.copyright,
@@ -81,13 +94,15 @@ class MessageCatalogBuilder(Builder):
self.catalogs.iteritems(), "writing message catalogs... ",
lambda (section, _):darkgreen(section), len(self.catalogs)):
pofile = open(path.join(self.outdir, '%s.pot' % section), 'w')
pofn = path.join(self.outdir, section + '.pot')
pofile = open(pofn, 'w', encoding='utf-8')
try:
pofile.write(POHEADER % data)
for message in messages:
for uid, message in messages.iteritems():
# message contains *one* line of text ready for translation
message = message.replace(u'\\', ur'\\').replace(u'"', ur'\"')
pomsg = u'msgid "%s"\nmsgstr ""\n\n' % message
pofile.write(pomsg.encode('utf-8'))
message = message.replace(u'\\', ur'\\'). \
replace(u'"', ur'\"')
pomsg = u'#%s\nmsgid "%s"\nmsgstr ""\n\n' % (uid, message)
pofile.write(pomsg)
finally:
pofile.close()

View File

@@ -211,7 +211,7 @@ class Locale(Transform):
# XXX ctx not used
#ctx = node.parent
patch = new_document(source, settings)
msgstr = catalog.ugettext(msg)
msgstr = catalog.gettext(msg)
# XXX add marker to untranslated parts
if not msgstr or msgstr == msg: # as-of-yet untranslated
continue
@@ -793,6 +793,7 @@ class BuildEnvironment:
if node['level'] < filterlevel:
node.parent.remove(node)
def process_dependencies(self, docname, doctree):
"""
Process docutils-generated dependency info.

View File

@@ -218,4 +218,6 @@ def init(locale_dirs, language, catalog='sphinx'):
translator = gettext.NullTranslations()
has_translation = False
translators[catalog] = translator
if hasattr(translator, 'ugettext'):
translator.gettext = translator.ugettext
return translator, has_translation

View File

@@ -46,7 +46,8 @@ def test_gettext(app):
if p.returncode != 0:
print stdout
print stderr
assert False, 'msginit exited with return code %s' % p.returncode
assert False, 'msginit exited with return code %s' % \
p.returncode
assert (app.outdir / 'en_US.po').isfile(), 'msginit failed'
try:
p = Popen(['msgfmt', 'en_US.po', '-o',
@@ -59,12 +60,14 @@ def test_gettext(app):
if p.returncode != 0:
print stdout
print stderr
assert False, 'msgfmt exited with return code %s' % p.returncode
assert (app.outdir / 'en' / 'LC_MESSAGES' / 'test_root.mo').isfile(), 'msgfmt failed'
assert False, 'msgfmt exited with return code %s' % \
p.returncode
assert (app.outdir / 'en' / 'LC_MESSAGES' / 'test_root.mo').isfile(), \
'msgfmt failed'
finally:
os.chdir(cwd)
_ = gettext.translation('test_root', app.outdir, languages=['en']).ugettext
_ = gettext.translation('test_root', app.outdir, languages=['en']).gettext
assert _("Testing various markup") == u"Testing various markup"
@with_app(buildername='gettext')
@@ -95,7 +98,9 @@ def setup_patch():
print stdout
print stderr
assert False, 'msgfmt exited with return code %s' % p.returncode
assert (test_root / 'xx' / 'LC_MESSAGES' / 'bom.mo').isfile(), 'msgfmt failed'
assert (test_root / 'xx' / 'LC_MESSAGES' / 'bom.mo').isfile(), \
'msgfmt failed'
def teardown_patch():
(test_root / 'xx').rmtree()
test_patch.setup = setup_patch