Edgewall Software

genshi.filters.i18n

Directives and utilities for internationalization and localization of templates.

since:version 0.4
note:Directives support added since version 0.6

I18NDirective

Simple interface for i18n directives to support messages extraction.

ExtractableI18NDirective

Simple interface for directives to support messages extraction.

extract(self, translator, stream, gettext_functions=GETTEXT_FUNCTIONS, search_text=True, comment_stack=None)

(Not documented)

CommentDirective

Implementation of the i18n:comment template directive which adds translation comments.

>>> tmpl = MarkupTemplate('''<html xmlns:i18n="http://genshi.edgewall.org/i18n">
...   <p i18n:comment="As in Foo Bar">Foo</p>
... </html>''')
>>> translator = Translator()
>>> translator.setup(tmpl)
>>> list(translator.extract(tmpl.stream))
[(2, None, u'Foo', [u'As in Foo Bar'])]

MsgDirective

Implementation of the i18n:msg directive which marks inner content as translatable. Consider the following examples:

>>> tmpl = MarkupTemplate('''<html xmlns:i18n="http://genshi.edgewall.org/i18n">
...   <div i18n:msg="">
...     <p>Foo</p>
...     <p>Bar</p>
...   </div>
...   <p i18n:msg="">Foo <em>bar</em>!</p>
... </html>''')
>>> translator = Translator()
>>> translator.setup(tmpl)
>>> list(translator.extract(tmpl.stream))
[(2, None, u'[1:Foo]\n    [2:Bar]', []), (6, None, u'Foo [1:bar]!', [])]
>>> print(tmpl.generate().render())
<html>
  <div><p>Foo</p>
    <p>Bar</p></div>
  <p>Foo <em>bar</em>!</p>
</html>
>>> tmpl = MarkupTemplate('''<html xmlns:i18n="http://genshi.edgewall.org/i18n">
...   <div i18n:msg="fname, lname">
...     <p>First Name: ${fname}</p>
...     <p>Last Name: ${lname}</p>
...   </div>
...   <p i18n:msg="">Foo <em>bar</em>!</p>
... </html>''')
>>> translator.setup(tmpl)
>>> list(translator.extract(tmpl.stream)) #doctest: +NORMALIZE_WHITESPACE
[(2, None, u'[1:First Name: %(fname)s]\n    [2:Last Name: %(lname)s]', []),
(6, None, u'Foo [1:bar]!', [])]
>>> tmpl = MarkupTemplate('''<html xmlns:i18n="http://genshi.edgewall.org/i18n">
...   <div i18n:msg="fname, lname">
...     <p>First Name: ${fname}</p>
...     <p>Last Name: ${lname}</p>
...   </div>
...   <p i18n:msg="">Foo <em>bar</em>!</p>
... </html>''')
>>> translator.setup(tmpl)
>>> print(tmpl.generate(fname='John', lname='Doe').render())
<html>
  <div><p>First Name: John</p>
    <p>Last Name: Doe</p></div>
  <p>Foo <em>bar</em>!</p>
</html>

Starting and ending white-space is stripped of to make it simpler for translators. Stripping it is not that important since it's on the html source, the rendered output will remain the same.

attach(cls, template, stream, value, namespaces, pos)

(Not documented)

extract(self, translator, stream, gettext_functions=GETTEXT_FUNCTIONS, search_text=True, comment_stack=None)

(Not documented)

ChooseBranchDirective

(Not documented)

extract(self, translator, stream, gettext_functions=GETTEXT_FUNCTIONS, search_text=True, comment_stack=None, msgbuf=None)

(Not documented)

SingularDirective

Implementation of the i18n:singular directive to be used with the i18n:choose directive.

PluralDirective

Implementation of the i18n:plural directive to be used with the i18n:choose directive.

ChooseDirective

Implementation of the i18n:choose directive which provides plural internationalisation of strings.

This directive requires at least one parameter, the one which evaluates to an integer which will allow to choose the plural/singular form. If you also have expressions inside the singular and plural version of the string you also need to pass a name for those parameters. Consider the following examples:

>>> tmpl = MarkupTemplate('''        <html xmlns:i18n="http://genshi.edgewall.org/i18n">
...   <div i18n:choose="num; num">
...     <p i18n:singular="">There is $num coin</p>
...     <p i18n:plural="">There are $num coins</p>
...   </div>
... </html>''')
>>> translator = Translator()
>>> translator.setup(tmpl)
>>> list(translator.extract(tmpl.stream)) #doctest: +NORMALIZE_WHITESPACE
[(2, 'ngettext', (u'There is %(num)s coin',
                  u'There are %(num)s coins'), [])]
>>> tmpl = MarkupTemplate('''        <html xmlns:i18n="http://genshi.edgewall.org/i18n">
...   <div i18n:choose="num; num">
...     <p i18n:singular="">There is $num coin</p>
...     <p i18n:plural="">There are $num coins</p>
...   </div>
... </html>''')
>>> translator.setup(tmpl)
>>> print(tmpl.generate(num=1).render())
<html>
  <div>
    <p>There is 1 coin</p>
  </div>
</html>
>>> print(tmpl.generate(num=2).render())
<html>
  <div>
    <p>There are 2 coins</p>
  </div>
</html>

When used as a element and not as an attribute:

>>> tmpl = MarkupTemplate('''        <html xmlns:i18n="http://genshi.edgewall.org/i18n">
...   <i18n:choose numeral="num" params="num">
...     <p i18n:singular="">There is $num coin</p>
...     <p i18n:plural="">There are $num coins</p>
...   </i18n:choose>
... </html>''')
>>> translator.setup(tmpl)
>>> list(translator.extract(tmpl.stream)) #doctest: +NORMALIZE_WHITESPACE
[(2, 'ngettext', (u'There is %(num)s coin',
                  u'There are %(num)s coins'), [])]

attach(cls, template, stream, value, namespaces, pos)

(Not documented)

extract(self, translator, stream, gettext_functions=GETTEXT_FUNCTIONS, search_text=True, comment_stack=None)

(Not documented)

DomainDirective

Implementation of the i18n:domain directive which allows choosing another i18n domain(catalog) to translate from.

>>> from genshi.filters.tests.i18n import DummyTranslations
>>> tmpl = MarkupTemplate('''        <html xmlns:i18n="http://genshi.edgewall.org/i18n">
...   <p i18n:msg="">Bar</p>
...   <div i18n:domain="foo">
...     <p i18n:msg="">FooBar</p>
...     <p>Bar</p>
...     <p i18n:domain="bar" i18n:msg="">Bar</p>
...     <p i18n:domain="">Bar</p>
...   </div>
...   <p>Bar</p>
... </html>''')
>>> translations = DummyTranslations({'Bar': 'Voh'})
>>> translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'foo_Bar'})
>>> translations.add_domain('bar', {'Bar': 'bar_Bar'})
>>> translator = Translator(translations)
>>> translator.setup(tmpl)
>>> print(tmpl.generate().render())
<html>
  <p>Voh</p>
  <div>
    <p>BarFoo</p>
    <p>foo_Bar</p>
    <p>bar_Bar</p>
    <p>Voh</p>
  </div>
  <p>Voh</p>
</html>

attach(cls, template, stream, value, namespaces, pos)

(Not documented)

Translator

Can extract and translate localizable strings from markup streams and templates.

For example, assume the following template:

>>> tmpl = MarkupTemplate('''<html xmlns:py="http://genshi.edgewall.org/">
...   <head>
...     <title>Example</title>
...   </head>
...   <body>
...     <h1>Example</h1>
...     <p>${_("Hello, %(name)s") % dict(name=username)}</p>
...   </body>
... </html>''', filename='example.html')

For demonstration, we define a dummy gettext-style function with a hard-coded translation table, and pass that to the Translator initializer:

>>> def pseudo_gettext(string):
...     return {
...         'Example': 'Beispiel',
...         'Hello, %(name)s': 'Hallo, %(name)s'
...     }[string]
>>> translator = Translator(pseudo_gettext)

Next, the translator needs to be prepended to any already defined filters on the template:

>>> tmpl.filters.insert(0, translator)

When generating the template output, our hard-coded translations should be applied as expected:

>>> print(tmpl.generate(username='Hans', _=pseudo_gettext))
<html>
  <head>
    <title>Beispiel</title>
  </head>
  <body>
    <h1>Beispiel</h1>
    <p>Hallo, Hans</p>
  </body>
</html>

Note that elements defining xml:lang attributes that do not contain variable expressions are ignored by this filter. That can be used to exclude specific parts of a template from being extracted and translated.

extract(self, stream, gettext_functions=GETTEXT_FUNCTIONS, search_text=True, comment_stack=None)

Extract localizable strings from the given template stream.

For every string found, this function yields a (lineno, function, message, comments) tuple, where:

  • lineno is the number of the line on which the string was found,
  • function is the name of the gettext function used (if the string was extracted from embedded Python code), and
  • message is the string itself (a unicode object, or a tuple of unicode objects for functions with multiple string arguments).
  • comments is a list of comments related to the message, extracted from i18n:comment attributes found in the markup
>>> tmpl = MarkupTemplate('''<html xmlns:py="http://genshi.edgewall.org/">
...   <head>
...     <title>Example</title>
...   </head>
...   <body>
...     <h1>Example</h1>
...     <p>${_("Hello, %(name)s") % dict(name=username)}</p>
...     <p>${ngettext("You have %d item", "You have %d items", num)}</p>
...   </body>
... </html>''', filename='example.html')
>>> for line, func, msg, comments in Translator().extract(tmpl.stream):
...    print('%d, %r, %r' % (line, func, msg))
3, None, u'Example'
6, None, u'Example'
7, '_', u'Hello, %(name)s'
8, 'ngettext', (u'You have %d item', u'You have %d items', None)
param stream:the event stream to extract strings from; can be a regular stream or a template stream
param gettext_functions:
 a sequence of function names that should be treated as gettext-style localization functions
param search_text:
 whether the content of text nodes should be extracted (used internally)
note:Changed in 0.4.1: For a function with multiple string arguments (such as ngettext), a single item with a tuple of strings is yielded, instead an item for each string argument.
note:Changed in 0.6: The returned tuples now include a fourth element, which is a list of comments for the translator.

get_directive_index(self, dir_cls)

(Not documented)

setup(self, template)

Convenience function to register the Translator filter and the related directives with the given template.

param template:a Template instance

MessageBuffer

Helper class for managing internationalized mixed content.

since:version 0.5

append(self, kind, data, pos)

Append a stream event to the buffer.

param kind:the stream event kind
param data:the event data
param pos:the position of the event in the source

format(self)

Return a message identifier representing the content in the buffer.

translate(self, string, regex=recompile%\((\w+)\)s)

Interpolate the given message translation with the events in the buffer and return the translated stream.

param string:the translated message string

parse_msg(string, regex=recompile(?:\[(\d+)\:)|(?<!\\)\])

Parse a translated message using Genshi mixed content message formatting.

>>> parse_msg("See [1:Help].")
[(0, 'See '), (1, 'Help'), (0, '.')]
>>> parse_msg("See [1:our [2:Help] page] for details.")
[(0, 'See '), (1, 'our '), (2, 'Help'), (1, ' page'), (0, ' for details.')]
>>> parse_msg("[2:Details] finden Sie in [1:Hilfe].")
[(2, 'Details'), (0, ' finden Sie in '), (1, 'Hilfe'), (0, '.')]
>>> parse_msg("[1:] Bilder pro Seite anzeigen.")
[(1, ''), (0, ' Bilder pro Seite anzeigen.')]
param string:the translated message string
return:a list of (order, string) tuples
rtype:list

extract_from_code(code, gettext_functions)

Extract strings from Python bytecode.

>>> from genshi.template.eval import Expression
>>> expr = Expression('_("Hello")')
>>> list(extract_from_code(expr, GETTEXT_FUNCTIONS))
[('_', u'Hello')]
>>> expr = Expression('ngettext("You have %(num)s item", '
...                            '"You have %(num)s items", num)')
>>> list(extract_from_code(expr, GETTEXT_FUNCTIONS))
[('ngettext', (u'You have %(num)s item', u'You have %(num)s items', None))]
param code:the Code object
type code:genshi.template.eval.Code
param gettext_functions:
 a sequence of function names
since:version 0.5

extract(fileobj, keywords, comment_tags, options)

Babel extraction method for Genshi templates.

param fileobj:the file-like object the messages should be extracted from
param keywords:a list of keywords (i.e. function names) that should be recognized as translation functions
param comment_tags:
 a list of translator tags to search for and include in the results
param options:a dictionary of additional options (optional)
return:an iterator over (lineno, funcname, message, comments) tuples
rtype:iterator


See Internationalization and Localization, ApiDocs/0.6.x, Documentation

Last modified 9 years ago Last modified on Dec 7, 2015, 3:29:32 AM