Opened 7 years ago

Closed 3 years ago

#5493 closed New feature (fixed)

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

Reported by: msaelices 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 7 years ago by damien_szczyt

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

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 7 years ago by PhiR

  • Keywords feature_request added

comment:3 Changed 7 years ago by webjunkie

  • Triage Stage changed from Unreviewed to Design decision needed

comment:4 Changed 7 years ago by ubernostrum

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 7 years ago by mtredinnick

  • Component changed from Tools to Internationalization

comment:6 Changed 7 years ago by jacob

  • Resolution set to fixed
  • Status changed from new to closed
  • Triage Stage changed from Design decision needed to Accepted

comment:7 Changed 3 years ago by tonnzor

  • Cc tonnzor added
  • Easy pickings unset
  • Has patch set
  • Resolution fixed deleted
  • Severity set to Normal
  • Status changed from closed to reopened
  • Summary changed from make-messages.py not parses templates *.html for domain djangojs to make-messages.py not parses JS *.html templates for domain djangojs
  • Triage Stage changed from Accepted to Unreviewed
  • Type set to Bug
  • UI/UX unset
  • Version changed from master to 1.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 3 years ago by tonnzor

  • Has patch unset
  • Type changed from Bug to New 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 3 years ago by aaugustin

  • Resolution set to fixed
  • Status changed from reopened to closed

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