merge of '5b4836353e90a3c1e388a18fe4184b748f920317'

and '6fd06d2ac31dd55d96ed51f368f4b3cf5c5faef0'
This commit is contained in:
str4d
2013-07-15 11:21:34 +00:00
19 changed files with 262 additions and 23 deletions

2
.mtn-ignore Normal file
View File

@@ -0,0 +1,2 @@
env
pots

View File

@@ -1,10 +1,73 @@
[I2P.website] [I2P.website_about]
source_file = ./messages.pot source_file = ./pots/about.pot
source_lang = en source_lang = en
trans.de = i2p2www/translations/de/LC_MESSAGES/messages.po trans.de = i2p2www/translations/de/LC_MESSAGES/about.po
trans.es = i2p2www/translations/es/LC_MESSAGES/messages.po trans.es = i2p2www/translations/es/LC_MESSAGES/about.po
trans.fr = i2p2www/translations/fr/LC_MESSAGES/messages.po trans.fr = i2p2www/translations/fr/LC_MESSAGES/about.po
trans.sv_SE = i2p2www/translations/sv/LC_MESSAGES/messages.po trans.sv_SE = i2p2www/translations/sv/LC_MESSAGES/about.po
type = PO
[I2P.website_blog]
source_file = ./pots/blog.pot
source_lang = en
trans.de = i2p2www/translations/de/LC_MESSAGES/blog.po
trans.es = i2p2www/translations/es/LC_MESSAGES/blog.po
trans.fr = i2p2www/translations/fr/LC_MESSAGES/blog.po
trans.sv_SE = i2p2www/translations/sv/LC_MESSAGES/blog.po
type = PO
[I2P.website_comparison]
source_file = ./pots/comparison.pot
source_lang = en
trans.de = i2p2www/translations/de/LC_MESSAGES/comparison.po
trans.es = i2p2www/translations/es/LC_MESSAGES/comparison.po
trans.fr = i2p2www/translations/fr/LC_MESSAGES/comparison.po
trans.sv_SE = i2p2www/translations/sv/LC_MESSAGES/comparison.po
type = PO
[I2P.website_docs]
source_file = ./pots/docs.pot
source_lang = en
trans.de = i2p2www/translations/de/LC_MESSAGES/docs.po
trans.es = i2p2www/translations/es/LC_MESSAGES/docs.po
trans.fr = i2p2www/translations/fr/LC_MESSAGES/docs.po
trans.sv_SE = i2p2www/translations/sv/LC_MESSAGES/docs.po
type = PO
[I2P.website_get-involved]
source_file = ./pots/get-involved.pot
source_lang = en
trans.de = i2p2www/translations/de/LC_MESSAGES/get-involved.po
trans.es = i2p2www/translations/es/LC_MESSAGES/get-involved.po
trans.fr = i2p2www/translations/fr/LC_MESSAGES/get-involved.po
trans.sv_SE = i2p2www/translations/sv/LC_MESSAGES/get-involved.po
type = PO
[I2P.website_misc]
source_file = ./pots/misc.pot
source_lang = en
trans.de = i2p2www/translations/de/LC_MESSAGES/misc.po
trans.es = i2p2www/translations/es/LC_MESSAGES/misc.po
trans.fr = i2p2www/translations/fr/LC_MESSAGES/misc.po
trans.sv_SE = i2p2www/translations/sv/LC_MESSAGES/misc.po
type = PO
[I2P.website_priority]
source_file = ./pots/priority.pot
source_lang = en
trans.de = i2p2www/translations/de/LC_MESSAGES/priority.po
trans.es = i2p2www/translations/es/LC_MESSAGES/priority.po
trans.fr = i2p2www/translations/fr/LC_MESSAGES/priority.po
trans.sv_SE = i2p2www/translations/sv/LC_MESSAGES/priority.po
type = PO
[I2P.website_research]
source_file = ./pots/research.pot
source_lang = en
trans.de = i2p2www/translations/de/LC_MESSAGES/research.po
trans.es = i2p2www/translations/es/LC_MESSAGES/research.po
trans.fr = i2p2www/translations/fr/LC_MESSAGES/research.po
trans.sv_SE = i2p2www/translations/sv/LC_MESSAGES/research.po
type = PO type = PO
[main] [main]

2
babel.cfg/about Normal file
View File

@@ -0,0 +1,2 @@
[jinja2: **/pages/site/about/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_,i2p2www.extensions.HighlightExtension

2
babel.cfg/blog Normal file
View File

@@ -0,0 +1,2 @@
[jinja2: **/blog/**.rst]
extensions=jinja2.ext.autoescape,jinja2.ext.with_

2
babel.cfg/comparison Normal file
View File

@@ -0,0 +1,2 @@
[jinja2: **/pages/site/comparison/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_,i2p2www.extensions.HighlightExtension

2
babel.cfg/docs Normal file
View File

@@ -0,0 +1,2 @@
[jinja2: **/pages/site/docs/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_,i2p2www.extensions.HighlightExtension

2
babel.cfg/get-involved Normal file
View File

@@ -0,0 +1,2 @@
[jinja2: **/pages/site/get-involved/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_,i2p2www.extensions.HighlightExtension

2
babel.cfg/misc Normal file
View File

@@ -0,0 +1,2 @@
[jinja2: **/pages/site/misc/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_,i2p2www.extensions.HighlightExtension

12
babel.cfg/priority Normal file
View File

@@ -0,0 +1,12 @@
[jinja2: **/pages/blog/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_,i2p2www.extensions.HighlightExtension
[jinja2: **/pages/downloads/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_,i2p2www.extensions.HighlightExtension
[jinja2: **/pages/global/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_,i2p2www.extensions.HighlightExtension
[jinja2: **/pages/global/macros]
extensions=jinja2.ext.autoescape,jinja2.ext.with_
[jinja2: **/pages/meetings/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_,i2p2www.extensions.HighlightExtension
[jinja2: **/pages/site/*.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_,i2p2www.extensions.HighlightExtension

2
babel.cfg/research Normal file
View File

@@ -0,0 +1,2 @@
[jinja2: **/pages/site/research/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_,i2p2www.extensions.HighlightExtension

View File

@@ -1,4 +1,6 @@
#!/bin/sh #!/bin/sh
. ./translation.vars . ./translation.vars
TZ=UTC env/bin/pybabel compile -d $TRANSDIR for domain in $(ls $BABELCFG); do
TZ=UTC env/bin/pybabel compile -D $domain -d $TRANSDIR
done

View File

@@ -1,8 +1,14 @@
#!/bin/sh #!/bin/sh
. ./translation.vars . ./translation.vars
if [ ! -e $POTDIR ]; then
mkdir $POTDIR
fi
for domain in $(ls $BABELCFG); do
TZ=UTC ./pybabel extract --msgid-bugs-address="http://trac.i2p2.de" \ TZ=UTC ./pybabel extract --msgid-bugs-address="http://trac.i2p2.de" \
--project=$PROJECT \ --project=$PROJECT \
--version=$VERSION \ --version=$VERSION \
-F $BABELCFG \ -F $BABELCFG/$domain \
-o $POTFILE $PROJDIR -o $POTDIR/$domain.pot $PROJDIR
done

View File

@@ -32,6 +32,17 @@ SUPPORTED_LANGS = [
# 'el', # 'el',
] ]
DEFAULT_GETTEXT_DOMAIN = 'priority'
GETTEXT_DOMAIN_MAPPING = {
'about': ['about'],
'blog': ['blog'],
'comparison': ['comparison'],
'docs': ['docs'],
'get-involved': ['get-involved'],
'misc': ['misc'],
'research': ['research'],
}
TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), 'pages') TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), 'pages')
STATIC_DIR = os.path.join(os.path.dirname(__file__), 'static') STATIC_DIR = os.path.join(os.path.dirname(__file__), 'static')
BLOG_DIR = os.path.join(os.path.dirname(__file__), 'blog') BLOG_DIR = os.path.join(os.path.dirname(__file__), 'blog')
@@ -50,7 +61,7 @@ class MyFlask(Flask):
app = application = MyFlask('i2p2www', template_folder=TEMPLATE_DIR, static_url_path='/_static', static_folder=STATIC_DIR) app = application = MyFlask('i2p2www', template_folder=TEMPLATE_DIR, static_url_path='/_static', static_folder=STATIC_DIR)
app.debug = bool(os.environ.get('APP_DEBUG', 'False')) app.debug = bool(os.environ.get('APP_DEBUG', 'False'))
babel = Babel(app) babel = Babel(app, default_domain='priority')
cache = Cache(app, config={ cache = Cache(app, config={
'CACHE_DEFAULT_TIMEOUT': 600, 'CACHE_DEFAULT_TIMEOUT': 600,
#'CACHE_TYPE': '', # See http://packages.python.org/Flask-Cache/#configuring-flask-cache #'CACHE_TYPE': '', # See http://packages.python.org/Flask-Cache/#configuring-flask-cache
@@ -67,7 +78,22 @@ def get_locale():
return g.lang return g.lang
# otherwise try to guess the language from the user accept # otherwise try to guess the language from the user accept
# header the browser transmits. The best match wins. # header the browser transmits. The best match wins.
return request.accept_languages.best_match(['en', 'es', 'zh', 'de', 'fr', 'it', 'nl', 'ru', 'sv', 'cs', 'ar']) return request.accept_languages.best_match(SUPPORTED_LANGS)
@babel.domainselector
def get_domains():
domains = []
frags = request.path.split('/', 2)
if len(frags) == 3:
path = frags[2]
for subpath in GETTEXT_DOMAIN_MAPPING:
if path.startswith(subpath):
domains.extend(GETTEXT_DOMAIN_MAPPING[subpath])
# Always end with the priority domain, as it contains
# various template strings and is likely to be the most
# up-to-date (in case of any common translation strings).
domains.append(DEFAULT_GETTEXT_DOMAIN)
return domains
########################## ##########################

View File

@@ -1,7 +0,0 @@
[python: **.py]
[jinja2: **/pages/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_,i2p2www.extensions.HighlightExtension
[jinja2: **/pages/global/macros]
extensions=jinja2.ext.autoescape,jinja2.ext.with_
[jinja2: **/blog/**.rst]
extensions=jinja2.ext.autoescape,jinja2.ext.with_

View File

@@ -3,7 +3,9 @@
if [ $# -ge 1 ] if [ $# -ge 1 ]
then then
TZ=UTC env/bin/pybabel init -i $POTFILE -d $TRANSDIR -l $1 for domain in $(ls $BABELCFG); do
TZ=UTC env/bin/pybabel init -D $domain -i $POTDIR/$domain.pot -d $TRANSDIR -l $1
done
else else
echo "Usage: ./init-new-po.sh lang" echo "Usage: ./init-new-po.sh lang"
fi fi

115
multi-domain.patch Normal file
View File

@@ -0,0 +1,115 @@
--- env/lib/python2.7/site-packages/flaskext/babel.py 2013-07-13 00:00:00 +0000
+++ env/lib/python2.7/site-packages/flaskext/babel.py 2013-07-13 00:00:00 +0000
@@ -19,6 +19,7 @@
from datetime import datetime
from flask import _request_ctx_stack
from babel import dates, numbers, support, Locale
+from gettext import NullTranslations
from werkzeug import ImmutableDict
try:
from pytz.gae import pytz
@@ -55,9 +56,11 @@
})
def __init__(self, app=None, default_locale='en', default_timezone='UTC',
- date_formats=None, configure_jinja=True):
+ date_formats=None, configure_jinja=True,
+ default_domain=support.Translations.DEFAULT_DOMAIN):
self._default_locale = default_locale
self._default_timezone = default_timezone
+ self._default_domain = default_domain
self._date_formats = date_formats
self._configure_jinja = configure_jinja
self.app = app
@@ -77,6 +80,7 @@
app.config.setdefault('BABEL_DEFAULT_LOCALE', self._default_locale)
app.config.setdefault('BABEL_DEFAULT_TIMEZONE', self._default_timezone)
+ app.config.setdefault('BABEL_DEFAULT_DOMAIN', self._default_domain)
if self._date_formats is None:
self._date_formats = self.default_date_formats.copy()
@@ -95,6 +99,7 @@
self.locale_selector_func = None
self.timezone_selector_func = None
+ self.domain_selector_func = None
if self._configure_jinja:
app.jinja_env.filters.update(
@@ -142,6 +147,19 @@
self.timezone_selector_func = f
return f
+ def domainselector(self, f):
+ """Registers a callback function for domain selection. The default
+ behaves as if a function was registered that returns `None` all the
+ time. If `None` is returned, the domain falls back to the one from
+ the configuration.
+
+ This has to return the domain as a list of strings (eg: ``['messages']``)
+ """
+ assert self.domain_selector_func is None, \
+ 'a localeselector function is already registered'
+ self.domain_selector_func = f
+ return f
+
def list_translations(self):
"""Returns a list of all the locales translations exist for. The
@@ -178,6 +196,13 @@
"""
return timezone(self.app.config['BABEL_DEFAULT_TIMEZONE'])
+ @property
+ def default_domain(self):
+ """The default domain from the configuration as instance of a
+ `string` object.
+ """
+ return self.app.config['BABEL_DEFAULT_DOMAIN']
+
def get_translations():
"""Returns the correct gettext translations that should be used for
@@ -191,7 +216,10 @@
translations = getattr(ctx, 'babel_translations', None)
if translations is None:
dirname = os.path.join(ctx.app.root_path, 'translations')
- translations = support.Translations.load(dirname, [get_locale()])
+ locale = get_locale()
+ for domain in get_domains():
+ dt = support.Translations.load(dirname, [locale], domain)
+ translations = dt if translations is None or not hasattr(translations, 'merge') else translations.merge(dt)
ctx.babel_translations = translations
return translations
@@ -243,6 +271,29 @@
return tzinfo
+def get_domains():
+ """Returns the domains that should be used for this request as
+ `list` object. This returns `None` if used outside of
+ a request.
+ """
+ ctx = _request_ctx_stack.top
+ if ctx is None:
+ return None
+ domains = getattr(ctx, 'babel_domains', None)
+ if domains is None:
+ babel = ctx.app.extensions['babel']
+ if babel.domain_selector_func is None:
+ domains = [babel.default_domain]
+ else:
+ rv = babel.domain_selector_func()
+ if rv is None:
+ domains = [babel.default_domain]
+ else:
+ domains = rv
+ ctx.babel_domains = domains
+ return domains
+
+
def refresh():
"""Refreshes the cached timezones and locale information. This can
be used to switch a translation between a request and if you want

View File

@@ -11,4 +11,6 @@ else
. $venv_dir/bin/activate . $venv_dir/bin/activate
pip install -r reqs.txt pip install -r reqs.txt
# Apply multi-domain patch to Flask-Babel
patch -p0 <multi-domain.patch
fi fi

View File

@@ -1,6 +1,6 @@
PROJECT=I2P PROJECT=I2P
VERSION=website VERSION=website
BABELCFG=babel.cfg
POTDIR=pots
PROJDIR=i2p2www PROJDIR=i2p2www
BABELCFG=$PROJDIR/babel.cfg
POTFILE=messages.pot
TRANSDIR=$PROJDIR/translations TRANSDIR=$PROJDIR/translations

View File

@@ -1,4 +1,6 @@
#!/bin/sh #!/bin/sh
. ./translation.vars . ./translation.vars
TZ=UTC env/bin/pybabel update -i $POTFILE -d $TRANSDIR for domain in $(ls $BABELCFG); do
TZ=UTC env/bin/pybabel update -D $domain -i $POTDIR/$domain.pot -d $TRANSDIR
done