python-babel / babel

The official repository for Babel, the Python Internationalization Library
http://babel.pocoo.org/
BSD 3-Clause "New" or "Revised" License
1.33k stars 444 forks source link

Flask jinja filter `assets` is incompatible with the `pybabel` command and fails to extract translations #444

Closed heartsucker closed 7 years ago

heartsucker commented 8 years ago

There's a chance I'm using this wrong, but I'm fairly certain this is a bug. If there is a better way to do this, it is certainly non-intuitive. (originally posted to https://github.com/python-babel/flask-babel/issues/108, but this is probably the right place).

My setup

One html file called index.html. I extract with the command

pybabel extract -F babel.cfg --charset=utf=8 -o messages.pot --no-wrap index.html

The file bable.cfg

[jinja2: **.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_

My env:

(venv) heartsucker@pythagoras:~/Downloads/test$ python --version
Python 3.4.2
(venv) heartsucker@pythagoras:~/Downloads/test$ pip freeze
Babel==2.3.4
click==6.6
Flask==0.11.1
Flask-Babel==0.11.1
itsdangerous==0.24
Jinja2==2.8
MarkupSafe==0.23
pytz==2016.6.1
Werkzeug==0.11.10
(venv) heartsucker@pythagoras:~/Downloads/test$ uname -a
Linux pythagoras 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt25-2+deb8u3 (2016-07-02) x86_64 GNU/Linux
(venv) heartsucker@pythagoras:~/Downloads/test$ 

What works

If index.html is this:

<!DOCTYPE html>
<html>
  <head>
       <link rel="stylesheet" href="{{ ASSET_URL }}" />
  </head>
  <body>
    {{ gettext('Test') }}
  </body>
</html>

The messages.pot is this:

# Translations template for PROJECT.
# Copyright (C) 2016 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2016-08-25 21:57+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf=8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.3.4\n"

#: index.html:7
msgid "Test"
msgstr ""

The one string called Test is correctly extracted.

What doesn't work

If index.html is this:

<!DOCTYPE html>
<html>
  <head>
    {% assets filters="cssmin", output="gen/source.css", "css/normalize.css" %}
       <link rel="stylesheet" href="{{ ASSET_URL }}" />
    {% endassets %}
  </head>
  <body>
    {{ gettext('Test') }}
  </body>
</html>

The messages.pot is this:


# Translations template for PROJECT.
# Copyright (C) 2016 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2016-08-25 21:58+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf=8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.3.4\n"

The one string called Test is not extracted.

akx commented 8 years ago

Hey,

Sorry it's taken us a while to get back to you.

What's happening here is that Jinja fails to parse the template with the {% assets %} tag (not a filter; a custom filter wouldn't cause problems), since the extension that provides it is not loaded.

Unfortunately the Jinja extractor has silent behavior by default, so you don't get sensible error messages about these cases. (You can add silent=false to the jinja2 section in your babel.cfg to have it fail loudly.)

The easiest fix is to augment your babel.cfg to add the assets extension -- I'm not sure how you configure it in your Flask app, so I can't directly help further:

[jinja2: **.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_,whatever.import.path.there.is.to.your.assets.extension

Another, slightly more involved but also more DRY and future-proof, way to fix this would be to use a extractor that uses the environment you already set up for the Flask app for Jinja files; this is what my django-i18nkit project does for compatibility with Django-Jinja: https://github.com/akx/django-i18nkit/blob/master/i18nkit/jinja2_extract.py

akx commented 8 years ago

@heartsucker Did you get things to work with the above instructions? :)

akx commented 7 years ago

Closing due to inactivity.

rlafuente commented 7 years ago

For Pelican users who ran into this, the assets path should be

extensions=webassets.ext.jinja2.AssetsExtension

Thanks to Or Duan at Stack Overflow for this answer

nastyaDjo commented 6 years ago

@rlafuente I use Pelican and try to set my custom jinja extension in babel.cfg in this way:

[jinja2: theme/templates/index.html]
extensions=jinja2.ext.i18n, custom_jinja_extension.IncludeMarkdownExtension
silent = false

But it doesn't work for me. Can you help me with the right settings?

P.S. This is a path to my custom extension /project_folder/custom_jinja_extension.py

rlafuente commented 6 years ago

It's been more than a year and I really don't remember much about this subject. Maybe the space between the extension names is causing an issue? Otherwise it might be a path problem (it doesn't find your extension because it isn't looking in that dir)? Anyway, that's all I can help with -- good luck!

nastyaDjo commented 6 years ago

@rlafuente Do you know how to specify the path rightin babel.cfg?

bornfree commented 6 years ago

Anyone using the compress tag from Jina Assets Compressor (https://github.com/jaysonsantos/jinja-assets-compressor) can use

extensions=jinja2.ext.autoescape,jinja2.ext.with_,jac.extension.CompressorExtension

Otherwise it fails with:

jinja2.exceptions.TemplateSyntaxError: Encountered unknown tag 'compress'.