Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django-admin makemessages --no-obsolete doesn't seem to be working

First of all, I am expecting --no-obsolete would comment out msgid and msgstr if gettext is deleted, right?

How I am testing is:

  1. I wrote gettext("some string here") in view
  2. I ran makemessages command
  3. It wrote a .po file as expected
  4. Then I deleted gettext() line from view and saved file, verified runserver working.
  5. I ran makemessages --no-obsolete and it has not made any changes to .po file.

.po file content extract .

#. Translators: This message is a test of wrap line
#: servers/views.py:31
msgid "Do let me know if it works."
msgstr ""

dev environment

Django = 1.11
OS = Mac/Ubuntu 14.04

settings.py

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

LOCALE = (
      os.path.join(os.path.dirname(__file__), "locale"),
)
like image 726
Kishor Pawar Avatar asked Mar 17 '18 16:03

Kishor Pawar


3 Answers

What the --no-obsolete does is to run a command called msgattrib with the --no-obsolete option on the content the po file. A typical case would be you generate your po file with makemessages, you get this:

#: servers/views.py:31
msgid "Do let me know if it works."
msgstr ""

Then you translate:

#: servers/views.py:31
msgid "Do let me know if it works."
msgstr "translation"

Then you remove the gettext entry, it'll still by default keep the translation, but mark it as obsolete.

#: servers/views.py:31
#~msgid "Do let me know if it works."
#~msgstr "translation"

If you set --no-obsolete option, then once your po file is done, it'll run msgattr with no-obsolete option. This will remove lines tagged with #~. See https://linux.die.net/man/1/msgattrib

But, the way makemessages is built, is that this will be called once the po file is written. But if there are no gettext in the files being processed, then it won't write to the po file. It'll just stop before getting to this msgattrib command. The po file you see is the one generated by the previous makemessages command. So the no-obsolete won't do anything.

There's no real solution to this. the no-obsolete option doesn't deal with the cases where you don't have any gettext to process.

like image 40
Julien Grégoire Avatar answered Nov 07 '22 19:11

Julien Grégoire


Now with the help of Julien and Tarun, I found following observations.

python manage.py makemessages -l <locale>

If there is no gettext in the file being processed, the above command won't write/update .po file. That means if the corresponding .po file earlier had entries for msgstr and msgid, then it won't remove those entries unless file being processed had at least one gettext.

Note: Above behavior is irrespective of --no-obsolete

Now to make the --no-obsolete work as expected we need to follow the steps below.

  1. First thing run python manage.py makemessages -l <locale>, this would write .po file with msgid and msgstr.

  2. Now set msgstr and run python manage.py compilemessages -l <locale>. This command writes .mo file in the same directory as .po file.

  3. Now next time when you run makemessages again (without --no-obsolete), .po and .mo files are compared and missing/deleted gettext are commented in .po file.

  4. And when you run makemessages --no-obsolete, commented entries are removed from the .po file.

E.g

if you have 3 gettext entries, and you run makemessages first time, it would write 3 msgid and 3 msgstr in .po file. Now if you remove all gettext entries, .po file won't be updated after you run makemessages again, but if your keep at least 1 gettext entry in same file and run makemessages again, it would delete all msgid and msgstr for deleted gettext entries.

But if you run compilemessages after makemessages, .mo file is created and then for subsequent makemessages commands .po and .mo files are compared and then msgid and msgstr is commented in .po file for deleted gettext entries.

Then finally when you run makemessages with --no-obsolete option the commented messages from .po files are deleted permanently.

like image 90
Kishor Pawar Avatar answered Nov 07 '22 20:11

Kishor Pawar


So I think @JulienGrégoire was right about the fact that if there is no translation processed then the --no-obsolete won't work. There needs to be at least one translation captured for --no-obsolete to work.

But the solution to this quite simple. You can update your settings.py to define LANGUAGES like below

from django.utils.translation import ugettext_lazy as _
LANGUAGES = (
    ('en', _('English')),
    ('fr', _('French')),
)

Now your settings will always generate a translation. So it will make sure that you get --no-obsolete working every time you use it

like image 1
Tarun Lalwani Avatar answered Nov 07 '22 20:11

Tarun Lalwani