2014-01-31 10:06:52 +01:00
""" i18n_subsites plugin creates i18n-ized subsites of the default site """
import os
import six
import logging
from itertools import chain
2014-02-05 21:28:15 +01:00
from collections import defaultdict , OrderedDict
2014-01-31 10:06:52 +01:00
2014-02-01 20:13:32 +01:00
import gettext
from pelican import signals
2014-01-31 10:06:52 +01:00
from pelican . contents import Page , Article
2014-02-04 15:07:24 +01:00
from pelican . settings import configure_settings
2014-01-31 10:06:52 +01:00
from . _regenerate_context_helpers import regenerate_context_articles
# Global vars
_main_site_generated = False
_main_site_lang = " en "
2014-02-01 20:13:32 +01:00
_main_siteurl = ' '
2014-02-05 21:28:15 +01:00
_lang_siteurls = None
2014-01-31 10:06:52 +01:00
logger = logging . getLogger ( __name__ )
def disable_lang_vars ( pelican_obj ) :
""" Set lang specific url and save_as vars to the non-lang defaults
e . g . ARTICLE_LANG_URL = ARTICLE_URL
They would conflict with this plugin otherwise
"""
2014-02-05 21:28:15 +01:00
global _main_site_lang , _main_siteurl , _lang_siteurls
2014-01-31 10:06:52 +01:00
s = pelican_obj . settings
for content in [ ' ARTICLE ' , ' PAGE ' ] :
for meta in [ ' _URL ' , ' _SAVE_AS ' ] :
s [ content + ' _LANG ' + meta ] = s [ content + meta ]
2014-02-01 20:13:32 +01:00
if not _main_site_generated :
_main_site_lang = s [ ' DEFAULT_LANG ' ]
_main_siteurl = s [ ' SITEURL ' ]
2014-02-05 21:28:15 +01:00
_lang_siteurls = [ ( lang , _main_siteurl + ' / ' + lang ) for lang in s . get ( ' I18N_SUBSITES ' , { } ) . keys ( ) ]
# To be able to use url for main site root when SITEURL == '' (e.g. when developing)
_lang_siteurls = [ ( _main_site_lang , ( ' / ' if _main_siteurl == ' ' else _main_siteurl ) ) ] + _lang_siteurls
_lang_siteurls = OrderedDict ( _lang_siteurls )
2014-01-31 10:06:52 +01:00
2014-02-01 20:13:32 +01:00
2014-01-31 10:06:52 +01:00
def create_lang_subsites ( pelican_obj ) :
""" For each language create a subsite using the lang-specific config
for each generated lang append language subpath to SITEURL and OUTPUT_PATH
and set DEFAULT_LANG to the language code to change perception of what is translated
and set DELETE_OUTPUT_DIRECTORY to False to prevent deleting output from previous runs
Then generate the subsite using a PELICAN_CLASS instance and its run method .
"""
2014-02-01 20:13:32 +01:00
global _main_site_generated
2014-01-31 10:06:52 +01:00
if _main_site_generated : # make sure this is only called once
return
else :
_main_site_generated = True
orig_settings = pelican_obj . settings
for lang , overrides in orig_settings . get ( ' I18N_SUBSITES ' , { } ) . items ( ) :
settings = orig_settings . copy ( )
settings . update ( overrides )
2014-02-05 21:28:15 +01:00
settings [ ' SITEURL ' ] = _lang_siteurls [ lang ]
2014-01-31 10:06:52 +01:00
settings [ ' OUTPUT_PATH ' ] = os . path . join ( orig_settings [ ' OUTPUT_PATH ' ] , lang , ' ' )
settings [ ' DEFAULT_LANG ' ] = lang # to change what is perceived as translations
2014-02-01 20:13:32 +01:00
settings [ ' DELETE_OUTPUT_DIRECTORY ' ] = False # prevent deletion of previous runs
2014-02-04 15:07:24 +01:00
settings = configure_settings ( settings ) # to set LOCALE, etc.
2014-02-01 20:13:32 +01:00
2014-01-31 10:06:52 +01:00
cls = settings [ ' PELICAN_CLASS ' ]
if isinstance ( cls , six . string_types ) :
module , cls_name = cls . rsplit ( ' . ' , 1 )
module = __import__ ( module )
cls = getattr ( module , cls_name )
pelican_obj = cls ( settings )
logger . debug ( " Generating i18n subsite for lang ' {} ' using class ' {} ' " . format ( lang , str ( cls ) ) )
pelican_obj . run ( )
2014-02-04 14:22:54 +01:00
_main_site_generated = False # for autoreload mode
2014-01-31 10:06:52 +01:00
def move_translations_links ( content_object ) :
""" This function points translations links to the sub-sites
by prepending their location with the language code
or directs an original DEFAULT_LANG translation back to top level site
"""
for translation in content_object . translations :
if translation . lang == _main_site_lang :
# cannot prepend, must take to top level
lang_prepend = ' ../ '
else :
lang_prepend = translation . lang + ' / '
translation . override_url = lang_prepend + translation . url
def update_generator_contents ( generator , * args ) :
""" Update the contents lists of a generator
Empty the ( hidden_ ) translation attribute of article and pages generators
to prevent generating the translations as they will be generated in the lang sub - site
and point the content translations links to the sub - sites
Hide content without a translation for current DEFAULT_LANG
if HIDE_UNTRANSLATED_CONTENT is True
"""
generator . translations = [ ]
is_pages_gen = hasattr ( generator , ' pages ' )
if is_pages_gen :
generator . hidden_translations = [ ]
for page in chain ( generator . pages , generator . hidden_pages ) :
move_translations_links ( page )
else : # is an article generator
for article in chain ( generator . articles , generator . drafts ) :
move_translations_links ( article )
2014-02-01 20:13:32 +01:00
2014-01-31 10:06:52 +01:00
if not generator . settings . get ( ' HIDE_UNTRANSLATED_CONTENT ' , True ) :
return
contents = generator . pages if is_pages_gen else generator . articles
2014-02-01 20:13:32 +01:00
hidden_contents = generator . hidden_pages if is_pages_gen else generator . drafts
2014-01-31 10:06:52 +01:00
default_lang = generator . settings [ ' DEFAULT_LANG ' ]
2014-02-04 14:14:43 +01:00
for content_object in contents [ : ] : # loop over copy for removing
2014-01-31 10:06:52 +01:00
if content_object . lang != default_lang :
2014-02-04 14:14:43 +01:00
if isinstance ( content_object , Article ) :
2014-02-01 20:13:32 +01:00
content_object . status = ' draft '
2014-02-04 14:14:43 +01:00
elif isinstance ( content_object , Page ) :
content_object . status = ' hidden '
2014-01-31 10:06:52 +01:00
contents . remove ( content_object )
hidden_contents . append ( content_object )
if not is_pages_gen : # regenerate categories, tags, etc. for articles
2014-02-01 20:13:32 +01:00
if hasattr ( generator , ' _generate_context_aggregate ' ) : # if implemented
2014-01-31 10:06:52 +01:00
# Simulate __init__ for fields that need it
generator . dates = { }
generator . tags = defaultdict ( list )
generator . categories = defaultdict ( list )
generator . authors = defaultdict ( list )
generator . _generate_context_aggregate ( )
else : # fallback for Pelican 3.3.0
regenerate_context_articles ( generator )
2014-02-01 20:13:32 +01:00
def install_templates_translations ( generator ) :
""" Install gettext translations for current DEFAULT_LANG in the jinja2.Environment
if the ' jinja2.ext.i18n ' jinja2 extension is enabled
adds some useful variables into the template context
"""
generator . context [ ' main_siteurl ' ] = _main_siteurl
generator . context [ ' main_lang ' ] = _main_site_lang
2014-02-05 21:28:15 +01:00
generator . context [ ' lang_siteurls ' ] = _lang_siteurls
2014-02-03 19:23:43 +01:00
current_def_lang = generator . settings [ ' DEFAULT_LANG ' ]
2014-02-05 21:28:15 +01:00
extra_siteurls = _lang_siteurls . copy ( )
2014-02-03 19:23:43 +01:00
extra_siteurls . pop ( current_def_lang )
2014-02-01 20:13:32 +01:00
generator . context [ ' extra_siteurls ' ] = extra_siteurls
if ' jinja2.ext.i18n ' not in generator . settings [ ' JINJA_EXTENSIONS ' ] :
return
domain = generator . settings . get ( ' I18N_GETTEXT_DOMAIN ' , ' messages ' )
localedir = generator . settings . get ( ' I18N_GETTEXT_LOCALEDIR ' )
if localedir is None :
2014-02-04 14:22:54 +01:00
localedir = os . path . join ( generator . theme , ' translations ' )
2014-02-03 19:23:43 +01:00
if current_def_lang == generator . settings . get ( ' I18N_TEMPLATES_LANG ' , _main_site_lang ) :
2014-02-01 20:13:32 +01:00
translations = gettext . NullTranslations ( )
2014-02-03 19:23:43 +01:00
else :
languages = [ current_def_lang ]
try :
translations = gettext . translation ( domain , localedir , languages )
except ( IOError , OSError ) :
logger . error ( " Cannot find translations for language ' {} ' in ' {} ' with domain ' {} ' . Installing NullTranslations. " . format ( languages [ 0 ] , localedir , domain ) )
translations = gettext . NullTranslations ( )
2014-02-01 20:13:32 +01:00
newstyle = generator . settings . get ( ' I18N_GETTEXT_NEWSTYLE ' , True )
generator . env . install_gettext_translations ( translations , newstyle )
2014-01-31 10:06:52 +01:00
def register ( ) :
signals . initialized . connect ( disable_lang_vars )
2014-02-01 20:13:32 +01:00
signals . generator_init . connect ( install_templates_translations )
2014-01-31 10:06:52 +01:00
signals . article_generator_finalized . connect ( update_generator_contents )
signals . page_generator_finalized . connect ( update_generator_contents )
signals . finalized . connect ( create_lang_subsites )