Repository: wagtail/wagtail

Issue:
Missing translation strings from .po files
Strings in wagtail.wagtailadmin.forms.LoginForm are not extracted to .po files 
("Enter your username", "Enter password").



Discussion:
Hmm they seem to be marked for extraction with ugettext_lazy -- I'll check them again.

They are marked. Just not extracted :)

I made an insteresting observation that I wasn't aware of after a number of tests wth `makemessagess`. **You can't use**

`
from django.utils.translation import ugettext as _, ugettext_lazy as __
`
or

`
from django.utils.translation import ugettext as _ 
from django.utils.translation import ugettext_lazy as __
`

both of which I've seen in various places. The `_` can substitute _only one_ of these functions (either `ugettext` or `ugettext_lazy`) and the other should _not_ be renamed to anything. This is evident if we take a look the django source, for instance here:
https://github.com/django/django/blob/master/django/contrib/admin/models.py
(only `ugettext_lazy` is renamed to _).

For the curious, as Robert Lujo explains in his answer here http://stackoverflow.com/questions/16509160/ugettext-and-ugettext-lazy-functions-not-recognized-by-makemessages-in-python-dj this behavior is because `makemessagess` calls the `xgettext` utility to extract the strings marked for translation, passing to it a number of keywords that actually mark the strings. __ (double underscore) is _not_ one of these keywords !

Unfortuanately, the double underscore idiom has been used in a number of places in Wagtail - tomorrow I will fix it so that all strings will be exracted correctly.


Resolving patch:
diff --git a/wagtail/wagtailadmin/edit_handlers.py b/wagtail/wagtailadmin/edit_handlers.py
--- a/wagtail/wagtailadmin/edit_handlers.py
+++ b/wagtail/wagtailadmin/edit_handlers.py
@@ -15,7 +15,8 @@
 from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured, ValidationError
 from django.core.urlresolvers import reverse
 from django.conf import settings
-from django.utils.translation import ugettext as _, ugettext_lazy as __
+from django.utils.translation import ugettext as _
+from django.utils.translation import ugettext_lazy
 
 from wagtail.wagtailcore.models import Page
 from wagtail.wagtailcore.util import camelcase_to_underscore
@@ -720,5 +721,5 @@ def InlinePanel(base_model, relation_name, panels=None, label='', help_text=''):
         FieldPanel('seo_title'),
         FieldPanel('show_in_menus'),
         FieldPanel('search_description'),
-    ], __('Common page configuration')),
+    ], ugettext_lazy('Common page configuration')),
 ]
diff --git a/wagtail/wagtailadmin/forms.py b/wagtail/wagtailadmin/forms.py
--- a/wagtail/wagtailadmin/forms.py
+++ b/wagtail/wagtailadmin/forms.py
@@ -1,7 +1,8 @@
 from django import forms
 from django.contrib.auth import get_user_model
 from django.contrib.auth.forms import AuthenticationForm, PasswordResetForm
-from django.utils.translation import ugettext as _, ugettext_lazy as __
+from django.utils.translation import ugettext as _
+from django.utils.translation import ugettext_lazy
 
 class SearchForm(forms.Form):
     def __init__(self, *args, **kwargs):
@@ -38,15 +39,15 @@ class EmailLinkChooserWithLinkTextForm(forms.Form):
 class LoginForm(AuthenticationForm):
     username = forms.CharField(
         max_length=254,
-        widget=forms.TextInput(attrs={'placeholder': __("Enter your username")}),
+        widget=forms.TextInput(attrs={'placeholder': ugettext_lazy("Enter your username")}),
     )
     password = forms.CharField(
-        widget=forms.PasswordInput(attrs={'placeholder': __("Enter password")}),
+        widget=forms.PasswordInput(attrs={'placeholder': ugettext_lazy("Enter password")}),
     )
 
 
 class PasswordResetForm(PasswordResetForm):
-    email = forms.EmailField(label=_("Enter your email address to reset your password"), max_length=254)
+    email = forms.EmailField(label=ugettext_lazy("Enter your email address to reset your password"), max_length=254)
 
     def clean(self):
         cleaned_data = super(PasswordResetForm, self).clean()


Test patch: