Sep 19, 2014 Tag: Ablog

Per Page Internationalization for ABlog

ABlog is Ahmet Bakan’s fantastic Sphinx extension for creating blogs. At the moment as of version 0.3 it lacks support for switching languages on a per post or per page basis. ABlog is OpenSource software and available from Github.This post offers a working solution.

Here we go:

  1. Provide some settings in the Sphinx configuration data in

    # [1]
    blog_default_language = 'en'
    # [2]
    #   This option 'language' must be present. Otherwise Sphinx doesn't invoke translation services at all.
    language = blog_default_language
    # [3]
    blog_languages = {
       'en': (u'English', None),
       'de': (u'Deutsch', None),

    [1] blog_default_language, [2] language, [3] blog_languages

  2. Some more preparations: At the end of the Blog constructor we create a translator instance for each blog language. In ablog/

    class Blog(object):
     """Handle blog operations."""
     # ...
     def _init(self, app):
         """Instantiate Blog."""
         # ...
         # add our Blog instance to the application so we can find it
         # when coming from the application = self
         # prepare a dictionary with translators for the blog languages
         self.translators = {}
            # construct locale_dirs in the same way Sphinx does
            from sphinx import package_dir, locale
            if is not None:
               locale_dirs = ([None, os.path.join(package_dir, 'locale')] +
                  [os.path.join(, x) for x in])
               locale_dirs = []
            for language in
               translator, has_translation = locale.init(locale_dirs, language)
               self.translators[language] = translator if has_translation else None
  3. Specify the language of a post in the post directive:

    .. post:: Sep 19, 2014
       :language: de
  4. For normal pages (non-posts) specify the language in the document’s metadata. Internally the builder can access this metadata.

    .. coding: -*- utf-8 -*- ÄÖÜ
    .. the following meta data must appear BEFORE anything else
       and BEFORE the page title
    :language:  de
    :orphan:    yes
    Page title

    Tip: Add the :orphan: field too to suppress Sphinx’s warning that a document isn’t included in any toctree.

  5. Each document is rendered in its individual context. We can hook into the procedure of setting that up. In ablog/

    from .post import ( # ...PostDirective, PostListDirective, UpdateDirective,
    def setup(app):
    """Setup ABlog extension."""
       # ...
       app.connect('html-page-context', html_page_context)
  6. Now let’s tweak the context of a document’s rendering process. We provide htmllang, a variable with a value like ‘en’ or ‘de’ that denotes the language of the page contents. And, if available, we provide the gettext() function for that language. In ablog/ we add:

    # coming from:
    #'html-page-context', pagename, templatename, ctx, event_arg)
    # with arguments:
    #    app, pagename, templatename, ctx, event_arg
    def html_page_context(app, docname, templatename, ctx, *args, **kwargs):
        htmllang = app.config.blog_default_language
        postinfo = app.env.ablog_posts.get(docname)
        # is it a post?
        if postinfo:
            languages = postinfo[0].get('language')
            if languages:
                htmllang = languages[0]
        # query the documents metadata otherwise
            htmllang = app.env.metadata.get(docname, {}).get('language', htmllang)
        ctx['htmllang'] = htmllang
        translator = app.ablog.translators.get(htmllang)
        if translator:
            ctx['gettext'] = translator.gettext

I’m using this technique in this blog - it works :-)

What do you think?

Previous topic

A Decoder for objects.inv

Next topic

More on ABlog Internationalization




Recent Posts

This Page