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 conf.py:

    # [1] http://ablog.readthedocs.org/manual/ablog-configuration-options/#confval-blog_default_language
    blog_default_language = 'en'
    
    # [2] http://sphinx-doc.org/config.html#confval-language
    # ATTENTION:
    #   This option 'language' must be present. Otherwise Sphinx doesn't invoke translation services at all.
    language = blog_default_language
    
    # [3] http://ablog.readthedocs.org/manual/ablog-configuration-options/#confval-blog_languages
    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/blog.py:

    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.app.ablog = self
    
         # prepare a dictionary with translators for the blog languages
         self.translators = {}
         if self.app:
            # construct locale_dirs in the same way Sphinx does
            from sphinx import package_dir, locale
            if self.app.config.language is not None:
               locale_dirs = ([None, os.path.join(package_dir, 'locale')] +
                  [os.path.join(self.app.srcdir, x) for x in self.app.config.locale_dirs])
            else:
               locale_dirs = []
    
            for language in self.app.config.blog_languages.keys():
               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/__init__.py:

    from .post import ( # ...PostDirective, PostListDirective, UpdateDirective,
                        html_page_context)
    
    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/post.py we add:

    # coming from:
    #    self.app.emit('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
        else:
            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

Tags

Archives

Languages

Recent Posts

This Page