Mercurial > genshi > mirror
changeset 885:b7e8b971d90a trunk
Started extending the i18n docs.
author | cmlenz |
---|---|
date | Fri, 16 Apr 2010 22:31:38 +0000 |
parents | e97cdbf09a18 |
children | 13017f59f5ea |
files | doc/i18n.txt doc/loader.txt |
diffstat | 2 files changed, 208 insertions(+), 26 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/i18n.txt +++ b/doc/i18n.txt @@ -5,14 +5,14 @@ ===================================== Genshi provides basic supporting infrastructure for internationalizing -and localizing templates. That includes functionality for extracting localizable -strings from templates, as well as a template filter that can apply translations -to templates as they get rendered. +and localizing templates. That includes functionality for extracting +localizable strings from templates, as well as a template filter that can +apply translations to templates as they get rendered. 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. +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. .. _`gettext`: http://www.gnu.org/software/gettext/ .. _`gettext python module`: http://docs.python.org/lib/module-gettext.html @@ -28,14 +28,15 @@ ====== The simplest way to internationalize and translate templates would be to wrap -all localizable strings in a ``gettext()`` function call (which is often aliased -to ``_()`` for brevity). In that case, no extra template filter is required. +all localizable strings in a ``gettext()`` function call (which is often +aliased to ``_()`` for brevity). In that case, no extra template filter is +required. .. code-block:: genshi <p>${_("Hello, world!")}</p> -However, this approach results in significant “character noise” in templates, +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 @@ -48,23 +49,28 @@ This text will still be extracted and translated as if you had wrapped it in a ``_()`` call. -.. note:: For parameterized or pluralizable messages, you need to continue using - the appropriate ``gettext`` functions. +.. note:: For parameterized or pluralizable messages, you need to use the + special `template directives`_ described below, or use the + corresponding ``gettext`` function in embedded Python expressions. -You can control which tags should be ignored by this process; for example, it +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 ``<script></script>`` element. Both ``<script>`` and ``<style>`` are excluded by default. 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 attribute -names, or none at all. +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 +attribute names, or none at all. -In addition, you can control automatic translation in your templates using the -``xml:lang`` attribute. If the value of that attribute is a literal string, the -contents and attributes of the element will be ignored: +---------------- +Language Tagging +---------------- + +You can control automatic translation in your templates using the ``xml:lang`` +attribute. If the value of that attribute is a literal string, the contents and +attributes of the element will be ignored: .. code-block:: genshi @@ -81,6 +87,182 @@ </html> +.. _`template directives`: + +Template Directives +=================== + +Sometimes localizable strings in templates may contain dynamic parameters, or +they may depend on the numeric value of some variable to choose a proper +plural form. Sometimes the strings contain embedded markup, such as tags for +emphasis or hyperlinks, and you don't want to rely on the people doing the +translations to know the syntax and escaping rules of HTML and XML. + +In those cases the simple text extraction and translation process described +above is not sufficient. You could just use ``gettext`` API functions in +embedded Python expressions for parameters and pluralization, but Genshi also +provides special template directives for internationalization that attempt to +provide a comprehensive solution for this problem space. + +To enable these directives, you'll need to register them with the templates +they are used in. You can do this by adding them manually via the +``Template.add_directives(namespace, factory)`` (where ``namespace`` would be +“http://genshi.edgewall.org/i18n” and ``factory`` would be an instance of the +``Translator`` class). Or you can just call the ``Translator.setup(template)`` +class method, which both registers the directives and adds the translation +filter. + +.. note:: The internationalization directives are still somewhat experimental + and have some known issues. However, the attribute language they + implement should be stable and is not subject to change + substantially in future versions. + + +-------- +Messages +-------- + +``i18n:msg`` +------------ + +This is the basic directive for defining localizable text passages that +contain parameters and/or markup. + +For example, consider the following template snippet: + +.. code-block:: genshi + + <p> + Please visit <a href="${site.url}">${site.name}</a> for help. + </p> + +Without further annotation, the translation filter would treat this sentence +as two separate messages (“Please click” and “here”), and the translator would +have no control over the position of the link in the sentence. + +However, when you use the Genshi internationalization directives, you simply +add an ``i18n:msg`` attribute to the enclosing ``<p>`` element: + +.. code-block:: genshi + + <p i18n:msg="name"> + Please visit <a href="${site.url}">${site.name}</a> for help. + </p> + +Genshi is then able to identify the text in the ``<p>`` element as a single +message for translation purposes. You'll see the following string in your +message catalog:: + + Please visit [1:%(name)s] for help. + +The `<a>` element with its attribute has been replaced by a part in square +brackets, which does not include the tag name or the attributes of the element. + +The value of the ``i18n:msg`` attribute is a comma-separated list of parameter +names, which serve as simplified aliases for the actual Python expressions the +message contains. The order of the paramer names in the list must correspond +to the order of the expressions in the text. In this example, there is only +one parameter: its alias for translation is “name”, while the corresponding +expression is ``${site.name}``. + +The translator now has complete control over the structure of the sentence. He +or she certainly does need to make sure that any bracketed parts are not +removed, and that the ``name`` parameter is preserved correctly. But those are +things that can be easily checked by validating the message catalogs. The +important thing is that the translator can change the sentence structure, and +has no way to break the application by forgetting to close a tag, for example. + +So if the German translator of this snippet decided to translate it to:: + + Um Hilfe zu erhalten, besuchen Sie bitte [1:%(name)s] + +The resulting output might be: + +.. code-block:: html + + <p> + Um Hilfe zu erhalten, besuchen Sie bitte + <a href="http://example.com/">Example</a> + </p> + +Please note that messages may contain multiple tags, and they may also be +nested. For example: + +.. code-block:: genshi + + <p i18n:msg="name"> + <i>Please</i> visit <b>the site <a href="${site.url}">${site.name}</a></b> + for help. + </p> + +This would result in the following message ID:: + + [1:Please] visit [2:the site [3:%(name)s]] for help. + +Again, the translator has full control over the structure of the sentence. So +the German translation could actually look like this:: + + Um Hilfe zu erhalten besuchen Sie [1:bitte] + [3:%(name)s], [2:das ist eine Web-Site] + +Which Genshi would recompose into the following outout: + +.. code-block:: html + + <p> + Um Hilfe zu erhalten besuchen Sie <i>bitte</i> + <a href="http://example.com/">Example</a>, <b>das ist eine Web-Site</b> + </p> + +Note how the translation has changed the order and even the nesting of the +tags. + +.. warning:: Please note that ``i18n:msg`` directives do not support other + nested directives. Directives commonly change the structure of + the generated markup dynamically, which often would result in the + structure of the text changing, thus making translation as a + single message ineffective. + +``i18n:comment`` +---------------- + +The ``i18n:comment`` directive can be used to supply a comment for the +translator. For example, if a template snippet is not easily understood +outside of its context, you can add a translator comment to help the +translator understand in what context the message will be used: + +.. code-block:: genshi + + <p i18n:msg="name" i18n:comment="Link to the relevant support site"> + Please visit <a href="${site.url}">${site.name}</a> help. + </p> + +This comment will be extracted together with the message itself, and will +commonly be placed along the message in the message catalog, so that it is +easily visible to the person doing the translation. + +This directive has no impact on how the template is rendered, and is ignored +outside of the extraction process. + + +------------- +Pluralization +------------- + +``i18n:choose``, ``i18n:singular``, ``i18n:plural`` +--------------------------------------------------- + +TODO + +------------------- +Translation Domains +------------------- + +``i18n:domain`` +--------------- + +TODO + Extraction ========== @@ -90,7 +272,11 @@ as well as strings in ``gettext()`` calls in embedded Python code. See the API documentation for details on how to use this method directly. -This functionality is integrated into the message extraction framework provided +----------------- +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 `Distutils`_. @@ -123,10 +309,6 @@ If all goes well, running the extraction with Babel should create a POT file containing the strings from your Genshi templates and your Python source files. -.. note:: Genshi currently does not support “translator comments”, i.e. text in - template comments that would get added to the POT file. This support - may or may not be added in future versions. - --------------------- Configuration Options @@ -202,7 +384,7 @@ from genshi.template import TemplateLoader def template_loaded(template): - template.filters.insert(0, Translator(translations.ugettext)) + Translator(translations.ugettext).setup(template) loader = TemplateLoader('templates', callback=template_loaded) template = loader.load('test.html')
--- a/doc/loader.txt +++ b/doc/loader.txt @@ -102,7 +102,7 @@ from genshi.template import TemplateLoader def template_loaded(template): - template.filters.insert(0, Translator(translations.ugettext)) + Translator(translations.ugettext).setup(template) loader = TemplateLoader('templates', callback=template_loaded)