localizing_using_jinja2.rst 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. -----------------------------
  2. Localizing themes with Jinja2
  3. -----------------------------
  4. 1. Localize templates
  5. ---------------------
  6. To enable the |ext| extension in your templates, you must add it to
  7. *JINJA_EXTENSIONS* in your Pelican configuration
  8. .. code-block:: python
  9. JINJA_EXTENSIONS = ['jinja2.ext.i18n', ...]
  10. Then follow the `Jinja2 templating documentation for the I18N plugin <http://jinja.pocoo.org/docs/templates/#i18n>`_ to make your templates localizable. This usually means surrounding strings with the ``{% trans %}`` directive or using ``gettext()`` in expressions
  11. .. code-block:: jinja
  12. {% trans %}translatable content{% endtrans %}
  13. {{ gettext('a translatable string') }}
  14. For pluralization support, etc. consult the documentation
  15. To enable `newstyle gettext calls <http://jinja.pocoo.org/docs/extensions/#newstyle-gettext>`_ the *I18N_GETTEXT_NEWSTYLE* config variable must be set to ``True`` (default).
  16. .. |ext| replace:: ``jinja2.ext.i18n``
  17. 2. Specify translations location
  18. --------------------------------
  19. The |ext| extension uses the `Python gettext library <http://docs.python.org/library/gettext.html>`_ for translating strings.
  20. In your Pelican config you can give the path in which to look for translations in the *I18N_GETTEXT_LOCALEDIR* variable. If not given, it is assumed to be the ``translations`` subfolder in the top folder of the theme specified by *THEME*.
  21. The domain of the translations (the name of each translation file is ``domain.mo``) is controlled by the *I18N_GETTEXT_DOMAIN* config variable (defaults to ``messages``).
  22. Example
  23. .......
  24. With the following in your Pelican settings file
  25. .. code-block:: python
  26. I18N_GETTEXT_LOCALEDIR = 'some/path/'
  27. I18N_GETTEXT_DOMAIN = 'my_domain'
  28. … the translation for language 'cz' will be expected to be in ``some/path/cz/LC_MESSAGES/my_domain.mo``
  29. 3. Extract translatable strings and translate them
  30. --------------------------------------------------
  31. There are many ways to extract translatable strings and create ``gettext`` compatible translations. You can create the ``*.po`` and ``*.mo`` message catalog files yourself, or you can use some helper tool as described in `the Python gettext library tutorial <http://docs.python.org/library/gettext.html#internationalizing-your-programs-and-modules>`_.
  32. You of course don't need to provide a translation for the language in which the templates are written which is assumed to be the original *DEFAULT_LANG*. This can be overridden in the *I18N_TEMPLATES_LANG* variable.
  33. Recommended tool: babel
  34. .......................
  35. `Babel <http://babel.pocoo.org/>`_ makes it easy to extract translatable strings from the localized Jinja2 templates and assists with creating translations as documented in this `Jinja2-Babel tutorial <http://pythonhosted.org/Flask-Babel/#translating-applications>`_ [#flask]_ on which the following is based.
  36. 1. Add babel mapping
  37. ~~~~~~~~~~~~~~~~~~~~
  38. Let's assume that you are localizing a theme in ``themes/my_theme/`` and that you use the default settings, i.e. the default domain ``messages`` and will put the translations in the ``translations`` subdirectory of the theme directory as ``themes/my_theme/translations/``.
  39. It is up to you where to store babel mappings and translation files templates (``*.pot``), but a convenient place is to put them in ``themes/my_theme/`` and work in that directory. From now on let's assume that it will be our current working directory (CWD).
  40. To tell babel to extract translatable strings from the templates create a mapping file ``babel.cfg`` with the following line
  41. .. code-block:: cfg
  42. [jinja2: ./templates/**.html]
  43. 2. Extract translatable strings from templates
  44. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  45. Run the following command to create a ``messages.pot`` message catalog template file from extracted translatable strings
  46. .. code-block:: bash
  47. pybabel extract --mapping babel.cfg --output messages.pot ./
  48. 3. Initialize message catalogs
  49. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  50. If you want to translate the template to language ``lang``, run the following command to create a message catalog
  51. ``translations/lang/LC_MESSAGES/messages.po`` using the template ``messages.pot``
  52. .. code-block:: bash
  53. pybabel init --input-file messages.pot --output-dir translations/ --locale lang --domain messages
  54. babel expects ``lang`` to be a valid locale identifier, so if e.g. you are translating for language ``cz`` but the corresponding locale is ``cs``, you have to use the locale identifier. Nevertheless, the gettext infrastructure should later correctly find the locale for a given language.
  55. 4. Fill the message catalogs
  56. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  57. The message catalog files format is quite intuitive, it is fully documented in the `GNU gettext manual <http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files>`_. Essentially, you fill in the ``msgstr`` strings
  58. .. code-block:: po
  59. msgid "just a simple string"
  60. msgstr "jenom jednoduchý řetězec"
  61. msgid ""
  62. "some multiline string"
  63. "looks like this"
  64. msgstr ""
  65. "nějaký více řádkový řetězec"
  66. "vypadá takto"
  67. You might also want to remove ``#,fuzzy`` flags once the translation is complete and reviewed to show that it can be compiled.
  68. 5. Compile the message catalogs
  69. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  70. The message catalogs must be compiled into binary format using this command
  71. .. code-block:: bash
  72. pybabel compile --directory translations/ --domain messages
  73. This command might complain about "fuzzy" translations, which means you should review the translations and once done, remove the fuzzy flag line.
  74. (6.) Update the catalogs when templates change
  75. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  76. If you add any translatable patterns into your templates, you have to update your message catalogs too.
  77. First you extract a new message catalog template as described in the 2. step. Then you run the following command [#pybabel_error]_
  78. .. code-block:: bash
  79. pybabel update --input-file messages.pot --output-dir translations/ --domain messages
  80. This will merge the new patterns with the old ones. Once you review and fill them, you have to recompile them as described in the 5. step.
  81. .. [#flask] Although the tutorial is focused on Flask-based web applications, the linked translation tutorial is not Flask-specific.
  82. .. [#pybabel_error] If you get an error ``TypeError: must be str, not bytes`` with Python 3.3, it is likely you are suffering from this `bug <https://github.com/mitsuhiko/flask-babel/issues/43>`_. Until the fix is released, you can use babel with Python 2.7.