from django import forms
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import password_validation

from accounts.models import User


class RegisterForm(forms.ModelForm):
    """Form used to create new user accounts."""

    email = forms.EmailField(
        label=_('Your email address'),
        required=True,
        help_text=_('We will send a confirmation link to '
                    'this address before creating the account.'))
    full_name = forms.CharField(
        label=_('Your full name'),
        required=True,
        help_text=_('This is how we will address you in our communications.'))
    ml_consent = forms.BooleanField(
        label=_('I want to receive news and communications from the service.'),
        required=False,
        help_text=_('You will be able to unsubscribe at any time.'))

    class Meta:
        model = User
        fields = ['full_name', 'email', 'ml_consent']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['full_name'].widget.attrs.update({'autofocus': True})
        self.fields['email'].widget.attrs.update({
            'placeholder': _('Please double-check this value.')})

    def clean_email(self):
        email = self.cleaned_data['email']
        return email.lower()


class LoginForm(AuthenticationForm):
    username = forms.EmailField(
        label=_('Your email address'),
        required=True)
    password = forms.CharField(
        label=_('Your password'),
        required=True,
        strip=False,
        widget=forms.PasswordInput)

    def clean_username(self):
        """Don't prevent users to login when they user uppercase emails."""

        username = self.cleaned_data['username']
        return username.lower()


class PasswordResetForm(forms.Form):
    """Password reset request form."""

    username = forms.EmailField(
        label=_('Your email address'),
        required=True)


class ProfileForm(forms.ModelForm):
    """Edit profile related user data."""

    new_password = forms.CharField(
        label=_('Choose a new password'),
        required=False,
        strip=False,
        help_text=password_validation.password_validators_help_text_html(),
        widget=forms.PasswordInput(attrs={
            'placeholder': _('Leave empty to keep your existing password')
        }))

    class Meta:
        model = User
        fields = ['full_name', 'new_password', 'ml_consent']
        labels = {
            'full_name': _('Your full name'),
            'ml_consent':
                _('Yes, I want to receive news about the service.'),
        }
        help_texts = {
            'full_name':
                _('This is how we will address you in our ' 'communications.'),
            'ml_consent':
                _('We will send regular updates (no more than once a month) '
                  'about the new features and updates about our service.'),
        }

    def _post_clean(self):
        super()._post_clean()
        # Validate the password after self.instance is updated with form data
        # by super().
        password = self.cleaned_data.get('new_password')
        if password:
            try:
                password_validation.validate_password(password, self.instance)
            except forms.ValidationError as error:
                self.add_error('new_password', error)

    def save(self, commit=True):
        user = super().save(commit=False)

        new_password = self.cleaned_data['new_password']
        if new_password:
            user.set_password(new_password)

        if commit:
            user.save()
        return user


class ContributorProfileForm(forms.ModelForm):
    """Edit contributor profile related user data."""

    class Meta:
        model = User
        fields = ['organization', 'role', 'contact_phone']
        labels = {
            'organization': _('Your organization'),
            'role': _('Your position'),
        }

src/accounts/forms.py
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import password_validation

from accounts.models import User


class RegisterForm(forms.ModelForm):
    """Form used to create new user accounts."""

    email = forms.EmailField(
        label=_('Your email address'),
        required=True,
        help_text=_('We will send a confirmation link to '
                    'this address before creating the account.'))
    full_name = forms.CharField(
        label=_('Your full name'),
        required=True,
        help_text=_('This is how we will address you in our communications.'))
    ml_consent = forms.BooleanField(
        label=_('I want to receive news and communications from the service.'),
        required=False,
        help_text=_('You will be able to unsubscribe at any time.'))

    class Meta:
        model = User
        fields = ['full_name', 'email', 'ml_consent']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['full_name'].widget.attrs.update({'autofocus': True})
        self.fields['email'].widget.attrs.update({
            'placeholder': _('Please double-check this value.')})

    def clean_email(self):
        email = self.cleaned_data['email']
        return email.lower()


class LoginForm(AuthenticationForm):
    error_messages = {
        'invalid_login': _(
            'Please enter a correct email address and password.'
        ),
        'inactive': _('This account is inactive.'),
    }

    username = forms.EmailField(
        label=_('Your email address'),
        required=True)
    password = forms.CharField(
        label=_('Your password'),
        required=True,
        strip=False,
        widget=forms.PasswordInput)

    def clean_username(self):
        """Don't prevent users to login when they user uppercase emails."""

        username = self.cleaned_data['username']
        return username.lower()


class PasswordResetForm(forms.Form):
    """Password reset request form."""

    username = forms.EmailField(
        label=_('Your email address'),
        required=True)


class ProfileForm(forms.ModelForm):
    """Edit profile related user data."""

    new_password = forms.CharField(
        label=_('Choose a new password'),
        required=False,
        strip=False,
        help_text=password_validation.password_validators_help_text_html(),
        widget=forms.PasswordInput(attrs={
            'placeholder': _('Leave empty to keep your existing password')
        }))

    class Meta:
        model = User
        fields = ['full_name', 'new_password', 'ml_consent']
        labels = {
            'full_name': _('Your full name'),
            'ml_consent':
                _('Yes, I want to receive news about the service.'),
        }
        help_texts = {
            'full_name':
                _('This is how we will address you in our ' 'communications.'),
            'ml_consent':
                _('We will send regular updates (no more than once a month) '
                  'about the new features and updates about our service.'),
        }

    def _post_clean(self):
        super()._post_clean()
        # Validate the password after self.instance is updated with form data
        # by super().
        password = self.cleaned_data.get('new_password')
        if password:
            try:
                password_validation.validate_password(password, self.instance)
            except forms.ValidationError as error:
                self.add_error('new_password', error)

    def save(self, commit=True):
        user = super().save(commit=False)

        new_password = self.cleaned_data['new_password']
        if new_password:
            user.set_password(new_password)

        if commit:
            user.save()
        return user


class ContributorProfileForm(forms.ModelForm):
    """Edit contributor profile related user data."""

    class Meta:
        model = User
        fields = ['organization', 'role', 'contact_phone']
        labels = {
            'organization': _('Your organization'),
            'role': _('Your position'),
        }

src/accounts/forms.py
diff --git a/src/accounts/forms.py b/src/accounts/forms.py
index 01db5c7a9..cd133623b 100644
--- a/src/accounts/forms.py
+++ b/src/accounts/forms.py
@@ -39,6 +39,13 @@ def clean_email(self):
 
 
 class LoginForm(AuthenticationForm):
+    error_messages = {
+        'invalid_login': _(
+            'Please enter a correct email address and password.'
+        ),
+        'inactive': _('This account is inactive.'),
+    }
+
     username = forms.EmailField(
         label=_('Your email address'),
         required=True)
diff --git a/src/locales/fr/LC_MESSAGES/django.po b/src/locales/fr/LC_MESSAGES/django.po
index 4ae825322..e3a9a589a 100644
--- a/src/locales/fr/LC_MESSAGES/django.po
+++ b/src/locales/fr/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-09-10 16:39+0200\n"
+"POT-Creation-Date: 2020-09-21 10:43+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -41,6 +41,12 @@ msgstr "Vous pourrez vous désabonner à tout moment."
 msgid "Please double-check this value."
 msgstr "Merci de bien vérifier l'adresse saisie."
 
+msgid "Please enter a correct email address and password."
+msgstr "Saisissez une adresse e-mail et un mot de passe valides."
+
+msgid "This account is inactive."
+msgstr "Ce compte n'est actuellement pas actif."
+
 msgid "Your password"
 msgstr "Votre mot de passe"
 

Mauvais article et mauvaise casse pour message d'erreur sur adresse mail
Sur la page `/comptes/connexion/`, on voit : 

```
Saisissez un Adresse e-mail…
```

Alors que l'on devrait avoir : 

```
Saisissez une adresse e-mail…
```

![image](https://user-images.githubusercontent.com/6030745/90972240-a399de00-e517-11ea-89e7-85a6d0445ee2.png)

La base du message d'erreur vient des [fichiers de traduction de Django](https://github.com/django/django/blob/6376278a904e2f8b34893a7166508dfd205fdceb/django/contrib/auth/locale/fr/LC_MESSAGES/django.po) : 

```py
msgid ""
"Please enter a correct %(username)s and password. Note that both fields may "
"be case-sensitive."
msgstr ""
"Saisissez un %(username)s et un mot de passe valides. Remarquez que chacun "
"de ces champs est sensible à la casse (différenciation des majuscules/"
"minuscules)."
```

Et à la place du placeholder `%(username)s`, on a `Adresse e-mail` dans ce projet.

Dans le fichier de traduction (`django.po`) du projet actuel, on voit : 

```py
msgid "Email address"
msgstr "Adresse e-mail"
```
