From a7d47b972d6e5fdea1256164895bc36362e7d433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Kervella?= Date: Sat, 31 Mar 2018 13:43:46 +0000 Subject: [PATCH 1/6] Translation: Marking of strings in cotisations app --- cotisations/acl.py | 3 +- cotisations/forms.py | 154 ++++++++++++++------- cotisations/models.py | 300 ++++++++++++++++++++++++++++------------- cotisations/payment.py | 9 +- cotisations/views.py | 205 +++++++++++++++++++++------- 5 files changed, 481 insertions(+), 190 deletions(-) diff --git a/cotisations/acl.py b/cotisations/acl.py index 868e3411..4e147a82 100644 --- a/cotisations/acl.py +++ b/cotisations/acl.py @@ -25,6 +25,7 @@ Here are defined some functions to check acl on the application. """ +from django.utils.translation import ugettext as _ def can_view(user): """Check if an user can view the application. @@ -37,4 +38,4 @@ def can_view(user): viewing is granted and msg is a message (can be None). """ can = user.has_module_perms('cotisations') - return can, None if can else "Vous ne pouvez pas voir cette application." + return can, None if can else _("You don't have the rights to see this application.") diff --git a/cotisations/forms.py b/cotisations/forms.py index 3459f0de..e2095f7b 100644 --- a/cotisations/forms.py +++ b/cotisations/forms.py @@ -40,6 +40,8 @@ from django import forms from django.db.models import Q from django.forms import ModelForm, Form from django.core.validators import MinValueValidator,MaxValueValidator +from django.utils.translation import ugettext as _ + from .models import Article, Paiement, Facture, Banque from preferences.models import OptionalUser from users.models import User @@ -50,15 +52,18 @@ from re2o.mixins import FormRevMixin class NewFactureForm(FormRevMixin, ModelForm): """Creation d'une facture, moyen de paiement, banque et numero de cheque""" + # TODO : translate doc string in English def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) super(NewFactureForm, self).__init__(*args, prefix=prefix, **kwargs) + # TODO : remove the use of cheque and banque and paiement + # for something more generic or at least in English self.fields['cheque'].required = False self.fields['banque'].required = False - self.fields['cheque'].label = 'Numero de chèque' - self.fields['banque'].empty_label = "Non renseigné" - self.fields['paiement'].empty_label = "Séléctionner\ - un moyen de paiement" + self.fields['cheque'].label = _("Cheque number") + self.fields['banque'].empty_label = _("Not specified") + self.fields['paiement'].empty_label = \ + _("Select a payment method") paiement_list = Paiement.objects.filter(type_paiement=1) if paiement_list: self.fields['paiement'].widget\ @@ -70,41 +75,47 @@ class NewFactureForm(FormRevMixin, ModelForm): def clean(self): cleaned_data = super(NewFactureForm, self).clean() - paiement = cleaned_data.get("paiement") - cheque = cleaned_data.get("cheque") - banque = cleaned_data.get("banque") + paiement = cleaned_data.get('paiement') + cheque = cleaned_data.get('cheque') + banque = cleaned_data.get('banque') if not paiement: - raise forms.ValidationError("Le moyen de paiement est obligatoire") - elif paiement.type_paiement == "check" and not (cheque and banque): - raise forms.ValidationError("Le numéro de chèque et\ - la banque sont obligatoires.") + raise forms.ValidationError( + _("A payment method must be specified") + ) + elif paiement.type_paiement == 'check' and not (cheque and banque): + raise forms.ValidationError( + _("A cheque number and a bank must be specified") + ) return cleaned_data class CreditSoldeForm(NewFactureForm): """Permet de faire des opérations sur le solde si il est activé""" + # TODO : translate docstring to English class Meta(NewFactureForm.Meta): model = Facture fields = ['paiement', 'banque', 'cheque'] def __init__(self, *args, **kwargs): super(CreditSoldeForm, self).__init__(*args, **kwargs) + # TODO : change solde to balance self.fields['paiement'].queryset = Paiement.objects.exclude( moyen='solde' - ).exclude(moyen="Solde") + ).exclude(moyen='Solde') montant = forms.DecimalField(max_digits=5, decimal_places=2, required=True) class SelectUserArticleForm(FormRevMixin, Form): """Selection d'un article lors de la creation d'une facture""" + # TODO : translate docstring to English article = forms.ModelChoiceField( queryset=Article.objects.filter(Q(type_user='All') | Q(type_user='Adherent')), - label="Article", + label=_("Article"), required=True ) quantity = forms.IntegerField( - label="Quantité", + label=_("Quantity"), validators=[MinValueValidator(1)], required=True ) @@ -112,54 +123,63 @@ class SelectUserArticleForm(FormRevMixin, Form): class SelectClubArticleForm(Form): """Selection d'un article lors de la creation d'une facture""" + # TODO : translate docstring to English article = forms.ModelChoiceField( queryset=Article.objects.filter(Q(type_user='All') | Q(type_user='Club')), - label="Article", + label=_("Article"), required=True ) quantity = forms.IntegerField( - label="Quantité", + label=_("Quantity"), validators=[MinValueValidator(1)], required=True ) - +# TODO : change Facture to Invoice class NewFactureFormPdf(Form): """Creation d'un pdf facture par le trésorier""" + # TODO : translate docstring to English article = forms.ModelMultipleChoiceField( queryset=Article.objects.all(), - label="Article" + label=_("Article") ) number = forms.IntegerField( - label="Quantité", + label=_("Quantity"), validators=[MinValueValidator(1)] ) - paid = forms.BooleanField(label="Payé", required=False) - dest = forms.CharField(required=True, max_length=255, label="Destinataire") - chambre = forms.CharField(required=False, max_length=10, label="Adresse") + paid = forms.BooleanField(label=_("Paid"), required=False) + # TODO : change dest field to recipient + dest = forms.CharField(required=True, max_length=255, label=_("Recipient")) + # TODO : change chambre field to address + chambre = forms.CharField(required=False, max_length=10, label=_("Address")) + # TODO : change fid field to invoice_id fid = forms.CharField( required=True, max_length=10, - label="Numéro de la facture" + label=_("Invoice number") ) - +# TODO : change Facture to Invoice class EditFactureForm(FieldPermissionFormMixin, NewFactureForm): """Edition d'une facture : moyen de paiement, banque, user parent""" + # TODO : translate docstring to English class Meta(NewFactureForm.Meta): + # TODO : change Facture to Invoice model = Facture fields = '__all__' def __init__(self, *args, **kwargs): + # TODO : change Facture to Invoice super(EditFactureForm, self).__init__(*args, **kwargs) - self.fields['user'].label = 'Adherent' - self.fields['user'].empty_label = "Séléctionner\ - l'adhérent propriétaire" - self.fields['valid'].label = 'Validité de la facture' + self.fields['user'].label = _("Member") + self.fields['user'].empty_label = \ + _("Select the proprietary member") + self.fields['valid'].label = _("Validated invoice") class ArticleForm(FormRevMixin, ModelForm): """Creation d'un article. Champs : nom, cotisation, durée""" + # TODO : translate docstring to English class Meta: model = Article fields = '__all__' @@ -167,15 +187,16 @@ class ArticleForm(FormRevMixin, ModelForm): def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) super(ArticleForm, self).__init__(*args, prefix=prefix, **kwargs) - self.fields['name'].label = "Désignation de l'article" + self.fields['name'].label = _("Article name") class DelArticleForm(FormRevMixin, Form): """Suppression d'un ou plusieurs articles en vente. Choix parmis les modèles""" + # TODO : translate docstring to English articles = forms.ModelMultipleChoiceField( queryset=Article.objects.none(), - label="Articles actuels", + label=_("Existing articles"), widget=forms.CheckboxSelectMultiple ) @@ -188,26 +209,36 @@ class DelArticleForm(FormRevMixin, Form): self.fields['articles'].queryset = Article.objects.all() +# TODO : change Paiement to Payment class PaiementForm(FormRevMixin, ModelForm): """Creation d'un moyen de paiement, champ text moyen et type permettant d'indiquer si il s'agit d'un chèque ou non pour le form""" + # TODO : translate docstring to English class Meta: model = Paiement + # TODO : change moyen to method and type_paiement to payment_type fields = ['moyen', 'type_paiement'] def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) super(PaiementForm, self).__init__(*args, prefix=prefix, **kwargs) - self.fields['moyen'].label = 'Moyen de paiement à ajouter' - self.fields['type_paiement'].label = 'Type de paiement à ajouter' + self.fields['moyen'].label = _("Payment method name") + self.fields['type_paiement'].label = _("Payment type") + self.fields['type_paiement'].help_text = \ + _("The payement type is use for specific behaviour.\ + The \"cheque\" type means a cheque number and a bank name\ + may be added when using this payment method.") +# TODO : change paiement to payment class DelPaiementForm(FormRevMixin, Form): """Suppression d'un ou plusieurs moyens de paiements, selection parmis les models""" + # TODO : translate docstring to English + # TODO : change paiement to payment paiements = forms.ModelMultipleChoiceField( queryset=Paiement.objects.none(), - label="Moyens de paiement actuels", + label=_("Existing payment method"), widget=forms.CheckboxSelectMultiple ) @@ -220,23 +251,29 @@ class DelPaiementForm(FormRevMixin, Form): self.fields['paiements'].queryset = Paiement.objects.all() +# TODO : change banque to bank class BanqueForm(FormRevMixin, ModelForm): """Creation d'une banque, field name""" + # TODO : translate docstring to Englishh class Meta: + # TODO : change banque to bank model = Banque fields = ['name'] def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) super(BanqueForm, self).__init__(*args, prefix=prefix, **kwargs) - self.fields['name'].label = 'Banque à ajouter' + self.fields['name'].label = _("Bank name") +# TODO : change banque to bank class DelBanqueForm(FormRevMixin, Form): """Selection d'une ou plusieurs banques, pour suppression""" + # TODO : translate docstrign to English + # TODO : change banque to bank banques = forms.ModelMultipleChoiceField( queryset=Banque.objects.none(), - label="Banques actuelles", + label=_("Existing banks"), widget=forms.CheckboxSelectMultiple ) @@ -249,43 +286,56 @@ class DelBanqueForm(FormRevMixin, Form): self.fields['banques'].queryset = Banque.objects.all() +# TODO : change facture to Invoice class NewFactureSoldeForm(NewFactureForm): """Creation d'une facture, moyen de paiement, banque et numero de cheque""" + # TODO : translate docstring to English def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) self.fields['cheque'].required = False self.fields['banque'].required = False - self.fields['cheque'].label = 'Numero de chèque' - self.fields['banque'].empty_label = "Non renseigné" - self.fields['paiement'].empty_label = "Séléctionner\ - une bite de paiement" + self.fields['cheque'].label = _('Cheque number') + self.fields['banque'].empty_label = _("Not specified") + self.fields['paiement'].empty_label = \ + _("Select a payment method") + # TODO : change paiement to payment paiement_list = Paiement.objects.filter(type_paiement=1) if paiement_list: self.fields['paiement'].widget\ .attrs['data-cheque'] = paiement_list.first().id class Meta: + # TODO : change facture to invoice model = Facture + # TODO : change paiement to payment and baque to bank fields = ['paiement', 'banque'] def clean(self): cleaned_data = super(NewFactureSoldeForm, self).clean() + # TODO : change paiement to payment paiement = cleaned_data.get("paiement") cheque = cleaned_data.get("cheque") + # TODO : change banque to bank banque = cleaned_data.get("banque") + # TODO : change paiement to payment if not paiement: - raise forms.ValidationError("Le moyen de paiement est obligatoire") + raise forms.ValidationError( + _("A payment method must be specified.") + ) + # TODO : change paiement and banque to payment and bank elif paiement.type_paiement == "check" and not (cheque and banque): - raise forms.ValidationError("Le numéro de chèque et\ - la banque sont obligatoires.") + raise forms.ValidationError( + _("A cheque number and a bank must be specified.") + ) return cleaned_data +# TODO : Better name and docstring class RechargeForm(FormRevMixin, Form): value = forms.FloatField( - label='Valeur', + label=_("Amount"), min_value=0.01, validators = [] ) @@ -297,7 +347,21 @@ class RechargeForm(FormRevMixin, Form): def clean_value(self): value = self.cleaned_data['value'] if value < OptionalUser.get_cached_value('min_online_payment'): - raise forms.ValidationError("Montant inférieur au montant minimal de paiement en ligne (%s) €" % OptionalUser.get_cached_value('min_online_payment')) + raise forms.ValidationError( + _("Requested amount is too small. Minimum amount possible : \ + %(min_online_amount)s €") % { + min_online_amount: OptionalUser.get_cached_value( + 'min_online_payment' + ) + } + ) if value + self.user.solde > OptionalUser.get_cached_value('max_solde'): - raise forms.ValidationError("Le solde ne peux excéder %s " % OptionalUser.get_cached_value('max_solde')) + raise forms.ValidationError( + _("Requested amount is too high. Your balance can't exceed \ + %(max_online_balance)s €") % { + max_online_balance: OptionalUser.get_cached_value( + 'max_solde' + ) + } + ) return value diff --git a/cotisations/models.py b/cotisations/models.py index cdf73a39..c529c281 100644 --- a/cotisations/models.py +++ b/cotisations/models.py @@ -42,6 +42,7 @@ Post_save et Post_delete : sychronisation des services et régénération des services d'accès réseau (ex dhcp) lors de la vente d'une cotisation par exemple """ +# TODO : translate docstring to English from __future__ import unicode_literals from dateutil.relativedelta import relativedelta @@ -55,55 +56,86 @@ from django.core.validators import MinValueValidator from django.db.models import Max from django.utils import timezone from machines.models import regen +from django.utils.translation import ugettext as _ from re2o.field_permissions import FieldPermissionModelMixin from re2o.mixins import AclMixin, RevMixin +# TODO : change facture to invoice class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model): """ Définition du modèle des factures. Une facture regroupe une ou plusieurs ventes, rattachée à un user, et reliée à un moyen de paiement et si il y a lieu un numero pour les chèques. Possède les valeurs valides et controle (trésorerie)""" - PRETTY_NAME = "Factures émises" + # TODO : translate docstrign to English user = models.ForeignKey('users.User', on_delete=models.PROTECT) + # TODO : change paiement to payment paiement = models.ForeignKey('Paiement', on_delete=models.PROTECT) + # TODO : change banque to bank banque = models.ForeignKey( 'Banque', on_delete=models.PROTECT, blank=True, - null=True) - cheque = models.CharField(max_length=255, blank=True) - date = models.DateTimeField(auto_now_add=True) - valid = models.BooleanField(default=True) - control = models.BooleanField(default=False) + null=True + ) + # TODO : maybe change to cheque nummber because not evident + cheque = models.CharField( + max_length=255, + blank=True, + verbose_name=_("Cheque number") + ) + date = models.DateTimeField( + auto_now_add=True, + verbose_name=_("Date") + ) + # TODO : change name to validity for clarity + valid = models.BooleanField( + default=True, + verbose_name=_("Validated") + ) + # TODO : changed name to controlled for clarity + control = models.BooleanField( + default=False, + verbose_name=_("Controlled") + ) class Meta: abstract = False permissions = ( - ("change_facture_control", "Peut changer l'etat de controle"), - ("change_facture_pdf", "Peut éditer une facture pdf"), - ("view_facture", "Peut voir un objet facture"), - ("change_all_facture", "Superdroit, peut modifier toutes les factures"), + # TODO : change facture to invoice + ('change_facture_control', _("Can change the controlled state")), + # TODO : seems more likely to be call create_facture_pdf or create_invoice_pdf + ('change_facture_pdf', _("Can create a custom PDF invoice")), + ('view_facture', _("Can see an invoice's details")), + ('change_all_facture', _("Can edit all the previous invoices")), ) + verbose_name = _("Invoice") + verbose_name_plural = _("Invoices") def linked_objects(self): """Return linked objects : machine and domain. Usefull in history display""" return self.vente_set.all() + # TODO : change prix to price def prix(self): """Renvoie le prix brut sans les quantités. Méthode dépréciée""" + # TODO : translate docstring to English + # TODO : change prix to price prix = Vente.objects.filter( facture=self ).aggregate(models.Sum('prix'))['prix__sum'] return prix + # TODO : change prix to price def prix_total(self): """Prix total : somme des produits prix_unitaire et quantité des ventes de l'objet""" + # TODO : translate docstrign to English + # TODO : change Vente to somethingelse return Vente.objects.filter( facture=self ).aggregate( @@ -115,6 +147,7 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model): def name(self): """String, somme des name des ventes de self""" + # TODO : translate docstring to English name = ' - '.join(Vente.objects.filter( facture=self ).values_list('name', flat=True)) @@ -122,44 +155,41 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model): def can_edit(self, user_request, *args, **kwargs): if not user_request.has_perm('cotisations.change_facture'): - return False, u"Vous n'avez pas le droit d'éditer les factures" + return False, _("You don't have the right to edit an invoice.") elif not user_request.has_perm('cotisations.change_all_facture') and not self.user.can_edit(user_request, *args, **kwargs)[0]: - return False, u"Vous ne pouvez pas éditer les factures de cet user protégé" + return False, _("You don't have the right to edit this user's invoices.") elif not user_request.has_perm('cotisations.change_all_facture') and\ (self.control or not self.valid): - return False, u"Vous n'avez pas le droit d'éditer une facture\ - controlée ou invalidée par un trésorier" + return False, _("You don't have the right to edit an invoice already controlled or invalidated.") else: return True, None def can_delete(self, user_request, *args, **kwargs): if not user_request.has_perm('cotisations.delete_facture'): - return False, u"Vous n'avez pas le droit de supprimer une facture" + return False, _("You don't have the right to delete an invoice.") if not self.user.can_edit(user_request, *args, **kwargs)[0]: - return False, u"Vous ne pouvez pas éditer les factures de cet user protégé" + return False, _("You don't have the right to delete this user's invoices.") if self.control or not self.valid: - return False, u"Vous ne pouvez pas supprimer une facture\ - contrôlée ou invalidée par un trésorier" + return False, _("You don't have the right to delete an invoice already controlled or invalidated.") else: return True, None def can_view(self, user_request, *args, **kwargs): if not user_request.has_perm('cotisations.view_facture') and\ self.user != user_request: - return False, u"Vous ne pouvez pas afficher l'historique d'une\ - facture d'un autre user que vous sans droit cableur" + return False, _("You don't have the right to see someone else's invoices history.") elif not self.valid: - return False, u"La facture est invalidée et ne peut être affichée" + return False, _("The invoice has been invalidated.") else: return True, None @staticmethod def can_change_control(user_request, *args, **kwargs): - return user_request.has_perm('cotisations.change_facture_control'), "Vous ne pouvez pas éditer le controle sans droit trésorier" + return user_request.has_perm('cotisations.change_facture_control'), _("You don't have the right to edit the controlled state.") @staticmethod def can_change_pdf(user_request, *args, **kwargs): - return user_request.has_perm('cotisations.change_facture_pdf'), "Vous ne pouvez pas éditer une facture sans droit trésorier" + return user_request.has_perm('cotisations.change_facture_pdf'), _("You don't have the right to edit an invoice.") def __init__(self, *args, **kwargs): super(Facture, self).__init__(*args, **kwargs) @@ -174,6 +204,7 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model): @receiver(post_save, sender=Facture) def facture_post_save(sender, **kwargs): """Post save d'une facture, synchronise l'user ldap""" + # TODO : translate docstrign into English facture = kwargs['instance'] user = facture.user user.ldap_sync(base=False, access_refresh=True, mac_refresh=False) @@ -182,51 +213,82 @@ def facture_post_save(sender, **kwargs): @receiver(post_delete, sender=Facture) def facture_post_delete(sender, **kwargs): """Après la suppression d'une facture, on synchronise l'user ldap""" + # TODO : translate docstring into English user = kwargs['instance'].user user.ldap_sync(base=False, access_refresh=True, mac_refresh=False) +# TODO : change Vente to Purchase class Vente(RevMixin, AclMixin, models.Model): """Objet vente, contient une quantité, une facture parente, un nom, un prix. Peut-être relié à un objet cotisation, via le boolean iscotisation""" - PRETTY_NAME = "Ventes effectuées" + # TODO : translate docstring into English + # TODO : change this to English COTISATION_TYPE = ( - ('Connexion', 'Connexion'), - ('Adhesion', 'Adhesion'), - ('All', 'All'), + ('Connexion', _("Connexion")), + ('Adhesion', _("Membership")), + ('All', _("Both of them")), ) - facture = models.ForeignKey('Facture', on_delete=models.CASCADE) - number = models.IntegerField(validators=[MinValueValidator(1)]) - name = models.CharField(max_length=255) - prix = models.DecimalField(max_digits=5, decimal_places=2) + # TODO : change facture to invoice + facture = models.ForeignKey( + 'Facture', + on_delete=models.CASCADE, + verbose_name=_("Invoice") + ) + # TODO : change number to amount for clarity + number = models.IntegerField( + validators=[MinValueValidator(1)], + verbose_name=_("Amount") + ) + # TODO : change this field for a ForeinKey to Article + name = models.CharField( + max_length=255, + verbose_name=_("Article") + ) + # TODO : change prix to price + # TODO : this field is not needed if you use Article ForeignKey + prix = models.DecimalField( + max_digits=5, + decimal_places=2, + verbose_name=_("Price")) + # TODO : this field is not needed if you use Article ForeignKey duration = models.PositiveIntegerField( - help_text="Durée exprimée en mois entiers", blank=True, - null=True) + null=True, + verbose_name=_("Duration (in whole month)") + ) + # TODO : this field is not needed if you use Article ForeignKey type_cotisation = models.CharField( choices=COTISATION_TYPE, blank=True, null=True, - max_length=255 + max_length=255, + verbose_name=_("Type of cotisation") ) class Meta: permissions = ( - ("view_vente", "Peut voir un objet vente"), - ("change_all_vente", "Superdroit, peut modifier toutes les ventes"), + ('view_vente', _("Can see a purchase's details")), + ('change_all_vente', _("Can edit all the previous purchases")), ) + verbose_name = _("Purchase") + verbose_name_plural = _("Purchases") + + # TODO : change prix_total to total_price def prix_total(self): """Renvoie le prix_total de self (nombre*prix)""" + # TODO : translate docstring to english return self.prix*self.number def update_cotisation(self): """Mets à jour l'objet related cotisation de la vente, si il existe : update la date de fin à partir de la durée de la vente""" + # TODO : translate docstring to English if hasattr(self, 'cotisation'): cotisation = self.cotisation cotisation.date_end = cotisation.date_start + relativedelta( @@ -237,6 +299,7 @@ class Vente(RevMixin, AclMixin, models.Model): """Update et crée l'objet cotisation associé à une facture, prend en argument l'user, la facture pour la quantitéi, et l'article pour la durée""" + # TODO : translate docstring to English if not hasattr(self, 'cotisation') and self.type_cotisation: cotisation = Cotisation(vente=self) cotisation.type_cotisation = self.type_cotisation @@ -264,41 +327,40 @@ class Vente(RevMixin, AclMixin, models.Model): return def save(self, *args, **kwargs): + # TODO : ecrire une docstring # On verifie que si iscotisation, duration est présent if self.type_cotisation and not self.duration: - raise ValidationError("Cotisation et durée doivent être présents\ - ensembles") + raise ValidationError( + _("A cotisation should always have a duration.") + ) self.update_cotisation() super(Vente, self).save(*args, **kwargs) def can_edit(self, user_request, *args, **kwargs): if not user_request.has_perm('cotisations.change_vente'): - return False, u"Vous n'avez pas le droit d'éditer les ventes" + return False, _("You don't have the rights to edit the purchases.") elif not user_request.has_perm('cotisations.change_all_facture') and not self.facture.user.can_edit(user_request, *args, **kwargs)[0]: - return False, u"Vous ne pouvez pas éditer les factures de cet user protégé" + return False, _("You don't have the right to edit this user's purchases.") elif not user_request.has_perm('cotisations.change_all_vente') and\ (self.facture.control or not self.facture.valid): - return False, u"Vous n'avez pas le droit d'éditer une vente\ - controlée ou invalidée par un trésorier" + return False, _("You don't have the right to edit a purchase already controlled or invalidated.") else: return True, None def can_delete(self, user_request, *args, **kwargs): if not user_request.has_perm('cotisations.delete_vente'): - return False, u"Vous n'avez pas le droit de supprimer une vente" + return False, _("You don't have the right to delete a purchase.") if not self.facture.user.can_edit(user_request, *args, **kwargs)[0]: - return False, u"Vous ne pouvez pas éditer les factures de cet user protégé" + return False, _("You don't have the right to delete this user's purchases.") if self.facture.control or not self.facture.valid: - return False, u"Vous ne pouvez pas supprimer une vente\ - contrôlée ou invalidée par un trésorier" + return False, _("You don't have the right to delete a purchase already controlled or invalidated.") else: return True, None def can_view(self, user_request, *args, **kwargs): if not user_request.has_perm('cotisations.view_vente') and\ self.facture.user != user_request: - return False, u"Vous ne pouvez pas afficher l'historique d'une\ - facture d'un autre user que vous sans droit cableur" + return False, _("You don't have the right to see someone else's purchase history.") else: return True, None @@ -306,10 +368,13 @@ class Vente(RevMixin, AclMixin, models.Model): return str(self.name) + ' ' + str(self.facture) +# TODO : change vente to purchase @receiver(post_save, sender=Vente) def vente_post_save(sender, **kwargs): """Post save d'une vente, déclencge la création de l'objet cotisation si il y a lieu(si iscotisation) """ + # TODO : translate docstring to English + # TODO : change vente to purchase vente = kwargs['instance'] if hasattr(vente, 'cotisation'): vente.cotisation.vente = vente @@ -321,10 +386,13 @@ def vente_post_save(sender, **kwargs): user.ldap_sync(base=False, access_refresh=True, mac_refresh=False) +# TODO : change vente to purchase @receiver(post_delete, sender=Vente) def vente_post_delete(sender, **kwargs): """Après suppression d'une vente, on synchronise l'user ldap (ex suppression d'une cotisation""" + # TODO : translate docstring to English + # TODO : change vente to purchase vente = kwargs['instance'] if vente.type_cotisation: user = vente.facture.user @@ -334,53 +402,69 @@ def vente_post_delete(sender, **kwargs): class Article(RevMixin, AclMixin, models.Model): """Liste des articles en vente : prix, nom, et attribut iscotisation et duree si c'est une cotisation""" - PRETTY_NAME = "Articles en vente" + # TODO : translate docstring to English + # TODO : Either use TYPE or TYPES in both choices but not both USER_TYPES = ( - ('Adherent', 'Adherent'), - ('Club', 'Club'), - ('All', 'All'), + ('Adherent', _("Member")), + ('Club', _("Club")), + ('All', _("Both of them")), ) COTISATION_TYPE = ( - ('Connexion', 'Connexion'), - ('Adhesion', 'Adhesion'), - ('All', 'All'), + ('Connexion', _("Connexion")), + ('Adhesion', _("Membership")), + ('All', _("Both of them")), ) - name = models.CharField(max_length=255) - prix = models.DecimalField(max_digits=5, decimal_places=2) + name = models.CharField( + max_length=255, + verbose_name=_("Designation") + ) + # TODO : change prix to price + prix = models.DecimalField( + max_digits=5, + decimal_places=2, + verbose_name=_("Unitary price") + ) duration = models.PositiveIntegerField( - help_text="Durée exprimée en mois entiers", blank=True, null=True, - validators=[MinValueValidator(0)]) + validators=[MinValueValidator(0)], + verbose_name=_("Duration (in whole month)") + ) type_user = models.CharField( choices=USER_TYPES, default='All', - max_length=255 + max_length=255, + verbose_name=_("Type of users concerned") ) type_cotisation = models.CharField( choices=COTISATION_TYPE, default=None, blank=True, null=True, - max_length=255 + max_length=255, + verbose_name=_("Type of cotisation") ) unique_together = ('name', 'type_user') class Meta: permissions = ( - ("view_article", "Peut voir un objet article"), + ('view_article', _("Can see an article's details")), ) + verbose_name = "Article" + verbose_name_plural = "Articles" def clean(self): - if self.name.lower() == "solde": - raise ValidationError("Solde est un nom d'article invalide") + if self.name.lower() == 'solde': + raise ValidationError( + _("Solde is a reserved article name") + ) if self.type_cotisation and not self.duration: raise ValidationError( - "La durée est obligatoire si il s'agit d'une cotisation" + _("Duration must be specified for a cotisation") ) def __str__(self): @@ -389,34 +473,51 @@ class Article(RevMixin, AclMixin, models.Model): class Banque(RevMixin, AclMixin, models.Model): """Liste des banques""" - PRETTY_NAME = "Banques enregistrées" + # TODO : translate docstring to English - name = models.CharField(max_length=255) + name = models.CharField( + max_length=255, + verbose_name=_("Name") + ) class Meta: permissions = ( - ("view_banque", "Peut voir un objet banque"), + ('view_banque', _("Can see a bank's details")), ) + verbose_name=_("Bank") + verbose_name_plural=_("Banks") def __str__(self): return self.name +# TODO : change Paiement to Payment class Paiement(RevMixin, AclMixin, models.Model): """Moyens de paiement""" - PRETTY_NAME = "Moyens de paiement" + # TODO : translate docstring to English + PAYMENT_TYPES = ( - (0, 'Autre'), - (1, 'Chèque'), + (0, _("Standard")), + (1, _("Cheque")), ) - moyen = models.CharField(max_length=255) - type_paiement = models.IntegerField(choices=PAYMENT_TYPES, default=0) + # TODO : change moyen to method + moyen = models.CharField( + max_length=255, + verbose_name=_("Method") + ) + type_paiement = models.IntegerField( + choices=PAYMENT_TYPES, + default=0, + verbose_name=_("Payment type") + ) class Meta: permissions = ( - ("view_paiement", "Peut voir un objet paiement"), + ('view_paiement', _("Can see a payement's details")), ) + verbose_name = _("Payment method") + verbose_name_plural = _("Payment methods") def __str__(self): return self.moyen @@ -426,61 +527,71 @@ class Paiement(RevMixin, AclMixin, models.Model): def save(self, *args, **kwargs): """Un seul type de paiement peut-etre cheque...""" + # TODO : translate docstring to English if Paiement.objects.filter(type_paiement=1).count() > 1: - raise ValidationError("On ne peut avoir plusieurs mode de paiement\ - chèque") + raise ValidationError( + _("You cannot have multiple payment method of type cheque") + ) super(Paiement, self).save(*args, **kwargs) class Cotisation(RevMixin, AclMixin, models.Model): """Objet cotisation, debut et fin, relié en onetoone à une vente""" - PRETTY_NAME = "Cotisations" + # TODO : translate docstring to English COTISATION_TYPE = ( - ('Connexion', 'Connexion'), - ('Adhesion', 'Adhesion'), - ('All', 'All'), + ('Connexion', _("Connexion")), + ('Adhesion', _("Adhesion")), + ('All', _("Both of them")), ) - vente = models.OneToOneField('Vente', on_delete=models.CASCADE, null=True) + # TODO : change vente to purchase + vente = models.OneToOneField( + 'Vente', + on_delete=models.CASCADE, + null=True, + verbose_name=_("Purchase") + ) type_cotisation = models.CharField( choices=COTISATION_TYPE, max_length=255, default='All', + verbose_name=_("Type of cotisation") + ) + date_start = models.DateTimeField( + verbose_name=_("Starting date") + ) + date_end = models.DateTimeField( + verbose_name=_("Ending date") ) - date_start = models.DateTimeField() - date_end = models.DateTimeField() class Meta: permissions = ( - ("view_cotisation", "Peut voir un objet cotisation"), - ("change_all_cotisation", "Superdroit, peut modifier toutes les cotisations"), + ('view_cotisation', _("Can see a cotisation's details")), + ('change_all_cotisation', _("Can edit the previous cotisations")), ) def can_edit(self, user_request, *args, **kwargs): if not user_request.has_perm('cotisations.change_cotisation'): - return False, u"Vous n'avez pas le droit d'éditer les cotisations" + return False, _("You don't have the right to edit a cotisation.") elif not user_request.has_perm('cotisations.change_all_cotisation') and\ (self.vente.facture.control or not self.vente.facture.valid): - return False, u"Vous n'avez pas le droit d'éditer une cotisation\ - controlée ou invalidée par un trésorier" + return False, _("You don't have the right to edit a cotisation already controlled or invalidated.") else: return True, None def can_delete(self, user_request, *args, **kwargs): if not user_request.has_perm('cotisations.delete_cotisation'): - return False, u"Vous n'avez pas le droit de supprimer une cotisations" + return False, _("You don't have the right to delete a cotisation.") if self.vente.facture.control or not self.vente.facture.valid: - return False, u"Vous ne pouvez pas supprimer une cotisations\ - contrôlée ou invalidée par un trésorier" + return False, _("You don't have the right to delete a cotisation already controlled or invalidated.") else: return True, None def can_view(self, user_request, *args, **kwargs): if not user_request.has_perm('cotisations.view_cotisation') and\ self.vente.facture.user != user_request: - return False, u"Vous ne pouvez pas afficher l'historique d'une\ - cotisation d'un autre user que vous sans droit cableur" + return False, _("You don't have the right to display someone else's cotisation history.") else: return True, None @@ -491,15 +602,18 @@ class Cotisation(RevMixin, AclMixin, models.Model): @receiver(post_save, sender=Cotisation) def cotisation_post_save(sender, **kwargs): """Après modification d'une cotisation, regeneration des services""" + # TODO : translate docstring to English regen('dns') regen('dhcp') regen('mac_ip_list') regen('mailing') +# TODO : should be name cotisation_post_delete @receiver(post_delete, sender=Cotisation) def vente_post_delete(sender, **kwargs): """Après suppression d'une vente, régénération des services""" + # TODO : translate docstring to English cotisation = kwargs['instance'] regen('mac_ip_list') regen('mailing') diff --git a/cotisations/payment.py b/cotisations/payment.py index f9a66bf6..a83660af 100644 --- a/cotisations/payment.py +++ b/cotisations/payment.py @@ -8,6 +8,7 @@ from django.contrib.auth.decorators import login_required from django.contrib import messages from django.views.decorators.csrf import csrf_exempt from django.utils.datastructures import MultiValueDictKeyError +from django.utils.translation import ugettext as _ from django.http import HttpResponse, HttpResponseBadRequest from collections import OrderedDict @@ -22,7 +23,9 @@ def accept_payment(request, factureid): facture = get_object_or_404(Facture, id=factureid) messages.success( request, - "Le paiement de {} € a été accepté.".format(facture.prix()) + _("The payment of %(amount)s € has been accepted.") % { + amount: facture.prix() + } ) return redirect(reverse('users:profil', kwargs={'userid':request.user.id})) @@ -32,7 +35,7 @@ def accept_payment(request, factureid): def refuse_payment(request): messages.error( request, - "Le paiement a été refusé." + _("The payment has been refused.") ) return redirect(reverse('users:profil', kwargs={'userid':request.user.id})) @@ -53,6 +56,7 @@ def ipn(request): idTransaction = request.POST['idTransaction'] # On vérifie que le paiement nous est destiné + # TODO : translate comment to English if not idTpe == AssoOption.get_cached_value('payment_id'): return HttpResponseBadRequest("HTTP/1.1 400 Bad Request") @@ -63,6 +67,7 @@ def ipn(request): facture = get_object_or_404(Facture, id=factureid) + # TODO : translate comments to English # On vérifie que le paiement est valide if not result: # Le paiement a échoué : on effectue les actions nécessaires (On indique qu'elle a échoué) diff --git a/cotisations/views.py b/cotisations/views.py index 545f9ebe..fd6256a9 100644 --- a/cotisations/views.py +++ b/cotisations/views.py @@ -36,6 +36,7 @@ from django.db import transaction from django.db.models import Q from django.forms import modelformset_factory, formset_factory from django.utils import timezone +from django.utils.translation import ugettext as _ from django.views.decorators.csrf import csrf_exempt from django.views.decorators.debug import sensitive_variables # Import des models, forms et fonctions re2o @@ -88,12 +89,16 @@ def new_facture(request, user, userid): enfin sauve la facture parente. TODO : simplifier cette fonction, déplacer l'intelligence coté models Facture et Vente.""" + # TODO : translate docstring to English + # TODO : change facture to invoice facture = Facture(user=user) + # TODO : change comment to English # Le template a besoin de connaitre les articles pour le js article_list = Article.objects.filter( Q(type_user='All') | Q(type_user=request.user.class_name) ) # On envoie la form fature et un formset d'articles + # TODO : change facture to invoice facture_form = NewFactureForm(request.POST or None, instance=facture) if request.user.is_class_club: article_formset = formset_factory(SelectClubArticleForm)(request.POST or None) @@ -104,26 +109,31 @@ def new_facture(request, user, userid): articles = article_formset # Si au moins un article est rempli if any(art.cleaned_data for art in articles): + # TODO : change solde to balance user_solde = OptionalUser.get_cached_value('user_solde') solde_negatif = OptionalUser.get_cached_value('solde_negatif') # Si on paye par solde, que l'option est activée, # on vérifie que le négatif n'est pas atteint if user_solde: + # TODO : change Paiement to Payment if new_facture_instance.paiement == Paiement.objects.get_or_create( moyen='solde' )[0]: prix_total = 0 for art_item in articles: if art_item.cleaned_data: + # change prix to price prix_total += art_item.cleaned_data['article']\ .prix*art_item.cleaned_data['quantity'] if float(user.solde) - float(prix_total) < solde_negatif: - messages.error(request, "Le solde est insuffisant pour\ - effectuer l'opération") + messages.error( + request, + _("Your balance is too low for this operation.") + ) return redirect(reverse( 'users:profil', kwargs={'userid': userid} - )) + )) new_facture_instance.save() for art_item in articles: if art_item.cleaned_data: @@ -142,34 +152,43 @@ def new_facture(request, user, userid): for art_item in articles if art_item.cleaned_data): messages.success( request, - "La cotisation a été prolongée\ - pour l'adhérent %s jusqu'au %s" % ( - user.pseudo, user.end_adhesion() - ) - ) + _("The cotisation of %(member_name)s has been \ + extended to %(end_date)s.") % { + member_name: user.pseudo, + end_date: user.end_adhesion() + } + ) else: - messages.success(request, "La facture a été crée") + messages.success( + request, + _("The invoice has been created.") + ) return redirect(reverse( 'users:profil', kwargs={'userid': userid} - )) + )) messages.error( request, - u"Il faut au moins un article valide pour créer une facture" - ) - return form({ - 'factureform': facture_form, - 'venteform': article_formset, - 'articlelist': article_list - }, 'cotisations/new_facture.html', request) + _("You need to choose at least one article.") + ) + return form( + { + 'factureform': facture_form, + 'venteform': article_formset, + 'articlelist': article_list + }, + 'cotisations/new_facture.html', request + ) +# TODO : change facture to invoice @login_required @can_change(Facture, 'pdf') def new_facture_pdf(request): """Permet de générer un pdf d'une facture. Réservée au trésorier, permet d'emettre des factures sans objet Vente ou Facture correspondant en bdd""" + # TODO : translate docstring to English facture_form = NewFactureFormPdf(request.POST or None) if facture_form.is_valid(): tbl = [] @@ -204,6 +223,7 @@ def new_facture_pdf(request): }, 'cotisations/facture.html', request) +# TODO : change facture to invoice @login_required @can_view(Facture) def facture_pdf(request, facture, factureid): @@ -211,7 +231,8 @@ def facture_pdf(request, facture, factureid): et génére une facture avec le total, le moyen de paiement, l'adresse de l'adhérent, etc. Réservée à self pour un user sans droits, les droits cableurs permettent d'afficher toute facture""" - + # TODO : translate docstring to English + # TODO : change vente to purchase ventes_objects = Vente.objects.all().filter(facture=facture) ventes = [] for vente in ventes_objects: @@ -233,12 +254,14 @@ def facture_pdf(request, facture, factureid): }) +# TODO : change facture to invoice @login_required @can_edit(Facture) def edit_facture(request, facture, factureid): """Permet l'édition d'une facture. On peut y éditer les ventes déjà effectuer, ou rendre une facture invalide (non payées, chèque en bois etc). Mets à jour les durée de cotisation attenantes""" + # TODO : translate docstring to English facture_form = EditFactureForm(request.POST or None, instance=facture, user=request.user) ventes_objects = Vente.objects.filter(facture=facture) vente_form_set = modelformset_factory( @@ -252,7 +275,10 @@ def edit_facture(request, facture, factureid): if facture_form.changed_data: facture_form.save() vente_form.save() - messages.success(request, "La facture a bien été modifiée") + messages.success( + request, + _("The invoice has been successfully edited.") + ) return redirect(reverse('cotisations:index')) return form({ 'factureform': facture_form, @@ -260,14 +286,18 @@ def edit_facture(request, facture, factureid): }, 'cotisations/edit_facture.html', request) +# TODO : change facture to invoice @login_required @can_delete(Facture) def del_facture(request, facture, factureid): """Suppression d'une facture. Supprime en cascade les ventes et cotisations filles""" + # TODO : translate docstring to English if request.method == "POST": - facture.delete() - messages.success(request, "La facture a été détruite") + messages.success( + request, + _("The invoice has been successfully deleted") + ) return redirect(reverse('cotisations:index')) return form({ 'objet': facture, @@ -275,11 +305,14 @@ def del_facture(request, facture, factureid): }, 'cotisations/delete.html', request) +# TODO : change solde to balance @login_required @can_create(Facture) @can_edit(User) def credit_solde(request, user, userid): """ Credit ou débit de solde """ + # TODO : translate docstring to English + # TODO : change facture to invoice facture = CreditSoldeForm(request.POST or None) if facture.is_valid(): facture_instance = facture.save(commit=False) @@ -292,7 +325,10 @@ def credit_solde(request, user, userid): number=1 ) new_vente.save() - messages.success(request, "Solde modifié") + messages.success( + request, + _("Banlance successfully updated.") + ) return redirect(reverse('cotisations:index')) return form({'factureform': facture, 'action_name' : 'Créditer'}, 'cotisations/facture.html', request) @@ -307,10 +343,14 @@ def add_article(request): aux articles en vente. La désignation, le prix... sont copiés à la création de la facture. Un changement de prix n'a PAS de conséquence sur les ventes déjà faites""" + # TODO : translate docstring to English article = ArticleForm(request.POST or None) if article.is_valid(): article.save() - messages.success(request, "L'article a été ajouté") + messages.success( + request, + _("The article has been successfully created.") + ) return redirect(reverse('cotisations:index-article')) return form({'factureform': article, 'action_name' : 'Ajouter'}, 'cotisations/facture.html', request) @@ -320,11 +360,15 @@ def add_article(request): def edit_article(request, article_instance, articleid): """Edition d'un article (designation, prix, etc) Réservé au trésorier""" + # TODO : translate dosctring to English article = ArticleForm(request.POST or None, instance=article_instance) if article.is_valid(): if article.changed_data: article.save() - messages.success(request, "Type d'article modifié") + messages.success( + request, + _("The article has been successfully edited.") + ) return redirect(reverse('cotisations:index-article')) return form({'factureform': article, 'action_name' : 'Editer'}, 'cotisations/facture.html', request) @@ -333,45 +377,62 @@ def edit_article(request, article_instance, articleid): @can_delete_set(Article) def del_article(request, instances): """Suppression d'un article en vente""" + # TODO : translate docstring to English article = DelArticleForm(request.POST or None, instances=instances) if article.is_valid(): article_del = article.cleaned_data['articles'] article_del.delete() - messages.success(request, "Le/les articles ont été supprimé") + messages.success( + request, + _("The article(s) have been successfully deleted.") + ) return redirect(reverse('cotisations:index-article')) return form({'factureform': article, 'action_name' : 'Supprimer'}, 'cotisations/facture.html', request) +# TODO : change paiement to payment @login_required @can_create(Paiement) def add_paiement(request): """Ajoute un moyen de paiement. Relié aux factures via foreign key""" + # TODO : translate docstring to English + # TODO : change paiement to Payment paiement = PaiementForm(request.POST or None) if paiement.is_valid(): paiement.save() - messages.success(request, "Le moyen de paiement a été ajouté") + messages.success( + request, + _("The payment method has been successfully created.") + ) return redirect(reverse('cotisations:index-paiement')) return form({'factureform': paiement, 'action_name' : 'Ajouter'}, 'cotisations/facture.html', request) +# TODO : chnage paiement to Payment @login_required @can_edit(Paiement) def edit_paiement(request, paiement_instance, paiementid): """Edition d'un moyen de paiement""" + # TODO : translate docstring to English paiement = PaiementForm(request.POST or None, instance=paiement_instance) if paiement.is_valid(): if paiement.changed_data: paiement.save() - messages.success(request, "Type de paiement modifié") + messages.success( + request, + _("The payement method has been successfully edited.") + ) return redirect(reverse('cotisations:index-paiement')) return form({'factureform': paiement, 'action_name' : 'Editer'}, 'cotisations/facture.html', request) +# TODO : change paiement to payment @login_required @can_delete_set(Paiement) def del_paiement(request, instances): """Suppression d'un moyen de paiement""" + # TODO : translate docstring to English paiement = DelPaiementForm(request.POST or None, instances=instances) if paiement.is_valid(): paiement_dels = paiement.cleaned_data['paiements'] @@ -380,67 +441,97 @@ def del_paiement(request, instances): paiement_del.delete() messages.success( request, - "Le moyen de paiement a été supprimé" - ) + _("The payment method %(method_name)s has been \ + successfully deleted") % { + method_name: paiement_del + } + ) except ProtectedError: messages.error( request, - "Le moyen de paiement %s est affecté à au moins une\ - facture, vous ne pouvez pas le supprimer" % paiement_del + _("The payment method %(method_name) can't be deleted \ + because there are invoices using it.") % { + method_name: paiement_del + } ) return redirect(reverse('cotisations:index-paiement')) return form({'factureform': paiement, 'action_name' : 'Supprimer'}, 'cotisations/facture.html', request) +# TODO : change banque to bank @login_required @can_create(Banque) def add_banque(request): """Ajoute une banque à la liste des banques""" + # TODO : tranlate docstring to English banque = BanqueForm(request.POST or None) if banque.is_valid(): banque.save() - messages.success(request, "La banque a été ajoutée") + messages.success( + request, + _("The bank has been successfully created.") + ) return redirect(reverse('cotisations:index-banque')) return form({'factureform': banque, 'action_name' : 'Ajouter'}, 'cotisations/facture.html', request) +# TODO : change banque to bank @login_required @can_edit(Banque) def edit_banque(request, banque_instance, banqueid): """Edite le nom d'une banque""" + # TODO : translate docstring to English banque = BanqueForm(request.POST or None, instance=banque_instance) if banque.is_valid(): if banque.changed_data: banque.save() - messages.success(request, "Banque modifiée") + messages.success( + request, + _("The bank has been successfully edited") + ) return redirect(reverse('cotisations:index-banque')) return form({'factureform': banque, 'action_name' : 'Editer'}, 'cotisations/facture.html', request) +# TODO : chnage banque to bank @login_required @can_delete_set(Banque) def del_banque(request, instances): """Supprime une banque""" + # TODO : translate docstring to English banque = DelBanqueForm(request.POST or None, instances=instances) if banque.is_valid(): banque_dels = banque.cleaned_data['banques'] for banque_del in banque_dels: try: banque_del.delete() - messages.success(request, "La banque a été supprimée") + messages.success( + request, + _("The bank %(bank_name)s has been successfully \ + deleted.") % { + bank_name: banque_del + } + ) except ProtectedError: - messages.error(request, "La banque %s est affectée à au moins\ - une facture, vous ne pouvez pas la supprimer" % banque_del) + messages.error( + request, + _("The bank %(bank_name)s can't be deleted \ + because there are invoices using it.") % { + bank_name: banque_del + } + ) return redirect(reverse('cotisations:index-banque')) return form({'factureform': banque, 'action_name' : 'Supprimer'}, 'cotisations/facture.html', request) +# TODO : change facture to invoice @login_required @can_view_all(Facture) @can_change(Facture, 'control') def control(request): """Pour le trésorier, vue pour controler en masse les factures.Case à cocher, pratique""" + # TODO : translate docstring to English pagination_number = GeneralOption.get_cached_value('pagination_number') facture_list = Facture.objects.select_related('user').select_related('paiement') facture_list = SortTable.sort( @@ -470,26 +561,31 @@ def control(request): @can_view_all(Article) def index_article(request): """Affiche l'ensemble des articles en vente""" + # TODO : translate docstrign to English article_list = Article.objects.order_by('name') return render(request, 'cotisations/index_article.html', { 'article_list': article_list }) +# TODO : change paiement to payment @login_required @can_view_all(Paiement) def index_paiement(request): """Affiche l'ensemble des moyens de paiement en vente""" + # TODO : translate docstring to English paiement_list = Paiement.objects.order_by('moyen') return render(request, 'cotisations/index_paiement.html', { 'paiement_list': paiement_list }) +# TODO : change banque to bank @login_required @can_view_all(Banque) def index_banque(request): """Affiche l'ensemble des banques""" + # TODO : translate docstring to English banque_list = Banque.objects.order_by('name') return render(request, 'cotisations/index_banque.html', { 'banque_list': banque_list @@ -500,6 +596,7 @@ def index_banque(request): @can_view_all(Facture) def index(request): """Affiche l'ensemble des factures, pour les cableurs et +""" + # TODO : translate docstring to English pagination_number = GeneralOption.get_cached_value('pagination_number') facture_list = Facture.objects.select_related('user')\ .select_related('paiement').prefetch_related('vente_set') @@ -515,6 +612,7 @@ def index(request): }) +# TODO : change facture to invoice @login_required def new_facture_solde(request, userid): """Creation d'une facture pour un user. Renvoie la liste des articles @@ -524,10 +622,12 @@ def new_facture_solde(request, userid): enfin sauve la facture parente. TODO : simplifier cette fonction, déplacer l'intelligence coté models Facture et Vente.""" + # TODO : translate docstring to English user = request.user facture = Facture(user=user) paiement, _created = Paiement.objects.get_or_create(moyen='Solde') facture.paiement = paiement + # TODO : translate comments to English # Le template a besoin de connaitre les articles pour le js article_list = Article.objects.filter( Q(type_user='All') | Q(type_user=request.user.class_name) @@ -551,12 +651,14 @@ def new_facture_solde(request, userid): prix_total += art_item.cleaned_data['article']\ .prix*art_item.cleaned_data['quantity'] if float(user.solde) - float(prix_total) < solde_negatif: - messages.error(request, "Le solde est insuffisant pour\ - effectuer l'opération") + messages.error( + request, + _("The balance is too low for this operation.") + ) return redirect(reverse( 'users:profil', kwargs={'userid': userid} - )) + )) facture.save() for art_item in articles: if art_item.cleaned_data: @@ -575,21 +677,25 @@ def new_facture_solde(request, userid): for art_item in articles if art_item.cleaned_data): messages.success( request, - "La cotisation a été prolongée\ - pour l'adhérent %s jusqu'au %s" % ( - user.pseudo, user.end_adhesion() - ) - ) + _("The balance of %(member_name)s has been successfully \ + extended to %(end_date)s") % { + member_name: user.pseudo, + end_date: user.end_adhesion() + } + ) else: - messages.success(request, "La facture a été crée") + messages.success( + request, + _("The invoice has been successuflly created.") + ) return redirect(reverse( 'users:profil', kwargs={'userid': userid} - )) + )) messages.error( request, - u"Il faut au moins un article valide pour créer une facture" - ) + _("You need to choose at least one article.") + ) return redirect(reverse( 'users:profil', kwargs={'userid': userid} @@ -601,12 +707,13 @@ def new_facture_solde(request, userid): }, 'cotisations/new_facture_solde.html', request) +# TODO : change recharge to reload @login_required def recharge(request): if AssoOption.get_cached_value('payment') == 'NONE': messages.error( request, - "Le paiement en ligne est désactivé." + _("Online payment is disabled.") ) return redirect(reverse( 'users:profil', From aa02016c3ac6d199f9c4cd8202b0e8bf1f53e3b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Kervella?= Date: Sat, 31 Mar 2018 15:23:34 +0000 Subject: [PATCH 2/6] Translation: Setup re2o to use locale and add French --- cotisations/forms.py | 10 +- cotisations/locale/fr/LC_MESSAGES/django.mo | Bin 0 -> 11461 bytes cotisations/locale/fr/LC_MESSAGES/django.po | 553 ++++++++++++++++++++ cotisations/models.py | 10 +- cotisations/views.py | 12 +- re2o/settings.py | 3 +- 6 files changed, 571 insertions(+), 17 deletions(-) create mode 100644 cotisations/locale/fr/LC_MESSAGES/django.mo create mode 100644 cotisations/locale/fr/LC_MESSAGES/django.po diff --git a/cotisations/forms.py b/cotisations/forms.py index e2095f7b..c16edf2c 100644 --- a/cotisations/forms.py +++ b/cotisations/forms.py @@ -80,11 +80,11 @@ class NewFactureForm(FormRevMixin, ModelForm): banque = cleaned_data.get('banque') if not paiement: raise forms.ValidationError( - _("A payment method must be specified") + _("A payment method must be specified.") ) elif paiement.type_paiement == 'check' and not (cheque and banque): raise forms.ValidationError( - _("A cheque number and a bank must be specified") + _("A cheque number and a bank must be specified.") ) return cleaned_data @@ -225,7 +225,7 @@ class PaiementForm(FormRevMixin, ModelForm): self.fields['moyen'].label = _("Payment method name") self.fields['type_paiement'].label = _("Payment type") self.fields['type_paiement'].help_text = \ - _("The payement type is use for specific behaviour.\ + _("The payement type is used for specific behaviour.\ The \"cheque\" type means a cheque number and a bank name\ may be added when using this payment method.") @@ -349,7 +349,7 @@ class RechargeForm(FormRevMixin, Form): if value < OptionalUser.get_cached_value('min_online_payment'): raise forms.ValidationError( _("Requested amount is too small. Minimum amount possible : \ - %(min_online_amount)s €") % { + %(min_online_amount)s €.") % { min_online_amount: OptionalUser.get_cached_value( 'min_online_payment' ) @@ -358,7 +358,7 @@ class RechargeForm(FormRevMixin, Form): if value + self.user.solde > OptionalUser.get_cached_value('max_solde'): raise forms.ValidationError( _("Requested amount is too high. Your balance can't exceed \ - %(max_online_balance)s €") % { + %(max_online_balance)s €.") % { max_online_balance: OptionalUser.get_cached_value( 'max_solde' ) diff --git a/cotisations/locale/fr/LC_MESSAGES/django.mo b/cotisations/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..6c0125834dfc4c86e6373b559bf0196daef05c57 GIT binary patch literal 11461 zcmb`MZHygPdB-O&5HKNtA%TP>oVWyg33s!065}k18^6ckO*Z!0;oY9ScXsdCb7!vS zW$ktOP$ASWg|sDVRaFW?RF$%js|3b;}8z?!hr*oS2Zi0G# zE98}TC%hHD7v2L8y60W^7VbX~|yZb+K_n(1HoEp3Y>!f33=t+ z^tN(*cR`KgK`6Z(fi&qo0e8bDJP!W`>ib{7S$OBo{M=xEo%E_rkYgyt+RC-w!Xr{qUdQBk)&_yD`39++Tn@;FqE7 z@ZaIoHP|nFnENS=MtX>$-hUCw4!`gC1INqo%{>1Jlz;sS$}VrldG!2tsP7t3cJKg{ z|LujEA0KKwe+uPy{{r6)e+cEDzlNHB!zAnZqfqnQfqMUE?)lfC`uPv2`T7x*y}trA zPp?Ax$+dK%=Wm2J!mSY1c<+Mu!#z-b+JQ`+w+!VcPeJ~9U*eDY`4&_^--R02WvG6B z>i9C0AN?P^4*mw-1g}F$vg55#@Ap92&t51wW}(^*q4f7DD0x2zRsZvje+|{&7of)R zENsE&;c0lADfN5_N`KG5cf;>M$@?OdJg>m_z-v*e>|p{^&>Fsg251xUN|4Z-zC}o@kyP?|qEc^)kI@|?s zLAb;4C{+J{4nGcGfU=KW80{Qfgdc`qhm!ARf{yfd1Wv(EL$&iYcmV!C)OUMP#uM;q zD1ZJblw9}Y1c>0Bg_7g*@ETZM>O*ooNeL(#!^0G{q3aR**YiFAKSn{V)~-^ea- zrJ%mvHR*n(@Im+cxFg-$E99^2@-|ABBHPj>UFbSRAp}|5N+4>o_6oc+6zPJYTiet; zRhPyrJv1oNTbrT_^R;oo-tfn#D6Z++OL>j`RsNBFJMRAVjx$hprE8v|Ig&jbqMW4= z25fwkZRlDk;oahRGyFq}eB*T#`M&H@m+WOLC8Eqyj!|S=`zar#5IU_*eh})qu7sUW zrrCRla=UvbG${uti)OXg`wLKUL-UT;}ah z^0rA9Ox_MU-T^;mjDEZr=-zB=CUKr7Q53YcnJlN3vPK&4lL0gtb<#1j2M?PtUP{7d z`95fcIYW(X8{ITm3X>wMYGk&F(N(%dO7B@vt0OUbP4pF7*2n@$p$XWYnO2bdVN`$7 zuRiiMDi5Ud(J!4Sqh7|wFO@&~rBg-yr8OJxK;3%015q*W9Z2FhxQK=5ms7QOP>Mbn zWZ`0L?ZZ3h48`mSV{@UMM1kp0y*<%?v&I0;LV|_XY|uLtx59YQ$QZms7sD*qof}Ek zenSwC#?r|uL(x1|veR>^vG^5t&e&89NRSvQrvADQ<=;m3KHFMG#v*KUXr@C(n* z@Dt-(2Q!G1Cy8l?i|tACk)%j5w9>npe!M+5!Nq1k?cwY09UcGT>BJ80wEJQrGe7?H zbCc`#k#+EvNi!41VW;R+0(6rs3(82s>k}eZ(?0lU_qE?_G`-UJBq)XC6Y2>AzPvk^9KW%yZ;CW?7bGTk81_Zl$ z^l92)!HizHs)B;%zE*QbHc>{)wGFozXs>!THEz888&q*tE!%i~_YUE- zf+mV9CzSB*+FYY=J(v%gev#S0m}=0dtMrA;6qytf=B4N(IvA~*QQZuUilt@rw*zXm zJ&vwd>eQ;V9}X4oF(Etkl@5BJkCH05mL23ysxP-AkTo_H?CSY)Aec=3tD*xBqYq)<)&KVdkP8vMVeZ1B0fyo#!ilJ6} ztqgoIJmXeP*4ye)x^Kfi`?PKu#Wcs%>^qY;=N_TPlpvL`vrFTk<(-T}8@mbOEN`bO zGw=VZY~5qoQgDk|cI}?CQ$%^#Wl0$tjP`%(tTYe%Su4>ZXTQoZr<7$dm;0AG8Q58{ z*CWWcu=m~`#<2Mq@IXm&6-`c#CquPi+%yTQ2FL3^t`xml{r4IitAFc@G7h$yE)Wrs z$Ix{B!)nA=_)>9cQzv~*gBwfks#ntfz6vj!>#2K_n;T;&@~N7;*u&MBpH(^-XU6I? zJ)VhJ&D1{|vpb!|vZNCv?C66i3$V$4C}S7RNikjCc!VRGsAT?~8>pneas%4#8;M{C z?{~XV*mTEpxm2vpJ~f){Bw-im=Ozk#4*eRh+X36r^^XZx*o)4l$ys*ljiar`DdIb4 zz-hB<@_{YKgKm=MjhSpQY&G^5i&`bY4aaNzImt> zEIrckgXo-lG8q(m`6^y4{KcR#7x*2-s_v)FLVEh}@hvk)XAbqpvvYE4iw?FNuo_y; zrcKUP^4@Obhw%rLX-KmmfB59w;l`eRJ&Cjsq>V#yGtr54+U%JR^DQiUI&H45q*{dd zc=g%ym|AWMW`G^A5;LtNTv8Tg^~*W?^E8OFfJ5}^3a)aJS~Y`YaH&s7%ah_P+b8x$ zR=nIUo`5Oj)SH>GOa#~nEUNOdf(aX1|xINGw)cSOh<9in+*!GMJR}DQ%VP`E97VT z8JpFWZDp0F24lyy;5YLEwJ2S~ktieez}6w-^-yEzB&VB*;=ai^?c%|VjNFXv*=kEQ zd}cB4zaM_xS9!nAnl@Szp4^RTZSPO!P(MR;`t5F1uQzWSRpBf(-zZ=ykmj3UG(A-fh;A^%>6_s(ukOm4#9x>%>b4BYWiM$i5D@qbE7jbY2 zOBtcF!79YBY97hPDtlx-7JZcQO!Co8tY}w-Iz!-5CJ7Dpl1G&lqPY1Y_m1`I`i2J4 zrlJ)XjEQTjm2q!G#T@|&BNuCxJMwp+s0r72R&mH>zjKFB8XWn0BSj83wT>o7RU4s6rR;|{6V(9LGiUaqI+fSr zl#Pa^pU9(^f zZLgw)jS`>rjMeT&^`vwVTuWIUsoKU`oBgN;Y4bsf-@IF^is6jVT0g4qnbvcp%8A&h zjM+~mUC$7PJz$iu)kmYFRezb0X71kM+y76Pu>S|pv)MB7BXwwBY*pC%-$M7u1q2pu z?N43$hnTAW*0{)gkp$9;Wb;1+*~4yoXVab-pm$3D>n1%W#S&q@+~9U2@_4pEI|l=+ zqNK2<;w;6ru$`E2iG^7^LeomM0j8o;n6;exPJ{IU>(i2FXTLh*$|E>M)!ng_@9J8g z99yPxW4f+11HxQwtK-*a!{w&MswLP=t+LRd^ql>y+htrd{9|^X(H^M#iC z#E#V*5nLhJ268K6xfBoNuWY0x<3SiFeMM@Btb-0pA^#_&4$IT6hTlKGjJXf~Eodo% AT>t<8 literal 0 HcmV?d00001 diff --git a/cotisations/locale/fr/LC_MESSAGES/django.po b/cotisations/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 00000000..48079d85 --- /dev/null +++ b/cotisations/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,553 @@ +# Re2o est un logiciel d'administration développé initiallement au rezometz. Il +# se veut agnostique au réseau considéré, de manière à être installable en +# quelques clics. +# +# Copyright © 2018 Maël Kervella +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +msgid "" +msgstr "" +"Project-Id-Version: 2.5\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-03-31 14:05+0000\n" +"PO-Revision-Date: 2018-03-31 16:09+0002\n" +"Last-Translator: Maël Kervella \n" +"Language-Team: \n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: cotisations/acl.py:41 +msgid "You don't have the rights to see this application." +msgstr "Vous n'avez pas les droits de voir cette application." + +#: cotisations/forms.py:63 cotisations/forms.py:298 cotisations/models.py:86 +msgid "Cheque number" +msgstr "Numéro de chèque" + +#: cotisations/forms.py:64 cotisations/forms.py:299 +msgid "Not specified" +msgstr "Non renseigné" + +#: cotisations/forms.py:66 cotisations/forms.py:301 +msgid "Select a payment method" +msgstr "Sélectionnez un moyen de paiement" + +#: cotisations/forms.py:83, cotisations/forms.py:325 +msgid "A payment method must be specified." +msgstr "Un moyen de paiement doit être renseigné." + +#: cotisations/forms.py:87, cotisations/forms.py:330 +msgid "A cheque number and a bank must be specified." +msgstr "Un numéro de chèqe et une banque doivent être renseignés." + +#: cotisations/forms.py:114 cotisations/forms.py:129 cotisations/forms.py:144 +#: cotisations/models.py:243 +msgid "Article" +msgstr "Article" + +#: cotisations/forms.py:118 cotisations/forms.py:133 cotisations/forms.py:147 +msgid "Quantity" +msgstr "Quantité" + +#: cotisations/forms.py:150 +msgid "Paid" +msgstr "Payé" + +#: cotisations/forms.py:152 +msgid "Recipient" +msgstr "Destinataire" + +#: cotisations/forms.py:154 +msgid "Address" +msgstr "Adresse" + +#: cotisations/forms.py:159 +msgid "Invoice number" +msgstr "Numéro de facture" + +#: cotisations/forms.py:174 cotisations/models.py:403 +msgid "Member" +msgstr "Adhérent" + +#: cotisations/forms.py:176 +msgid "Select the proprietary member" +msgstr "Sélectionnez l'adhérent propriétaire" + +#: cotisations/forms.py:177 +msgid "Validated invoice" +msgstr "Facture validée" + +#: cotisations/forms.py:190 +msgid "Article name" +msgstr "Nom de l'article" + +#: cotisations/forms.py:199 +msgid "Existing articles" +msgstr "Articles disponibles" + +#: cotisations/forms.py:225 +msgid "Payment method name" +msgstr "Nom du moyen de paiement" + +#: cotisations/forms.py:226 cotisations/models.py:505 +msgid "Payment type" +msgstr "Type de paiement" + +#: cotisations/forms.py:228 +msgid "" +"The payement type is used for specific behaviour. The \"cheque\" " +"type means a cheque number and a bank name may be added when " +"using this payment method." +msgstr "" +"Le type de paiement est utilisé pour des comportements spécifiques. Le type " +"\"chèque\" permet de spécifier un numéro de chèque et une banque lors de " +" l'utilisation de cette méthode." + +#: cotisations/forms.py:241 +msgid "Existing payment method" +msgstr "Moyen de paiements disponibles" + +#: cotisations/forms.py:266 +msgid "Bank name" +msgstr "Nom de la banque" + +#: cotisations/forms.py:276 +msgid "Existing banks" +msgstr "Banques disponibles" + +#: cotisations/forms.py:337 cotisations/models.py:238 +msgid "Amount" +msgstr "Montant" + +#: cotisations/forms.py:350 +#, python-format +msgid "" +"Requested amount is too small. Minimum amount possible : " +"%(min_online_amount)s €." +msgstr "" +"Montant demandé est trop faible. Montant minimal possible : " +"%(min_online_amount)s €" + +#: cotisations/forms.py:359 +#, python-format +msgid "" +"Requested amount is too high. Your balance can't exceed " +"%(max_online_balance)s €." +msgstr "" +"Montant demandé trop grand. Votre solde ne peut excéder " +"%(max_online_balance)s €" + +#: cotisations/models.py:90 +msgid "Date" +msgstr "Date" + +#: cotisations/models.py:95 +msgid "Validated" +msgstr "Validé" + +#: cotisations/models.py:100 +msgid "Controlled" +msgstr "Controllé" + +#: cotisations/models.py:107 +msgid "Can change the \"controlled\" state" +msgstr "Peut modifier l'état \"controllé\"" + +#: cotisations/models.py:109 +msgid "Can create a custom PDF invoice" +msgstr "Peut crée une facture PDF personnalisée" + +#: cotisations/models.py:110 +msgid "Can see an invoice's details" +msgstr "Peut voir les détails d'une facture" + +#: cotisations/models.py:111 +msgid "Can edit all the previous invoices" +msgstr "Peut modifier toutes les factures existantes" + +#: cotisations/models.py:113 cotisations/models.py:233 +msgid "Invoice" +msgstr "Facture" + +#: cotisations/models.py:114 +msgid "Invoices" +msgstr "Factures" + +#: cotisations/models.py:152 cotisations/models.py:186 +msgid "You don't have the right to edit an invoice." +msgstr "Vous n'avez pas le droit de modifier une facture." + +#: cotisations/models.py:154 +msgid "You don't have the right to edit this user's invoices." +msgstr "Vous n'avez pas le droit de modifier les facture de cette utilisateur." + +#: cotisations/models.py:157 +msgid "" +"You don't have the right to edit an invoice already controlled or " +"invalidated." +msgstr "" +"Vous n'avez pas le droit de modifier une facture précedement controllée " +"ou invalidée." + +#: cotisations/models.py:163 +msgid "You don't have the right to delete an invoice." +msgstr "Vous n'avez pas le droit de supprimer une facture." + +#: cotisations/models.py:165 +msgid "You don't have the right to delete this user's invoices." +msgstr "Vous n'avez pas le droit de supprimer les factures de cet utilisateur." + +#: cotisations/models.py:167 +msgid "" +"You don't have the right to delete an invoice already controlled or " +"invalidated." +msgstr "" +"Vous n'avez pas le droit de supprimer une facture précedement controllée " +"ou invalidée." + +#: cotisations/models.py:174 +msgid "You don't have the right to see someone else's invoices history." +msgstr "" +"Vous n'avez pas le droit de voir l'historique de la facture de " +"quelqu'un d'autre." + +#: cotisations/models.py:176 +msgid "The invoice has been invalidated." +msgstr "La facture a été invalidée." + +#: cotisations/models.py:182 +msgid "You don't have the right to edit the controlled state." +msgstr "Vous n'avez pas le droit de modifier l'état \"controllé\"." + +#: cotisations/models.py:224 cotisations/models.py:409 +#: cotisations/models.py:536 +msgid "Connexion" +msgstr "Connexion" + +#: cotisations/models.py:225 cotisations/models.py:410 +msgid "Membership" +msgstr "Adhésion" + +#: cotisations/models.py:226 cotisations/models.py:405 +#: cotisations/models.py:411 cotisations/models.py:538 +msgid "Both of them" +msgstr "Les deux" + +#: cotisations/models.py:250 +msgid "Price" +msgstr "Prix" + +#: cotisations/models.py:255 cotisations/models.py:428 +msgid "Duration (in whole month)" +msgstr "Durée (en mois entiers)" + +#: cotisations/models.py:263 cotisations/models.py:442 +#: cotisations/models.py:552 +msgid "Type of cotisation" +msgstr "Type de cotisation" + +#: cotisations/models.py:268 +msgid "Can see a purchase's details" +msgstr "Peut voir les détails d'un achat" + +#: cotisations/models.py:269 +msgid "Can edit all the previous purchases" +msgstr "Peut voir les achats existants" + +#: cotisations/models.py:271 cotisations/models.py:546 +msgid "Purchase" +msgstr "Achat" + +#: cotisations/models.py:272 +msgid "Purchases" +msgstr "Achat" + +#: cotisations/models.py:328 +msgid "A cotisation should always have a duration." +msgstr "Une cotisation devrait toujours avoir une durée." + +#: cotisations/models.py:335 +msgid "You don't have the right to edit the purchases." +msgstr "Vous n'avez pas le droit de modifier les achats." + +#: cotisations/models.py:337 +msgid "You don't have the right to edit this user's purchases." +msgstr "Vous n'avez pas le droit de modifier les achats de cet utilisateur." + +#: cotisations/models.py:340 +msgid "" +"You don't have the right to edit a purchase already controlled or " +"invalidated." +msgstr "" +"Vous n'avez pas le droit de modifier un achat précédement controllé ou " +"invalidé." + +#: cotisations/models.py:346 +msgid "You don't have the right to delete a purchase." +msgstr "Vous n'avez pas le droit de supprimer un achat." + +#: cotisations/models.py:348 +msgid "You don't have the right to delete this user's purchases." +msgstr "Vous n'avez pas le droit de supprimer les achats de cet utilisateur." + +#: cotisations/models.py:350 +msgid "" +"You don't have the right to delete a purchase already controlled or " +"invalidated." +msgstr "" +"Vous n'avez pas le droit de supprimer un achat précédement controllé ou " +"invalidé." + +#: cotisations/models.py:357 +msgid "You don't have the right to see someone else's purchase history." +msgstr "Vous n'avez pas le droit de voir l'historique d'un achat de quelqu'un d'autre." + +#: cotisations/models.py:404 +msgid "Club" +msgstr "Club" + +#: cotisations/models.py:416 +msgid "Designation" +msgstr "Désignation" + +#: cotisations/models.py:422 +msgid "Unitary price" +msgstr "Prix unitaire" + +#: cotisations/models.py:434 +msgid "Type of users concerned" +msgstr "Type d'utilisateurs concernés" + +#: cotisations/models.py:449 +msgid "Can see an article's details" +msgstr "Peut voir les détails d'un article" + +#: cotisations/models.py:457 +msgid "Solde is a reserved article name" +msgstr "Solde est un nom d'article réservé" + +#: cotisations/models.py:461 +msgid "Duration must be specified for a cotisation" +msgstr "La durée doit être spécifiée pour une cotisation" + +#: cotisations/models.py:474 +msgid "Name" +msgstr "Nom" + +#: cotisations/models.py:479 +msgid "Can see a bank's details" +msgstr "Peut voir les détails d'une banque" + +#: cotisations/models.py:481 +msgid "Bank" +msgstr "Banque" + +#: cotisations/models.py:482 +msgid "Banks" +msgstr "Banques" + +#: cotisations/models.py:493 +msgid "Standard" +msgstr "Standard" + +#: cotisations/models.py:494 +msgid "Cheque" +msgstr "Chèque" + +#: cotisations/models.py:500 +msgid "Method" +msgstr "Moyen" + +#: cotisations/models.py:510 +msgid "Can see a payement's details" +msgstr "Peut voir les détails d'un paiement" + +#: cotisations/models.py:512 +msgid "Payment method" +msgstr "Moyen de paiement" + +#: cotisations/models.py:513 +msgid "Payment methods" +msgstr "Moyens de paiement" + +#: cotisations/models.py:526 +msgid "You cannot have multiple payment method of type cheque" +msgstr "Vous ne pouvez avoir plusieurs moyens de paiement de type chèque" + +#: cotisations/models.py:555 +msgid "Starting date" +msgstr "Date de début" + +#: cotisations/models.py:558 +msgid "Ending date" +msgstr "Date de fin" + +#: cotisations/models.py:563 +msgid "Can see a cotisation's details" +msgstr "Peut voir les détails d'une cotisation" + +#: cotisations/models.py:564 +msgid "Can edit the previous cotisations" +msgstr "Peut voir les cotisations existantes" + +#: cotisations/models.py:569 +msgid "You don't have the right to edit a cotisation." +msgstr "Vous n'avez pas le droit de modifier une cotisation." + +#: cotisations/models.py:572 +msgid "" +"You don't have the right to edit a cotisation already controlled or " +"invalidated." +msgstr "" +"Vous n'avez pas le droit de modifier une cotisaiton précédement controllée " +"ou invalidée." + +#: cotisations/models.py:578 +msgid "You don't have the right to delete a cotisation." +msgstr "Vous n'avez pas le droit de supprimer une cotisation." + +#: cotisations/models.py:580 +msgid "" +"You don't have the right to delete a cotisation already controlled or " +"invalidated." +msgstr "" +"Vous n'avez pas le droit de supprimer une cotisation précédement controllée " +"ou invalidée." + +#: cotisations/models.py:587 +msgid "You don't have the right to see someone else's cotisation history." +msgstr "" +"Vous n'avez pas le droit de voir l'historique d'une cotisation de " +"quelqu'un d'autre." + +#: cotisations/payment.py:26 +#, python-format +msgid "The payment of %(amount)s € has been accepted." +msgstr "Le paiement de %(amount)s € a été accepté." + +#: cotisations/payment.py:38 +msgid "The payment has been refused." +msgstr "Le paiment a été refusé." + +#: cotisations/views.py:133 +msgid "Your balance is too low for this operation." +msgstr "Votre solde est trop faible pour cette opération." + +#: cotisations/views.py:163 +#, python-format +msgid "" +"The cotisation of %(member_name)s has been extended to " +"%(end_date)s." +msgstr "La cotisation de %(member_name)s a été étendu jusqu'à %(end_date)s." + +#: cotisations/views.py:172 +msgid "The invoice has been created." +msgstr "La facture a été créée." + +#: cotisations/views.py:180 cotisations/views.py:777 +msgid "You need to choose at least one article." +msgstr "Vous devez choisir au moins un article." + +#: cotisations/views.py:292 +msgid "The invoice has been successfully edited." +msgstr "La facture a été crée avec succès." + +#: cotisations/views.py:314 +msgid "The invoice has been successfully deleted." +msgstr "La facture a été supprimée avec succès." + +#: cotisations/views.py:351 +msgid "Balance successfully updated." +msgstr "Solde mis à jour avec succès." + +#: cotisations/views.py:376 +msgid "The article has been successfully created." +msgstr "L'article a été créé avec succès." + +#: cotisations/views.py:400 +msgid "The article has been successfully edited." +msgstr "L'article a été modifié avec succès." + +#: cotisations/views.py:419 +msgid "The article(s) have been successfully deleted." +msgstr "L'(es) article(s) a(ont) été supprimé(s) avec succès. " + +#: cotisations/views.py:441 +msgid "The payment method has been successfully created." +msgstr "Le moyen de paiement a été créé avec succès." + +#: cotisations/views.py:465 +msgid "The payement method has been successfully edited." +msgstr "Le moyen de paiement a été modifié avec succès." + +#: cotisations/views.py:488 +#, python-format +msgid "" +"The payment method %(method_name)s has been successfully " +"deleted." +msgstr "Le moyen de paiement %(method_name)s a été supprimé avec succès." + +#: cotisations/views.py:496 +#, python-format +msgid "" +"The payment method %(method_name)s can't be deleted " +"because there are invoices using it." +msgstr "" +"Le moyen de paiement %(method_name)s ne peut pas être mis à jour car il y a " +"des factures l'utilisant." + +#: cotisations/views.py:519 +msgid "The bank has been successfully created." +msgstr "La banque a été crée avec succès." + +#: cotisations/views.py:543 +msgid "The bank has been successfully edited" +msgstr "La banque a été modifée avec succès." + +#: cotisations/views.py:566 +#, python-format +msgid "" +"The bank %(bank_name)s has been successfully deleted." +msgstr "La banque %(bank_name)s a été supprimée avec succès." + +#: cotisations/views.py:574 +#, python-format +msgid "" +"The bank %(bank_name)s can't be deleted because there " +"are invoices using it." +msgstr "" +"La banque %(bank_name)s ne peut pas être supprimée car il y a des factures " +"qui l'utilisent." + +#: cotisations/views.py:730 +msgid "The balance is too low for this operation." +msgstr "Le solde est trop faible pour cette opération." + +#: cotisations/views.py:760 +#, python-format +msgid "" +"The cotisation of %(member_name)s has been successfully " +"extended to %(end_date)s." +msgstr "La cotisation de %(member_name)s a été prolongée jusqu'à %(end_date)s." + +#: cotisations/views.py:769 +msgid "The invoice has been successuflly created." +msgstr "La facture a été créée avec succès." + +#: cotisations/views.py:796 +msgid "Online payment is disabled." +msgstr "Le paiement en ligne est désactivé." diff --git a/cotisations/models.py b/cotisations/models.py index c529c281..f46598b2 100644 --- a/cotisations/models.py +++ b/cotisations/models.py @@ -105,7 +105,7 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model): abstract = False permissions = ( # TODO : change facture to invoice - ('change_facture_control', _("Can change the controlled state")), + ('change_facture_control', _("Can change the \"controlled\" state")), # TODO : seems more likely to be call create_facture_pdf or create_invoice_pdf ('change_facture_pdf', _("Can create a custom PDF invoice")), ('view_facture', _("Can see an invoice's details")), @@ -185,7 +185,7 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model): @staticmethod def can_change_control(user_request, *args, **kwargs): - return user_request.has_perm('cotisations.change_facture_control'), _("You don't have the right to edit the controlled state.") + return user_request.has_perm('cotisations.change_facture_control'), _("You don't have the right to edit the \"controlled\" state.") @staticmethod def can_change_pdf(user_request, *args, **kwargs): @@ -338,7 +338,7 @@ class Vente(RevMixin, AclMixin, models.Model): def can_edit(self, user_request, *args, **kwargs): if not user_request.has_perm('cotisations.change_vente'): - return False, _("You don't have the rights to edit the purchases.") + return False, _("You don't have the right to edit the purchases.") elif not user_request.has_perm('cotisations.change_all_facture') and not self.facture.user.can_edit(user_request, *args, **kwargs)[0]: return False, _("You don't have the right to edit this user's purchases.") elif not user_request.has_perm('cotisations.change_all_vente') and\ @@ -541,7 +541,7 @@ class Cotisation(RevMixin, AclMixin, models.Model): COTISATION_TYPE = ( ('Connexion', _("Connexion")), - ('Adhesion', _("Adhesion")), + ('Adhesion', _("Membership")), ('All', _("Both of them")), ) @@ -591,7 +591,7 @@ class Cotisation(RevMixin, AclMixin, models.Model): def can_view(self, user_request, *args, **kwargs): if not user_request.has_perm('cotisations.view_cotisation') and\ self.vente.facture.user != user_request: - return False, _("You don't have the right to display someone else's cotisation history.") + return False, _("You don't have the right to see someone else's cotisation history.") else: return True, None diff --git a/cotisations/views.py b/cotisations/views.py index fd6256a9..9c05ade6 100644 --- a/cotisations/views.py +++ b/cotisations/views.py @@ -296,7 +296,7 @@ def del_facture(request, facture, factureid): if request.method == "POST": messages.success( request, - _("The invoice has been successfully deleted") + _("The invoice has been successfully deleted.") ) return redirect(reverse('cotisations:index')) return form({ @@ -327,7 +327,7 @@ def credit_solde(request, user, userid): new_vente.save() messages.success( request, - _("Banlance successfully updated.") + _("Balance successfully updated.") ) return redirect(reverse('cotisations:index')) return form({'factureform': facture, 'action_name' : 'Créditer'}, 'cotisations/facture.html', request) @@ -442,14 +442,14 @@ def del_paiement(request, instances): messages.success( request, _("The payment method %(method_name)s has been \ - successfully deleted") % { + successfully deleted.") % { method_name: paiement_del } ) except ProtectedError: messages.error( request, - _("The payment method %(method_name) can't be deleted \ + _("The payment method %(method_name)s can't be deleted \ because there are invoices using it.") % { method_name: paiement_del } @@ -677,8 +677,8 @@ def new_facture_solde(request, userid): for art_item in articles if art_item.cleaned_data): messages.success( request, - _("The balance of %(member_name)s has been successfully \ - extended to %(end_date)s") % { + _("The cotisation of %(member_name)s has been successfully \ + extended to %(end_date)s.") % { member_name: user.pseudo, end_date: user.end_adhesion() } diff --git a/re2o/settings.py b/re2o/settings.py index c101460b..e7853141 100644 --- a/re2o/settings.py +++ b/re2o/settings.py @@ -82,6 +82,7 @@ INSTALLED_APPS = ( MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.locale.LocaleMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', @@ -120,7 +121,7 @@ WSGI_APPLICATION = 're2o.wsgi.application' # Internationalization # https://docs.djangoproject.com/en/1.8/topics/i18n/ -LANGUAGE_CODE = 'fr-fr' +LANGUAGE_CODE = 'en' TIME_ZONE = 'Europe/Paris' From ccab7ff71897e3b5b43f08ffb3bbdaa5bb4ee92b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Kervella?= Date: Sat, 31 Mar 2018 15:32:26 +0000 Subject: [PATCH 3/6] Translation: Fix some lazy translations --- cotisations/forms.py | 29 +++++------ cotisations/models.py | 111 +++++++++++++++++++++--------------------- 2 files changed, 71 insertions(+), 69 deletions(-) diff --git a/cotisations/forms.py b/cotisations/forms.py index c16edf2c..5cdf06bb 100644 --- a/cotisations/forms.py +++ b/cotisations/forms.py @@ -41,6 +41,7 @@ from django.db.models import Q from django.forms import ModelForm, Form from django.core.validators import MinValueValidator,MaxValueValidator from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _l from .models import Article, Paiement, Facture, Banque from preferences.models import OptionalUser @@ -111,11 +112,11 @@ class SelectUserArticleForm(FormRevMixin, Form): # TODO : translate docstring to English article = forms.ModelChoiceField( queryset=Article.objects.filter(Q(type_user='All') | Q(type_user='Adherent')), - label=_("Article"), + label=_l("Article"), required=True ) quantity = forms.IntegerField( - label=_("Quantity"), + label=_l("Quantity"), validators=[MinValueValidator(1)], required=True ) @@ -126,11 +127,11 @@ class SelectClubArticleForm(Form): # TODO : translate docstring to English article = forms.ModelChoiceField( queryset=Article.objects.filter(Q(type_user='All') | Q(type_user='Club')), - label=_("Article"), + label=_l("Article"), required=True ) quantity = forms.IntegerField( - label=_("Quantity"), + label=_l("Quantity"), validators=[MinValueValidator(1)], required=True ) @@ -141,22 +142,22 @@ class NewFactureFormPdf(Form): # TODO : translate docstring to English article = forms.ModelMultipleChoiceField( queryset=Article.objects.all(), - label=_("Article") + label=_l("Article") ) number = forms.IntegerField( - label=_("Quantity"), + label=_l("Quantity"), validators=[MinValueValidator(1)] ) - paid = forms.BooleanField(label=_("Paid"), required=False) + paid = forms.BooleanField(label=_l("Paid"), required=False) # TODO : change dest field to recipient - dest = forms.CharField(required=True, max_length=255, label=_("Recipient")) + dest = forms.CharField(required=True, max_length=255, label=_l("Recipient")) # TODO : change chambre field to address - chambre = forms.CharField(required=False, max_length=10, label=_("Address")) + chambre = forms.CharField(required=False, max_length=10, label=_l("Address")) # TODO : change fid field to invoice_id fid = forms.CharField( required=True, max_length=10, - label=_("Invoice number") + label=_l("Invoice number") ) # TODO : change Facture to Invoice @@ -196,7 +197,7 @@ class DelArticleForm(FormRevMixin, Form): # TODO : translate docstring to English articles = forms.ModelMultipleChoiceField( queryset=Article.objects.none(), - label=_("Existing articles"), + label=_l("Existing articles"), widget=forms.CheckboxSelectMultiple ) @@ -238,7 +239,7 @@ class DelPaiementForm(FormRevMixin, Form): # TODO : change paiement to payment paiements = forms.ModelMultipleChoiceField( queryset=Paiement.objects.none(), - label=_("Existing payment method"), + label=_l("Existing payment method"), widget=forms.CheckboxSelectMultiple ) @@ -273,7 +274,7 @@ class DelBanqueForm(FormRevMixin, Form): # TODO : change banque to bank banques = forms.ModelMultipleChoiceField( queryset=Banque.objects.none(), - label=_("Existing banks"), + label=_l("Existing banks"), widget=forms.CheckboxSelectMultiple ) @@ -335,7 +336,7 @@ class NewFactureSoldeForm(NewFactureForm): # TODO : Better name and docstring class RechargeForm(FormRevMixin, Form): value = forms.FloatField( - label=_("Amount"), + label=_l("Amount"), min_value=0.01, validators = [] ) diff --git a/cotisations/models.py b/cotisations/models.py index f46598b2..d270857f 100644 --- a/cotisations/models.py +++ b/cotisations/models.py @@ -57,6 +57,7 @@ from django.db.models import Max from django.utils import timezone from machines.models import regen from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _l from re2o.field_permissions import FieldPermissionModelMixin from re2o.mixins import AclMixin, RevMixin @@ -84,35 +85,35 @@ class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model): cheque = models.CharField( max_length=255, blank=True, - verbose_name=_("Cheque number") + verbose_name=_l("Cheque number") ) date = models.DateTimeField( auto_now_add=True, - verbose_name=_("Date") + verbose_name=_l("Date") ) # TODO : change name to validity for clarity valid = models.BooleanField( default=True, - verbose_name=_("Validated") + verbose_name=_l("Validated") ) # TODO : changed name to controlled for clarity control = models.BooleanField( default=False, - verbose_name=_("Controlled") + verbose_name=_l("Controlled") ) class Meta: abstract = False permissions = ( # TODO : change facture to invoice - ('change_facture_control', _("Can change the \"controlled\" state")), + ('change_facture_control', _l("Can change the \"controlled\" state")), # TODO : seems more likely to be call create_facture_pdf or create_invoice_pdf - ('change_facture_pdf', _("Can create a custom PDF invoice")), - ('view_facture', _("Can see an invoice's details")), - ('change_all_facture', _("Can edit all the previous invoices")), + ('change_facture_pdf', _l("Can create a custom PDF invoice")), + ('view_facture', _l("Can see an invoice's details")), + ('change_all_facture', _l("Can edit all the previous invoices")), ) - verbose_name = _("Invoice") - verbose_name_plural = _("Invoices") + verbose_name = _l("Invoice") + verbose_name_plural = _l("Invoices") def linked_objects(self): """Return linked objects : machine and domain. @@ -227,38 +228,38 @@ class Vente(RevMixin, AclMixin, models.Model): # TODO : change this to English COTISATION_TYPE = ( - ('Connexion', _("Connexion")), - ('Adhesion', _("Membership")), - ('All', _("Both of them")), + ('Connexion', _l("Connexion")), + ('Adhesion', _l("Membership")), + ('All', _l("Both of them")), ) # TODO : change facture to invoice facture = models.ForeignKey( 'Facture', on_delete=models.CASCADE, - verbose_name=_("Invoice") + verbose_name=_l("Invoice") ) # TODO : change number to amount for clarity number = models.IntegerField( validators=[MinValueValidator(1)], - verbose_name=_("Amount") + verbose_name=_l("Amount") ) # TODO : change this field for a ForeinKey to Article name = models.CharField( max_length=255, - verbose_name=_("Article") + verbose_name=_l("Article") ) # TODO : change prix to price # TODO : this field is not needed if you use Article ForeignKey prix = models.DecimalField( max_digits=5, decimal_places=2, - verbose_name=_("Price")) + verbose_name=_l("Price")) # TODO : this field is not needed if you use Article ForeignKey duration = models.PositiveIntegerField( blank=True, null=True, - verbose_name=_("Duration (in whole month)") + verbose_name=_l("Duration (in whole month)") ) # TODO : this field is not needed if you use Article ForeignKey type_cotisation = models.CharField( @@ -266,16 +267,16 @@ class Vente(RevMixin, AclMixin, models.Model): blank=True, null=True, max_length=255, - verbose_name=_("Type of cotisation") + verbose_name=_l("Type of cotisation") ) class Meta: permissions = ( - ('view_vente', _("Can see a purchase's details")), - ('change_all_vente', _("Can edit all the previous purchases")), + ('view_vente', _l("Can see a purchase's details")), + ('change_all_vente', _l("Can edit all the previous purchases")), ) - verbose_name = _("Purchase") - verbose_name_plural = _("Purchases") + verbose_name = _l("Purchase") + verbose_name_plural = _l("Purchases") # TODO : change prix_total to total_price @@ -406,38 +407,38 @@ class Article(RevMixin, AclMixin, models.Model): # TODO : Either use TYPE or TYPES in both choices but not both USER_TYPES = ( - ('Adherent', _("Member")), - ('Club', _("Club")), - ('All', _("Both of them")), + ('Adherent', _l("Member")), + ('Club', _l("Club")), + ('All', _l("Both of them")), ) COTISATION_TYPE = ( - ('Connexion', _("Connexion")), - ('Adhesion', _("Membership")), - ('All', _("Both of them")), + ('Connexion', _l("Connexion")), + ('Adhesion', _l("Membership")), + ('All', _l("Both of them")), ) name = models.CharField( max_length=255, - verbose_name=_("Designation") + verbose_name=_l("Designation") ) # TODO : change prix to price prix = models.DecimalField( max_digits=5, decimal_places=2, - verbose_name=_("Unitary price") + verbose_name=_l("Unitary price") ) duration = models.PositiveIntegerField( blank=True, null=True, validators=[MinValueValidator(0)], - verbose_name=_("Duration (in whole month)") + verbose_name=_l("Duration (in whole month)") ) type_user = models.CharField( choices=USER_TYPES, default='All', max_length=255, - verbose_name=_("Type of users concerned") + verbose_name=_l("Type of users concerned") ) type_cotisation = models.CharField( choices=COTISATION_TYPE, @@ -445,14 +446,14 @@ class Article(RevMixin, AclMixin, models.Model): blank=True, null=True, max_length=255, - verbose_name=_("Type of cotisation") + verbose_name=_l("Type of cotisation") ) unique_together = ('name', 'type_user') class Meta: permissions = ( - ('view_article', _("Can see an article's details")), + ('view_article', _l("Can see an article's details")), ) verbose_name = "Article" verbose_name_plural = "Articles" @@ -477,15 +478,15 @@ class Banque(RevMixin, AclMixin, models.Model): name = models.CharField( max_length=255, - verbose_name=_("Name") + verbose_name=_l("Name") ) class Meta: permissions = ( - ('view_banque', _("Can see a bank's details")), + ('view_banque', _l("Can see a bank's details")), ) - verbose_name=_("Bank") - verbose_name_plural=_("Banks") + verbose_name=_l("Bank") + verbose_name_plural=_l("Banks") def __str__(self): return self.name @@ -497,27 +498,27 @@ class Paiement(RevMixin, AclMixin, models.Model): # TODO : translate docstring to English PAYMENT_TYPES = ( - (0, _("Standard")), - (1, _("Cheque")), + (0, _l("Standard")), + (1, _l("Cheque")), ) # TODO : change moyen to method moyen = models.CharField( max_length=255, - verbose_name=_("Method") + verbose_name=_l("Method") ) type_paiement = models.IntegerField( choices=PAYMENT_TYPES, default=0, - verbose_name=_("Payment type") + verbose_name=_l("Payment type") ) class Meta: permissions = ( - ('view_paiement', _("Can see a payement's details")), + ('view_paiement', _l("Can see a payement's details")), ) - verbose_name = _("Payment method") - verbose_name_plural = _("Payment methods") + verbose_name = _l("Payment method") + verbose_name_plural = _l("Payment methods") def __str__(self): return self.moyen @@ -540,9 +541,9 @@ class Cotisation(RevMixin, AclMixin, models.Model): # TODO : translate docstring to English COTISATION_TYPE = ( - ('Connexion', _("Connexion")), - ('Adhesion', _("Membership")), - ('All', _("Both of them")), + ('Connexion', _l("Connexion")), + ('Adhesion', _l("Membership")), + ('All', _l("Both of them")), ) # TODO : change vente to purchase @@ -550,25 +551,25 @@ class Cotisation(RevMixin, AclMixin, models.Model): 'Vente', on_delete=models.CASCADE, null=True, - verbose_name=_("Purchase") + verbose_name=_l("Purchase") ) type_cotisation = models.CharField( choices=COTISATION_TYPE, max_length=255, default='All', - verbose_name=_("Type of cotisation") + verbose_name=_l("Type of cotisation") ) date_start = models.DateTimeField( - verbose_name=_("Starting date") + verbose_name=_l("Starting date") ) date_end = models.DateTimeField( - verbose_name=_("Ending date") + verbose_name=_l("Ending date") ) class Meta: permissions = ( - ('view_cotisation', _("Can see a cotisation's details")), - ('change_all_cotisation', _("Can edit the previous cotisations")), + ('view_cotisation', _l("Can see a cotisation's details")), + ('change_all_cotisation', _l("Can edit the previous cotisations")), ) def can_edit(self, user_request, *args, **kwargs): From 433ee298dc7703005c63b298ab76df8b340d3e09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Kervella?= Date: Sun, 8 Apr 2018 17:41:45 +0000 Subject: [PATCH 4/6] Translation: Mark all strings in templates of cotisation --- .../templates/cotisations/aff_article.html | 15 ++-- .../templates/cotisations/aff_banque.html | 7 +- .../cotisations/aff_cotisations.html | 86 ++++++++++++------- .../templates/cotisations/aff_paiement.html | 11 +-- .../templates/cotisations/control.html | 64 ++++++++++---- cotisations/templates/cotisations/delete.html | 15 ++-- .../templates/cotisations/edit_facture.html | 18 ++-- .../templates/cotisations/facture.html | 5 +- cotisations/templates/cotisations/index.html | 10 +-- .../templates/cotisations/index_article.html | 22 ++--- .../templates/cotisations/index_banque.html | 22 ++--- .../templates/cotisations/index_paiement.html | 22 ++--- .../templates/cotisations/new_facture.html | 59 +++++++------ .../cotisations/new_facture_solde.html | 57 ++++++------ .../templates/cotisations/payment.html | 18 ++-- .../templates/cotisations/recharge.html | 22 +++-- .../templates/cotisations/sidebar.html | 19 ++-- 17 files changed, 275 insertions(+), 197 deletions(-) diff --git a/cotisations/templates/cotisations/aff_article.html b/cotisations/templates/cotisations/aff_article.html index 833b7de0..eb4ec0a7 100644 --- a/cotisations/templates/cotisations/aff_article.html +++ b/cotisations/templates/cotisations/aff_article.html @@ -23,15 +23,16 @@ with this program; if not, write to the Free Software Foundation, Inc., {% endcomment %} {% load acl %} +{% load i18n %} - - - - - + + + + + @@ -44,11 +45,11 @@ with this program; if not, write to the Free Software Foundation, Inc., diff --git a/cotisations/templates/cotisations/aff_banque.html b/cotisations/templates/cotisations/aff_banque.html index 1ef4cb76..d9ec8d1c 100644 --- a/cotisations/templates/cotisations/aff_banque.html +++ b/cotisations/templates/cotisations/aff_banque.html @@ -23,11 +23,12 @@ with this program; if not, write to the Free Software Foundation, Inc., {% endcomment %} {% load acl %} +{% load i18n %}
ArticlePrixType CotisationDurée (mois)Article pour{% trans "Article" %}{% trans "Price" %}{% trans "Cotisation type" %}{% trans "Duration (month)" %}{% trans "Concerned users" %}
{{ article.type_user }} {% can_edit article %} - + {% acl_end %} - +
- + @@ -36,11 +37,11 @@ with this program; if not, write to the Free Software Foundation, Inc., diff --git a/cotisations/templates/cotisations/aff_cotisations.html b/cotisations/templates/cotisations/aff_cotisations.html index 48a856a2..fdb575ed 100644 --- a/cotisations/templates/cotisations/aff_cotisations.html +++ b/cotisations/templates/cotisations/aff_cotisations.html @@ -23,20 +23,34 @@ with this program; if not, write to the Free Software Foundation, Inc., {% endcomment %} {% load acl %} +{% load i18n %} +
{% if facture_list.paginator %} -{% include "pagination.html" with list=facture_list %} +{% include 'pagination.html' with list=facture_list %} {% endif %}
Banque{% trans "Bank" %}
{{ banque.name }} {% can_edit banque %} - + {% acl_end %} - +
- - - - - - + + + + + + @@ -50,39 +64,49 @@ with this program; if not, write to the Free Software Foundation, Inc., {% endfor %}
{% include "buttons/sort.html" with prefix='cotis' col='user' text='Utilisateur' %}DesignationPrix total{% include "buttons/sort.html" with prefix='cotis' col='paiement' text='Moyen de paiement' %}{% include "buttons/sort.html" with prefix='cotis' col='date' text='Date' %}{% include "buttons/sort.html" with prefix='cotis' col='id' text='Id facture' %} + {% trans "User" as tr_user %} + {% include 'buttons/sort.html' with prefix='cotis' col='user' text=tr_user %} + {% trans "Designation" %}{% trans "Total price" %} + {% trans "Payment method" as tr_payment_method %} + {% include 'buttons/sort.html' with prefix='cotis' col='paiement' text=tr_payment_method %} + + {% trans "Date" as tr_date %} + {% include 'buttons/sort.html' with prefix='cotis' col='date' text=tr_date %} + + {% trans "Invoice id" as tr_invoice_id %} + {% include 'buttons/sort.html' with prefix='cotis' col='id' text=tr_invoice_id %} +
{{ facture.date }} {{ facture.id }} - + - {% if facture.valid %} + {% if facture.valid %} - - PDF + {% trans "PDF" %} - {% else %} - Facture invalide - {% endif %} + {% else %} + {% trans "Invalidated invoice" %} + {% endif %}
{% if facture_list.paginator %} -{% include "pagination.html" with list=facture_list %} +{% include 'pagination.html' with list=facture_list %} {% endif %} diff --git a/cotisations/templates/cotisations/aff_paiement.html b/cotisations/templates/cotisations/aff_paiement.html index 09e5acc3..63a5cf35 100644 --- a/cotisations/templates/cotisations/aff_paiement.html +++ b/cotisations/templates/cotisations/aff_paiement.html @@ -23,11 +23,12 @@ with this program; if not, write to the Free Software Foundation, Inc., {% endcomment %} {% load acl %} +{% load i18n %} - + @@ -35,12 +36,12 @@ with this program; if not, write to the Free Software Foundation, Inc., diff --git a/cotisations/templates/cotisations/control.html b/cotisations/templates/cotisations/control.html index 48071429..cdd212e3 100644 --- a/cotisations/templates/cotisations/control.html +++ b/cotisations/templates/cotisations/control.html @@ -25,13 +25,14 @@ with this program; if not, write to the Free Software Foundation, Inc., {% load bootstrap3 %} {% load staticfiles%} +{% load i18n %} -{% block title %}Controle des factures{% endblock %} +{% block title %}{% trans "Invoice control" %}{% endblock %} {% block content %} -

Controle et validité des factures

+

{% trans "Invoice control and validation" %}

{% if facture_list.paginator %} -{% include "pagination.html" with list=facture_list %} +{% include 'pagination.html' with list=facture_list %} {% endif %} {% csrf_token %} @@ -39,24 +40,50 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Moyen de paiement{% trans "Payment method" %}
{{ paiement.moyen }} - {% can_edit paiement %} - + {% can_edit paiement %} + - {% acl_end %} - + {% acl_end %} +
- - - - - - - - - - - + + + + + + + + + {% for form in controlform.forms %} {% bootstrap_form_errors form %} - - @@ -74,10 +101,11 @@ with this program; if not, write to the Free Software Foundation, Inc., {% endfor %}
Profil{% include "buttons/sort.html" with prefix='control' col='name' text='Nom' %}{% include "buttons/sort.html" with prefix='control' col='surname' text='Prénom' %}{% include "buttons/sort.html" with prefix='control' col='id' text='Id facture' %}{% include "buttons/sort.html" with prefix='control' col='user-id' text='Id user' %}DesignationPrix total{% include "buttons/sort.html" with prefix='control' col='paiement' text='Moyen de paiement' %}{% include "buttons/sort.html" with prefix='control' col='date' text='Date' %}{% include "buttons/sort.html" with prefix='control' col='valid' text='Valide' %}{% include "buttons/sort.html" with prefix='control' col='control' text='Contrôlée' %}{% trans "Profil" %} + {% trans "Last name" as tr_last_name %} + {% include 'buttons/sort.html' with prefix='control' col='name' text=tr_last_name %} + + {% trans "First name" as tr_first_name %} + {% include 'buttons/sort.html' with prefix='control' col='surname' text=tr_first_name %} + + {% trans "Invoice id" as tr_invoice_id %} + {% include 'buttons/sort.html' with prefix='control' col='id' text=tr_invoice_id %} + + {% trans "User id" as tr_user_id %} + {% include 'buttons/sort.html' with prefix='control' col='user-id' text=tr_user_id %} + {% trans "Designation" %}{% trans "Total price" %} + {% trans "Payment method" as tr_payment_method %} + {% include 'buttons/sort.html' with prefix='control' col='paiement' text=tr_payment_method %} + + {% trans "Date" as tr_date %} + {% include 'buttons/sort.html' with prefix='control' col='date' text=tr_date %}< + /th> + + {% trans "Validated" as tr_validated %} + {% include 'buttons/sort.html' with prefix='control' col='valid' text=tr_validated %}< + /th> + + {% trans "Controlled" as tr_controlled %} + {% include 'buttons/sort.html' with prefix='control' col='control' text=tr_controlled %} +
+ + + + {{ form.instance.user.name }} {{ form.instance.user.surname }}
- {% bootstrap_button "Modifier" button_type="submit" icon="star" %} + {% trans "Edit" as tr_edit %} + {% bootstrap_button tr_edit button_type='submit' icon='star' %} {% endblock %} {% if facture_list.paginator %} -{% include "pagination.html" with list=facture_list %} +{% include 'pagination.html' with list=facture_list %} {% endif %} diff --git a/cotisations/templates/cotisations/delete.html b/cotisations/templates/cotisations/delete.html index 318be65d..8dbe142a 100644 --- a/cotisations/templates/cotisations/delete.html +++ b/cotisations/templates/cotisations/delete.html @@ -24,17 +24,20 @@ with this program; if not, write to the Free Software Foundation, Inc., {% endcomment %} {% load bootstrap3 %} +{% load i18n %} -{% block title %}Création et modification de machines{% endblock %} +{% block title %}{% trans "Deletion of cotisations" %}{% endblock %} {% block content %}
{% csrf_token %} -

Attention, voulez-vous vraiment supprimer cet objet {{ objet_name }} ( {{ objet }} ) ?

- {% bootstrap_button "Confirmer" button_type="submit" icon="trash" %} +

+ {% blocktrans %} + Warning. Are you sure you really want te delete this this {{ object_name }} object ( {{ objet }} ) ? + {% endblocktrans %} +

+ {% trans "Confirm" as tr_confirm %} + {% bootstrap_button tr_confirm button_type='submit' icon='trash' %}
-
-
-
{% endblock %} diff --git a/cotisations/templates/cotisations/edit_facture.html b/cotisations/templates/cotisations/edit_facture.html index f1af2b8b..d28f8511 100644 --- a/cotisations/templates/cotisations/edit_facture.html +++ b/cotisations/templates/cotisations/edit_facture.html @@ -26,27 +26,28 @@ with this program; if not, write to the Free Software Foundation, Inc., {% load bootstrap3 %} {% load staticfiles%} {% load massive_bootstrap_form %} +{% load i18n %} -{% block title %}Création et modification de factures{% endblock %} +{% block title %}{% trans "Invoices creation and edition" %}{% endblock %} {% block content %} {% bootstrap_form_errors factureform %}
{% csrf_token %} -

Editer la facture

+

{% trans "Edit the invoice" %}

{% massive_bootstrap_form factureform 'user' %} {{ venteform.management_form }} -

Articles de la facture

+

{% trans "Invoice's articles" %}

- - + + - {% for form in venteform.forms %} - {% bootstrap_form_errors form %} + {% for form in venteform.forms %} + {% bootstrap_form_errors form %} @@ -56,7 +57,8 @@ with this program; if not, write to the Free Software Foundation, Inc., {% endfor %}
DésignationQuantité{% trans "Designation" %}{% trans "Quantity" %}
{{ form.name }} {{ form.number }}
- {% bootstrap_button "Créer ou modifier" button_type="submit" icon="star" %} + {% trans "Confirm" as tr_confirm %} + {% bootstrap_button tr_confirm button_type='submit' icon='star' %}
{% endblock %} diff --git a/cotisations/templates/cotisations/facture.html b/cotisations/templates/cotisations/facture.html index 5ed3e94e..69fcf2a4 100644 --- a/cotisations/templates/cotisations/facture.html +++ b/cotisations/templates/cotisations/facture.html @@ -25,8 +25,9 @@ with this program; if not, write to the Free Software Foundation, Inc., {% load bootstrap3 %} {% load staticfiles%} +{% load i18n %} -{% block title %}Création et modification de factures{% endblock %} +{% block title %}{% trans "invoices creation and edition" %}{% endblock %} {% block content %} {% bootstrap_form_errors factureform %} @@ -34,7 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% csrf_token %} {% bootstrap_form factureform %} - {% bootstrap_button action_name button_type="submit" icon="star" %} + {% bootstrap_button action_name button_type='submit' icon='star' %}
{% endblock %} diff --git a/cotisations/templates/cotisations/index.html b/cotisations/templates/cotisations/index.html index 52ff4689..9482cb5a 100644 --- a/cotisations/templates/cotisations/index.html +++ b/cotisations/templates/cotisations/index.html @@ -24,14 +24,12 @@ with this program; if not, write to the Free Software Foundation, Inc., {% endcomment %} {% load bootstrap3 %} +{% load i18n %} -{% block title %}Facture{% endblock %} +{% block title %}{% trans "Invoices" %}{% endblock %} {% block content %} -

Cotisations

- {% include "cotisations/aff_cotisations.html" with facture_list=facture_list %} -
-
-
+

{% trans "Cotisations" %}

+ {% include 'cotisations/aff_cotisations.html' with facture_list=facture_list %} {% endblock %} diff --git a/cotisations/templates/cotisations/index_article.html b/cotisations/templates/cotisations/index_article.html index 7803c2ca..24b1abde 100644 --- a/cotisations/templates/cotisations/index_article.html +++ b/cotisations/templates/cotisations/index_article.html @@ -25,18 +25,20 @@ with this program; if not, write to the Free Software Foundation, Inc., {% load bootstrap3 %} {% load acl %} +{% load i18n %} -{% block title %}Articles{% endblock %} +{% block title %}{% trans "Articles" %}{% endblock %} {% block content %} -

Liste des types d'articles

- {% can_create Article %} - Ajouter un type d'articles - {% acl_end %} - Supprimer un ou plusieurs types d'articles - {% include "cotisations/aff_article.html" with article_list=article_list %} -
-
-
+

{% trans "Article type list" %}

+ {% can_create Article %} + + {% trans "Add an article type" %} + + {% acl_end %} + + {% trans "Delete article types" %} + + {% include 'cotisations/aff_article.html' with article_list=article_list %} {% endblock %} diff --git a/cotisations/templates/cotisations/index_banque.html b/cotisations/templates/cotisations/index_banque.html index 77c23977..e9118d75 100644 --- a/cotisations/templates/cotisations/index_banque.html +++ b/cotisations/templates/cotisations/index_banque.html @@ -25,18 +25,20 @@ with this program; if not, write to the Free Software Foundation, Inc., {% load bootstrap3 %} {% load acl %} +{% load i18n %} -{% block title %}Banques{% endblock %} +{% block title %}{% trans "Banks" %}{% endblock %} {% block content %} -

Liste des banques

- {% can_create Banque %} - Ajouter une banque - {% acl_end %} - Supprimer une ou plusieurs banques - {% include "cotisations/aff_banque.html" with banque_list=banque_list %} -
-
-
+

{% trans "Banks list" %}

+ {% can_create Banque %} + + {% trans "Add a bank" %} + + {% acl_end %} + + {% trans "Delete banks" %} + + {% include 'cotisations/aff_banque.html' with banque_list=banque_list %} {% endblock %} diff --git a/cotisations/templates/cotisations/index_paiement.html b/cotisations/templates/cotisations/index_paiement.html index 414c6b38..d84c72eb 100644 --- a/cotisations/templates/cotisations/index_paiement.html +++ b/cotisations/templates/cotisations/index_paiement.html @@ -25,18 +25,20 @@ with this program; if not, write to the Free Software Foundation, Inc., {% load bootstrap3 %} {% load acl %} +{% load i18n %} -{% block title %}Paiements{% endblock %} +{% block title %}{% trans "Payments" %}{% endblock %} {% block content %} -

Liste des types de paiements

- {% can_create Paiement %} - Ajouter un type de paiement - {% acl_end %} - Supprimer un ou plusieurs types de paiements - {% include "cotisations/aff_paiement.html" with paiement_list=paiement_list %} -
-
-
+

{% trans "Payment types list" %}

+ {% can_create Paiement %} + + {% trans "Add a payment type" %} + + {% acl_end %} + + {% trans "Delete payment types" %} + + {% include 'cotisations/aff_paiement.html' with paiement_list=paiement_list %} {% endblock %} diff --git a/cotisations/templates/cotisations/new_facture.html b/cotisations/templates/cotisations/new_facture.html index 10aa69fd..4dab92d3 100644 --- a/cotisations/templates/cotisations/new_facture.html +++ b/cotisations/templates/cotisations/new_facture.html @@ -25,40 +25,45 @@ with this program; if not, write to the Free Software Foundation, Inc., {% load bootstrap3 %} {% load staticfiles%} +{% load i18n %} -{% block title %}Création et modification de factures{% endblock %} +{% block title %}{% trans "Invoices creation and edition" %}{% endblock %} {% block content %} {% bootstrap_form_errors factureform %}
{% csrf_token %} -

Nouvelle facture

+

{% trans "New invoice" %}

- Solde de l'utilisateur : {{ user.solde }} € + {% blocktrans %} + User's balance : {{ user.solde }} € + {% endblocktrans %}

{% bootstrap_form factureform %} {{ venteform.management_form }} -

Articles de la facture

+

{% trans "Invoice's articles" %}

- {% for form in venteform.forms %} + {% for form in venteform.forms %}
- Article :   - {% bootstrap_form form label_class='sr-only' %} -   - + {% trans "Article" %} :   + {% bootstrap_form form label_class='sr-only' %} +   +
- {% endfor %} + {% endfor %}
- +

- Prix total : 0,00 € + {% blocktrans %} + Total price : 0,00 € + {% endblocktrans %}

- {% bootstrap_button "Créer" button_type="submit" icon="star" %} + {% trans "Create" as tr_create %} + {% bootstrap_button tr_create button_type='submit' icon='star' %}