Code

Opened 20 months ago

Closed 19 months ago

Last modified 18 months ago

#18881 closed Bug (fixed)

tag "trans" not working with "context"

Reported by: lanyjie Owned by: julien
Component: Template system Version: 1.4
Severity: Release blocker Keywords: trans context i18n
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Hi I am using the "trans" tag to do context aware translation. In my template I had something like:

    {%trans "Budget" context "finance"%}

then as I "makemessages", the context does not appear in my django.po file. What's more, it fails to translate properly even if I had provided the correct translation in the django.po file and compiled the messages.

Attachments (2)

18881.trans-context-single-quotes.diff (3.4 KB) - added by julien 19 months ago.
18881.trans-context-single-quotes-CODE-ONLY.diff (968 bytes) - added by julien 19 months ago.

Download all attachments as: .zip

Change History (16)

comment:1 Changed 20 months ago by lanyjie

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

I also used pgettext("context", "message") in my code, and it didn't work either. Note the context was given in Chinese.

comment:2 Changed 20 months ago by claudep

I'm not able to reproduce your problem. Maybe you can give us your real file so we can test?

comment:3 Changed 19 months ago by lanyjie

Maybe it is my mistake -- I can't reproduce it anymore. When I played with it, I found something highly related: if you use both double quote and single quote, the single quote version won't show up with context. Here is what I mean:

    {%trans "Budget" context "finance"%}

Then somewhere else you have:

    {%trans 'Budget' context 'finance'%}

Seems the translation system treats them as two different entries.

comment:4 Changed 19 months ago by julien

For the record, a while ago a similar ticket was created: #18114. But I couldn't reproduce the problem either for that one either.

That seems unlikely, but perhaps there's an issue with this tag handling single quotes.

Could you try writing a unit test showing the problem?

comment:5 Changed 19 months ago by lanyjie

I would love to try write a unit test if someone can give me an example for the i18n module. For now, I can specify how to reproduce this problem:

  1. in a django project, write a real simple template file named "testempt.html" with two lines like this:
        {%trans "budget" context "finance"%}
    
        "{%trans 'budget' context 'finance'%}"
    
  2. now issue this command:
        python manage.py makemessages -l en
    
  3. then open the message file django.po and you will get this:
    #: testempt.html:1
    msgctxt "finance"
    msgid "budget"
    msgstr ""
    
    #: testempt.html:3
    msgid "budget"
    msgstr ""
    

comment:6 Changed 19 months ago by julien

Thanks for the code snippet. If you'd like to have a go at writing a unit test, you can take a look at the existing tests in https://github.com/django/django/blob/master/tests/regressiontests/i18n/commands/extraction.py

comment:7 Changed 19 months ago by lanyjie

@julien: I looked at that code and it seems we can do the following with the testempt.html:

    def test_template_message_context_extractor(self):
        """
        Ensure that message contexts are correctly extracted for the
        {% trans %} and {% blocktrans %} template tags.
        Refs #14806.
        """
        os.chdir(self.test_dir)
        management.call_command('makemessages', locale=LOCALE, verbosity=0)
        self.assertTrue(os.path.exists(self.PO_FILE))
        with open(self.PO_FILE, 'r') as fp:
            po_contents = fp.read()
            # {% trans %}
            self.assertTrue('msgctxt "Special trans context #1"' in po_contents)
            self.assertTrue("Translatable literal #7a" in po_contents)
            self.assertTrue('msgctxt "Special trans context #2"' in po_contents)
            self.assertTrue("Translatable literal #7b" in po_contents)
            self.assertTrue('msgctxt "Special trans context #3"' in po_contents)
            self.assertTrue("Translatable literal #7c" in po_contents)

            #ticket #18881, single quote context
            self.assertTrue('msgctxt "finance"' in po_contents)
            self.assertMsgId('budget', po_contents)

            #{% blocktrans %}

However, the call of

    self.assertMsgId('finance', po_contents)

currently does NOT check for duplicate message id in the po file, which is not quite adequate.
Therefore, in the same file, where assertMsgId is defined, we can use the following definition instead:

    def assertMsgId(self, msgid, s, use_quotes=True):
        q = '"'
        if use_quotes:
            msgid = '"%s"' % msgid
            q = "'"
        needle = 'msgid %s' % msgid
        msgid = re.escape(msgid)
        matches = len(re.findall('^msgid %s' % msgid, s, re.MULTILINE))
        return self.assertTrue( matches==1, 
            'Could not find %(q)s%(n)s%(q)s in generated PO file' % {'n':needle, 'q':q} if matches==0 else
            'Found more than one occurrences of %(q)s%(n)s%(q)s in generated PO file' % {'n':needle, 'q':q})

comment:8 Changed 19 months ago by julien

  • Owner changed from nobody to julien
  • Severity changed from Normal to Release blocker
  • Triage Stage changed from Unreviewed to Accepted

It looks like there's a bug with the context's regular expressions. Marking this ticket as a release blocker as this was a new feature in 1.4 and therefore it should be fixed in 1.4.X as well.

I wrote a patch (see attached). Could you please try it in your project and check that it fixes your problem?

Changed 19 months ago by julien

comment:9 Changed 19 months ago by lanyjie

Thanks for the patch. I tried to use it by cd to the django installation folder and do

    django> patch --dry-run -p2 < ~/Downloads/18881.trans-context-single-quotes.diff

but it complains about "can't find file to patch at input line 5". any ideas?

comment:10 Changed 19 months ago by julien

Which exact version of Django are you using? If it's a git clone, which revision is it at?

The error you got is because the first patch I submitted also contained the tests. I've re-submitted another patch with the code change only. Could you try again with that one instead?

comment:11 Changed 19 months ago by lanyjie

patch succeeded, and problem fixed. many thanks!

comment:12 Changed 19 months ago by claudep

  • Has patch set
  • Triage Stage changed from Accepted to Ready for checkin

comment:13 Changed 19 months ago by Julien Phalip <jphalip@…>

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

In b8244c654c85034bd4209a93a7802eb306c32e2b:

Fixed #18881 -- Made the context option in {% trans %} and {% blocktrans %} accept literals wrapped in single quotes. Thanks to lanyjie for the report.

comment:14 Changed 18 months ago by Julien Phalip <jphalip@…>

In cc0478606a1d3dd804bc005a78e616550d3d0d41:

[1.4.x] Fixed #18881 -- Made the context option in {% trans %} and {% blocktrans %} accept literals wrapped in single quotes. Thanks to lanyjie for the report.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.