Parcourir la source

missing translations, remove unicode from translation strings

master
Janusz Harkot il y a 13 ans
Parent
révision
cb9ff7e52e

+ 6
- 6
oscar/apps/address/abstract_models.py Voir le fichier

@@ -129,8 +129,8 @@ class AbstractCountry(models.Model):
129 129
     name = models.CharField(_('Official name (CAPS)'), max_length=128)
130 130
     printable_name = models.CharField(_('Country name'), max_length=128)
131 131
     
132
-    is_highlighted = models.BooleanField(default=False, db_index=True)
133
-    is_shipping_country = models.BooleanField(default=False, db_index=True)
132
+    is_highlighted = models.BooleanField(_("Is Highlighted"), default=False, db_index=True)
133
+    is_shipping_country = models.BooleanField(_("Is Shipping Country"), default=False, db_index=True)
134 134
     
135 135
     class Meta:
136 136
         abstract = True
@@ -181,7 +181,7 @@ class AbstractUserAddress(AbstractShippingAddress):
181 181
     users the ability to add/edit/delete from their address book without affecting
182 182
     orders already placed. 
183 183
     """
184
-    user = models.ForeignKey('auth.User', related_name='addresses')
184
+    user = models.ForeignKey('auth.User', related_name='addresses', verbose_name=_("User"))
185 185
     
186 186
     # Customers can set defaults
187 187
     is_default_for_shipping = models.BooleanField(_("Default shipping address?"), default=False)
@@ -190,12 +190,12 @@ class AbstractUserAddress(AbstractShippingAddress):
190 190
     # We keep track of the number of times an address has been used
191 191
     # as a shipping address so we can show the most popular ones 
192 192
     # first at the checkout.
193
-    num_orders = models.PositiveIntegerField(default=0)
193
+    num_orders = models.PositiveIntegerField(_("Number of Orders"), default=0)
194 194
     
195 195
     # A hash is kept to try and avoid duplicate addresses being added
196 196
     # to the address book.
197
-    hash = models.CharField(max_length=255, db_index=True)
198
-    date_created = models.DateTimeField(auto_now_add=True)
197
+    hash = models.CharField(_("Address Hash"), max_length=255, db_index=True)
198
+    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
199 199
     
200 200
     def generate_hash(self):
201 201
         """

+ 7
- 7
oscar/apps/analytics/abstract_models.py Voir le fichier

@@ -12,7 +12,7 @@ class AbstractProductRecord(models.Model):
12 12
     products.
13 13
     """
14 14
     
15
-    product = models.OneToOneField('catalogue.Product')
15
+    product = models.OneToOneField('catalogue.Product', verbose_name=_("Product"))
16 16
     
17 17
     # Data used for generating a score
18 18
     num_views = models.PositiveIntegerField(_('Views'), default=0)
@@ -37,7 +37,7 @@ class AbstractUserRecord(models.Model):
37 37
     A record of a user's activity.
38 38
     """
39 39
     
40
-    user = models.OneToOneField('auth.User')
40
+    user = models.OneToOneField('auth.User', verbose_name=_("User"))
41 41
     
42 42
     # Browsing stats
43 43
     num_product_views = models.PositiveIntegerField(_('Product Views'), default=0)
@@ -58,9 +58,9 @@ class AbstractUserRecord(models.Model):
58 58
 
59 59
 class AbstractUserProductView(models.Model):
60 60
     
61
-    user = models.ForeignKey('auth.User')
62
-    product = models.ForeignKey('catalogue.Product')
63
-    date_created = models.DateTimeField(auto_now_add=True)
61
+    user = models.ForeignKey('auth.User', verbose_name=_("User"))
62
+    product = models.ForeignKey('catalogue.Product', verbose_name=_("Product"))
63
+    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
64 64
      
65 65
     class Meta:
66 66
         abstract = True
@@ -75,9 +75,9 @@ class AbstractUserProductView(models.Model):
75 75
 
76 76
 class AbstractUserSearch(models.Model):
77 77
     
78
-    user = models.ForeignKey('auth.User')
78
+    user = models.ForeignKey('auth.User', verbose_name=_("User"))
79 79
     query = models.CharField(_("Search term"), max_length=255, db_index=True)
80
-    date_created = models.DateTimeField(auto_now_add=True)
80
+    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
81 81
      
82 82
     class Meta:
83 83
         abstract = True

+ 11
- 11
oscar/apps/basket/abstract_models.py Voir le fichier

@@ -22,7 +22,7 @@ class AbstractBasket(models.Model):
22 22
     Basket object
23 23
     """
24 24
     # Baskets can be anonymously owned (which are merged if the user signs in)
25
-    owner = models.ForeignKey('auth.User', related_name='baskets', null=True)
25
+    owner = models.ForeignKey('auth.User', related_name='baskets', null=True, verbose_name=_("Owner"))
26 26
     STATUS_CHOICES = (
27 27
         (OPEN, _("Open - currently active")),
28 28
         (MERGED, _("Merged - superceded by another basket")),
@@ -31,11 +31,11 @@ class AbstractBasket(models.Model):
31 31
         (SUBMITTED, _("Submitted - has been ordered at the checkout")),
32 32
     )
33 33
     status = models.CharField(_("Status"), max_length=128, default=OPEN, choices=STATUS_CHOICES)
34
-    vouchers = models.ManyToManyField('voucher.Voucher', null=True)
34
+    vouchers = models.ManyToManyField('voucher.Voucher', null=True, verbose_name=_("Vouchers"))
35 35
 
36
-    date_created = models.DateTimeField(auto_now_add=True)
37
-    date_merged = models.DateTimeField(null=True, blank=True)
38
-    date_submitted = models.DateTimeField(null=True, blank=True)
36
+    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
37
+    date_merged = models.DateTimeField(_("Date Merged"), null=True, blank=True)
38
+    date_submitted = models.DateTimeField(_("Date Submitted"), null=True, blank=True)
39 39
 
40 40
     class Meta:
41 41
         abstract = True
@@ -389,15 +389,15 @@ class AbstractLine(models.Model):
389 389
     """
390 390
     A line of a basket (product and a quantity)
391 391
     """
392
-    basket = models.ForeignKey('basket.Basket', related_name='lines')
392
+    basket = models.ForeignKey('basket.Basket', related_name='lines', verbose_name=_("Basket"))
393 393
 
394 394
     # This is to determine which products belong to the same line
395 395
     # We can't just use product.id as you can have customised products
396 396
     # which should be treated as separate lines.  Set as a
397 397
     # SlugField as it is included in the path for certain views.
398
-    line_reference = models.SlugField(max_length=128, db_index=True)
398
+    line_reference = models.SlugField(_("Line Reference"), max_length=128, db_index=True)
399 399
 
400
-    product = models.ForeignKey('catalogue.Product', related_name='basket_lines')
400
+    product = models.ForeignKey('catalogue.Product', related_name='basket_lines', verbose_name=_("Product"))
401 401
     quantity = models.PositiveIntegerField(_('Quantity'), default=1)
402 402
 
403 403
     # We store the unit price incl tax of the product when it is first added to
@@ -408,7 +408,7 @@ class AbstractLine(models.Model):
408 408
     price_incl_tax = models.DecimalField(_('Price incl. Tax'), decimal_places=2, max_digits=12,
409 409
                                          null=True)
410 410
     # Track date of first addition
411
-    date_created = models.DateTimeField(auto_now_add=True)
411
+    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
412 412
 
413 413
     # Instance variables used to persist discount information
414 414
     _discount = Decimal('0.00')
@@ -601,8 +601,8 @@ class AbstractLineAttribute(models.Model):
601 601
     """
602 602
     An attribute of a basket line
603 603
     """
604
-    line = models.ForeignKey('basket.Line', related_name='attributes')
605
-    option = models.ForeignKey('catalogue.Option')
604
+    line = models.ForeignKey('basket.Line', related_name='attributes', verbose_name=_("Line"))
605
+    option = models.ForeignKey('catalogue.Option', verbose_name=_("Option"))
606 606
     value = models.CharField(_("Value"), max_length=255)
607 607
 
608 608
     class Meta:

+ 93
- 87
oscar/apps/catalogue/abstract_models.py Voir le fichier

@@ -21,8 +21,8 @@ class AbstractProductClass(models.Model):
21 21
 
22 22
     Not necessarily equivalent to top-level categories but usually will be.
23 23
     """
24
-    name = models.CharField(_('name'), max_length=128)
25
-    slug = models.SlugField(_('slug'), max_length=128, unique=True)
24
+    name = models.CharField(_('Name'), max_length=128)
25
+    slug = models.SlugField(_('Slug'), max_length=128, unique=True)
26 26
 
27 27
     # Some product type don't require shipping (eg digital products) - we use
28 28
     # this field to take some shortcuts in the checkout.
@@ -31,13 +31,13 @@ class AbstractProductClass(models.Model):
31 31
     # These are the options (set by the user when they add to basket) for this
32 32
     # item class.  For instance, a product class of "SMS message" would always
33 33
     # require a message to be specified before it could be bought.
34
-    options = models.ManyToManyField('catalogue.Option', blank=True)
34
+    options = models.ManyToManyField('catalogue.Option', blank=True, verbose_name=_("Options"))
35 35
 
36 36
     class Meta:
37 37
         abstract = True
38 38
         ordering = ['name']
39
-        verbose_name = _("Product class")
40
-        verbose_name_plural = _("Product classes")
39
+        verbose_name = _("Product Class")
40
+        verbose_name_plural = _("Product Classes")
41 41
 
42 42
     def save(self, *args, **kwargs):
43 43
         if not self.slug:
@@ -54,11 +54,11 @@ class AbstractCategory(MP_Node):
54 54
 
55 55
     Uses django-treebeard.
56 56
     """
57
-    name = models.CharField(_('name'), max_length=255, db_index=True)
58
-    description = models.TextField(_('description'), blank=True, null=True)
59
-    image = models.ImageField(_('image'), upload_to='categories', blank=True, null=True)
60
-    slug = models.SlugField(_('slug'), max_length=1024, db_index=True, editable=False)
61
-    full_name = models.CharField(_('full name'), max_length=1024, db_index=True, editable=False)
57
+    name = models.CharField(_('Name'), max_length=255, db_index=True)
58
+    description = models.TextField(_('Description'), blank=True, null=True)
59
+    image = models.ImageField(_('Image'), upload_to='categories', blank=True, null=True)
60
+    slug = models.SlugField(_('Slug'), max_length=1024, db_index=True, editable=False)
61
+    full_name = models.CharField(_('Full Name'), max_length=1024, db_index=True, editable=False)
62 62
 
63 63
     _slug_separator = '/'
64 64
     _full_name_separator = ' > '
@@ -162,15 +162,15 @@ class AbstractProductCategory(models.Model):
162 162
     """
163 163
     Joining model between products and categories.
164 164
     """
165
-    product = models.ForeignKey('catalogue.Product')
166
-    category = models.ForeignKey('catalogue.Category')
167
-    is_canonical = models.BooleanField(_('is cannonical'), default=False, db_index=True)
165
+    product = models.ForeignKey('catalogue.Product', verbose_name=_("Product"))
166
+    category = models.ForeignKey('catalogue.Category', verbose_name=_("Categry"))
167
+    is_canonical = models.BooleanField(_('Is Cannonical'), default=False, db_index=True)
168 168
 
169 169
     class Meta:
170 170
         abstract = True
171 171
         ordering = ['-is_canonical']
172
-        verbose_name = _('Product category')
173
-        verbose_name_plural = _('Product categories')
172
+        verbose_name = _('Product Category')
173
+        verbose_name_plural = _('Product Categories')
174 174
 
175 175
     def __unicode__(self):
176 176
         return u"<productcategory for product '%s'>" % self.product
@@ -180,8 +180,8 @@ class AbstractContributorRole(models.Model):
180 180
     """
181 181
     A role that may be performed by a contributor to a product, eg Author, Actor, Director.
182 182
     """
183
-    name = models.CharField(_('name'), max_length=50)
184
-    name_plural = models.CharField(_('name plural'), max_length=50)
183
+    name = models.CharField(_('Name'), max_length=50)
184
+    name_plural = models.CharField(_('Name Plural'), max_length=50)
185 185
     slug = models.SlugField()
186 186
 
187 187
     def __unicode__(self):
@@ -221,17 +221,17 @@ class AbstractContributor(models.Model):
221 221
 
222 222
 
223 223
 class AbstractProductContributor(models.Model):
224
-    product = models.ForeignKey('catalogue.Product')
225
-    contributor = models.ForeignKey('catalogue.Contributor')
226
-    role = models.ForeignKey('catalogue.ContributorRole', blank=True, null=True)
224
+    product = models.ForeignKey('catalogue.Product', verbose_name=_("Product"))
225
+    contributor = models.ForeignKey('catalogue.Contributor', verbose_name=_("Contributor"))
226
+    role = models.ForeignKey('catalogue.ContributorRole', blank=True, null=True, verbose_name=_("Contributor Role"))
227 227
 
228 228
     def __unicode__(self):
229 229
         return '%s <- %s - %s' % (self.product, self.role, self.contributor)
230 230
 
231 231
     class Meta:
232 232
         abstract = True
233
-        verbose_name = _('Product contributor')
234
-        verbose_name_plural = _('Product contributors')
233
+        verbose_name = _('Product Contributor')
234
+        verbose_name_plural = _('Product Contributors')
235 235
 
236 236
 
237 237
 class AbstractProduct(models.Model):
@@ -251,7 +251,7 @@ class AbstractProduct(models.Model):
251 251
                      not specific to a particular supplier.  Eg an ISBN for a book."""))
252 252
 
253 253
     # No canonical product should have a stock record as they cannot be bought.
254
-    parent = models.ForeignKey('self', null=True, blank=True, related_name='variants',
254
+    parent = models.ForeignKey('self', null=True, blank=True, related_name='variants', verbose_name=_("Parent"),
255 255
         help_text=_("""Only choose a parent product if this is a 'variant' of a canonical catalogue.  For example
256 256
                      if this is a size 4 of a particular t-shirt.  Leave blank if this is a CANONICAL PRODUCT (ie
257 257
                      there is only one version of this product)."""))
@@ -263,33 +263,35 @@ class AbstractProduct(models.Model):
263 263
 
264 264
     # Use this field to indicate if the product is inactive or awaiting approval
265 265
     status = models.CharField(_('Status'), max_length=128, blank=True, null=True, db_index=True)
266
-    product_class = models.ForeignKey('catalogue.ProductClass', verbose_name=_('product class'), null=True,
266
+    product_class = models.ForeignKey('catalogue.ProductClass', verbose_name=_('Product Class'), null=True,
267 267
         help_text=_("""Choose what type of product this is"""))
268 268
     attributes = models.ManyToManyField('catalogue.ProductAttribute', through='ProductAttributeValue',
269
-        help_text=_("""A product attribute is something that this product MUST have, such as a size, as specified by its class"""))
270
-    product_options = models.ManyToManyField('catalogue.Option', blank=True,
269
+        verbose_name=_("Attributes"), help_text=_("A product attribute is something that this product MUST have, "
270
+        "such as a size, as specified by its class"))
271
+    product_options = models.ManyToManyField('catalogue.Option', blank=True, verbose_name=_("Product Options"),
271 272
         help_text=_("""Options are values that can be associated with a item when it is added to
272 273
                      a customer's basket.  This could be something like a personalised message to be
273 274
                      printed on a T-shirt."""))
274 275
 
275 276
     related_products = models.ManyToManyField('catalogue.Product', related_name='relations', blank=True,
276
-        help_text=_("""Related items are things like different formats of the same book.  Grouping them together allows
277
-                     better linking betwen products on the site."""))
277
+        verbose_name=_("Related Products"), help_text=_("""Related items are things like different formats
278
+            of the same book.  Grouping them together allows better linking betwen products on the site."""))
278 279
 
279 280
     # Recommended products
280
-    recommended_products = models.ManyToManyField('catalogue.Product', through='ProductRecommendation', blank=True)
281
+    recommended_products = models.ManyToManyField('catalogue.Product', through='ProductRecommendation', blank=True,
282
+        verbose_name=_("Recommended Products"))
281 283
 
282 284
     # Product score
283 285
     score = models.FloatField(_('Score'), default=0.00, db_index=True)
284 286
 
285
-    date_created = models.DateTimeField(auto_now_add=True)
287
+    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
286 288
 
287 289
     # This field is used by Haystack to reindex search
288
-    date_updated = models.DateTimeField(auto_now=True, db_index=True)
290
+    date_updated = models.DateTimeField(_("Date Updated"), auto_now=True, db_index=True)
289 291
 
290
-    categories = models.ManyToManyField('catalogue.Category', through='ProductCategory')
292
+    categories = models.ManyToManyField('catalogue.Category', through='ProductCategory', verbose_name=_("Categories"))
291 293
 
292
-    is_discountable = models.BooleanField(default=True)
294
+    is_discountable = models.BooleanField(_("Is Discountable"), default=True)
293 295
 
294 296
     objects = models.Manager()
295 297
     browsable = BrowsableProductManager()
@@ -458,13 +460,14 @@ class ProductRecommendation(models.Model):
458 460
     """
459 461
     'Through' model for product recommendations
460 462
     """
461
-    primary = models.ForeignKey('catalogue.Product', related_name='primary_recommendations')
462
-    recommendation = models.ForeignKey('catalogue.Product')
463
+    primary = models.ForeignKey('catalogue.Product', related_name='primary_recommendations',
464
+        verbose_name=_("Primary Product"))
465
+    recommendation = models.ForeignKey('catalogue.Product', verbose_name=_("Recommended Product"))
463 466
     ranking = models.PositiveSmallIntegerField(_('Ranking'), default=0)
464 467
 
465 468
     class Meta:
466
-        verbose_name = _('Product recommendation')
467
-        verbose_name_plural = _('Product recomendations')
469
+        verbose_name = _('Product Recommendation')
470
+        verbose_name_plural = _('Product Recomendations')
468 471
 
469 472
 
470 473
 class ProductAttributesContainer(object):
@@ -487,8 +490,8 @@ class ProductAttributesContainer(object):
487 490
             self.initialised = True
488 491
             if result:
489 492
                 return result
490
-        raise AttributeError((_(u"%(obj)s has no attribute named " \
491
-                                u"'%(attr)s'") % \
493
+        raise AttributeError((_("%(obj)s has no attribute named " \
494
+                                "'%(attr)s'") % \
492 495
                               {'obj': self.product.product_class, 'attr': name}))
493 496
 
494 497
     def validate_attributes(self):
@@ -496,14 +499,14 @@ class ProductAttributesContainer(object):
496 499
             value = getattr(self, attribute.code, None)
497 500
             if value is None:
498 501
                 if attribute.required:
499
-                    raise ValidationError(_(u"%(attr)s attribute cannot " \
500
-                                            u"be blank") % \
502
+                    raise ValidationError(_("%(attr)s attribute cannot " \
503
+                                            "be blank") % \
501 504
                                             {'attr': attribute.code})
502 505
             else:
503 506
                 try:
504 507
                     attribute.validate_value(value)
505 508
                 except ValidationError, e:
506
-                    raise ValidationError(_(u"%(attr)s attribute %(err)s") % \
509
+                    raise ValidationError(_("%(attr)s attribute %(err)s") % \
507 510
                                             {'attr': attribute.code,
508 511
                                              'err': e})
509 512
 
@@ -545,64 +548,65 @@ class AbstractProductAttribute(models.Model):
545 548
     """
546 549
     Defines an attribute for a product class. (For example, number_of_pages for a 'book' class)
547 550
     """
548
-    product_class = models.ForeignKey('catalogue.ProductClass', related_name='attributes', blank=True, null=True)
549
-    name = models.CharField(_('name'), max_length=128)
550
-    code = models.SlugField(_('code'), max_length=128, validators=[RegexValidator(regex=r'^[a-zA-Z_][0-9a-zA-Z_]*$',
551
+    product_class = models.ForeignKey('catalogue.ProductClass', related_name='attributes', blank=True, null=True,
552
+        verbose_name=_("Product Class"))
553
+    name = models.CharField(_('Name'), max_length=128)
554
+    code = models.SlugField(_('Code'), max_length=128, validators=[RegexValidator(regex=r'^[a-zA-Z_][0-9a-zA-Z_]*$',
551 555
         message=_("Code must match ^[a-zA-Z_][0-9a-zA-Z_]*$"))])
552
-    type = models.CharField(choices=TYPE_CHOICES, default=TYPE_CHOICES[0][0], max_length=20)
556
+    type = models.CharField(choices=TYPE_CHOICES, default=TYPE_CHOICES[0][0], max_length=20, verbose_name=_("Type"))
553 557
     option_group = models.ForeignKey('catalogue.AttributeOptionGroup', blank=True, null=True,
554
-        help_text=_('Select an option group if using type "Option"'))
558
+        verbose_name=_("Option Group"), help_text=_('Select an option group if using type "Option"'))
555 559
     entity_type = models.ForeignKey('catalogue.AttributeEntityType', blank=True, null=True,
556
-        help_text=_('Select an entity type if using type "Entity"'))
557
-    required = models.BooleanField(_('required'), default=False)
560
+        verbose_name=_("Entity Type"), help_text=_('Select an entity type if using type "Entity"'))
561
+    required = models.BooleanField(_('Required'), default=False)
558 562
 
559 563
     class Meta:
560 564
         abstract = True
561 565
         ordering = ['code']
562
-        verbose_name = _('Product attribute')
563
-        verbose_name_plural = _('Product attributes')
566
+        verbose_name = _('Product Attribute')
567
+        verbose_name_plural = _('Product Attributes')
564 568
 
565 569
     def _validate_text(self, value):
566 570
         if not (type(value) == unicode or type(value) == str):
567
-            raise ValidationError(_(u"Must be str or unicode"))
571
+            raise ValidationError(_("Must be str or unicode"))
568 572
 
569 573
     def _validate_float(self, value):
570 574
         try:
571 575
             float(value)
572 576
         except ValueError:
573
-            raise ValidationError(_(u"Must be a float"))
577
+            raise ValidationError(_("Must be a float"))
574 578
 
575 579
     def _validate_int(self, value):
576 580
         try:
577 581
             int(value)
578 582
         except ValueError:
579
-            raise ValidationError(_(u"Must be an integer"))
583
+            raise ValidationError(_("Must be an integer"))
580 584
 
581 585
     def _validate_date(self, value):
582 586
         if not (isinstance(value, datetime) or isinstance(value, date)):
583
-            raise ValidationError(_(u"Must be a date or datetime"))
587
+            raise ValidationError(_("Must be a date or datetime"))
584 588
 
585 589
     def _validate_bool(self, value):
586 590
         if not type(value) == bool:
587
-            raise ValidationError(_(u"Must be a boolean"))
591
+            raise ValidationError(_("Must be a boolean"))
588 592
 
589 593
     def _validate_entity(self, value):
590 594
         if not isinstance(value, get_model('catalogue', 'AttributeEntity')):
591
-            raise ValidationError(_(u"Must be an AttributeEntity model object instance"))
595
+            raise ValidationError(_("Must be an AttributeEntity model object instance"))
592 596
         if not value.pk:
593
-            raise ValidationError(_(u"Model has not been saved yet"))
597
+            raise ValidationError(_("Model has not been saved yet"))
594 598
         if value.type != self.entity_type:
595
-            raise ValidationError(_(u"Entity must be of type %s" % self.entity_type.name))
599
+            raise ValidationError(_("Entity must be of type %s" % self.entity_type.name))
596 600
 
597 601
     def _validate_option(self, value):
598 602
         if not isinstance(value, get_model('catalogue', 'AttributeOption')):
599
-            raise ValidationError(_(u"Must be an AttributeOption model object instance"))
603
+            raise ValidationError(_("Must be an AttributeOption model object instance"))
600 604
         if not value.pk:
601
-            raise ValidationError(_(u"AttributeOption has not been saved yet"))
605
+            raise ValidationError(_("AttributeOption has not been saved yet"))
602 606
         valid_values = self.option_group.options.values_list('option', flat=True)
603 607
         if value.option not in valid_values:
604
-            raise ValidationError(_(u"%(enum)s is not a valid choice "
605
-                                        u"for %(attr)s") % \
608
+            raise ValidationError(_("%(enum)s is not a valid choice "
609
+                                        "for %(attr)s") % \
606 610
                                        {'enum': value, 'attr': self})
607 611
 
608 612
     def get_validator(self):
@@ -660,16 +664,18 @@ class AbstractProductAttributeValue(models.Model):
660 664
 
661 665
     For example: number_of_pages = 295
662 666
     """
663
-    attribute = models.ForeignKey('catalogue.ProductAttribute')
664
-    product = models.ForeignKey('catalogue.Product', related_name='attribute_values')
665
-    value_text = models.CharField(_('text'), max_length=255, blank=True, null=True)
666
-    value_integer = models.IntegerField(_('integer'), blank=True, null=True)
667
-    value_boolean = models.BooleanField(_('boolean'), blank=True)
668
-    value_float = models.FloatField(_('float'), blank=True, null=True)
669
-    value_richtext = models.TextField(_('richtext'), blank=True, null=True)
670
-    value_date = models.DateField(_('date'), blank=True, null=True)
671
-    value_option = models.ForeignKey('catalogue.AttributeOption', blank=True, null=True)
672
-    value_entity = models.ForeignKey('catalogue.AttributeEntity', blank=True, null=True)
667
+    attribute = models.ForeignKey('catalogue.ProductAttribute', verbose_name=_("Attribute"))
668
+    product = models.ForeignKey('catalogue.Product', related_name='attribute_values', verbose_name=_("Product"))
669
+    value_text = models.CharField(_('Text'), max_length=255, blank=True, null=True)
670
+    value_integer = models.IntegerField(_('Integer'), blank=True, null=True)
671
+    value_boolean = models.BooleanField(_('Boolean'), blank=True)
672
+    value_float = models.FloatField(_('Float'), blank=True, null=True)
673
+    value_richtext = models.TextField(_('Richtext'), blank=True, null=True)
674
+    value_date = models.DateField(_('Date'), blank=True, null=True)
675
+    value_option = models.ForeignKey('catalogue.AttributeOption', blank=True, null=True,
676
+        verbose_name=_("Value Option"))
677
+    value_entity = models.ForeignKey('catalogue.AttributeEntity', blank=True, null=True,
678
+        verbose_name=_("Value Entity"))
673 679
 
674 680
     def _get_value(self):
675 681
         return getattr(self, 'value_%s' % self.attribute.type)
@@ -697,7 +703,7 @@ class AbstractAttributeOptionGroup(models.Model):
697 703
     attribute type
698 704
     For example, Language
699 705
     """
700
-    name = models.CharField(_('name'), max_length=128)
706
+    name = models.CharField(_('Name'), max_length=128)
701 707
 
702 708
     def __unicode__(self):
703 709
         return self.name
@@ -713,16 +719,16 @@ class AbstractAttributeOption(models.Model):
713 719
     Provides an option within an option group for an attribute type
714 720
     Examples: In a Language group, English, Greek, French
715 721
     """
716
-    group = models.ForeignKey('catalogue.AttributeOptionGroup', related_name='options')
717
-    option = models.CharField(_('option'), max_length=255)
722
+    group = models.ForeignKey('catalogue.AttributeOptionGroup', related_name='options', verbose_name=_("Group"))
723
+    option = models.CharField(_('Option'), max_length=255)
718 724
 
719 725
     def __unicode__(self):
720 726
         return self.option
721 727
 
722 728
     class Meta:
723 729
         abstract = True
724
-        verbose_name = _('Attribute option')
725
-        verbose_name_plural = _('Attribute options')
730
+        verbose_name = _('Attribute Option')
731
+        verbose_name_plural = _('Attribute Options')
726 732
 
727 733
 
728 734
 class AbstractAttributeEntity(models.Model):
@@ -731,15 +737,15 @@ class AbstractAttributeEntity(models.Model):
731 737
     """
732 738
     name = models.CharField(_("Name"), max_length=255)
733 739
     slug = models.SlugField(_("Slug"), max_length=255, unique=False, blank=True)
734
-    type = models.ForeignKey('catalogue.AttributeEntityType', related_name='entities')
740
+    type = models.ForeignKey('catalogue.AttributeEntityType', related_name='entities', verbose_name=_("Type"))
735 741
 
736 742
     def __unicode__(self):
737 743
         return self.name
738 744
 
739 745
     class Meta:
740 746
         abstract = True
741
-        verbose_name = _('Attribute entity')
742
-        verbose_name_plural = _('Attribute entities')
747
+        verbose_name = _('Attribute Entity')
748
+        verbose_name_plural = _('Attribute Entities')
743 749
 
744 750
     def save(self, *args, **kwargs):
745 751
         if not self.slug:
@@ -779,8 +785,8 @@ class AbstractOption(models.Model):
779 785
     This is not the same as an attribute as options do not have a fixed value for
780 786
     a particular item - options, they need to be specified by the customer.
781 787
     """
782
-    name = models.CharField(_('name'), max_length=128)
783
-    code = models.SlugField(_('code'), max_length=128)
788
+    name = models.CharField(_("Name"), max_length=128)
789
+    code = models.SlugField(_("Code"), max_length=128)
784 790
 
785 791
     REQUIRED, OPTIONAL = ('Required', 'Optional')
786 792
     TYPE_CHOICES = (
@@ -791,8 +797,8 @@ class AbstractOption(models.Model):
791 797
 
792 798
     class Meta:
793 799
         abstract = True
794
-        verbose_name = _('Option')
795
-        verbose_name_plural = _('Options')
800
+        verbose_name = _("Option")
801
+        verbose_name_plural = _("Options")
796 802
 
797 803
     def __unicode__(self):
798 804
         return self.name
@@ -813,7 +819,7 @@ class AbstractProductImage(models.Model):
813 819
     """
814 820
     An image of a product
815 821
     """
816
-    product = models.ForeignKey('catalogue.Product', related_name='images')
822
+    product = models.ForeignKey('catalogue.Product', related_name='images', verbose_name=_("Product"))
817 823
     original = models.ImageField(_("Original"), upload_to=settings.OSCAR_IMAGE_FOLDER)
818 824
     caption = models.CharField(_("Caption"), max_length=200, blank=True, null=True)
819 825
 
@@ -821,7 +827,7 @@ class AbstractProductImage(models.Model):
821 827
     display_order = models.PositiveIntegerField(_("Display Order"), default=0,
822 828
         help_text=_("""An image with a display order of
823 829
                        zero will be the primary image for a product"""))
824
-    date_created = models.DateTimeField(auto_now_add=True)
830
+    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
825 831
 
826 832
     class Meta:
827 833
         abstract = True

+ 7
- 7
oscar/apps/customer/abstract_models.py Voir le fichier

@@ -12,11 +12,11 @@ class AbstractEmail(models.Model):
12 12
     This is a record of all emails sent to a customer.
13 13
     Normally, we only record order-related emails.
14 14
     """
15
-    user = models.ForeignKey('auth.User', related_name='emails')
15
+    user = models.ForeignKey('auth.User', related_name='emails', verbose_name=_("User"))
16 16
     subject = models.TextField(_('Subject'), max_length=255)
17
-    body_text = models.TextField()
18
-    body_html = models.TextField(blank=True, null=True)
19
-    date_sent = models.DateTimeField(auto_now_add=True)
17
+    body_text = models.TextField(_("Body Text"))
18
+    body_html = models.TextField(_("Body HTML"), blank=True, null=True)
19
+    date_sent = models.DateTimeField(_("Date Sent"), auto_now_add=True)
20 20
 
21 21
     class Meta:
22 22
         abstract = True
@@ -24,7 +24,7 @@ class AbstractEmail(models.Model):
24 24
         verbose_name_plural = _('Emails')
25 25
 
26 26
     def __unicode__(self):
27
-        return _(u"Email to %(user)s with subject '%(subject)s'") % {
27
+        return _("Email to %(user)s with subject '%(subject)s'") % {
28 28
             'user': self.user.username, 'subject': self.subject}
29 29
 
30 30
 
@@ -51,8 +51,8 @@ class AbstractCommunicationEventType(models.Model):
51 51
     # Template content for SMS messages
52 52
     sms_template = models.CharField(_('SMS Template'), max_length=170, blank=True, help_text=_("SMS template"))
53 53
 
54
-    date_created = models.DateTimeField(auto_now_add=True)
55
-    date_updated = models.DateTimeField(auto_now=True)
54
+    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
55
+    date_updated = models.DateTimeField(_("Date Updated"), auto_now=True)
56 56
 
57 57
     objects = CommunicationTypeManager()
58 58
 

+ 5
- 5
oscar/apps/dashboard/catalogue/views.py Voir le fichier

@@ -321,11 +321,11 @@ class CategoryCreateView(CategoryListMixin, generic.CreateView):
321 321
 
322 322
     def get_context_data(self, **kwargs):
323 323
         ctx = super(CategoryCreateView, self).get_context_data(**kwargs)
324
-        ctx['title'] = "Add a new category"
324
+        ctx['title'] = _("Add a new category")
325 325
         return ctx
326 326
 
327 327
     def get_success_url(self):
328
-        messages.info(self.request, "Category created successfully")
328
+        messages.info(self.request, _("Category created successfully"))
329 329
         return super(CategoryCreateView, self).get_success_url()
330 330
 
331 331
 
@@ -336,11 +336,11 @@ class CategoryUpdateView(CategoryListMixin, generic.UpdateView):
336 336
 
337 337
     def get_context_data(self, **kwargs):
338 338
         ctx = super(CategoryUpdateView, self).get_context_data(**kwargs)
339
-        ctx['title'] = "Update category '%s'" % self.object.name
339
+        ctx['title'] = _("Update category '%s'") % self.object.name
340 340
         return ctx
341 341
 
342 342
     def get_success_url(self):
343
-        messages.info(self.request, "Category updated successfully")
343
+        messages.info(self.request, _("Category updated successfully"))
344 344
         return super(CategoryUpdateView, self).get_success_url()
345 345
 
346 346
 
@@ -354,5 +354,5 @@ class CategoryDeleteView(CategoryListMixin, generic.DeleteView):
354 354
         return ctx
355 355
 
356 356
     def get_success_url(self):
357
-        messages.info(self.request, "Category deleted successfully")
357
+        messages.info(self.request, _("Category deleted successfully"))
358 358
         return super(CategoryDeleteView, self).get_success_url()

+ 4
- 4
oscar/apps/dashboard/offers/views.py Voir le fichier

@@ -261,7 +261,7 @@ class OfferDeleteView(DeleteView):
261 261
     context_object_name = 'offer'
262 262
 
263 263
     def get_success_url(self):
264
-        messages.success(self.request, "Offer deleted!")
264
+        messages.success(self.request, _("Offer deleted!"))
265 265
         return reverse('dashboard:offer-list')
266 266
 
267 267
 
@@ -287,7 +287,7 @@ class RangeCreateView(CreateView):
287 287
     template_name = 'dashboard/offers/range_form.html'
288 288
 
289 289
     def get_success_url(self):
290
-        messages.success(self.request, "Range created")
290
+        messages.success(self.request, _("Range created"))
291 291
         return reverse('dashboard:range-list')
292 292
 
293 293
 
@@ -296,7 +296,7 @@ class RangeUpdateView(UpdateView):
296 296
     template_name = 'dashboard/offers/range_form.html'
297 297
 
298 298
     def get_success_url(self):
299
-        messages.success(self.request, "Range updated")
299
+        messages.success(self.request, _("Range updated"))
300 300
         return reverse('dashboard:range-list')
301 301
 
302 302
 
@@ -306,7 +306,7 @@ class RangeDeleteView(DeleteView):
306 306
     context_object_name = 'range'
307 307
 
308 308
     def get_success_url(self):
309
-        messages.warning(self.request, "Range deleted")
309
+        messages.warning(self.request, _("Range deleted"))
310 310
         return reverse('dashboard:range-list')
311 311
 
312 312
 

+ 2
- 2
oscar/apps/dashboard/orders/views.py Voir le fichier

@@ -296,7 +296,7 @@ class OrderDetailView(DetailView):
296 296
         order_action = request.POST.get('order_action', '').lower()
297 297
         if order_action:
298 298
             if order_action not in self.order_actions:
299
-                messages.error(self.request, "Invalid action")
299
+                messages.error(self.request, _("Invalid action"))
300 300
                 return self.reload_page_response()
301 301
             else:
302 302
                 return getattr(self, order_action)(request, order)
@@ -503,7 +503,7 @@ def get_change_summary(model1, model2):
503 503
     changes = get_changes_between_models(model1, model2, ['search_text'])
504 504
     change_descriptions = []
505 505
     for field, delta in changes.items():
506
-        change_descriptions.append(_(u"%(field)s changed from '%(old_value)s' to '%(new_value)s'") % {
506
+        change_descriptions.append(_("%(field)s changed from '%(old_value)s' to '%(new_value)s'") % {
507 507
             'field': field,
508 508
             'old_value': delta[0],
509 509
             'new_value': delta[1]})

+ 1
- 1
oscar/apps/dashboard/pages/forms.py Voir le fichier

@@ -20,7 +20,7 @@ class PageUpdateForm(forms.ModelForm):
20 20
     and *content* field. The specified URL will be validated and check if
21 21
     the same URL already exists in the system.
22 22
     """
23
-    url = forms.CharField(max_length=128, required=False,
23
+    url = forms.CharField(max_length=128, required=False, label=_("URL"),
24 24
                           help_text=_("Example: '/about/contact/'. Make sure"
25 25
                                       " to have leading and trailing slashes."))
26 26
 

+ 1
- 1
oscar/apps/dashboard/pages/views.py Voir le fichier

@@ -127,7 +127,7 @@ class PageUpdateView(generic.UpdateView):
127 127
         Get context data with additional *title* and *page* objects attached.
128 128
         """
129 129
         ctx = super(PageUpdateView, self).get_context_data(**kwargs)
130
-        ctx['title'] = 'Update Page'
130
+        ctx['title'] = _('Update Page')
131 131
         return ctx
132 132
 
133 133
     def form_valid(self, form):

+ 16
- 12
oscar/apps/dashboard/ranges/models.py Voir le fichier

@@ -1,17 +1,19 @@
1 1
 import datetime
2 2
 import os
3 3
 import re
4
-
4
+from django.utils.translation import ugettext_lazy as _
5 5
 from django.db import models
6
+
7
+
6 8
 Product = models.get_model('catalogue', 'Product')
7 9
 
8 10
 
9 11
 class RangeProductFileUpload(models.Model):
10
-    range = models.ForeignKey('offer.Range', related_name='file_uploads')
11
-    filepath = models.CharField(max_length=255)
12
-    size = models.PositiveIntegerField()
13
-    uploaded_by = models.ForeignKey('auth.User')
14
-    date_uploaded = models.DateTimeField(auto_now_add=True)
12
+    range = models.ForeignKey('offer.Range', related_name='file_uploads', verbose_name=_("Range"))
13
+    filepath = models.CharField(_("File Path"), max_length=255)
14
+    size = models.PositiveIntegerField(_("Size"))
15
+    uploaded_by = models.ForeignKey('auth.User', verbose_name=_("Uploaded By"))
16
+    date_uploaded = models.DateTimeField(_("Date Uploaded"), auto_now_add=True)
15 17
 
16 18
     PENDING, FAILED, PROCESSED = 'Pending', 'Failed', 'Processed'
17 19
     choices = (
@@ -19,17 +21,19 @@ class RangeProductFileUpload(models.Model):
19 21
         (FAILED, FAILED),
20 22
         (PROCESSED, PROCESSED),
21 23
     )
22
-    status = models.CharField(max_length=32, choices=choices, default=PENDING)
23
-    error_message = models.CharField(max_length=255, null=True)
24
+    status = models.CharField(_("Status"), max_length=32, choices=choices, default=PENDING)
25
+    error_message = models.CharField(_("Error Message"), max_length=255, null=True)
24 26
 
25 27
     # Post-processing audit fields
26
-    date_processed = models.DateTimeField(null=True)
27
-    num_new_skus = models.PositiveIntegerField(null=True)
28
-    num_unknown_skus = models.PositiveIntegerField(null=True)
29
-    num_duplicate_skus = models.PositiveIntegerField(null=True)
28
+    date_processed = models.DateTimeField(_("Date Processed"), null=True)
29
+    num_new_skus = models.PositiveIntegerField(_("Number of New SKUs"), null=True)
30
+    num_unknown_skus = models.PositiveIntegerField(_("Number of Unknown SKUs"), null=True)
31
+    num_duplicate_skus = models.PositiveIntegerField(_("Number of Duplicate SKUs"), null=True)
30 32
 
31 33
     class Meta:
32 34
         ordering = ('-date_uploaded',)
35
+        verbose_name = _("Range Product Uploaded File")
36
+        verbose_name_plural = _("Range Product Uploaded Files")
33 37
 
34 38
     @property
35 39
     def filename(self):

+ 13
- 13
oscar/apps/dashboard/ranges/views.py Voir le fichier

@@ -1,13 +1,11 @@
1 1
 import os
2
-
3 2
 from django.views.generic import (ListView, DeleteView, CreateView, UpdateView)
4
-from django.utils.translation import ugettext_lazy as _
3
+from django.utils.translation import ungettext, ugettext_lazy as _
5 4
 from django.db.models.loading import get_model
6 5
 from django.core.urlresolvers import reverse
7 6
 from django.contrib import messages
8 7
 from django.shortcuts import get_object_or_404
9 8
 from django.http import HttpResponseRedirect
10
-from django.template.defaultfilters import pluralize
11 9
 from django.conf import settings
12 10
 
13 11
 from oscar.views.generic import BulkEditMixin
@@ -36,7 +34,7 @@ class RangeCreateView(CreateView):
36 34
         if 'action' in self.request.POST:
37 35
             return reverse('dashboard:range-products', kwargs={'pk': self.object.id})
38 36
         else:
39
-            messages.success(self.request, "Range created")
37
+            messages.success(self.request, _("Range created"))
40 38
             return reverse('dashboard:range-list')
41 39
 
42 40
     def get_context_data(self, **kwargs):
@@ -54,7 +52,7 @@ class RangeUpdateView(UpdateView):
54 52
         if 'action' in self.request.POST:
55 53
             return reverse('dashboard:range-products', kwargs={'pk': self.object.id})
56 54
         else:
57
-            messages.success(self.request, "Range updated")
55
+            messages.success(self.request, _("Range updated"))
58 56
             return reverse('dashboard:range-list')
59 57
 
60 58
     def get_context_data(self, **kwargs):
@@ -69,7 +67,7 @@ class RangeDeleteView(DeleteView):
69 67
     context_object_name = 'range'
70 68
 
71 69
     def get_success_url(self):
72
-        messages.warning(self.request, "Range deleted")
70
+        messages.warning(self.request, _("Range deleted"))
73 71
         return reverse('dashboard:range-list')
74 72
 
75 73
 
@@ -106,8 +104,10 @@ class RangeProductListView(ListView, BulkEditMixin):
106 104
         range = self.get_range()
107 105
         for product in products:
108 106
             range.included_products.remove(product)
109
-        messages.success(request, _('Removed %d products from range') %
110
-                         len(products))
107
+        num_products = len(products)
108
+        messages.success(request, ungettext("Removed %d product from range",
109
+                                            "Removed %d products from range",
110
+                                            num_products) % num_products)
111 111
         return HttpResponseRedirect(self.get_success_url(request))
112 112
 
113 113
     def add_products(self, request):
@@ -130,19 +130,19 @@ class RangeProductListView(ListView, BulkEditMixin):
130 130
             range.included_products.add(product)
131 131
 
132 132
         num_products = len(products)
133
-        messages.success(request, _("Products added to range: %d") % (
134
-            num_products))
135
-
133
+        messages.success(request, ungettext("%d product added to range",
134
+                                            "%d products added to range",
135
+                                            num_products) % num_products)
136 136
         dupe_skus = form.get_duplicate_skus()
137 137
         if dupe_skus:
138 138
             messages.warning(
139 139
                 request,
140
-                _("The products with SKUs or UPCs matching %s are already in this range") % (", ".join(dupe_skus)))
140
+                _("The products with SKUs or UPCs matching %s are already in this range") % ", ".join(dupe_skus))
141 141
 
142 142
         missing_skus = form.get_missing_skus()
143 143
         if missing_skus:
144 144
             messages.warning(request,
145
-                             _("No product was found with SKU or UPC matching %s") % ', '.join(missing_skus))
145
+                             _("No product(s) were found with SKU or UPC matching %s") % ", ".join(missing_skus))
146 146
 
147 147
     def handle_file_products(self, request, range, form):
148 148
         if not 'file_upload' in request.FILES:

+ 1
- 1
oscar/apps/dashboard/reports/forms.py Voir le fichier

@@ -11,7 +11,7 @@ class ReportForm(forms.Form):
11 11
     type_choices = []
12 12
     for generator in generators:
13 13
         type_choices.append((generator.code, generator.description))
14
-    report_type = forms.ChoiceField(widget=forms.Select(), choices=type_choices,
14
+    report_type = forms.ChoiceField(widget=forms.Select(), choices=type_choices, label=_("Report Type"),
15 15
                                     help_text=_("Only the offer and order reports "
16 16
                                                 "use the selected date range"))
17 17
 

+ 1
- 1
oscar/apps/dashboard/users/views.py Voir le fichier

@@ -17,7 +17,7 @@ class IndexView(ListView, BulkEditMixin):
17 17
     actions = ('make_active', 'make_inactive', )
18 18
     current_view = 'dashboard:users-index'
19 19
     form_class = forms.UserSearchForm
20
-    desc_template = _(u'%(main_filter)s %(email_filter)s %(name_filter)s')
20
+    desc_template = _('%(main_filter)s %(email_filter)s %(name_filter)s')
21 21
     description = ''
22 22
 
23 23
     def get_queryset(self):

+ 3
- 3
oscar/apps/dashboard/vouchers/forms.py Voir le fichier

@@ -71,9 +71,9 @@ class VoucherForm(forms.Form):
71 71
 
72 72
 
73 73
 class VoucherSearchForm(forms.Form):
74
-    name = forms.CharField(required=False)
75
-    code = forms.CharField(required=False)
76
-    is_active = forms.BooleanField(required=False)
74
+    name = forms.CharField(required=False, label=_("Name"))
75
+    code = forms.CharField(required=False, label=_("Code"))
76
+    is_active = forms.BooleanField(required=False, label=_("Is Active?"))
77 77
 
78 78
     def clean_code(self):
79 79
         return self.cleaned_data['code'].upper()

+ 1
- 1
oscar/apps/dashboard/vouchers/views.py Voir le fichier

@@ -84,7 +84,7 @@ class VoucherCreateView(FormView):
84 84
         )
85 85
         name = form.cleaned_data['name']
86 86
         offer = ConditionalOffer.objects.create(
87
-            name="Offer for voucher '%s'" % name,
87
+            name=_("Offer for voucher '%s'") % name,
88 88
             offer_type="Voucher",
89 89
             benefit=benefit,
90 90
             condition=condition,

+ 32
- 28
oscar/apps/offer/models.py Voir le fichier

@@ -18,11 +18,11 @@ class ConditionalOffer(models.Model):
18 18
     """
19 19
     A conditional offer (eg buy 1, get 10% off)
20 20
     """
21
-    name = models.CharField(_('Name'), max_length=128, unique=True,
21
+    name = models.CharField(_("Name"), max_length=128, unique=True,
22 22
                             help_text=_("""This is displayed within the customer's
23 23
                             basket"""))
24
-    slug = models.SlugField(_('Slug'), max_length=128, unique=True, null=True)
25
-    description = models.TextField(_('Description'), blank=True, null=True)
24
+    slug = models.SlugField(_("Slug"), max_length=128, unique=True, null=True)
25
+    description = models.TextField(_("Description"), blank=True, null=True)
26 26
 
27 27
     # Offers come in a few different types:
28 28
     # (a) Offers that are available to all customers on the site.  Eg a
@@ -40,34 +40,34 @@ class ConditionalOffer(models.Model):
40 40
         (USER, _("User offer - available to certain types of user")),
41 41
         (SESSION, _("Session offer - temporary offer, available for a user for the duration of their session")),
42 42
     )
43
-    offer_type = models.CharField(_('Type'), choices=TYPE_CHOICES, default=SITE, max_length=128)
43
+    offer_type = models.CharField(_("Type"), choices=TYPE_CHOICES, default=SITE, max_length=128)
44 44
 
45
-    condition = models.ForeignKey('offer.Condition')
46
-    benefit = models.ForeignKey('offer.Benefit')
45
+    condition = models.ForeignKey('offer.Condition', verbose_name=_("Condition"))
46
+    benefit = models.ForeignKey('offer.Benefit', verbose_name=_("Benefit"))
47 47
 
48 48
     # Range of availability.  Note that if this is a voucher offer, then these
49 49
     # dates are ignored and only the dates from the voucher are used to determine
50 50
     # availability.
51
-    start_date = models.DateField(_('Start Date'), blank=True, null=True)
52
-    end_date = models.DateField(_('End Date'), blank=True, null=True,
53
-                                help_text=_("""Offers are not active on their end
54
-                                date, only the days preceding"""))
51
+    start_date = models.DateField(_("Start Date"), blank=True, null=True)
52
+    end_date = models.DateField(_("End Date"), blank=True, null=True,
53
+                                help_text=_("Offers are not active on their end "
54
+                                            "date, only the days preceding"))
55 55
 
56 56
     # Some complicated situations require offers to be applied in a set order.
57
-    priority = models.IntegerField(_('Priority'), default=0,
57
+    priority = models.IntegerField(_("Priority"), default=0,
58 58
         help_text=_("The highest priority offers are applied first"))
59 59
 
60 60
     # We track some information on usage
61
-    total_discount = models.DecimalField(_('Total Discount'), decimal_places=2, max_digits=12, default=Decimal('0.00'))
62
-    num_orders = models.PositiveIntegerField(_('Number of Orders'), default=0)
61
+    total_discount = models.DecimalField(_("Total Discount"), decimal_places=2, max_digits=12, default=Decimal('0.00'))
62
+    num_orders = models.PositiveIntegerField(_("Number of Orders"), default=0)
63 63
 
64
-    date_created = models.DateTimeField(auto_now_add=True)
64
+    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
65
+
66
+    redirect_url = ExtendedURLField(_("URL redirect (optional)"), blank=True)
65 67
 
66 68
     objects = models.Manager()
67 69
     active = ActiveOfferManager()
68 70
 
69
-    redirect_url = ExtendedURLField(_('URL redirect (optional)'), blank=True)
70
-
71 71
     # We need to track the voucher that this offer came from (if it is a voucher offer)
72 72
     _voucher = None
73 73
 
@@ -166,7 +166,7 @@ class Condition(models.Model):
166 166
         (VALUE, _("Depends on value of items in basket that are in condition range")),
167 167
         (COVERAGE, _("Needs to contain a set number of DISTINCT items from the condition range"))
168 168
     )
169
-    range = models.ForeignKey('offer.Range')
169
+    range = models.ForeignKey('offer.Range', verbose_name=_("Range"))
170 170
     type = models.CharField(_('Type'), max_length=128, choices=TYPE_CHOICES)
171 171
     value = PositiveDecimalField(_('Value'), decimal_places=2, max_digits=12)
172 172
 
@@ -220,22 +220,22 @@ class Condition(models.Model):
220 220
 class Benefit(models.Model):
221 221
     PERCENTAGE, FIXED, MULTIBUY, FIXED_PRICE = ("Percentage", "Absolute", "Multibuy", "Fixed price")
222 222
     TYPE_CHOICES = (
223
-        (PERCENTAGE, _("Discount is a % of the product's value")),
223
+        (PERCENTAGE, _("Discount is a %% of the product's value")),
224 224
         (FIXED, _("Discount is a fixed amount off the product's value")),
225 225
         (MULTIBUY, _("Discount is to give the cheapest product for free")),
226 226
         (FIXED_PRICE, _("Get the products that meet the condition for a fixed price")),
227 227
     )
228
-    range = models.ForeignKey('offer.Range', null=True, blank=True)
229
-    type = models.CharField(_('Type'), max_length=128, choices=TYPE_CHOICES)
230
-    value = PositiveDecimalField(_('Value'), decimal_places=2, max_digits=12,
228
+    range = models.ForeignKey('offer.Range', null=True, blank=True, verbose_name=_("Range"))
229
+    type = models.CharField(_("Type"), max_length=128, choices=TYPE_CHOICES)
230
+    value = PositiveDecimalField(_("Value"), decimal_places=2, max_digits=12,
231 231
                                  null=True, blank=True)
232 232
 
233 233
     price_field = 'price_incl_tax'
234 234
 
235 235
     # If this is not set, then there is no upper limit on how many products
236 236
     # can be discounted by this benefit.
237
-    max_affected_items = models.PositiveIntegerField(_('Max Affected Items'), blank=True, null=True,
238
-        help_text=_("""Set this to prevent the discount consuming all items within the range that are in the basket."""))
237
+    max_affected_items = models.PositiveIntegerField(_("Max Affected Items"), blank=True, null=True,
238
+        help_text=_("Set this to prevent the discount consuming all items within the range that are in the basket."))
239 239
 
240 240
     class Meta:
241 241
         verbose_name = _("Benefit")
@@ -302,11 +302,15 @@ class Range(models.Model):
302 302
     """
303 303
     name = models.CharField(_("Name"), max_length=128, unique=True)
304 304
     includes_all_products = models.BooleanField(_('Includes All Products'), default=False)
305
-    included_products = models.ManyToManyField('catalogue.Product', related_name='includes', blank=True)
306
-    excluded_products = models.ManyToManyField('catalogue.Product', related_name='excludes', blank=True)
307
-    classes = models.ManyToManyField('catalogue.ProductClass', related_name='classes', blank=True)
308
-    included_categories = models.ManyToManyField('catalogue.Category', related_name='includes', blank=True)
309
-    date_created = models.DateTimeField(auto_now_add=True)
305
+    included_products = models.ManyToManyField('catalogue.Product', related_name='includes', blank=True,
306
+        verbose_name=_("Included Products"))
307
+    excluded_products = models.ManyToManyField('catalogue.Product', related_name='excludes', blank=True,
308
+        verbose_name=_("Excluded Products"))
309
+    classes = models.ManyToManyField('catalogue.ProductClass', related_name='classes', blank=True,
310
+        verbose_name=_("Product Classes"))
311
+    included_categories = models.ManyToManyField('catalogue.Category', related_name='includes', blank=True,
312
+        verbose_name=_("Included Categories"))
313
+    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
310 314
 
311 315
     __included_product_ids = None
312 316
     __excluded_product_ids = None

+ 81
- 76
oscar/apps/order/abstract_models.py Voir le fichier

@@ -20,12 +20,13 @@ class AbstractOrder(models.Model):
20 20
     """
21 21
     number = models.CharField(_("Order number"), max_length=128, db_index=True)
22 22
     # We track the site that each order is placed within
23
-    site = models.ForeignKey('sites.Site')
24
-    basket_id = models.PositiveIntegerField(_('Basket ID'), null=True, blank=True)
23
+    site = models.ForeignKey('sites.Site', verbose_name=_("Site"))
24
+    basket_id = models.PositiveIntegerField(_("Basket ID"), null=True, blank=True)
25 25
     # Orders can be anonymous so we don't always have a customer ID
26
-    user = models.ForeignKey(User, related_name='orders', null=True, blank=True)
26
+    user = models.ForeignKey(User, related_name='orders', null=True, blank=True, verbose_name=_("User"))
27 27
     # Billing address is not always required (eg paying by gift card)
28
-    billing_address = models.ForeignKey('order.BillingAddress', null=True, blank=True)
28
+    billing_address = models.ForeignKey('order.BillingAddress', null=True, blank=True,
29
+        verbose_name=_("Billing Address"))
29 30
 
30 31
     # Total price looks like it could be calculated by adding up the
31 32
     # prices of the associated lines, but in some circumstances extra
@@ -39,7 +40,8 @@ class AbstractOrder(models.Model):
39 40
 
40 41
     # Not all lines are actually shipped (such as downloads), hence shipping address
41 42
     # is not mandatory.
42
-    shipping_address = models.ForeignKey('order.ShippingAddress', null=True, blank=True)
43
+    shipping_address = models.ForeignKey('order.ShippingAddress', null=True, blank=True,
44
+        verbose_name=_("Shipping Address"))
43 45
     shipping_method = models.CharField(_("Shipping method"), max_length=128, null=True, blank=True)
44 46
 
45 47
     # Use this field to indicate that an order is on hold / awaiting payment
@@ -65,7 +67,7 @@ class AbstractOrder(models.Model):
65 67
         if new_status == self.status:
66 68
             return
67 69
         if new_status not in self.available_statuses():
68
-            raise InvalidOrderStatus(_("'%(new_status)s' is not a valid status for order %(number)s "+
70
+            raise InvalidOrderStatus(_("'%(new_status)s' is not a valid status for order %(number)s "
69 71
                                        "(current status: '%(status)s')") % {
70 72
                                             'new_status': new_status,
71 73
                                             'number': self.number,
@@ -184,7 +186,7 @@ class AbstractOrder(models.Model):
184 186
         abstract = True
185 187
         ordering = ['-date_placed',]
186 188
         permissions = (
187
-            ("can_view", "Can view orders (eg for reporting)"),
189
+            ("can_view", _("Can view orders (eg for reporting)")),
188 190
         )
189 191
         verbose_name = _("Order")
190 192
         verbose_name_plural = _("Orders")
@@ -210,19 +212,19 @@ class AbstractOrderNote(models.Model):
210 212
     This are often used for audit purposes too.  IE, whenever an admin
211 213
     makes a change to an order, we create a note to record what happened.
212 214
     """
213
-    order = models.ForeignKey('order.Order', related_name="notes")
215
+    order = models.ForeignKey('order.Order', related_name="notes", verbose_name=_("Order"))
214 216
 
215 217
     # These are sometimes programatically generated so don't need a
216 218
     # user everytime
217
-    user = models.ForeignKey('auth.User', null=True)
219
+    user = models.ForeignKey('auth.User', null=True, verbose_name=_("User"))
218 220
 
219 221
     # We allow notes to be classified although this isn't always needed
220 222
     INFO, WARNING, ERROR, SYSTEM = 'Info', 'Warning', 'Error', 'System'
221
-    note_type = models.CharField(_('Note Type'), max_length=128, null=True)
223
+    note_type = models.CharField(_("Note Type"), max_length=128, null=True)
222 224
 
223
-    message = models.TextField(_('Message'))
224
-    date_created = models.DateTimeField(auto_now_add=True)
225
-    date_updated = models.DateTimeField(auto_now=True)
225
+    message = models.TextField(_("Message"))
226
+    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
227
+    date_updated = models.DateTimeField(_("Date Updated"), auto_now=True)
226 228
 
227 229
     # Notes can only be edited for 5 minutes after being created
228 230
     editable_lifetime = 300
@@ -246,9 +248,9 @@ class AbstractCommunicationEvent(models.Model):
246 248
     An order-level event involving a communication to the customer, such
247 249
     as an confirmation email being sent.
248 250
     """
249
-    order = models.ForeignKey('order.Order', related_name="communication_events")
250
-    event_type = models.ForeignKey('customer.CommunicationEventType')
251
-    date = models.DateTimeField(auto_now_add=True)
251
+    order = models.ForeignKey('order.Order', related_name="communication_events", verbose_name=_("Order"))
252
+    event_type = models.ForeignKey('customer.CommunicationEventType', verbose_name=_("Event Type"))
253
+    date = models.DateTimeField(_("Date"), auto_now_add=True)
252 254
 
253 255
     class Meta:
254 256
         abstract = True
@@ -266,12 +268,13 @@ class AbstractLine(models.Model):
266 268
     Not using a line model as it's difficult to capture and payment
267 269
     information when it splits across a line.
268 270
     """
269
-    order = models.ForeignKey('order.Order', related_name='lines')
271
+    order = models.ForeignKey('order.Order', related_name='lines', verbose_name=_("Order"))
270 272
 
271 273
     # We store the partner, their SKU and the title for cases where the product has been
272 274
     # deleted from the catalogue.  We also store the partner name in case the partner
273 275
     # gets deleted at a later date.
274
-    partner = models.ForeignKey('partner.Partner', related_name='order_lines', blank=True, null=True, on_delete=models.SET_NULL)
276
+    partner = models.ForeignKey('partner.Partner', related_name='order_lines', blank=True, null=True,
277
+        on_delete=models.SET_NULL, verbose_name=_("Partner"))
275 278
     partner_name = models.CharField(_("Partner name"), max_length=128)
276 279
     partner_sku = models.CharField(_("Partner SKU"), max_length=128)
277 280
 
@@ -280,43 +283,44 @@ class AbstractLine(models.Model):
280 283
 
281 284
     # We don't want any hard links between orders and the products table so we allow
282 285
     # this link to be NULLable.
283
-    product = models.ForeignKey('catalogue.Product', on_delete=models.SET_NULL, blank=True, null=True)
284
-    quantity = models.PositiveIntegerField(_('Quantity'), default=1)
286
+    product = models.ForeignKey('catalogue.Product', on_delete=models.SET_NULL, blank=True, null=True,
287
+        verbose_name=_("Product"))
288
+    quantity = models.PositiveIntegerField(_("Quantity"), default=1)
285 289
 
286 290
     # Price information (these fields are actually redundant as the information
287 291
     # can be calculated from the LinePrice models
288
-    line_price_incl_tax = models.DecimalField(_('Price (inc. tax)'), decimal_places=2, max_digits=12)
289
-    line_price_excl_tax = models.DecimalField(_('Price (excl. tax)'), decimal_places=2, max_digits=12)
292
+    line_price_incl_tax = models.DecimalField(_("Price (inc. tax)"), decimal_places=2, max_digits=12)
293
+    line_price_excl_tax = models.DecimalField(_("Price (excl. tax)"), decimal_places=2, max_digits=12)
290 294
 
291 295
     # Price information before discounts are applied
292
-    line_price_before_discounts_incl_tax = models.DecimalField(_('Price before discounts (inc. tax)'),
296
+    line_price_before_discounts_incl_tax = models.DecimalField(_("Price before discounts (inc. tax)"),
293 297
         decimal_places=2, max_digits=12)
294
-    line_price_before_discounts_excl_tax = models.DecimalField(_('Price before discounts (excl. tax)'),
298
+    line_price_before_discounts_excl_tax = models.DecimalField(_("Price before discounts (excl. tax)"),
295 299
         decimal_places=2, max_digits=12)
296 300
 
297 301
     # REPORTING FIELDS
298 302
     # Cost price (the price charged by the fulfilment partner for this product).
299
-    unit_cost_price = models.DecimalField(_('Unit Cost Price'), decimal_places=2, max_digits=12, blank=True, null=True)
303
+    unit_cost_price = models.DecimalField(_("Unit Cost Price"), decimal_places=2, max_digits=12, blank=True, null=True)
300 304
     # Normal site price for item (without discounts)
301
-    unit_price_incl_tax = models.DecimalField(_('Unit Price (inc. tax)'),decimal_places=2, max_digits=12,
305
+    unit_price_incl_tax = models.DecimalField(_("Unit Price (inc. tax)"),decimal_places=2, max_digits=12,
302 306
         blank=True, null=True)
303
-    unit_price_excl_tax = models.DecimalField(_('Unit Price (excl. tax)'), decimal_places=2, max_digits=12,
307
+    unit_price_excl_tax = models.DecimalField(_("Unit Price (excl. tax)"), decimal_places=2, max_digits=12,
304 308
         blank=True, null=True)
305 309
     # Retail price at time of purchase
306
-    unit_retail_price = models.DecimalField(_('Unit Retail Price'), decimal_places=2, max_digits=12,
310
+    unit_retail_price = models.DecimalField(_("Unit Retail Price"), decimal_places=2, max_digits=12,
307 311
         blank=True, null=True)
308 312
 
309 313
     # Partner information
310 314
     partner_line_reference = models.CharField(_("Partner reference"), max_length=128, blank=True, null=True,
311 315
         help_text=_("This is the item number that the partner uses within their system"))
312
-    partner_line_notes = models.TextField(_('Partner Notes'), blank=True, null=True)
316
+    partner_line_notes = models.TextField(_("Partner Notes"), blank=True, null=True)
313 317
 
314 318
     # Partners often want to assign some status to each line to help with their own
315 319
     # business processes.
316 320
     status = models.CharField(_("Status"), max_length=255, null=True, blank=True)
317 321
 
318 322
     # Estimated dispatch date - should be set at order time
319
-    est_dispatch_date = models.DateField(_('Estimated Dispatch Date'), blank=True, null=True)
323
+    est_dispatch_date = models.DateField(_("Estimated Dispatch Date"), blank=True, null=True)
320 324
 
321 325
     pipeline = getattr(settings,  'OSCAR_LINE_STATUS_PIPELINE', {})
322 326
 
@@ -429,8 +433,8 @@ class AbstractLine(models.Model):
429 433
 
430 434
     class Meta:
431 435
         abstract = True
432
-        verbose_name = _("Order line")
433
-        verbose_name_plural = _("Order lines")
436
+        verbose_name = _("Order Line")
437
+        verbose_name_plural = _("Order Lines")
434 438
 
435 439
     def __unicode__(self):
436 440
         if self.product:
@@ -442,8 +446,9 @@ class AbstractLine(models.Model):
442 446
 
443 447
 class AbstractLineAttribute(models.Model):
444 448
     u"""An attribute of a line."""
445
-    line = models.ForeignKey('order.Line', related_name='attributes')
446
-    option = models.ForeignKey('catalogue.Option', null=True, on_delete=models.SET_NULL, related_name="line_attributes")
449
+    line = models.ForeignKey('order.Line', related_name='attributes', verbose_name=_("Line"))
450
+    option = models.ForeignKey('catalogue.Option', null=True, on_delete=models.SET_NULL,
451
+        related_name="line_attributes", verbose_name=_("Option"))
447 452
     type = models.CharField(_("Type"), max_length=128)
448 453
     value = models.CharField(_("Value"), max_length=255)
449 454
 
@@ -464,13 +469,13 @@ class AbstractLinePrice(models.Model):
464 469
     having different prices.  For example, one product may be sold at
465 470
     50% off as it's part of an offer while the remainder are full price.
466 471
     """
467
-    order = models.ForeignKey('order.Order', related_name='line_prices')
468
-    line = models.ForeignKey('order.Line', related_name='prices')
469
-    quantity = models.PositiveIntegerField(_('Quantity'), default=1)
470
-    price_incl_tax = models.DecimalField(_('Price (inc. tax)'), decimal_places=2, max_digits=12)
471
-    price_excl_tax = models.DecimalField(_('Price (excl. tax)'), decimal_places=2, max_digits=12)
472
-    shipping_incl_tax = models.DecimalField(_('Shiping (inc. tax)'), decimal_places=2, max_digits=12, default=0)
473
-    shipping_excl_tax = models.DecimalField(_('Shipping (excl. tax)'), decimal_places=2, max_digits=12, default=0)
472
+    order = models.ForeignKey('order.Order', related_name='line_prices', verbose_name=_("Option"))
473
+    line = models.ForeignKey('order.Line', related_name='prices', verbose_name=_("Line"))
474
+    quantity = models.PositiveIntegerField(_("Quantity"), default=1)
475
+    price_incl_tax = models.DecimalField(_("Price (inc. tax)"), decimal_places=2, max_digits=12)
476
+    price_excl_tax = models.DecimalField(_("Price (excl. tax)"), decimal_places=2, max_digits=12)
477
+    shipping_incl_tax = models.DecimalField(_("Shiping (inc. tax)"), decimal_places=2, max_digits=12, default=0)
478
+    shipping_excl_tax = models.DecimalField(_("Shipping (excl. tax)"), decimal_places=2, max_digits=12, default=0)
474 479
 
475 480
     class Meta:
476 481
         abstract = True
@@ -490,9 +495,9 @@ class AbstractPaymentEventType(models.Model):
490 495
     """
491 496
     Payment events are things like 'Paid', 'Failed', 'Refunded'
492 497
     """
493
-    name = models.CharField(_('Name'), max_length=128, unique=True)
494
-    code = models.SlugField(_('Code'), max_length=128, unique=True)
495
-    sequence_number = models.PositiveIntegerField(_('Sequence'), default=0)
498
+    name = models.CharField(_("Name"), max_length=128, unique=True)
499
+    code = models.SlugField(_("Code"), max_length=128, unique=True)
500
+    sequence_number = models.PositiveIntegerField(_("Sequence"), default=0)
496 501
 
497 502
     def save(self, *args, **kwargs):
498 503
         if not self.code:
@@ -501,8 +506,8 @@ class AbstractPaymentEventType(models.Model):
501 506
 
502 507
     class Meta:
503 508
         abstract = True
504
-        verbose_name = _("Payment event type")
505
-        verbose_name_plural = _("Payment event types")
509
+        verbose_name = _("Payment Event Type")
510
+        verbose_name_plural = _("Payment Event Types")
506 511
         ordering = ('sequence_number',)
507 512
 
508 513
     def __unicode__(self):
@@ -514,16 +519,16 @@ class AbstractPaymentEvent(models.Model):
514 519
     An event is something which happens to a line such as
515 520
     payment being taken for 2 items, or 1 item being dispatched.
516 521
     """
517
-    order = models.ForeignKey('order.Order', related_name='payment_events')
518
-    amount = models.DecimalField(_('Amount'), decimal_places=2, max_digits=12)
519
-    lines = models.ManyToManyField('order.Line', through='PaymentEventQuantity')
520
-    event_type = models.ForeignKey('order.PaymentEventType')
521
-    date = models.DateTimeField(auto_now_add=True)
522
+    order = models.ForeignKey('order.Order', related_name='payment_events', verbose_name=_("Order"))
523
+    amount = models.DecimalField(_("Amount"), decimal_places=2, max_digits=12)
524
+    lines = models.ManyToManyField('order.Line', through='PaymentEventQuantity', verbose_name=_("Lines"))
525
+    event_type = models.ForeignKey('order.PaymentEventType', verbose_name=_("Event Type"))
526
+    date = models.DateTimeField(_("Date Created"), auto_now_add=True)
522 527
 
523 528
     class Meta:
524 529
         abstract = True
525
-        verbose_name = _("Payment event")
526
-        verbose_name_plural = _("Payment events")
530
+        verbose_name = _("Payment Event")
531
+        verbose_name_plural = _("Payment Events")
527 532
 
528 533
     def __unicode__(self):
529 534
         return _("Payment event for order %s") % self.order
@@ -536,9 +541,9 @@ class PaymentEventQuantity(models.Model):
536 541
     """
537 542
     A "through" model linking lines to payment events
538 543
     """
539
-    event = models.ForeignKey('order.PaymentEvent', related_name='line_quantities')
540
-    line = models.ForeignKey('order.Line')
541
-    quantity = models.PositiveIntegerField(_('Quantity'))
544
+    event = models.ForeignKey('order.PaymentEvent', related_name='line_quantities', verbose_name=_("Event"))
545
+    line = models.ForeignKey('order.Line', verbose_name=_("Line"))
546
+    quantity = models.PositiveIntegerField(_("Quantity"))
542 547
 
543 548
     class Meta:
544 549
         verbose_name = _("Payment Event Quantity")
@@ -553,17 +558,17 @@ class AbstractShippingEvent(models.Model):
553 558
     An event is something which happens to a group of lines such as
554 559
     1 item being dispatched.
555 560
     """
556
-    order = models.ForeignKey('order.Order', related_name='shipping_events')
557
-    lines = models.ManyToManyField('order.Line', through='ShippingEventQuantity')
558
-    event_type = models.ForeignKey('order.ShippingEventType')
561
+    order = models.ForeignKey('order.Order', related_name='shipping_events', verbose_name=_("Order"))
562
+    lines = models.ManyToManyField('order.Line', through='ShippingEventQuantity', verbose_name=_("Lines"))
563
+    event_type = models.ForeignKey('order.ShippingEventType', verbose_name=_("Event Type"))
559 564
     notes = models.TextField(_("Event notes"), blank=True, null=True,
560 565
         help_text=_("This could be the dispatch reference, or a tracking number"))
561
-    date = models.DateTimeField(auto_now_add=True)
566
+    date = models.DateTimeField(_("Date Created"), auto_now_add=True)
562 567
 
563 568
     class Meta:
564 569
         abstract = True
565
-        verbose_name = _("Shipping event")
566
-        verbose_name_plural = _("Shipping events")
570
+        verbose_name = _("Shipping Event")
571
+        verbose_name_plural = _("Shipping Events")
567 572
         ordering = ['-date']
568 573
 
569 574
     def __unicode__(self):
@@ -578,9 +583,9 @@ class ShippingEventQuantity(models.Model):
578 583
     """
579 584
     A "through" model linking lines to shipping events
580 585
     """
581
-    event = models.ForeignKey('order.ShippingEvent', related_name='line_quantities')
582
-    line = models.ForeignKey('order.Line')
583
-    quantity = models.PositiveIntegerField(_('Quantity'))
586
+    event = models.ForeignKey('order.ShippingEvent', related_name='line_quantities', verbose_name=_("Event"))
587
+    line = models.ForeignKey('order.Line', verbose_name=_("Line"))
588
+    quantity = models.PositiveIntegerField(_("Quantity"))
584 589
 
585 590
     class Meta:
586 591
         verbose_name = _("Shipping Event Quantity")
@@ -619,7 +624,7 @@ class ShippingEventQuantity(models.Model):
619 624
         super(ShippingEventQuantity, self).save(*args, **kwargs)
620 625
 
621 626
     def __unicode__(self):
622
-        return _(u"%(product)s - quantity %(qty)d") % {'product': self.line.product, 'qty': self.quantity}
627
+        return _("%(product)s - quantity %(qty)d") % {'product': self.line.product, 'qty': self.quantity}
623 628
 
624 629
 
625 630
 class AbstractShippingEventType(models.Model):
@@ -627,13 +632,13 @@ class AbstractShippingEventType(models.Model):
627 632
     Shipping events are things like 'OrderPlaced', 'Acknowledged', 'Dispatched', 'Refunded'
628 633
     """
629 634
     # Name is the friendly description of an event
630
-    name = models.CharField(_('Name'), max_length=255, unique=True)
635
+    name = models.CharField(_("Name"), max_length=255, unique=True)
631 636
     # Code is used in forms
632
-    code = models.SlugField(_('Code'), max_length=128, unique=True)
633
-    is_required = models.BooleanField(_('Is Required'), default=True,
637
+    code = models.SlugField(_("Code"), max_length=128, unique=True)
638
+    is_required = models.BooleanField(_("Is Required"), default=True,
634 639
         help_text=_("This event must be passed before the next shipping event can take place"))
635 640
     # The normal order in which these shipping events take place
636
-    sequence_number = models.PositiveIntegerField(_('Sequence'), default=0)
641
+    sequence_number = models.PositiveIntegerField(_("Sequence"), default=0)
637 642
 
638 643
     def save(self, *args, **kwargs):
639 644
         if not self.code:
@@ -642,8 +647,8 @@ class AbstractShippingEventType(models.Model):
642 647
 
643 648
     class Meta:
644 649
         abstract = True
645
-        verbose_name = _("Shipping event type")
646
-        verbose_name_plural = _("Shipping event types")
650
+        verbose_name = _("Shipping Event Type")
651
+        verbose_name_plural = _("Shipping Event Types")
647 652
         ordering = ('sequence_number',)
648 653
 
649 654
     def __unicode__(self):
@@ -662,11 +667,11 @@ class AbstractOrderDiscount(models.Model):
662 667
     Normally only used for display purposes so an order can be listed with discounts displayed
663 668
     separately even though in reality, the discounts are applied at the line level.
664 669
     """
665
-    order = models.ForeignKey('order.Order', related_name="discounts")
666
-    offer_id = models.PositiveIntegerField(_('Offer ID'), blank=True, null=True)
667
-    voucher_id = models.PositiveIntegerField(_('Voucher ID'), blank=True, null=True)
670
+    order = models.ForeignKey('order.Order', related_name="discounts", verbose_name=_("Order"))
671
+    offer_id = models.PositiveIntegerField(_("Offer ID"), blank=True, null=True)
672
+    voucher_id = models.PositiveIntegerField(_("Voucher ID"), blank=True, null=True)
668 673
     voucher_code = models.CharField(_("Code"), max_length=128, db_index=True, null=True)
669
-    amount = models.DecimalField(_('Amount'), decimal_places=2, max_digits=12, default=0)
674
+    amount = models.DecimalField(_("Amount"), decimal_places=2, max_digits=12, default=0)
670 675
 
671 676
     class Meta:
672 677
         abstract = True

+ 24
- 23
oscar/apps/partner/abstract_models.py Voir le fichier

@@ -32,15 +32,16 @@ class AbstractPartner(models.Model):
32 32
     """
33 33
     Fulfillment partner
34 34
     """
35
-    name = models.CharField(_('Name'), max_length=128, unique=True)
35
+    name = models.CharField(_("Name"), max_length=128, unique=True)
36 36
 
37 37
     # A partner can have users assigned to it.  These can be used
38 38
     # to provide authentication for webservices etc.
39
-    users = models.ManyToManyField('auth.User', related_name="partners", blank=True, null=True)
39
+    users = models.ManyToManyField('auth.User', related_name="partners", blank=True, null=True,
40
+        verbose_name=_("Users"))
40 41
 
41 42
     class Meta:
42
-        verbose_name = _('Fulfillment partner')
43
-        verbose_name_plural = _('Fulfillment partners')
43
+        verbose_name = _('Fulfillment Partner')
44
+        verbose_name_plural = _('Fulfillment Partners')
44 45
         abstract = True
45 46
         permissions = (
46 47
             ("can_edit_stock_records", _("Can edit stock records")),
@@ -66,42 +67,42 @@ class AbstractStockRecord(models.Model):
66 67
     We deliberately don't store tax information to allow each project
67 68
     to subclass this model and put its own fields for convey tax.
68 69
     """
69
-    product = models.OneToOneField('catalogue.Product', related_name="stockrecord")
70
-    partner = models.ForeignKey('partner.Partner')
70
+    product = models.OneToOneField('catalogue.Product', related_name="stockrecord", verbose_name=_("Product"))
71
+    partner = models.ForeignKey('partner.Partner', verbose_name=_("Partner"))
71 72
 
72 73
     # The fulfilment partner will often have their own SKU for a product, which
73 74
     # we store here.
74 75
     partner_sku = models.CharField(_("Partner SKU"), max_length=128)
75 76
 
76 77
     # Price info:
77
-    price_currency = models.CharField(_('Currency'), max_length=12, default=settings.OSCAR_DEFAULT_CURRENCY)
78
+    price_currency = models.CharField(_("Currency"), max_length=12, default=settings.OSCAR_DEFAULT_CURRENCY)
78 79
 
79 80
     # This is the base price for calculations - tax should be applied
80 81
     # by the appropriate method.  We don't store it here as its calculation is
81 82
     # highly domain-specific.  It is NULLable because some items don't have a fixed
82 83
     # price.
83
-    price_excl_tax = models.DecimalField(_('Price (excl. tax)'), decimal_places=2, max_digits=12, blank=True, null=True)
84
+    price_excl_tax = models.DecimalField(_("Price (excl. tax)"), decimal_places=2, max_digits=12, blank=True, null=True)
84 85
 
85 86
     # Retail price for this item
86
-    price_retail = models.DecimalField(_('Price (retail)'), decimal_places=2, max_digits=12, blank=True, null=True)
87
+    price_retail = models.DecimalField(_("Price (retail)"), decimal_places=2, max_digits=12, blank=True, null=True)
87 88
 
88 89
     # Cost price is optional as not all partners supply it
89
-    cost_price = models.DecimalField(_('Cost Price'), decimal_places=2, max_digits=12, blank=True, null=True)
90
+    cost_price = models.DecimalField(_("Cost Price"), decimal_places=2, max_digits=12, blank=True, null=True)
90 91
 
91 92
     # Stock level information
92
-    num_in_stock = models.PositiveIntegerField(_('Number in stock'), default=0, blank=True, null=True)
93
+    num_in_stock = models.PositiveIntegerField(_("Number in stock"), default=0, blank=True, null=True)
93 94
 
94 95
     # Threshold for low-stock alerts
95
-    low_stock_threshold = models.PositiveIntegerField(_('Low Stock Threshold'), blank=True, null=True)
96
+    low_stock_threshold = models.PositiveIntegerField(_("Low Stock Threshold"), blank=True, null=True)
96 97
 
97 98
     # The amount of stock allocated to orders but not fed back to the master
98 99
     # stock system.  A typical stock update process will set the num_in_stock
99 100
     # variable to a new value and reset num_allocated to zero
100
-    num_allocated = models.IntegerField(_('Number of Allocated'), default=0, blank=True, null=True)
101
+    num_allocated = models.IntegerField(_("Number of Allocated"), default=0, blank=True, null=True)
101 102
 
102 103
     # Date information
103
-    date_created = models.DateTimeField(auto_now_add=True)
104
-    date_updated = models.DateTimeField(auto_now=True, db_index=True)
104
+    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
105
+    date_updated = models.DateTimeField(_("Date Updated"), auto_now=True, db_index=True)
105 106
 
106 107
     class Meta:
107 108
         abstract = True
@@ -256,16 +257,16 @@ class AbstractStockRecord(models.Model):
256 257
 
257 258
 
258 259
 class AbstractStockAlert(models.Model):
259
-    stockrecord = models.ForeignKey('partner.StockRecord', related_name='alerts')
260
-    threshold = models.PositiveIntegerField(_('Threshold'))
261
-    OPEN, CLOSED = 'Open', 'Closed'
260
+    stockrecord = models.ForeignKey('partner.StockRecord', related_name='alerts', verbose_name=_("Stock Record"))
261
+    threshold = models.PositiveIntegerField(_("Threshold"))
262
+    OPEN, CLOSED = "Open", "Closed"
262 263
     status_choices = (
263
-        (OPEN, _('Open')),
264
-        (CLOSED, _('Closed')),
264
+        (OPEN, _("Open")),
265
+        (CLOSED, _("Closed")),
265 266
     )
266
-    status = models.CharField(max_length=128, default=OPEN, choices=status_choices)
267
-    date_created = models.DateTimeField(auto_now_add=True)
268
-    date_closed = models.DateTimeField(blank=True, null=True)
267
+    status = models.CharField(_("Status"), max_length=128, default=OPEN, choices=status_choices)
268
+    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
269
+    date_closed = models.DateTimeField(_("Date Closed"), blank=True, null=True)
269 270
 
270 271
     def close(self):
271 272
         self.status = self.CLOSED

+ 22
- 22
oscar/apps/payment/models.py Voir le fichier

@@ -13,15 +13,15 @@ class Transaction(models.Model):
13 13
     This applies mainly to credit card sources which can be a pre-auth for the money.  A 'complete'
14 14
     needs to be run later to debit the money from the account.
15 15
     """
16
-    source = models.ForeignKey('payment.Source', related_name='transactions')
16
+    source = models.ForeignKey('payment.Source', related_name='transactions', verbose_name=_("Source"))
17 17
     
18 18
     # We define some sample types
19 19
     AUTHORISE, DEBIT, REFUND = 'Authorise', 'Debit', 'Refund'
20
-    txn_type = models.CharField(_('Type'), max_length=128, blank=True)
21
-    amount = models.DecimalField(_('Amount'), decimal_places=2, max_digits=12)
22
-    reference = models.CharField(_('Reference'), max_length=128, null=True)
23
-    status = models.CharField(_('Status'), max_length=128, null=True)
24
-    date_created = models.DateTimeField(auto_now_add=True)
20
+    txn_type = models.CharField(_("Type"), max_length=128, blank=True)
21
+    amount = models.DecimalField(_("Amount"), decimal_places=2, max_digits=12)
22
+    reference = models.CharField(_("Reference"), max_length=128, null=True)
23
+    status = models.CharField(_("Status"), max_length=128, null=True)
24
+    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
25 25
     
26 26
     def __unicode__(self):
27 27
         return _("%(type)s of %(amount).2f") % {'type': self.txn_type, 'amount': self.amount}
@@ -40,21 +40,21 @@ class Source(models.Model):
40 40
     multiple sources such as cheque, credit accounts, gift cards.  Each payment
41 41
     source will have its own entry.
42 42
     """
43
-    order = models.ForeignKey('order.Order', related_name='sources')
44
-    source_type = models.ForeignKey('payment.SourceType')
45
-    currency = models.CharField(_('Currency'), max_length=12, default=settings.OSCAR_DEFAULT_CURRENCY)
43
+    order = models.ForeignKey('order.Order', related_name='sources', verbose_name=_("Order"))
44
+    source_type = models.ForeignKey('payment.SourceType', verbose_name=_("Source Type"))
45
+    currency = models.CharField(_("Currency"), max_length=12, default=settings.OSCAR_DEFAULT_CURRENCY)
46 46
     
47 47
     # Track the various amounts associated with this source
48
-    amount_allocated = models.DecimalField(_('Amount Allocated'), decimal_places=2, max_digits=12, default=Decimal('0.00'))
49
-    amount_debited = models.DecimalField(_('Amount Debited'), decimal_places=2, max_digits=12, default=Decimal('0.00'))
50
-    amount_refunded = models.DecimalField(_('Amount Refunded'), decimal_places=2, max_digits=12, default=Decimal('0.00'))
48
+    amount_allocated = models.DecimalField(_("Amount Allocated"), decimal_places=2, max_digits=12, default=Decimal('0.00'))
49
+    amount_debited = models.DecimalField(_("Amount Debited"), decimal_places=2, max_digits=12, default=Decimal('0.00'))
50
+    amount_refunded = models.DecimalField(_("Amount Refunded"), decimal_places=2, max_digits=12, default=Decimal('0.00'))
51 51
     
52 52
     # Reference number for this payment source.  This is often used to look up a
53 53
     # transaction model for a particular payment partner. 
54
-    reference = models.CharField(_('Reference'), max_length=128, blank=True, null=True)
54
+    reference = models.CharField(_("Reference"), max_length=128, blank=True, null=True)
55 55
     
56 56
     # A customer-friendly label for the source, eg XXXX-XXXX-XXXX-1234
57
-    label = models.CharField(_('Label'), max_length=128, blank=True, null=True)
57
+    label = models.CharField(_("Label"), max_length=128, blank=True, null=True)
58 58
     
59 59
     # A dictionary of submission data that is stored as part of the
60 60
     # checkout process.
@@ -142,8 +142,8 @@ class SourceType(models.Model):
142 142
     This could be an external partner like PayPal or DataCash,
143 143
     or an internal source such as a managed account.i
144 144
     """
145
-    name = models.CharField(_('Name'), max_length=128)
146
-    code = models.SlugField(_('Code'), max_length=128, help_text=_("""This is used within
145
+    name = models.CharField(_("Name"), max_length=128)
146
+    code = models.SlugField(_("Code"), max_length=128, help_text=_("""This is used within
147 147
         forms to identify this source type"""))
148 148
 
149 149
     class Meta:
@@ -160,14 +160,14 @@ class SourceType(models.Model):
160 160
     
161 161
 
162 162
 class Bankcard(models.Model):
163
-    user = models.ForeignKey('auth.User', related_name='bankcards')
164
-    card_type = models.CharField(_('Card Type'), max_length=128)
165
-    name = models.CharField(_('Name'), max_length=255)
166
-    number = models.CharField(_('Number'), max_length=32)
167
-    expiry_date = models.DateField(_('Expiry Date'))
163
+    user = models.ForeignKey('auth.User', related_name='bankcards', verbose_name=_("User"))
164
+    card_type = models.CharField(_("Card Type"), max_length=128)
165
+    name = models.CharField(_("Name"), max_length=255)
166
+    number = models.CharField(_("Number"), max_length=32)
167
+    expiry_date = models.DateField(_("Expiry Date"))
168 168
     
169 169
     # For payment partners who are storing the full card details for us
170
-    partner_reference = models.CharField(_('Partner Reference'), max_length=255, null=True, blank=True)
170
+    partner_reference = models.CharField(_("Partner Reference"), max_length=255, null=True, blank=True)
171 171
 
172 172
     class Meta:
173 173
         verbose_name = _("Bankcard")

+ 7
- 6
oscar/apps/promotions/models.py Voir le fichier

@@ -26,7 +26,7 @@ class LinkedPromotion(models.Model):
26 26
     position = models.CharField(_("Position"), max_length=100, help_text="Position on page")
27 27
     display_order = models.PositiveIntegerField(_("Display Order"), default=0)
28 28
     clicks = models.PositiveIntegerField(_("Clicks"), default=0)
29
-    date_created = models.DateTimeField(auto_now_add=True)
29
+    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
30 30
 
31 31
     class Meta:
32 32
         abstract = True
@@ -242,7 +242,8 @@ class HandPickedProductList(AbstractProductList):
242 242
     products.
243 243
     """
244 244
     _type = 'Product list'
245
-    products = models.ManyToManyField('catalogue.Product', through='OrderedProduct', blank=True, null=True)
245
+    products = models.ManyToManyField('catalogue.Product', through='OrderedProduct', blank=True, null=True,
246
+        verbose_name=_("Products"))
246 247
 
247 248
     def get_queryset(self):
248 249
         return self.products.all().order_by('%s.display_order' % OrderedProduct._meta.db_table)
@@ -257,8 +258,8 @@ class HandPickedProductList(AbstractProductList):
257 258
 
258 259
 class OrderedProduct(models.Model):
259 260
 
260
-    list = models.ForeignKey('promotions.HandPickedProductList')
261
-    product = models.ForeignKey('catalogue.Product')
261
+    list = models.ForeignKey('promotions.HandPickedProductList', verbose_name=_("List"))
262
+    product = models.ForeignKey('catalogue.Product', verbose_name=_("Product"))
262 263
     display_order = models.PositiveIntegerField(_('Display Order'), default=0)
263 264
 
264 265
     class Meta:
@@ -299,7 +300,7 @@ class AutomaticProductList(AbstractProductList):
299 300
 
300 301
 class OrderedProductList(HandPickedProductList):
301 302
     tabbed_block = models.ForeignKey('promotions.TabbedBlock',
302
-                                     related_name='tabs')
303
+                                     related_name='tabs', verbose_name=_("Tabbed Block"))
303 304
     display_order = models.PositiveIntegerField(_('Display Order'), default=0)
304 305
 
305 306
     class Meta:
@@ -312,7 +313,7 @@ class TabbedBlock(AbstractPromotion):
312 313
 
313 314
     _type = 'Tabbed block'
314 315
     name = models.CharField(_("Title"), max_length=255)
315
-    date_created = models.DateTimeField(auto_now_add=True)
316
+    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
316 317
 
317 318
     class Meta:
318 319
         verbose_name = _("Tabbed Block")

+ 13
- 13
oscar/apps/shipping/models.py Voir le fichier

@@ -13,7 +13,7 @@ class ShippingMethod(models.Model):
13 13
     description = models.TextField(_("Description"), blank=True)
14 14
 
15 15
     # We allow shipping methods to be linked to a specific set of countries
16
-    countries = models.ManyToManyField('address.Country', null=True, blank=True)
16
+    countries = models.ManyToManyField('address.Country', null=True, blank=True, verbose_name=_("Countries"))
17 17
 
18 18
     _basket = None
19 19
 
@@ -47,17 +47,17 @@ class OrderAndItemCharges(ShippingMethod):
47 47
     complex shipping logic, a custom shipping method object will need to be provided
48 48
     that subclasses ShippingMethod.
49 49
     """
50
-    price_per_order = models.DecimalField(_('Price per order'), decimal_places=2, max_digits=12, default=D('0.00'))
51
-    price_per_item = models.DecimalField(_('Price per item'), decimal_places=2, max_digits=12, default=D('0.00'))
50
+    price_per_order = models.DecimalField(_("Price per order"), decimal_places=2, max_digits=12, default=D('0.00'))
51
+    price_per_item = models.DecimalField(_("Price per item"), decimal_places=2, max_digits=12, default=D('0.00'))
52 52
     
53 53
     # If basket value is above this threshold, then shipping is free
54
-    free_shipping_threshold = models.DecimalField(_('Free Shipping'), decimal_places=2, max_digits=12, blank=True, null=True)
54
+    free_shipping_threshold = models.DecimalField(_("Free Shipping"), decimal_places=2, max_digits=12, blank=True, null=True)
55 55
     
56 56
     _basket = None
57 57
 
58 58
     class Meta:
59
-        verbose_name = _('Order and item charge')
60
-        verbose_name_plural = _('Order and item charges')
59
+        verbose_name = _("Order and Item Charge")
60
+        verbose_name_plural = _("Order and Item Charges")
61 61
 
62 62
     def set_basket(self, basket):
63 63
         self._basket = basket
@@ -85,19 +85,19 @@ class OrderAndItemCharges(ShippingMethod):
85 85
 
86 86
 
87 87
 class WeightBased(ShippingMethod):
88
-    upper_charge = models.DecimalField(_('Upper Charge'), decimal_places=2, max_digits=12, null=True,
88
+    upper_charge = models.DecimalField(_("Upper Charge"), decimal_places=2, max_digits=12, null=True,
89 89
                                       help_text=_("""This is the charge when the
90 90
                                        weight of the basket is greater than all
91 91
                                       the weight bands"""))
92 92
 
93 93
     weight_attribute = 'weight'
94
-    default_weight = models.DecimalField(_('Default Weight'), decimal_places=2, max_digits=12, default=D('0.00'),
94
+    default_weight = models.DecimalField(_("Default Weight"), decimal_places=2, max_digits=12, default=D('0.00'),
95 95
                         help_text=_("""Default product weight in Kg when no
96 96
                                         weight attribute is defined"""))
97 97
 
98 98
     class Meta:
99
-        verbose_name = _('Weight-based shipping method')
100
-        verbose_name_plural = _('Weight-based shipping methods')
99
+        verbose_name = _("Weight-based Shipping Method")
100
+        verbose_name_plural = _("Weight-based Shipping Methods")
101 101
 
102 102
     def basket_charge_incl_tax(self):
103 103
         weight = Scales(attribute_code=self.weight_attribute, default_weight=self.default_weight).weigh_basket(self._basket)
@@ -127,12 +127,12 @@ class WeightBand(models.Model):
127 127
     """
128 128
     Represents a weight band which are used by the WeightBasedShipping method.
129 129
     """
130
-    method = models.ForeignKey(WeightBased, related_name='bands')
131
-    upper_limit = models.FloatField(_('Upper Limit'), help_text=_("""Enter upper limit of this
130
+    method = models.ForeignKey(WeightBased, related_name='bands', verbose_name=_("Method"))
131
+    upper_limit = models.FloatField(_("Upper Limit"), help_text=_("""Enter upper limit of this
132 132
                                                 weight band in Kg, the lower
133 133
                                                 limit will be determine by the
134 134
                                                 other weight bands"""))
135
-    charge = models.DecimalField(_('Charge'), decimal_places=2, max_digits=12)
135
+    charge = models.DecimalField(_("Charge"), decimal_places=2, max_digits=12)
136 136
     
137 137
     @property
138 138
     def weight_from(self):

+ 8
- 8
oscar/apps/voucher/abstract_models.py Voir le fichier

@@ -19,7 +19,7 @@ class AbstractVoucher(models.Model):
19 19
         help_text=_("""This will be shown in the checkout and basket once the voucher is entered"""))
20 20
     code = models.CharField(_("Code"), max_length=128, db_index=True, unique=True,
21 21
         help_text=_("""Case insensitive / No spaces allowed"""))
22
-    offers = models.ManyToManyField('offer.ConditionalOffer', related_name='vouchers',
22
+    offers = models.ManyToManyField('offer.ConditionalOffer', related_name='vouchers', verbose_name=_("Offers"),
23 23
                                     limit_choices_to={'offer_type': "Voucher"})
24 24
 
25 25
     SINGLE_USE, MULTI_USE, ONCE_PER_CUSTOMER = ('Single use', 'Multi-use', 'Once per customer')
@@ -34,9 +34,9 @@ class AbstractVoucher(models.Model):
34 34
     end_date = models.DateField(_('End Date'))
35 35
 
36 36
     # Audit information
37
-    num_basket_additions = models.PositiveIntegerField(_('Times added to basket'), default=0)
38
-    num_orders = models.PositiveIntegerField(_('Times on orders'), default=0)
39
-    total_discount = models.DecimalField(_('Total discount'), decimal_places=2, max_digits=12, default=Decimal('0.00'))
37
+    num_basket_additions = models.PositiveIntegerField(_("Times added to basket"), default=0)
38
+    num_orders = models.PositiveIntegerField(_("Times on orders"), default=0)
39
+    total_discount = models.DecimalField(_("Total discount"), decimal_places=2, max_digits=12, default=Decimal('0.00'))
40 40
     
41 41
     date_created = models.DateField(auto_now_add=True)
42 42
 
@@ -115,13 +115,13 @@ class AbstractVoucherApplication(models.Model):
115 115
     """
116 116
     For tracking how often a voucher has been used
117 117
     """
118
-    voucher = models.ForeignKey('voucher.Voucher', related_name="applications")
118
+    voucher = models.ForeignKey('voucher.Voucher', related_name="applications", verbose_name=_("Voucher"))
119 119
 
120 120
     # It is possible for an anonymous user to apply a voucher so we need to allow
121 121
     # the user to be nullable
122
-    user = models.ForeignKey('auth.User', blank=True, null=True)
123
-    order = models.ForeignKey('order.Order')
124
-    date_created = models.DateField(auto_now_add=True)
122
+    user = models.ForeignKey('auth.User', blank=True, null=True, verbose_name=_("User"))
123
+    order = models.ForeignKey('order.Order', verbose_name=_("Order"))
124
+    date_created = models.DateField(_("Date Creted"), auto_now_add=True)
125 125
 
126 126
     class Meta:
127 127
         abstract = True

Chargement…
Annuler
Enregistrer