diff --git a/InvenTree/InvenTree/api.py b/InvenTree/InvenTree/api.py index 2fc85ef653..2d04195d42 100644 --- a/InvenTree/InvenTree/api.py +++ b/InvenTree/InvenTree/api.py @@ -7,7 +7,7 @@ from __future__ import unicode_literals import logging -from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _ from django.http import JsonResponse from django_filters.rest_framework import DjangoFilterBackend diff --git a/InvenTree/InvenTree/fields.py b/InvenTree/InvenTree/fields.py index c0e1633ac7..155f77c639 100644 --- a/InvenTree/InvenTree/fields.py +++ b/InvenTree/InvenTree/fields.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals from .validators import allowable_url_schemes -from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _ from django.forms.fields import URLField as FormURLField from django.db import models as models @@ -42,6 +42,7 @@ class DatePickerFormField(forms.DateField): def __init__(self, **kwargs): help_text = kwargs.get('help_text', _('Enter date')) + label = kwargs.get('label', None) required = kwargs.get('required', False) initial = kwargs.get('initial', None) @@ -56,7 +57,8 @@ class DatePickerFormField(forms.DateField): required=required, initial=initial, help_text=help_text, - widget=widget + widget=widget, + label=label ) diff --git a/InvenTree/InvenTree/forms.py b/InvenTree/InvenTree/forms.py index 56a1a116da..52d1c8758f 100644 --- a/InvenTree/InvenTree/forms.py +++ b/InvenTree/InvenTree/forms.py @@ -5,7 +5,7 @@ Helper forms which subclass Django forms to provide additional functionality # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _ from django import forms from crispy_forms.helper import FormHelper from crispy_forms.layout import Layout, Field @@ -123,6 +123,7 @@ class DeleteForm(forms.Form): confirm_delete = forms.BooleanField( required=False, initial=False, + label=_('Confirm delete'), help_text=_('Confirm item deletion') ) @@ -155,6 +156,7 @@ class SetPasswordForm(HelperForm): required=True, initial='', widget=forms.PasswordInput(attrs={'autocomplete': 'off'}), + label=_('Enter password'), help_text=_('Enter new password')) confirm_password = forms.CharField(max_length=100, @@ -162,6 +164,7 @@ class SetPasswordForm(HelperForm): required=True, initial='', widget=forms.PasswordInput(attrs={'autocomplete': 'off'}), + label=_('Confirm password'), help_text=_('Confirm new password')) class Meta: diff --git a/InvenTree/InvenTree/helpers.py b/InvenTree/InvenTree/helpers.py index 62e50bd52f..c2441590f5 100644 --- a/InvenTree/InvenTree/helpers.py +++ b/InvenTree/InvenTree/helpers.py @@ -13,7 +13,7 @@ from decimal import Decimal from wsgiref.util import FileWrapper from django.http import StreamingHttpResponse from django.core.exceptions import ValidationError, FieldError -from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _ from django.contrib.auth.models import Permission @@ -382,17 +382,17 @@ def extract_serial_numbers(serials, expected_quantity): if a < b: for n in range(a, b + 1): if n in numbers: - errors.append(_('Duplicate serial: {n}'.format(n=n))) + errors.append(_('Duplicate serial: {n}').format(n=n)) else: numbers.append(n) else: - errors.append(_("Invalid group: {g}".format(g=group))) + errors.append(_("Invalid group: {g}").format(g=group)) except ValueError: - errors.append(_("Invalid group: {g}".format(g=group))) + errors.append(_("Invalid group: {g}").format(g=group)) continue else: - errors.append(_("Invalid group: {g}".format(g=group))) + errors.append(_("Invalid group: {g}").format(g=group)) continue else: @@ -409,7 +409,7 @@ def extract_serial_numbers(serials, expected_quantity): # The number of extracted serial numbers must match the expected quantity if not expected_quantity == len(numbers): - raise ValidationError([_("Number of unique serial number ({s}) must match quantity ({q})".format(s=len(numbers), q=expected_quantity))]) + raise ValidationError([_("Number of unique serial number ({s}) must match quantity ({q})").format(s=len(numbers), q=expected_quantity)]) return numbers diff --git a/InvenTree/InvenTree/models.py b/InvenTree/InvenTree/models.py index cffe48cc0b..8494b52a10 100644 --- a/InvenTree/InvenTree/models.py +++ b/InvenTree/InvenTree/models.py @@ -56,19 +56,20 @@ class InvenTreeAttachment(models.Model): def __str__(self): return os.path.basename(self.attachment.name) - attachment = models.FileField(upload_to=rename_attachment, + attachment = models.FileField(upload_to=rename_attachment, verbose_name=_('Attachment'), help_text=_('Select file to attach')) - comment = models.CharField(blank=True, max_length=100, help_text=_('File comment')) + comment = models.CharField(blank=True, max_length=100, verbose_name=_('Comment'), help_text=_('File comment')) user = models.ForeignKey( User, on_delete=models.SET_NULL, blank=True, null=True, + verbose_name=_('User'), help_text=_('User'), ) - upload_date = models.DateField(auto_now_add=True, null=True, blank=True) + upload_date = models.DateField(auto_now_add=True, null=True, blank=True, verbose_name=_('upload date')) @property def basename(self): @@ -103,12 +104,14 @@ class InvenTreeTree(MPTTModel): blank=False, max_length=100, validators=[validate_tree_name], + verbose_name=_("Name"), help_text=_("Name"), ) description = models.CharField( blank=True, max_length=250, + verbose_name=_("Description"), help_text=_("Description (optional)") ) @@ -117,6 +120,7 @@ class InvenTreeTree(MPTTModel): on_delete=models.DO_NOTHING, blank=True, null=True, + verbose_name=_("parent"), related_name='children') @property diff --git a/InvenTree/InvenTree/status.py b/InvenTree/InvenTree/status.py index 841a54f92b..92e4737f25 100644 --- a/InvenTree/InvenTree/status.py +++ b/InvenTree/InvenTree/status.py @@ -3,13 +3,11 @@ Provides system status functionality checks. """ # -*- coding: utf-8 -*- -from __future__ import unicode_literals +from django.utils.translation import ugettext_lazy as _ import logging from datetime import datetime, timedelta -from django.utils.translation import ugettext as _ - from django_q.models import Success from django_q.monitor import Stat diff --git a/InvenTree/InvenTree/status_codes.py b/InvenTree/InvenTree/status_codes.py index 916b3341cb..5eb97504c6 100644 --- a/InvenTree/InvenTree/status_codes.py +++ b/InvenTree/InvenTree/status_codes.py @@ -1,4 +1,4 @@ -from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _ class StatusCode: diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index a9f53a7014..7c22639e65 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -110,6 +110,7 @@ dynamic_javascript_urls = [ url(r'^stock.js', DynamicJsView.as_view(template_name='js/stock.js'), name='stock.js'), url(r'^tables.js', DynamicJsView.as_view(template_name='js/tables.js'), name='tables.js'), url(r'^table_filters.js', DynamicJsView.as_view(template_name='js/table_filters.js'), name='table_filters.js'), + url(r'^filters.js', DynamicJsView.as_view(template_name='js/filters.js'), name='filters.js'), ] urlpatterns = [ diff --git a/InvenTree/InvenTree/validators.py b/InvenTree/InvenTree/validators.py index 70322df062..f8199ef20b 100644 --- a/InvenTree/InvenTree/validators.py +++ b/InvenTree/InvenTree/validators.py @@ -60,7 +60,7 @@ def validate_part_ipn(value): match = re.search(pattern, value) if match is None: - raise ValidationError(_('IPN must match regex pattern') + " '{pat}'".format(pat=pattern)) + raise ValidationError(_('IPN must match regex pattern {pat}').format(pat=pattern)) def validate_build_order_reference(value): diff --git a/InvenTree/InvenTree/version.py b/InvenTree/InvenTree/version.py index 05946059fc..cba2822ad1 100644 --- a/InvenTree/InvenTree/version.py +++ b/InvenTree/InvenTree/version.py @@ -71,7 +71,7 @@ def inventreeCommitHash(): try: return str(subprocess.check_output('git rev-parse --short HEAD'.split()), 'utf-8').strip() - except FileNotFoundError: + except: return None @@ -81,5 +81,5 @@ def inventreeCommitDate(): try: d = str(subprocess.check_output('git show -s --format=%ci'.split()), 'utf-8').strip() return d.split(' ')[0] - except FileNotFoundError: + except: return None diff --git a/InvenTree/barcodes/api.py b/InvenTree/barcodes/api.py index d727f5a778..e6b3ea84e3 100644 --- a/InvenTree/barcodes/api.py +++ b/InvenTree/barcodes/api.py @@ -2,7 +2,7 @@ from django.urls import reverse from django.conf.urls import url -from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _ from rest_framework.exceptions import ValidationError from rest_framework import permissions diff --git a/InvenTree/build/forms.py b/InvenTree/build/forms.py index 4892fa631f..0726779b87 100644 --- a/InvenTree/build/forms.py +++ b/InvenTree/build/forms.py @@ -5,7 +5,7 @@ Django Forms for interacting with Build objects # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _ from django import forms from InvenTree.forms import HelperForm @@ -36,11 +36,13 @@ class EditBuildForm(HelperForm): } target_date = DatePickerFormField( + label=_('Target Date'), help_text=_('Target date for build completion. Build will be overdue after this date.') ) quantity = RoundingDecimalFormField( max_digits=10, decimal_places=5, + label=_('Quantity'), help_text=_('Number of items to build') ) @@ -87,7 +89,7 @@ class BuildOutputCreateForm(HelperForm): ) serial_numbers = forms.CharField( - label=_('Serial numbers'), + label=_('Serial Numbers'), required=False, help_text=_('Enter serial numbers for build outputs'), ) @@ -115,6 +117,7 @@ class BuildOutputDeleteForm(HelperForm): confirm = forms.BooleanField( required=False, + label=_('Confirm'), help_text=_('Confirm deletion of build output') ) @@ -136,7 +139,7 @@ class UnallocateBuildForm(HelperForm): Form for auto-de-allocation of stock from a build """ - confirm = forms.BooleanField(required=False, help_text=_('Confirm unallocation of stock')) + confirm = forms.BooleanField(required=False, label=_('Confirm'), help_text=_('Confirm unallocation of stock')) output_id = forms.IntegerField( required=False, @@ -160,7 +163,7 @@ class UnallocateBuildForm(HelperForm): class AutoAllocateForm(HelperForm): """ Form for auto-allocation of stock to a build """ - confirm = forms.BooleanField(required=True, help_text=_('Confirm stock allocation')) + confirm = forms.BooleanField(required=True, label=_('Confirm'), help_text=_('Confirm stock allocation')) # Keep track of which build output we are interested in output = forms.ModelChoiceField( @@ -207,15 +210,17 @@ class CompleteBuildOutputForm(HelperForm): location = forms.ModelChoiceField( queryset=StockLocation.objects.all(), + label=_('Location'), help_text=_('Location of completed parts'), ) confirm_incomplete = forms.BooleanField( required=False, + label=_('Confirm incomplete'), help_text=_("Confirm completion with incomplete stock allocation") ) - confirm = forms.BooleanField(required=True, help_text=_('Confirm build completion')) + confirm = forms.BooleanField(required=True, label=_('Confirm'), help_text=_('Confirm build completion')) output = forms.ModelChoiceField( queryset=StockItem.objects.all(), # Queryset is narrowed in the view @@ -235,7 +240,7 @@ class CompleteBuildOutputForm(HelperForm): class CancelBuildForm(HelperForm): """ Form for cancelling a build """ - confirm_cancel = forms.BooleanField(required=False, help_text=_('Confirm build cancellation')) + confirm_cancel = forms.BooleanField(required=False, label=_('Confirm cancel'), help_text=_('Confirm build cancellation')) class Meta: model = Build @@ -249,7 +254,7 @@ class EditBuildItemForm(HelperForm): Form for creating (or editing) a BuildItem object. """ - quantity = RoundingDecimalFormField(max_digits=10, decimal_places=5, help_text=_('Select quantity of stock to allocate')) + quantity = RoundingDecimalFormField(max_digits=10, decimal_places=5, label=_('Quantity'), help_text=_('Select quantity of stock to allocate')) part_id = forms.IntegerField(required=False, widget=forms.HiddenInput()) diff --git a/InvenTree/build/migrations/0027_auto_20210404_2016.py b/InvenTree/build/migrations/0027_auto_20210404_2016.py new file mode 100644 index 0000000000..f4a2c1afde --- /dev/null +++ b/InvenTree/build/migrations/0027_auto_20210404_2016.py @@ -0,0 +1,85 @@ +# Generated by Django 3.0.7 on 2021-04-04 20:16 + +import InvenTree.models +from django.conf import settings +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('stock', '0058_stockitem_packaging'), + ('users', '0005_owner_model'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('build', '0026_auto_20210216_1539'), + ] + + operations = [ + migrations.AlterField( + model_name='build', + name='completed_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='builds_completed', to=settings.AUTH_USER_MODEL, verbose_name='completed by'), + ), + migrations.AlterField( + model_name='build', + name='completion_date', + field=models.DateField(blank=True, null=True, verbose_name='Completion Date'), + ), + migrations.AlterField( + model_name='build', + name='creation_date', + field=models.DateField(auto_now_add=True, verbose_name='Creation Date'), + ), + migrations.AlterField( + model_name='build', + name='issued_by', + field=models.ForeignKey(blank=True, help_text='User who issued this build order', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='builds_issued', to=settings.AUTH_USER_MODEL, verbose_name='Issued by'), + ), + migrations.AlterField( + model_name='build', + name='responsible', + field=models.ForeignKey(blank=True, help_text='User responsible for this build order', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='builds_responsible', to='users.Owner', verbose_name='Responsible'), + ), + migrations.AlterField( + model_name='builditem', + name='build', + field=models.ForeignKey(help_text='Build to allocate parts', on_delete=django.db.models.deletion.CASCADE, related_name='allocated_stock', to='build.Build', verbose_name='Build'), + ), + migrations.AlterField( + model_name='builditem', + name='install_into', + field=models.ForeignKey(blank=True, help_text='Destination stock item', limit_choices_to={'is_building': True}, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='items_to_install', to='stock.StockItem', verbose_name='Install into'), + ), + migrations.AlterField( + model_name='builditem', + name='quantity', + field=models.DecimalField(decimal_places=5, default=1, help_text='Stock quantity to allocate to build', max_digits=15, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Quantity'), + ), + migrations.AlterField( + model_name='builditem', + name='stock_item', + field=models.ForeignKey(help_text='Source stock item', limit_choices_to={'belongs_to': None, 'sales_order': None}, on_delete=django.db.models.deletion.CASCADE, related_name='allocations', to='stock.StockItem', verbose_name='Stock Item'), + ), + migrations.AlterField( + model_name='buildorderattachment', + name='attachment', + field=models.FileField(help_text='Select file to attach', upload_to=InvenTree.models.rename_attachment, verbose_name='Attachment'), + ), + migrations.AlterField( + model_name='buildorderattachment', + name='comment', + field=models.CharField(blank=True, help_text='File comment', max_length=100, verbose_name='Comment'), + ), + migrations.AlterField( + model_name='buildorderattachment', + name='upload_date', + field=models.DateField(auto_now_add=True, null=True, verbose_name='upload date'), + ), + migrations.AlterField( + model_name='buildorderattachment', + name='user', + field=models.ForeignKey(blank=True, help_text='User', null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='User'), + ), + ] diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index ada9db1e08..4ee8de0d73 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -9,7 +9,7 @@ import os from datetime import datetime from django.contrib.auth.models import User -from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _ from django.core.exceptions import ValidationError from django.urls import reverse @@ -216,7 +216,7 @@ class Build(MPTTModel): help_text=_('Batch code for this build output') ) - creation_date = models.DateField(auto_now_add=True, editable=False) + creation_date = models.DateField(auto_now_add=True, editable=False, verbose_name=_('Creation Date')) target_date = models.DateField( null=True, blank=True, @@ -224,12 +224,13 @@ class Build(MPTTModel): help_text=_('Target date for build completion. Build will be overdue after this date.') ) - completion_date = models.DateField(null=True, blank=True) + completion_date = models.DateField(null=True, blank=True, verbose_name=_('Completion Date')) completed_by = models.ForeignKey( User, on_delete=models.SET_NULL, blank=True, null=True, + verbose_name=_('completed by'), related_name='builds_completed' ) @@ -237,6 +238,7 @@ class Build(MPTTModel): User, on_delete=models.SET_NULL, blank=True, null=True, + verbose_name=_('Issued by'), help_text=_('User who issued this build order'), related_name='builds_issued', ) @@ -245,6 +247,7 @@ class Build(MPTTModel): UserModels.Owner, on_delete=models.SET_NULL, blank=True, null=True, + verbose_name=_('Responsible'), help_text=_('User responsible for this build order'), related_name='builds_responsible', ) @@ -1017,14 +1020,14 @@ class BuildItem(models.Model): try: # Allocated part must be in the BOM for the master part if self.stock_item.part not in self.build.part.getRequiredParts(recursive=False): - errors['stock_item'] = [_("Selected stock item not found in BOM for part '{p}'".format(p=self.build.part.full_name))] + errors['stock_item'] = [_("Selected stock item not found in BOM for part '{p}'").format(p=self.build.part.full_name)] # Allocated quantity cannot exceed available stock quantity if self.quantity > self.stock_item.quantity: - errors['quantity'] = [_("Allocated quantity ({n}) must not exceed available quantity ({q})".format( + errors['quantity'] = [_("Allocated quantity ({n}) must not exceed available quantity ({q})").format( n=normalize(self.quantity), q=normalize(self.stock_item.quantity) - ))] + )] # Allocated quantity cannot cause the stock item to be over-allocated if self.stock_item.quantity - self.stock_item.allocation_count() + self.quantity < self.quantity: @@ -1076,6 +1079,7 @@ class BuildItem(models.Model): Build, on_delete=models.CASCADE, related_name='allocated_stock', + verbose_name=_('Build'), help_text=_('Build to allocate parts') ) @@ -1083,6 +1087,7 @@ class BuildItem(models.Model): 'stock.StockItem', on_delete=models.CASCADE, related_name='allocations', + verbose_name=_('Stock Item'), help_text=_('Source stock item'), limit_choices_to={ 'sales_order': None, @@ -1095,6 +1100,7 @@ class BuildItem(models.Model): max_digits=15, default=1, validators=[MinValueValidator(0)], + verbose_name=_('Quantity'), help_text=_('Stock quantity to allocate to build') ) @@ -1103,6 +1109,7 @@ class BuildItem(models.Model): on_delete=models.SET_NULL, blank=True, null=True, related_name='items_to_install', + verbose_name=_('Install into'), help_text=_('Destination stock item'), limit_choices_to={ 'is_building': True, diff --git a/InvenTree/build/templates/build/build_base.html b/InvenTree/build/templates/build/build_base.html index 83cef5bd44..a8e5e53377 100644 --- a/InvenTree/build/templates/build/build_base.html +++ b/InvenTree/build/templates/build/build_base.html @@ -164,7 +164,7 @@ src="{% static 'img/blank_image.png' %}" launchModalForm("{% url 'build-cancel' build.id %}", { reload: true, - submit_text: "Cancel Build", + submit_text: '{% trans "Cancel Build" %}', }); }); @@ -173,7 +173,7 @@ src="{% static 'img/blank_image.png' %}" "{% url 'build-complete' build.id %}", { reload: true, - submit_text: "Complete Build", + submit_text: '{% trans "Complete Build" %}', } ); }); diff --git a/InvenTree/build/templates/build/index.html b/InvenTree/build/templates/build/index.html index 75dc497b4b..f710928ee7 100644 --- a/InvenTree/build/templates/build/index.html +++ b/InvenTree/build/templates/build/index.html @@ -130,6 +130,7 @@ InvenTree | {% trans "Build Orders" %} initialView: 'dayGridMonth', nowIndicator: true, aspectRatio: 2.5, + locale: '{{request.LANGUAGE_CODE}}', datesSet: function() { loadOrderEvents(calendar); } diff --git a/InvenTree/build/views.py b/InvenTree/build/views.py index e8a1d33ddc..15ced77130 100644 --- a/InvenTree/build/views.py +++ b/InvenTree/build/views.py @@ -5,7 +5,7 @@ Django views for interacting with Build objects # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _ from django.core.exceptions import ValidationError from django.views.generic import DetailView, ListView, UpdateView from django.forms import HiddenInput diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 6d74ace343..79580aabd9 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -17,7 +17,7 @@ from djmoney.models.fields import MoneyField from djmoney.contrib.exchange.models import convert_money from djmoney.contrib.exchange.exceptions import MissingRate -from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _ from django.core.validators import MinValueValidator, URLValidator from django.core.exceptions import ValidationError diff --git a/InvenTree/common/views.py b/InvenTree/common/views.py index 1f3c827532..31d11e30cc 100644 --- a/InvenTree/common/views.py +++ b/InvenTree/common/views.py @@ -5,7 +5,7 @@ Django views for interacting with common models # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _ from django.forms import CheckboxInput, Select from InvenTree.views import AjaxUpdateView diff --git a/InvenTree/company/forms.py b/InvenTree/company/forms.py index 67ac402ba7..2677402334 100644 --- a/InvenTree/company/forms.py +++ b/InvenTree/company/forms.py @@ -8,7 +8,7 @@ from __future__ import unicode_literals from InvenTree.forms import HelperForm from InvenTree.fields import RoundingDecimalFormField -from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _ import django.forms import djmoney.settings @@ -34,6 +34,7 @@ class EditCompanyForm(HelperForm): currency = django.forms.ChoiceField( required=False, + label=_('Currency'), help_text=_('Default currency used for this company'), choices=[('', '----------')] + djmoney.settings.CURRENCY_CHOICES, initial=common.settings.currency_code_default, diff --git a/InvenTree/company/migrations/0032_auto_20210403_1837.py b/InvenTree/company/migrations/0032_auto_20210403_1837.py new file mode 100644 index 0000000000..41b6977d31 --- /dev/null +++ b/InvenTree/company/migrations/0032_auto_20210403_1837.py @@ -0,0 +1,69 @@ +# Generated by Django 3.0.7 on 2021-04-03 18:37 + +import InvenTree.fields +import company.models +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion +import markdownx.models +import stdimage.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('company', '0031_auto_20210103_2215'), + ] + + operations = [ + migrations.AlterField( + model_name='company', + name='image', + field=stdimage.models.StdImageField(blank=True, null=True, upload_to=company.models.rename_company_image, verbose_name='Image'), + ), + migrations.AlterField( + model_name='company', + name='is_customer', + field=models.BooleanField(default=False, help_text='Do you sell items to this company?', verbose_name='is customer'), + ), + migrations.AlterField( + model_name='company', + name='is_manufacturer', + field=models.BooleanField(default=False, help_text='Does this company manufacture parts?', verbose_name='is manufacturer'), + ), + migrations.AlterField( + model_name='company', + name='is_supplier', + field=models.BooleanField(default=True, help_text='Do you purchase items from this company?', verbose_name='is supplier'), + ), + migrations.AlterField( + model_name='company', + name='link', + field=InvenTree.fields.InvenTreeURLField(blank=True, help_text='Link to external company information', verbose_name='Link'), + ), + migrations.AlterField( + model_name='company', + name='notes', + field=markdownx.models.MarkdownxField(blank=True, verbose_name='Notes'), + ), + migrations.AlterField( + model_name='supplierpart', + name='base_cost', + field=models.DecimalField(decimal_places=3, default=0, help_text='Minimum charge (e.g. stocking fee)', max_digits=10, validators=[django.core.validators.MinValueValidator(0)], verbose_name='base cost'), + ), + migrations.AlterField( + model_name='supplierpart', + name='multiple', + field=models.PositiveIntegerField(default=1, help_text='Order multiple', validators=[django.core.validators.MinValueValidator(1)], verbose_name='multiple'), + ), + migrations.AlterField( + model_name='supplierpart', + name='packaging', + field=models.CharField(blank=True, help_text='Part packaging', max_length=50, null=True, verbose_name='Packaging'), + ), + migrations.AlterField( + model_name='supplierpricebreak', + name='part', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pricebreaks', to='company.SupplierPart', verbose_name='Part'), + ), + ] diff --git a/InvenTree/company/models.py b/InvenTree/company/models.py index e4386712c8..17091dcbc3 100644 --- a/InvenTree/company/models.py +++ b/InvenTree/company/models.py @@ -9,7 +9,7 @@ import os import math -from django.utils.translation import gettext_lazy as _ +from django.utils.translation import ugettext_lazy as _ from django.core.validators import MinValueValidator from django.db import models from django.db.models import Sum, Q, UniqueConstraint @@ -114,7 +114,7 @@ class Company(models.Model): verbose_name=_('Contact'), blank=True, help_text=_('Point of contact')) - link = InvenTreeURLField(blank=True, help_text=_('Link to external company information')) + link = InvenTreeURLField(blank=True, verbose_name=_('Link'), help_text=_('Link to external company information')) image = StdImageField( upload_to=rename_company_image, @@ -122,15 +122,16 @@ class Company(models.Model): blank=True, variations={'thumbnail': (128, 128)}, delete_orphans=True, + verbose_name=_('Image'), ) - notes = MarkdownxField(blank=True) + notes = MarkdownxField(blank=True, verbose_name=_('Notes')) - is_customer = models.BooleanField(default=False, help_text=_('Do you sell items to this company?')) + is_customer = models.BooleanField(default=False, verbose_name=_('is customer'), help_text=_('Do you sell items to this company?')) - is_supplier = models.BooleanField(default=True, help_text=_('Do you purchase items from this company?')) + is_supplier = models.BooleanField(default=True, verbose_name=_('is supplier'), help_text=_('Do you purchase items from this company?')) - is_manufacturer = models.BooleanField(default=False, help_text=_('Does this company manufacture parts?')) + is_manufacturer = models.BooleanField(default=False, verbose_name=_('is manufacturer'), help_text=_('Does this company manufacture parts?')) currency = models.CharField( max_length=3, @@ -366,11 +367,11 @@ class SupplierPart(models.Model): help_text=_('Notes') ) - base_cost = models.DecimalField(max_digits=10, decimal_places=3, default=0, validators=[MinValueValidator(0)], help_text=_('Minimum charge (e.g. stocking fee)')) + base_cost = models.DecimalField(max_digits=10, decimal_places=3, default=0, validators=[MinValueValidator(0)], verbose_name=_('base cost'), help_text=_('Minimum charge (e.g. stocking fee)')) - packaging = models.CharField(max_length=50, blank=True, null=True, help_text=_('Part packaging')) + packaging = models.CharField(max_length=50, blank=True, null=True, verbose_name=_('Packaging'), help_text=_('Part packaging')) - multiple = models.PositiveIntegerField(default=1, validators=[MinValueValidator(1)], help_text=('Order multiple')) + multiple = models.PositiveIntegerField(default=1, validators=[MinValueValidator(1)], verbose_name=_('multiple'), help_text=_('Order multiple')) # TODO - Reimplement lead-time as a charfield with special validation (pattern matching). # lead_time = models.DurationField(blank=True, null=True) @@ -530,7 +531,7 @@ class SupplierPriceBreak(common.models.PriceBreak): currency: Reference to the currency of this pricebreak (leave empty for base currency) """ - part = models.ForeignKey(SupplierPart, on_delete=models.CASCADE, related_name='pricebreaks') + part = models.ForeignKey(SupplierPart, on_delete=models.CASCADE, related_name='pricebreaks', verbose_name=_('Part'),) class Meta: unique_together = ("part", "quantity") diff --git a/InvenTree/company/templates/company/company_base.html b/InvenTree/company/templates/company/company_base.html index 9331e5d895..236cc58981 100644 --- a/InvenTree/company/templates/company/company_base.html +++ b/InvenTree/company/templates/company/company_base.html @@ -43,17 +43,17 @@ InvenTree | {% trans "Company" %} - {{ company.name }}

{{ company.description }}

{% if company.is_supplier and roles.purchase_order.add %} - {% endif %} {% if perms.company.change_company %} - {% endif %} {% if perms.company.delete_company %} - {% endif %} diff --git a/InvenTree/company/templates/company/delete.html b/InvenTree/company/templates/company/delete.html index 191e07c2f3..3236a7a58d 100644 --- a/InvenTree/company/templates/company/delete.html +++ b/InvenTree/company/templates/company/delete.html @@ -1,14 +1,16 @@ {% extends "modal_delete_form.html" %} +{% load i18n %} + {% block pre_form_content %} -Are you sure you want to delete company '{{ company.name }}'? +{% blocktrans with company.name as name %}Are you sure you want to delete company '{{ name }}'?{% endblocktrans %}
{% if company.supplied_part_count > 0 %} -

There are {{ company.supplied_part_count }} parts sourced from this company.
-If this supplier is deleted, these supplier part entries will also be deleted.

+

{% blocktrans with company.supplied_part_count as count %}There are {{ count }} parts sourced from this company.
+If this supplier is deleted, these supplier part entries will also be deleted.{% endblocktrans %}

\ No newline at end of file + diff --git a/InvenTree/templates/base.html b/InvenTree/templates/base.html index 2120d0ccfb..140971a8ce 100644 --- a/InvenTree/templates/base.html +++ b/InvenTree/templates/base.html @@ -134,12 +134,12 @@ InvenTree + - @@ -156,6 +156,7 @@ InvenTree + @@ -180,6 +181,7 @@ $(document).ready(function () { }); {% endif %} + moment.locale('{{request.LANGUAGE_CODE}}'); }); diff --git a/InvenTree/InvenTree/static/script/inventree/filters.js b/InvenTree/templates/js/filters.js similarity index 94% rename from InvenTree/InvenTree/static/script/inventree/filters.js rename to InvenTree/templates/js/filters.js index df767441d4..01b74763e0 100644 --- a/InvenTree/InvenTree/static/script/inventree/filters.js +++ b/InvenTree/templates/js/filters.js @@ -1,3 +1,5 @@ +{% load i18n %} + /** * Code for managing query filters / table options. * @@ -188,7 +190,7 @@ function generateAvailableFilterList(tableKey) { var html = `