Opened 9 years ago

Closed 4 years ago

#5493 closed New feature (fixed)

make-messages.py not parses JS *.html templates for domain djangojs

Reported by: Manuel Saelices Owned by: nobody
Component: Internationalization Version: 1.4
Severity: Normal Keywords: javascript tools feature_request
Cc: tonnzor Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

When you do translations in javascripts and creates you want to create .po catalogs with:

  make-messages.py -d djangojs -l es

make-messages.py only parse *.js files but not code inside templates like this:

 <h1><script type="text/javascript">document.write(gettext('this is to be translated'));<script></h1>

Change History (9)

comment:1 Changed 9 years ago by damien_szczyt

I think you should place HTML code and JS code in different files. Your HTML page will be smaller, and your application will load faster.
I don't think this is a bug to resolve.

comment:2 Changed 9 years ago by Philippe Raoult

Keywords: feature_request added

comment:3 Changed 9 years ago by Julian Bez

Triage Stage: UnreviewedDesign decision needed

comment:4 Changed 9 years ago by James Bennett

I'd be -1 on parsing strings out of JS hard-coded in HTML, because it goes against best practices for application development.

comment:5 Changed 9 years ago by Malcolm Tredinnick

Component: ToolsInternationalization

comment:6 Changed 9 years ago by Jacob

Resolution: fixed
Status: newclosed
Triage Stage: Design decision neededAccepted

comment:7 Changed 4 years ago by tonnzor

Cc: tonnzor added
Easy pickings: unset
Has patch: set
Resolution: fixed
Severity: Normal
Status: closedreopened
Summary: make-messages.py not parses templates *.html for domain djangojsmake-messages.py not parses JS *.html templates for domain djangojs
Triage Stage: AcceptedUnreviewed
Type: Bug
UI/UX: unset
Version: master1.4

In 2012 it becomes very popular to use template engine right inside JS. That brings developers to need of translations for those templates.

Imagine this app:

index.js:

var objects = [];
$.ajax("/static/index.html", function(template){
    $('body').append(Template().render({"list": objects}));
});

index.html:

<%= ngettext("Show your photo", "Show all your photos", list.length) %>
<ul>
<% for obj in list %>
<li><%= obj.name %><a href="<%= obj.url %>"><img src="/media/images/graphics/1.png" /><%= gettext("See them all") %></a></li>
<% end %>
</ul>

But when you try to generate translations:

./manage.py makemessages -l de -e html -d djangojs

You would find that this index.html is being parsed by Django and terribly broken by prepare_js_for_gettext (as file is almost HTML).

Even if you try to use django domain -- it is broken by django.utils.translation.templatize.

My proposal is for djangojs domain to try to parse file only its extension is .js. Otherwise try to use original file. xgettext seems to be smart enough to find translations in given template.

Here is the patch that does the stuff:

diff --git a/django/core/management/commands/makemessages.py b/django/core/management/commands/makemessages.py
--- a/django/core/management/commands/makemessages.py
+++ b/django/core/management/commands/makemessages.py
@@ -165,7 +165,8 @@
         is_templatized = True
         orig_file = os.path.join(dirpath, file)
         src_data = open(orig_file).read()
-        src_data = prepare_js_for_gettext(src_data)
+        if file_ext == ".js":
+            src_data = prepare_js_for_gettext(src_data)
         thefile = '%s.c' % file
         work_file = os.path.join(dirpath, thefile)
         f = open(work_file, "w")

comment:8 Changed 4 years ago by tonnzor

Has patch: unset
Type: BugNew feature

It was a good start, but we need something more sophisticated as xgettext breaks in some cases on EJS files..

We need a way to provide a way to use custom pre-processors for makemessages for each of extensions.

In this case I would be able to simply attach needed parser to my file extension (e.g. .ejs) and do any needed logic there.

Something like this:

# in settings.py
GETTEXT_PROCESSORS = {
'.ejs': 'mysite.gettext_processors.ejs'
}

# in django/core/management/commands/makemessages.py
processor = django.conf.settings.GETTEXT_PROCESSORS.get(file_ext, default_processor)
src_data = processor(src_data)

It seems to be quite straightforward change that would break nothing but add a way to customize it.

Any better ideas how to allow using custom processors are welcome.

comment:9 Changed 4 years ago by Aymeric Augustin

Resolution: fixed
Status: reopenedclosed

To keep the tracker readable, please don't reopen five-year old bugs, especially to request tangentially related new features.

Per the contributing guide, the recommended way to request new features is to propose them on the mailing list and see if the idea gets traction. If it does, please open a new ticket with your proposal (and a link to the discussion). Thanks!

PS: relying on "xgettext seems to be smart enough" hasn't served us very well in the past. We used a 99%-correct approximation (or maybe 95%, or 80%, who knows) until Ned Batchelder bit the bullet and wrote a Javascript parser, which we're now using. If you want to parse JS in Django you really have to use it.

Note: See TracTickets for help on using tickets.
Back to Top