Skip to content

Commit

Permalink
Merge pull request #13 from drd/drd/i18n-ctxt
Browse files Browse the repository at this point in the history
Add support for msgctxt to i18n.
  • Loading branch information
hodgestar authored May 3, 2021
2 parents ac3a59e + b410a22 commit adedcdd
Show file tree
Hide file tree
Showing 4 changed files with 399 additions and 82 deletions.
61 changes: 40 additions & 21 deletions doc/i18n.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ and localizing templates. That includes functionality for extracting
localizable strings from templates, as well as a template filter and special
directives that can apply translations to templates as they get rendered.

This support is based on `gettext`_ message catalogs and the `gettext Python
This support is based on `gettext`_ message catalogs and the `gettext Python
module`_. The extraction process can be used from the API level, or through
the front-ends implemented by the `Babel`_ project, for which Genshi provides
a plugin.
Expand Down Expand Up @@ -39,7 +39,7 @@ required.
However, this approach results in significant “character noise” in templates,
making them harder to read and preview.

The ``genshi.filters.Translator`` filter allows you to get rid of the
The ``genshi.filters.Translator`` filter allows you to get rid of the
explicit `gettext`_ function calls, so you can (often) just continue to write:

.. code-block:: genshi
Expand All @@ -54,11 +54,11 @@ This text will still be extracted and translated as if you had wrapped it in a
corresponding ``gettext`` function in embedded Python expressions.

You can control which tags should be ignored by this process; for example, it
doesn't really make sense to translate the content of the HTML
doesn't really make sense to translate the content of the HTML
``<script></script>`` element. Both ``<script>`` and ``<style>`` are excluded
by default.

Attribute values can also be automatically translated. The default is to
Attribute values can also be automatically translated. The default is to
consider the attributes ``abbr``, ``alt``, ``label``, ``prompt``, ``standby``,
``summary``, and ``title``, which is a list that makes sense for HTML
documents. Of course, you can tell the translator to use a different set of
Expand All @@ -77,7 +77,7 @@ attributes of the element will be ignored:
<p xml:lang="en">Hello, world!</p>
On the other hand, if the value of the ``xml:lang`` attribute contains a Python
expression, the element contents and attributes are still considered for
expression, the element contents and attributes are still considered for
automatic translation:

.. code-block:: genshi
Expand Down Expand Up @@ -337,11 +337,30 @@ translation domain for a particular scope. For example:
</div>
``i18n.ctxt``
-------------

Sometimes a source string can have two different meanings. Without resorting to
splitting these two occurrences into different domains, gettext provides a
means to specify a *context* for each translatable string. For instance, the
word "volunteer" can either mean the noun, one who volunteers, or the verb,
to volunteer.

The ``i18n:ctxt`` directive allows you to mark a scope with a particular
context. Here is a rather contrived example:

.. code-block:: genshi
<p>A <span i18n:ctxt="noun">volunteer</span> can really help their community.
Why don't you <span i18n:ctxt="verb">volunteer</span> some time today?
</p>
Extraction
==========

The ``Translator`` class provides a class method called ``extract``, which is
a generator yielding all localizable strings found in a template or markup
a generator yielding all localizable strings found in a template or markup
stream. This includes both literal strings in text nodes and attribute values,
as well as strings in ``gettext()`` calls in embedded Python code. See the API
documentation for details on how to use this method directly.
Expand All @@ -351,14 +370,14 @@ Babel Integration
-----------------

This functionality is integrated with the message extraction framework provided
by the `Babel`_ project. Babel provides a command-line interface as well as
commands that can be used from ``setup.py`` scripts using `Setuptools`_ or
by the `Babel`_ project. Babel provides a command-line interface as well as
commands that can be used from ``setup.py`` scripts using `Setuptools`_ or
`Distutils`_.

.. _`setuptools`: http://peak.telecommunity.com/DevCenter/setuptools
.. _`distutils`: http://docs.python.org/dist/dist.html

The first thing you need to do to make Babel extract messages from Genshi
The first thing you need to do to make Babel extract messages from Genshi
templates is to let Babel know which files are Genshi templates. This is done
using a “mapping configuration”, which can be stored in a configuration file,
or specified directly in your ``setup.py``.
Expand Down Expand Up @@ -407,19 +426,19 @@ default is to assume “utf-8”.

``include_attrs``
-----------------
Comma-separated list of attribute names that should be considered to have
Comma-separated list of attribute names that should be considered to have
localizable values. Only used for markup templates.

``ignore_tags``
---------------
Comma-separated list of tag names that should be ignored. Only used for markup
Comma-separated list of tag names that should be ignored. Only used for markup
templates.

``extract_text``
----------------
Whether text outside explicit ``gettext`` function calls should be extracted.
By default, any text nodes not inside ignored tags, and values of attribute in
the ``include_attrs`` list are extracted. If this option is disabled, only
the ``include_attrs`` list are extracted. If this option is disabled, only
strings in ``gettext`` function calls are extracted.

.. note:: If you disable this option, and do not make use of the
Expand All @@ -446,7 +465,7 @@ filters that Genshi adds itself:
from genshi.filters import Translator
from genshi.template import MarkupTemplate
template = MarkupTemplate("...")
template.filters.insert(0, Translator(translations.ugettext))
Expand All @@ -457,7 +476,7 @@ which will both add the filter and register the i18n directives:
from genshi.filters import Translator
from genshi.template import MarkupTemplate
template = MarkupTemplate("...")
translator = Translator(translations.ugettext)
translator.setup(template)
Expand All @@ -473,7 +492,7 @@ which will both add the filter and register the i18n directives:
Related Considerations
======================

If you intend to produce an application that is fully prepared for an
If you intend to produce an application that is fully prepared for an
international audience, there are a couple of other things to keep in mind:

-------
Expand All @@ -482,25 +501,25 @@ Unicode

Use ``unicode`` internally, not encoded bytestrings. Only encode/decode where
data enters or exits the system. This means that your code works with characters
and not just with bytes, which is an important distinction for example when
and not just with bytes, which is an important distinction for example when
calculating the length of a piece of text. When you need to decode/encode, it's
probably a good idea to use UTF-8.

-------------
Date and Time
-------------

If your application uses datetime information that should be displayed to users
in different timezones, you should try to work with UTC (universal time)
internally. Do the conversion from and to "local time" when the data enters or
exits the system. Make use the Python `datetime`_ module and the third-party
If your application uses datetime information that should be displayed to users
in different timezones, you should try to work with UTC (universal time)
internally. Do the conversion from and to "local time" when the data enters or
exits the system. Make use the Python `datetime`_ module and the third-party
`pytz`_ package.

--------------------------
Formatting and Locale Data
--------------------------

Make sure you check out the functionality provided by the `Babel`_ project for
Make sure you check out the functionality provided by the `Babel`_ project for
things like number and date formatting, locale display strings, etc.

.. _`datetime`: http://docs.python.org/lib/module-datetime.html
Expand Down
22 changes: 20 additions & 2 deletions examples/bench/bigtable.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import timeit
from StringIO import StringIO
from genshi.builder import tag
from genshi.filters.i18n import Translator
from genshi.filters.tests.i18n import DummyTranslations
from genshi.template import MarkupTemplate, NewTextTemplate

try:
Expand Down Expand Up @@ -58,6 +60,17 @@
</table>
""")

genshi_tmpl_i18n = MarkupTemplate("""
<table xmlns:py="http://genshi.edgewall.org/"
xmlns:i18n="http://genshi.edgewall.org/i18n">
<tr py:for="row in table">
<td py:for="c in row.values()">${c}</td>
</tr>
</table>
""")
t = Translator(DummyTranslations())
t.setup(genshi_tmpl_i18n)

genshi_tmpl2 = MarkupTemplate("""
<table xmlns:py="http://genshi.edgewall.org/">$table</table>
""")
Expand Down Expand Up @@ -105,6 +118,11 @@ def test_genshi():
stream = genshi_tmpl.generate(table=table)
stream.render('html', strip_whitespace=False)

def test_genshi_i18n():
"""Genshi template w/ i18n"""
stream = genshi_tmpl_i18n.generate(table=table)
stream.render('html', strip_whitespace=False)

def test_genshi_text():
"""Genshi text template"""
stream = genshi_text_tmpl.generate(table=table)
Expand Down Expand Up @@ -169,7 +187,7 @@ def test_et():
et.tostring(_table)

if cet:
def test_cet():
def test_cet():
"""cElementTree"""
_table = cet.Element('table')
for row in table:
Expand Down Expand Up @@ -198,7 +216,7 @@ def test_clearsilver():


def run(which=None, number=10):
tests = ['test_builder', 'test_genshi', 'test_genshi_text',
tests = ['test_builder', 'test_genshi', 'test_genshi_i18n', 'test_genshi_text',
'test_genshi_builder', 'test_mako', 'test_kid', 'test_kid_et',
'test_et', 'test_cet', 'test_clearsilver', 'test_django']

Expand Down
Loading

0 comments on commit adedcdd

Please sign in to comment.