Add i18n capabilities for custom templates.

For example: The Sphinx reference documentation in doc directory provides
sphinx.pot file from ``doc/_templates/*.html`` by ``make gettext``.
This commit is contained in:
Takayuki Shimizukawa 2013-03-10 22:07:31 +09:00
parent 7b443298a3
commit 2c409959ac
9 changed files with 167 additions and 62 deletions

View File

@ -1,6 +1,10 @@
Release 1.2 (in development)
============================
* Add i18n capabilities for custom templates.
For example: The Sphinx reference documentation in doc directory provides
sphinx.pot file from ``doc/_templates/*.html`` by ``make gettext``.
* PR#123, #1106: Add epub_use_index configuration value.
If provided, it will be used instead of html_use_index for epub builder.

View File

@ -1,87 +1,87 @@
{% extends "layout.html" %}
{% set title = 'Overview' %}
{% set title = _('Overview') %}
{% block body %}
<h1>Welcome</h1>
<h1>{{ _('Welcome') }}</h1>
<div class="quotebar">
<p><em>What users say:</em></p>
<p>&ldquo;Cheers for a great tool that actually makes programmers <b>want</b>
to write documentation!&rdquo;</p>
<p><em>{%trans%}What users say:{%endtrans%}</em></p>
<p>{%trans%}&ldquo;Cheers for a great tool that actually makes programmers <b>want</b>
to write documentation!&rdquo;{%endtrans%}</p>
</div>
<p>
<p>{%trans%}
Sphinx is a tool that makes it easy to create intelligent and beautiful
documentation, written by Georg Brandl and licensed under the BSD license.</p>
<p>It was originally created for <a href="http://docs.python.org/">the
documentation, written by Georg Brandl and licensed under the BSD license.{%endtrans%}</p>
<p>{%trans%}It was originally created for <a href="http://docs.python.org/">the
new Python documentation</a>, and it has excellent facilities for the
documentation of Python projects, but C/C++ is already supported as well,
and it is planned to add special support for other languages as well. Of
course, this site is also created from reStructuredText sources using
Sphinx! The following features should be highlighted:
Sphinx! The following features should be highlighted:{%endtrans%}
</p>
<ul>
<li><b>Output formats:</b> HTML (including Windows HTML Help), LaTeX (for
printable PDF versions), Texinfo, manual pages, plain text</li>
<li><b>Extensive cross-references:</b> semantic markup and automatic links
<li>{%trans%}<b>Output formats:</b> HTML (including Windows HTML Help), LaTeX (for
printable PDF versions), Texinfo, manual pages, plain text{%endtrans%}</li>
<li>{%trans%}<b>Extensive cross-references:</b> semantic markup and automatic links
for functions, classes, citations, glossary terms and similar pieces of
information</li>
<li><b>Hierarchical structure:</b> easy definition of a document tree, with
automatic links to siblings, parents and children</li>
<li><b>Automatic indices:</b> general index as well as a language-specific
module indices</li>
<li><b>Code handling:</b> automatic highlighting using the <a
href="http://pygments.org">Pygments</a> highlighter</li>
<li><b>Extensions:</b> automatic testing of code snippets, inclusion of
information{%endtrans%}</li>
<li>{%trans%}<b>Hierarchical structure:</b> easy definition of a document tree, with
automatic links to siblings, parents and children{%endtrans%}</li>
<li>{%trans%}<b>Automatic indices:</b> general index as well as a language-specific
module indices{%endtrans%}</li>
<li>{%trans%}<b>Code handling:</b> automatic highlighting using the <a
href="http://pygments.org">Pygments</a> highlighter{%endtrans%}</li>
<li>{%trans path=pathto('extensions')%}<b>Extensions:</b> automatic testing of code snippets, inclusion of
docstrings from Python modules (API docs), and
<a href="{{ pathto('extensions') }}#builtin-sphinx-extensions">more</a></li>
<a href="{{ path }}#builtin-sphinx-extensions">more</a>{%endtrans%}</li>
</ul>
<p>
<p>{%trans%}
Sphinx uses <a href="http://docutils.sf.net/rst.html">reStructuredText</a>
as its markup language, and many of its strengths come from the power and
straightforwardness of reStructuredText and its parsing and translating
suite, the <a href="http://docutils.sf.net/">Docutils</a>.
suite, the <a href="http://docutils.sf.net/">Docutils</a>.{%endtrans%}
</p>
<h2 style="margin-bottom: 0">Documentation</h2>
<h2 style="margin-bottom: 0">{%trans%}Documentation{%endtrans%}</h2>
<table class="contentstable" align="center" style="margin-left: 30px"><tr>
<td width="50%">
<p class="biglink"><a class="biglink" href="{{ pathto("tutorial") }}">First steps with Sphinx</a><br/>
<span class="linkdescr">overview of basic tasks</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">Contents</a><br/>
<span class="linkdescr">for a complete overview</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("tutorial") }}">{%trans%}First steps with Sphinx{%endtrans%}</a><br/>
<span class="linkdescr">{%trans%}overview of basic tasks{%endtrans%}</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">{%trans%}Contents{%endtrans%}</a><br/>
<span class="linkdescr">{%trans%}for a complete overview{%endtrans%}</span></p>
</td><td width="50%">
<p class="biglink"><a class="biglink" href="{{ pathto("search") }}">Search page</a><br/>
<span class="linkdescr">search the documentation</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("genindex") }}">General Index</a><br/>
<span class="linkdescr">all functions, classes, terms</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("search") }}">{%trans%}Search page{%endtrans%}</a><br/>
<span class="linkdescr">{%trans%}search the documentation{%endtrans%}</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("genindex") }}">{%trans%}General Index{%endtrans%}</a><br/>
<span class="linkdescr">{%trans%}all functions, classes, terms{%endtrans%}</span></p>
</td></tr>
</table>
<p>
<p>{%trans%}
You can also download PDF versions of the Sphinx documentation:
a <a href="http://sphinx-doc.org/sphinx.pdf">version</a> generated from
the LaTeX Sphinx produces, and
a <a href="http://sphinx-doc.org/sphinx-rst2pdf.pdf">version</a> generated
by rst2pdf.
by rst2pdf.{%endtrans%}
</p>
<h2>Examples</h2>
<p>Links to documentation generated with Sphinx can be found on the
<a href="{{ pathto("examples") }}">Projects using Sphinx</a> page.
<h2>{%trans%}Examples{%endtrans%}</h2>
<p>{%trans path=pathto("examples")%}Links to documentation generated with Sphinx can be found on the
<a href="{{ path }}">Projects using Sphinx</a> page.{%endtrans%}
</p>
<p>
<p>{%trans%}
For examples of how Sphinx source files look, use the &#8220;Show
source&#8221; links on all pages of the documentation apart from this
welcome page.
welcome page.{%endtrans%}
</p>
<p>You may also be interested in the very nice
<p>{%trans%}You may also be interested in the very nice
<a href="http://matplotlib.sourceforge.net/sampledoc/">tutorial</a> on how to
create a customized documentation using Sphinx written by the matplotlib
developers.</p>
developers.{%endtrans%}</p>
<p>There is a <a href="http://sphinx-users.jp/doc10/">Japanese translation</a>
of this documentation, thanks to Yoshiki Shibukawa.</p>
<p>{%trans%}There is a <a href="http://sphinx-users.jp/doc10/">Japanese translation</a>
of this documentation, thanks to Yoshiki Shibukawa.{%endtrans%}</p>
{% endblock %}

View File

@ -1,32 +1,32 @@
<p class="logo">A <a href="http://pocoo.org/">
<img src="{{ pathto("_static/pocoo.png", 1) }}" /></a> project</a></p>
<img src="{{ pathto("_static/pocoo.png", 1) }}" /></a> {%trans%}project{%endtrans%}</a></p>
<h3>Download</h3>
{% if version.endswith('(hg)') %}
<p>This documentation is for version <b>{{ version }}</b>, which is
not released yet.</p>
<p>You can use it from the
<p>{%trans%}This documentation is for version <b>{{ version }}</b>, which is
not released yet.{%endtrans%}</p>
<p>{%trans%}You can use it from the
<a href="http://bitbucket.org/birkenfeld/sphinx/">Mercurial repo</a> or look for
released versions in the <a href="http://pypi.python.org/pypi/Sphinx">Python
Package Index</a>.</p>
Package Index</a>.{%endtrans%}</p>
{% else %}
<p>Current version: <b>{{ version }}</b></p>
<p>Get Sphinx from the <a href="http://pypi.python.org/pypi/Sphinx">Python Package
Index</a>, or install it with:</p>
<p>{%trans%}Current version: <b>{{ version }}</b>{%endtrans%}</p>
<p>{%trans%}Get Sphinx from the <a href="http://pypi.python.org/pypi/Sphinx">Python Package
Index</a>, or install it with:{%endtrans%}</p>
<pre>easy_install -U Sphinx</pre>
<p>Latest <a href="http://sphinx-doc.org/latest/">development version docs</a>
are also available.</p>
<p>{%trans%}Latest <a href="http://sphinx-doc.org/latest/">development version docs</a>
are also available.{%endtrans%}</p>
{% endif %}
<h3>Questions? Suggestions?</h3>
<h3>{%trans%}Questions? Suggestions?{%endtrans%}</h3>
<p>Join the <a href="http://groups.google.com/group/sphinx-users">Google group</a>:</p>
<p>{%trans%}Join the <a href="http://groups.google.com/group/sphinx-users">Google group</a>:{%endtrans%}</p>
<form action="http://groups.google.com/group/sphinx-users/boxsubscribe"
style="padding-left: 0.5em">
<input type="text" name="email" value="your@email" style="font-size: 90%; width: 120px"
onfocus="$(this).val('');"/>
<input type="submit" name="sub" value="Subscribe" style="font-size: 90%; width: 70px"/>
</form>
<p>or come to the <tt>#pocoo</tt> channel on FreeNode.</p>
<p>You can also open an issue at the
<a href="http://www.bitbucket.org/birkenfeld/sphinx/issues/">tracker</a>.</p>
<p>{%trans%}or come to the <tt>#pocoo</tt> channel on FreeNode.{%endtrans%}</p>
<p>{%trans%}You can also open an issue at the
<a href="http://www.bitbucket.org/birkenfeld/sphinx/issues/">tracker</a>.{%endtrans%}</p>

View File

@ -9,16 +9,17 @@
:license: BSD, see LICENSE for details.
"""
from os import path
from os import path, walk
from codecs import open
from datetime import datetime
from collections import defaultdict
from uuid import uuid4
from sphinx.builders import Builder
from sphinx.util import split_index_msg
from sphinx.util.nodes import extract_messages, traverse_translatable_index
from sphinx.util.osutil import safe_relpath, ensuredir, find_catalog
from sphinx.util.console import darkgreen
from sphinx.util.osutil import safe_relpath, ensuredir, find_catalog, SEP
from sphinx.util.console import darkgreen, purple, bold
from sphinx.locale import pairindextypes
POHEADER = ur"""
@ -57,6 +58,17 @@ class Catalog(object):
self.metadata[msg].append((origin.source, origin.line, origin.uid))
class MsgOrigin(object):
"""
Origin holder for Catalog message origin.
"""
def __init__(self, source, line):
self.source = source
self.line = line
self.uid = uuid4().hex
class I18nBuilder(Builder):
"""
General i18n builder.
@ -101,6 +113,43 @@ class MessageCatalogBuilder(I18nBuilder):
"""
name = 'gettext'
def init(self):
I18nBuilder.init(self)
self.create_template_bridge()
self.templates.init(self)
def _collect_templates(self):
template_files = set()
for template_path in self.config.templates_path:
tmpl_abs_path = path.join(self.app.srcdir, template_path)
for dirpath, dirs, files in walk(tmpl_abs_path):
for fn in files:
if fn.endswith('.html'):
filename = path.join(dirpath, fn)
filename = filename.replace(path.sep, SEP)
template_files.add(filename)
return template_files
def _extract_from_template(self):
files = self._collect_templates()
self.info(bold('building [%s]: ' % self.name), nonl=1)
self.info('targets for %d template files' % len(files))
extract_translations = self.templates.environment.extract_translations
for template in self.status_iterator(files,
'reading templates... ', purple, len(files)):
#catalog = self.catalogs[template]
catalog = self.catalogs['sphinx']
context = open(template, 'rt').read() #TODO: encoding
for line, meth, msg in extract_translations(context):
origin = MsgOrigin(template, line)
catalog.add(msg, origin)
def build(self, docnames, summary=None, method='update'):
self._extract_from_template()
I18nBuilder.build(self, docnames, summary, method)
def finish(self):
I18nBuilder.finish(self)
data = dict(
@ -136,7 +185,8 @@ class MessageCatalogBuilder(I18nBuilder):
# message contains *one* line of text ready for translation
message = message.replace(u'\\', ur'\\'). \
replace(u'"', ur'\"')
replace(u'"', ur'\"'). \
replace(u'\n', u'\\n"\n"')
pofile.write(u'msgid "%s"\nmsgstr ""\n\n' % message)
finally:

View File

@ -0,0 +1,5 @@
{% extends "layout.html" %}
{% block body %}
<h1>{{ _('Welcome') }}</h1>
<p>{%trans%}Sphinx {{ version }}{%endtrans%}</p>
{% endblock %}

View File

@ -5,3 +5,6 @@ import sys, os
project = 'Sphinx intl <Tests>'
source_suffix = '.txt'
keep_warnings = True
templates_path = ['_templates']
html_additional_pages = {'index': 'index.html'}
release = version = '2013.120'

View File

@ -0,0 +1,23 @@
# 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-11-22 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 "Welcome"
msgstr "WELCOME"
msgid "Sphinx %(version)s"
msgstr "SPHINX %(version)s"

View File

@ -137,3 +137,15 @@ def test_gettext_index_entries(app):
# unexpected msgid existent
assert msgids == []
@with_app(buildername='gettext',
srcdir=(test_roots / 'test-intl'),
doctreedir=(test_roots / 'test-intl' / '_build' / 'doctree'))
def test_gettext_template(app):
app.builder.build_all()
assert (app.outdir / 'sphinx.pot').isfile()
result = (app.outdir / 'sphinx.pot').text(encoding='utf-8')
assert "Welcome" in result
assert "Sphinx %(version)s" in result

View File

@ -420,3 +420,11 @@ def test_i18n_docfields_html(app):
app.builder.build(['docfields'])
result = (app.outdir / 'docfields.html').text(encoding='utf-8')
# expect no error by build
@with_intl_app(buildername='html')
def test_gettext_template(app):
app.builder.build_all()
result = (app.outdir / 'index.html').text(encoding='utf-8')
assert "WELCOME" in result
assert "SPHINX 2013.120" in result