tower icon indicating copy to clipboard operation
tower copied to clipboard

A library that builds on Babel and Jinja to make extracting strings easy and uniform

===== Tower

.. image:: https://secure.travis-ci.org/clouserw/tower.png?branch=master :alt: Build Status :target: https://secure.travis-ci.org/clouserw/tower

Tower provides some additional functionality to Jinja and it's i18n extension, and the Babel library.

  • Author: Wil Clouser and contributors_
  • Licence: BSD
  • Compatibility: Python 2.6 and 2.7, Django 1.4, 1.5 and 1.6
  • Requirements: django, babel, jinja2, jingo and translate-toolkit
  • Project URL: https://github.com/clouserw/tower
  • Documentation: http://tower.readthedocs.org/en/latest/

.. _contributors: https://github.com/clouserw/tower/contributors

Specifics:

  • Pulls strings from a variety of sources: Python, JavaScript, and .lhtml files.
  • Collapses whitespace in all strings to prevent unwieldy msgids.
  • Supports Gettext context (msgctxt) in all gettext, and ngettext calls.
  • Supports merging PHP and Python .pot files. This is temporary. If you want to support that for an extended time look at phppo2pypo in the Translate Toolkit <http://translate.sourceforge.net/>_.

Requirements

  • Django
  • Babel
  • Jinja2 and Jingo
  • translate-toolkit

See requirements.txt <https://github.com/clouserw/tower/blob/master/requirements.txt>_ for details.

Installation

Install from pypi with::

pip install tower

Source code is at <http://github.com/clouserw/tower>_.

Install from GitHub with::

pip install -e git://github.com/clouserw/tower.git#egg=tower

Configure

Add to INSTALLED_APPS in your Django settings file::

INSTALLED_APPS = (
    # ...
    'tower',
    # ...
)

Then configure.

django.conf.settings.DOMAIN_METHODS

**Default:** None--you must set this.

The value is a dict of domain to file spec and extraction method tuples.

For example, this creates a domain "messages" and in that domain
extracts all the l10n strings from .py and .html files::

    DOMAIN_METHODS = {
        'messages': [
            ('fjord/**.py', 'tower.extract_tower_python'),
            ('fjord/**.html', 'tower.extract_tower_template'),
        ]
    }

Use ``tower.extract_tower_python`` for Python files and
``tower.extract_tower_template`` for Jinja2 templates.

The l10n strings will be saved in a .pot file with the name of the
domain. In the above example, it'd be ``messages.pot``.

django.conf.settings.STANDALONE_DOMAINS

**Default:** ``['messages']``

By default, all domains specified in ``DOMAIN_METHODS`` get merged
into one big .pot file. If you don't want that, you can specify
which domains get their own .pot file with ``STANDALONE_DOMAINS``.

django.conf.settings.TOWER_KEYWORDS

Gettext keywords are the actual names of the functions your application uses
to denote strings which should be extracted.  Babel defines a sane default
list in `DEFAULT_KEYWORDS
<https://github.com/mitsuhiko/babel/blob/af983/babel/messages/extract.py#L31>`_
which includes the regulars like _(), gettext(), ngettext(), etc.  If your
app uses different functions you'll need to define them here.  This setting
is a dictionary and the value follows `gettext's keywordspec
<http://www.gnu.org/software/gettext/manual/gettext.html#index-adding-keywords_002c-xgettext>`_.

If you set this, it is *merged* with Babel's DEFAULT_KEYWORDS setting.

Example::

    # We lazy load strings in our classes so we can cache them and they are
    # still localized in the right language for the end user.  This will let
    # us use _lazy('Localized string').
    TOWER_KEYWORDS = {
        '_lazy': None,
    }

django.conf.settings.TOWER_ADD_HEADERS

**Default:** False

If you have trouble extracting strings with Tower, try setting this
to True.

django.conf.settings.ROOT

This points to the source code directory where you want your
``locale/`` directory to be.

django.conf.settings.path

This is a function that takes arbitrary set of args and combines
them with ``ROOT`` to form a new path.

Example::

    import os

    # The settings file is in fjord/fjord/settings/base.py. From
    # base, up two directories is the initial fjord directory
    # which is where all the source code and the fjord Django
    # project are.
    ROOT = os.path.dirname(os.path.dirname(__file__))

    path = lambda *args: os.path.abspath(os.path.join(ROOT, *args))

django.conf.settings.TOWER_INSTALL_JINJA_TRANSLATIONS

**Default:** True

By default tower will ensure it's gettext and ngettext functions are
installed into Jinja2 on every call to ``tower.activate()``.  You likely
want this, but if you need to provide your own gettext and ngettext
functions, set this to ``False``, and in your project call
``jingo.env.install_gettext_translations`` or
``jingo.env.install_gettext_callables``.

Usage

Extract::

./manage.py extract

Merge::

./manage.py merge

A note on whitespace

When tower extracts strings, it collapses whitespace. This makes it easier for localizers. It also means you need to use ugettext, ungettext, ugettext_lazy and ungettext_lazy from tower. Otherwise the msgids being passed in won't have their whitespace stripped and thus won't match anything in your .mo file.

A note on safe-ness

L10n strings are marked "safe" for Jinja2 automatically, so they will not be HTML-escaped::

{{ _('Hello <strong>World</strong>') }}

This works as expected. When interpolating into an L10n string, however, it will be marked as "unsafe" and escaped, unless you use jingo's <https://github.com/jbalogh/jingo/>_ |fe() helper (which will escape the arguments but not the string they are interpolated into). Like this::

{{ _('Hello <strong>{0}</strong>')|fe(user.nickname) }}

Run tests

Run::

python run_tests.py

To test on all supported versions of Python and Django::

$ pip install tox
$ tox