2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-05-04 14:28:48 +00:00

Merge remote-tracking branch 'inventree/master'

This commit is contained in:
Oliver Walters 2019-09-27 10:25:11 +10:00
commit e891f117f3
23 changed files with 2252 additions and 57 deletions

View File

@ -10,6 +10,8 @@ addons:
-sqlite3
before_install:
- sudo apt-get update
- sudo apt-get install gettext
- make install
- make migrate
- cd InvenTree && python3 manage.py createsuperuser --username InvenTreeAdmin --email admin@inventree.com --noinput && cd ..
@ -18,6 +20,7 @@ script:
- cd InvenTree && python3 manage.py makemigrations && cd ..
- python3 ci/check_migration_files.py
- make coverage
- make translate
- make style
after_success:

View File

@ -8,6 +8,14 @@ No pushing to master! New featues must be submitted in a separate branch (one br
Any required migration files **must** be included in the commit, or the pull-request will be rejected. If you change the underlying database schema, make sure you run `make migrate` and commit the migration files before submitting the PR.
## Update Translation Files
Any PRs which update translatable strings (i.e. text strings that will appear in the web-front UI) must also update the translation (locale) files to include hooks for the translated strings.
*This does not mean that all translations must be provided, but that the translation files must include locations for the translated strings to be written.*
To perform this step, simply run `make_translate` from the top level directory before submitting the PR.
## Testing
Any new code should be covered by unit tests - a submitted PR may not be accepted if the code coverage is decreased.

View File

@ -17,6 +17,8 @@ import logging
import tempfile
import yaml
from django.utils.translation import gettext_lazy as _
def eprint(*args, **kwargs):
""" Print a warning message to stderr """
@ -115,6 +117,7 @@ LOGGING = {
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'corsheaders.middleware.CorsMiddleware',
@ -225,7 +228,20 @@ if not type(EXTRA_URL_SCHEMES) in [list]:
# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/
LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = CONFIG.get('language', 'en-us')
# If a new language translation is supported, it must be added here
LANGUAGES = [
('en', _('English')),
('de', _('German')),
('fr', _('French')),
('pk', _('Polish')),
]
LOCALE_PATHS = (
os.path.join(BASE_DIR, 'locale/'),
)
TIME_ZONE = 'UTC'

View File

@ -18,6 +18,9 @@ database:
#HOST: ''
#PORT: ''
# Select default system language (default is 'en-us')
language: en-us
# Set debug to False to run in production mode
debug: True

Binary file not shown.

View File

@ -0,0 +1,694 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-27 00:12+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: InvenTree/helpers.py:157 order/models.py:158 order/models.py:203
msgid "Invalid quantity provided"
msgstr ""
#: InvenTree/helpers.py:160
msgid "Empty serial number string"
msgstr ""
#: InvenTree/helpers.py:181 InvenTree/helpers.py:198
#, python-brace-format
msgid "Duplicate serial: {n}"
msgstr ""
#: InvenTree/helpers.py:185 InvenTree/helpers.py:188 InvenTree/helpers.py:191
#: InvenTree/helpers.py:202
#, python-brace-format
msgid "Invalid group: {g}"
msgstr ""
#: InvenTree/helpers.py:208
msgid "No serial numbers found"
msgstr ""
#: InvenTree/helpers.py:212
#, python-brace-format
msgid "Number of unique serial number ({s}) must match quantity ({q})"
msgstr ""
#: InvenTree/settings.py:235
msgid "English"
msgstr ""
#: InvenTree/settings.py:236
msgid "German"
msgstr ""
#: InvenTree/settings.py:237
msgid "French"
msgstr ""
#: InvenTree/settings.py:238
msgid "Polish"
msgstr ""
#: InvenTree/status_codes.py:27 InvenTree/status_codes.py:82
msgid "Pending"
msgstr ""
#: InvenTree/status_codes.py:28
msgid "Placed"
msgstr ""
#: InvenTree/status_codes.py:29 InvenTree/status_codes.py:85
msgid "Complete"
msgstr ""
#: InvenTree/status_codes.py:30 InvenTree/status_codes.py:84
msgid "Cancelled"
msgstr ""
#: InvenTree/status_codes.py:31 InvenTree/status_codes.py:62
msgid "Lost"
msgstr ""
#: InvenTree/status_codes.py:32
msgid "Returned"
msgstr ""
#: InvenTree/status_codes.py:58
msgid "OK"
msgstr ""
#: InvenTree/status_codes.py:59
msgid "Attention needed"
msgstr ""
#: InvenTree/status_codes.py:60
msgid "Damaged"
msgstr ""
#: InvenTree/status_codes.py:61
msgid "Destroyed"
msgstr ""
#: InvenTree/status_codes.py:83
msgid "Allocated"
msgstr ""
#: InvenTree/validators.py:35
msgid "Invalid character in part name"
msgstr ""
#: InvenTree/validators.py:44
#, python-brace-format
msgid "Illegal character in name ({x})"
msgstr ""
#: InvenTree/validators.py:63 InvenTree/validators.py:79
msgid "Overage value must not be negative"
msgstr ""
#: InvenTree/validators.py:81
msgid "Overage must not exceed 100%"
msgstr ""
#: InvenTree/validators.py:88
msgid "Overage must be an integer value or a percentage"
msgstr ""
#: build/forms.py:36
msgid "Confirm"
msgstr ""
#: build/forms.py:53 stock/forms.py:34
msgid "Enter unique serial numbers (or leave blank)"
msgstr ""
#: build/forms.py:55
msgid "Confirm build completion"
msgstr ""
#: build/models.py:381
#, python-brace-format
msgid "Selected stock item not found in BOM for part '{p}'"
msgstr ""
#: build/models.py:384
#, python-brace-format
msgid "Allocated quantity ({n}) must not exceed available quantity ({q})"
msgstr ""
#: build/views.py:289 stock/views.py:834
#, python-brace-format
msgid "The following serial numbers already exist: ({sn})"
msgstr ""
#: common/models.py:65
msgid "Settings key (must be unique - case insensitive"
msgstr ""
#: common/models.py:67
msgid "Settings value"
msgstr ""
#: common/models.py:69
msgid "Settings description"
msgstr ""
#: common/models.py:82
msgid "Key string must be unique"
msgstr ""
#: common/models.py:103
msgid "Currency Symbol e.g. $"
msgstr ""
#: common/models.py:105
msgid "Currency Suffix e.g. AUD"
msgstr ""
#: common/models.py:107
msgid "Currency Description"
msgstr ""
#: common/models.py:109
msgid "Currency Value"
msgstr ""
#: common/models.py:111
msgid "Use this currency as the base currency"
msgstr ""
#: order/forms.py:21
msgid "Place order"
msgstr ""
#: order/forms.py:32
msgid "Cancel order"
msgstr ""
#: order/forms.py:43
msgid "Receive parts to this location"
msgstr ""
#: order/models.py:62
msgid "Order reference"
msgstr ""
#: order/models.py:64
msgid "Order description"
msgstr ""
#: order/models.py:66
msgid "Link to external page"
msgstr ""
#: order/models.py:83
msgid "Order notes"
msgstr ""
#: order/models.py:125
msgid "Company"
msgstr ""
#: order/models.py:156 order/models.py:201 part/views.py:1032
#: stock/models.py:437
msgid "Quantity must be greater than zero"
msgstr ""
#: order/models.py:161
msgid "Part supplier must match PO supplier"
msgstr ""
#: order/models.py:196
msgid "Lines can only be received against an order marked as 'Placed'"
msgstr ""
#: order/models.py:245
msgid "Item quantity"
msgstr ""
#: order/models.py:247
msgid "Line item reference"
msgstr ""
#: order/models.py:249
msgid "Line item notes"
msgstr ""
#: order/models.py:275
msgid "Purchase Order"
msgstr ""
#: order/models.py:284
msgid "Supplier part"
msgstr ""
#: order/models.py:287
msgid "Number of items received"
msgstr ""
#: order/views.py:140
msgid "Confirm order cancellation"
msgstr ""
#: order/views.py:173
msgid "Confirm order placement"
msgstr ""
#: order/views.py:695
msgid "Invalid Purchase Order"
msgstr ""
#: order/views.py:703
msgid "Supplier must match for Part and Order"
msgstr ""
#: order/views.py:708
msgid "Invalid SupplierPart selection"
msgstr ""
#: part/bom.py:107
#, python-brace-format
msgid "Unsupported file format: {f}"
msgstr ""
#: part/bom.py:112
msgid "Error reading BOM file (invalid data)"
msgstr ""
#: part/bom.py:114
msgid "Error reading BOM file (incorrect row size)"
msgstr ""
#: part/forms.py:37
msgid "Confirm that the BOM is correct"
msgstr ""
#: part/forms.py:49
msgid "Select BOM file to upload"
msgstr ""
#: part/forms.py:73
msgid "Select part category"
msgstr ""
#: part/forms.py:81
msgid "Perform 'deep copy' which will duplicate all BOM data for this part"
msgstr ""
#: part/forms.py:86
msgid "Confirm part creation"
msgstr ""
#: part/forms.py:173
msgid "Input quantity for price calculation"
msgstr ""
#: part/forms.py:176
msgid "Select currency for price calculation"
msgstr ""
#: part/models.py:308
msgid "Part must be unique for name, IPN and revision"
msgstr ""
#: part/models.py:322
msgid "Part cannot be a template part if it is a variant of another part"
msgstr ""
#: part/models.py:323
msgid "Part cannot be a variant of another part if it is already a template"
msgstr ""
#: part/models.py:992
msgid "Parameter template name must be unique"
msgstr ""
#: part/models.py:1141
msgid "Part cannot be added to its own Bill of Materials"
msgstr ""
#: part/models.py:1148
#, python-brace-format
msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)"
msgstr ""
#: part/templates/part/category.html:13 part/templates/part/category.html:69
msgid "Part Categories"
msgstr ""
#: part/templates/part/category.html:14
msgid "All parts"
msgstr ""
#: part/templates/part/category.html:34
msgid "Category Details"
msgstr ""
#: part/templates/part/category.html:37
msgid "Category Path"
msgstr ""
#: part/templates/part/category.html:41
msgid "Category Description"
msgstr ""
#: part/templates/part/category.html:46 part/templates/part/detail.html:63
msgid "Default Location"
msgstr ""
#: part/templates/part/category.html:52 part/templates/part/detail.html:43
msgid "Keywords"
msgstr ""
#: part/templates/part/category.html:57
msgid "Subcategories"
msgstr ""
#: part/templates/part/category.html:61
msgid "Parts (Including subcategories)"
msgstr ""
#: part/templates/part/category.html:66 part/templates/part/detail.html:8
msgid "Part Details"
msgstr ""
#: part/templates/part/category.html:73
msgid "Parts"
msgstr ""
#: part/templates/part/detail.html:16
msgid "Part name"
msgstr ""
#: part/templates/part/detail.html:21
msgid "IPN"
msgstr ""
#: part/templates/part/detail.html:27
msgid "Revision"
msgstr ""
#: part/templates/part/detail.html:32
msgid "Description"
msgstr ""
#: part/templates/part/detail.html:37
msgid "Variant Of"
msgstr ""
#: part/templates/part/detail.html:49
msgid "URL"
msgstr ""
#: part/templates/part/detail.html:54
msgid "Category"
msgstr ""
#: part/templates/part/detail.html:69
msgid "Default Supplier"
msgstr ""
#: part/templates/part/detail.html:76
msgid "Units"
msgstr ""
#: part/templates/part/detail.html:81
msgid "Minimum Stock"
msgstr ""
#: part/templates/part/detail.html:90
msgid "Virtual"
msgstr ""
#: part/templates/part/detail.html:93
msgid "Part is virtual (not a physical part)"
msgstr ""
#: part/templates/part/detail.html:95
msgid "Part is not a virtual part"
msgstr ""
#: part/templates/part/detail.html:99
msgid "Assembly"
msgstr ""
#: part/templates/part/detail.html:102
msgid "Part can be assembled from other parts"
msgstr ""
#: part/templates/part/detail.html:104
msgid "Part cannot be assembled from other parts"
msgstr ""
#: part/templates/part/detail.html:108
msgid "Component"
msgstr ""
#: part/templates/part/detail.html:111
msgid "Part can be used in assemblies"
msgstr ""
#: part/templates/part/detail.html:113
msgid "Part cannot be used in assemblies"
msgstr ""
#: part/templates/part/detail.html:117
msgid "Trackable"
msgstr ""
#: part/templates/part/detail.html:120
msgid "Part stock is tracked by serial number"
msgstr ""
#: part/templates/part/detail.html:122
msgid "Part stock is not tracked by serial number"
msgstr ""
#: part/templates/part/detail.html:126
msgid "Purchaseable"
msgstr ""
#: part/templates/part/detail.html:129 part/templates/part/detail.html:131
msgid "Part can be purchased from external suppliers"
msgstr ""
#: part/templates/part/detail.html:136
msgid "Sellable"
msgstr ""
#: part/templates/part/detail.html:139
msgid "Part can be sold to customers"
msgstr ""
#: part/templates/part/detail.html:141
msgid "Part cannot be sold to customers"
msgstr ""
#: part/templates/part/detail.html:151
msgid "Notes"
msgstr ""
#: part/views.py:196
#, python-brace-format
msgid "Set category for {n} parts"
msgstr ""
#: part/views.py:773
msgid "No BOM file provided"
msgstr ""
#: part/views.py:1034
msgid "Enter a valid quantity"
msgstr ""
#: part/views.py:1058 part/views.py:1061
msgid "Select valid part"
msgstr ""
#: part/views.py:1067
msgid "Duplicate part selected"
msgstr ""
#: part/views.py:1095
msgid "Select a part"
msgstr ""
#: part/views.py:1099
msgid "Specify quantity"
msgstr ""
#: stock/forms.py:92
msgid "File Format"
msgstr ""
#: stock/forms.py:92
msgid "Select output file format"
msgstr ""
#: stock/forms.py:94
msgid "Include stock items in sub locations"
msgstr ""
#: stock/forms.py:127
msgid "Destination stock location"
msgstr ""
#: stock/forms.py:133
msgid "Confirm movement of stock items"
msgstr ""
#: stock/forms.py:135
msgid "Set the destination as the default location for selected parts"
msgstr ""
#: stock/models.py:201
#, python-brace-format
msgid ""
"A stock item with this serial number already exists for template part {part}"
msgstr ""
#: stock/models.py:206
msgid "A stock item with this serial number already exists"
msgstr ""
#: stock/models.py:225
#, python-brace-format
msgid "Part type ('{pf}') must be {pe}"
msgstr ""
#: stock/models.py:235 stock/models.py:244
msgid "Quantity must be 1 for item with a serial number"
msgstr ""
#: stock/models.py:236
msgid "Serial number cannot be set if quantity greater than 1"
msgstr ""
#: stock/models.py:252
msgid "Stock item cannot be created for a template Part"
msgstr ""
#: stock/models.py:261
msgid "Item cannot belong to itself"
msgstr ""
#: stock/models.py:434
msgid "Quantity must be integer"
msgstr ""
#: stock/models.py:440
#, python-brace-format
msgid "Quantity must not exceed available stock quantity ({n})"
msgstr ""
#: stock/models.py:443 stock/models.py:446
msgid "Serial numbers must be a list of integers"
msgstr ""
#: stock/models.py:449
msgid "Quantity does not match serial numbers"
msgstr ""
#: stock/models.py:459
msgid "Serial numbers already exist: "
msgstr ""
#: stock/models.py:480
msgid "Add serial number"
msgstr ""
#: stock/models.py:483
#, python-brace-format
msgid "Serialized {n} items"
msgstr ""
#: stock/templates/stock/location.html:37
msgid "Location Details"
msgstr ""
#: stock/templates/stock/location.html:40
msgid "Location Path"
msgstr ""
#: stock/templates/stock/location.html:44
msgid "Location Description"
msgstr ""
#: stock/templates/stock/location.html:48
msgid "Sublocations"
msgstr ""
#: stock/templates/stock/location.html:52
#: stock/templates/stock/location.html:64
msgid "Stock Items"
msgstr ""
#: stock/templates/stock/location.html:57
msgid "Stock Details"
msgstr ""
#: stock/templates/stock/location.html:60
msgid "Stock Locations"
msgstr ""
#: stock/views.py:399
msgid "Must enter integer value"
msgstr ""
#: stock/views.py:404
msgid "Quantity must be positive"
msgstr ""
#: stock/views.py:411
#, python-brace-format
msgid "Quantity must not exceed {x}"
msgstr ""
#: stock/views.py:419
msgid "Confirm stock adjustment"
msgstr ""
#: stock/views.py:487
#, python-brace-format
msgid "Added stock to {n} items"
msgstr ""
#: stock/views.py:502
#, python-brace-format
msgid "Removed stock from {n} items"
msgstr ""
#: stock/views.py:515
#, python-brace-format
msgid "Counted stock for {n} items"
msgstr ""
#: stock/views.py:543
msgid "No items were moved"
msgstr ""
#: stock/views.py:546
#, python-brace-format
msgid "Moved {n} items to {dest}"
msgstr ""
#: stock/views.py:813
msgid "Invalid part selection"
msgstr ""
#: stock/views.py:875
msgid "Created new stock item"
msgstr ""

Binary file not shown.

View File

@ -0,0 +1,694 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-27 00:12+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: InvenTree/helpers.py:157 order/models.py:158 order/models.py:203
msgid "Invalid quantity provided"
msgstr ""
#: InvenTree/helpers.py:160
msgid "Empty serial number string"
msgstr ""
#: InvenTree/helpers.py:181 InvenTree/helpers.py:198
#, python-brace-format
msgid "Duplicate serial: {n}"
msgstr ""
#: InvenTree/helpers.py:185 InvenTree/helpers.py:188 InvenTree/helpers.py:191
#: InvenTree/helpers.py:202
#, python-brace-format
msgid "Invalid group: {g}"
msgstr ""
#: InvenTree/helpers.py:208
msgid "No serial numbers found"
msgstr ""
#: InvenTree/helpers.py:212
#, python-brace-format
msgid "Number of unique serial number ({s}) must match quantity ({q})"
msgstr ""
#: InvenTree/settings.py:235
msgid "English"
msgstr ""
#: InvenTree/settings.py:236
msgid "German"
msgstr ""
#: InvenTree/settings.py:237
msgid "French"
msgstr ""
#: InvenTree/settings.py:238
msgid "Polish"
msgstr ""
#: InvenTree/status_codes.py:27 InvenTree/status_codes.py:82
msgid "Pending"
msgstr ""
#: InvenTree/status_codes.py:28
msgid "Placed"
msgstr ""
#: InvenTree/status_codes.py:29 InvenTree/status_codes.py:85
msgid "Complete"
msgstr ""
#: InvenTree/status_codes.py:30 InvenTree/status_codes.py:84
msgid "Cancelled"
msgstr ""
#: InvenTree/status_codes.py:31 InvenTree/status_codes.py:62
msgid "Lost"
msgstr ""
#: InvenTree/status_codes.py:32
msgid "Returned"
msgstr ""
#: InvenTree/status_codes.py:58
msgid "OK"
msgstr ""
#: InvenTree/status_codes.py:59
msgid "Attention needed"
msgstr ""
#: InvenTree/status_codes.py:60
msgid "Damaged"
msgstr ""
#: InvenTree/status_codes.py:61
msgid "Destroyed"
msgstr ""
#: InvenTree/status_codes.py:83
msgid "Allocated"
msgstr ""
#: InvenTree/validators.py:35
msgid "Invalid character in part name"
msgstr ""
#: InvenTree/validators.py:44
#, python-brace-format
msgid "Illegal character in name ({x})"
msgstr ""
#: InvenTree/validators.py:63 InvenTree/validators.py:79
msgid "Overage value must not be negative"
msgstr ""
#: InvenTree/validators.py:81
msgid "Overage must not exceed 100%"
msgstr ""
#: InvenTree/validators.py:88
msgid "Overage must be an integer value or a percentage"
msgstr ""
#: build/forms.py:36
msgid "Confirm"
msgstr ""
#: build/forms.py:53 stock/forms.py:34
msgid "Enter unique serial numbers (or leave blank)"
msgstr ""
#: build/forms.py:55
msgid "Confirm build completion"
msgstr ""
#: build/models.py:381
#, python-brace-format
msgid "Selected stock item not found in BOM for part '{p}'"
msgstr ""
#: build/models.py:384
#, python-brace-format
msgid "Allocated quantity ({n}) must not exceed available quantity ({q})"
msgstr ""
#: build/views.py:289 stock/views.py:834
#, python-brace-format
msgid "The following serial numbers already exist: ({sn})"
msgstr ""
#: common/models.py:65
msgid "Settings key (must be unique - case insensitive"
msgstr ""
#: common/models.py:67
msgid "Settings value"
msgstr ""
#: common/models.py:69
msgid "Settings description"
msgstr ""
#: common/models.py:82
msgid "Key string must be unique"
msgstr ""
#: common/models.py:103
msgid "Currency Symbol e.g. $"
msgstr ""
#: common/models.py:105
msgid "Currency Suffix e.g. AUD"
msgstr ""
#: common/models.py:107
msgid "Currency Description"
msgstr ""
#: common/models.py:109
msgid "Currency Value"
msgstr ""
#: common/models.py:111
msgid "Use this currency as the base currency"
msgstr ""
#: order/forms.py:21
msgid "Place order"
msgstr ""
#: order/forms.py:32
msgid "Cancel order"
msgstr ""
#: order/forms.py:43
msgid "Receive parts to this location"
msgstr ""
#: order/models.py:62
msgid "Order reference"
msgstr ""
#: order/models.py:64
msgid "Order description"
msgstr ""
#: order/models.py:66
msgid "Link to external page"
msgstr ""
#: order/models.py:83
msgid "Order notes"
msgstr ""
#: order/models.py:125
msgid "Company"
msgstr ""
#: order/models.py:156 order/models.py:201 part/views.py:1032
#: stock/models.py:437
msgid "Quantity must be greater than zero"
msgstr ""
#: order/models.py:161
msgid "Part supplier must match PO supplier"
msgstr ""
#: order/models.py:196
msgid "Lines can only be received against an order marked as 'Placed'"
msgstr ""
#: order/models.py:245
msgid "Item quantity"
msgstr ""
#: order/models.py:247
msgid "Line item reference"
msgstr ""
#: order/models.py:249
msgid "Line item notes"
msgstr ""
#: order/models.py:275
msgid "Purchase Order"
msgstr ""
#: order/models.py:284
msgid "Supplier part"
msgstr ""
#: order/models.py:287
msgid "Number of items received"
msgstr ""
#: order/views.py:140
msgid "Confirm order cancellation"
msgstr ""
#: order/views.py:173
msgid "Confirm order placement"
msgstr ""
#: order/views.py:695
msgid "Invalid Purchase Order"
msgstr ""
#: order/views.py:703
msgid "Supplier must match for Part and Order"
msgstr ""
#: order/views.py:708
msgid "Invalid SupplierPart selection"
msgstr ""
#: part/bom.py:107
#, python-brace-format
msgid "Unsupported file format: {f}"
msgstr ""
#: part/bom.py:112
msgid "Error reading BOM file (invalid data)"
msgstr ""
#: part/bom.py:114
msgid "Error reading BOM file (incorrect row size)"
msgstr ""
#: part/forms.py:37
msgid "Confirm that the BOM is correct"
msgstr ""
#: part/forms.py:49
msgid "Select BOM file to upload"
msgstr ""
#: part/forms.py:73
msgid "Select part category"
msgstr ""
#: part/forms.py:81
msgid "Perform 'deep copy' which will duplicate all BOM data for this part"
msgstr ""
#: part/forms.py:86
msgid "Confirm part creation"
msgstr ""
#: part/forms.py:173
msgid "Input quantity for price calculation"
msgstr ""
#: part/forms.py:176
msgid "Select currency for price calculation"
msgstr ""
#: part/models.py:308
msgid "Part must be unique for name, IPN and revision"
msgstr ""
#: part/models.py:322
msgid "Part cannot be a template part if it is a variant of another part"
msgstr ""
#: part/models.py:323
msgid "Part cannot be a variant of another part if it is already a template"
msgstr ""
#: part/models.py:992
msgid "Parameter template name must be unique"
msgstr ""
#: part/models.py:1141
msgid "Part cannot be added to its own Bill of Materials"
msgstr ""
#: part/models.py:1148
#, python-brace-format
msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)"
msgstr ""
#: part/templates/part/category.html:13 part/templates/part/category.html:69
msgid "Part Categories"
msgstr ""
#: part/templates/part/category.html:14
msgid "All parts"
msgstr ""
#: part/templates/part/category.html:34
msgid "Category Details"
msgstr ""
#: part/templates/part/category.html:37
msgid "Category Path"
msgstr ""
#: part/templates/part/category.html:41
msgid "Category Description"
msgstr ""
#: part/templates/part/category.html:46 part/templates/part/detail.html:63
msgid "Default Location"
msgstr ""
#: part/templates/part/category.html:52 part/templates/part/detail.html:43
msgid "Keywords"
msgstr ""
#: part/templates/part/category.html:57
msgid "Subcategories"
msgstr ""
#: part/templates/part/category.html:61
msgid "Parts (Including subcategories)"
msgstr ""
#: part/templates/part/category.html:66 part/templates/part/detail.html:8
msgid "Part Details"
msgstr ""
#: part/templates/part/category.html:73
msgid "Parts"
msgstr ""
#: part/templates/part/detail.html:16
msgid "Part name"
msgstr ""
#: part/templates/part/detail.html:21
msgid "IPN"
msgstr ""
#: part/templates/part/detail.html:27
msgid "Revision"
msgstr ""
#: part/templates/part/detail.html:32
msgid "Description"
msgstr ""
#: part/templates/part/detail.html:37
msgid "Variant Of"
msgstr ""
#: part/templates/part/detail.html:49
msgid "URL"
msgstr ""
#: part/templates/part/detail.html:54
msgid "Category"
msgstr ""
#: part/templates/part/detail.html:69
msgid "Default Supplier"
msgstr ""
#: part/templates/part/detail.html:76
msgid "Units"
msgstr ""
#: part/templates/part/detail.html:81
msgid "Minimum Stock"
msgstr ""
#: part/templates/part/detail.html:90
msgid "Virtual"
msgstr ""
#: part/templates/part/detail.html:93
msgid "Part is virtual (not a physical part)"
msgstr ""
#: part/templates/part/detail.html:95
msgid "Part is not a virtual part"
msgstr ""
#: part/templates/part/detail.html:99
msgid "Assembly"
msgstr ""
#: part/templates/part/detail.html:102
msgid "Part can be assembled from other parts"
msgstr ""
#: part/templates/part/detail.html:104
msgid "Part cannot be assembled from other parts"
msgstr ""
#: part/templates/part/detail.html:108
msgid "Component"
msgstr ""
#: part/templates/part/detail.html:111
msgid "Part can be used in assemblies"
msgstr ""
#: part/templates/part/detail.html:113
msgid "Part cannot be used in assemblies"
msgstr ""
#: part/templates/part/detail.html:117
msgid "Trackable"
msgstr ""
#: part/templates/part/detail.html:120
msgid "Part stock is tracked by serial number"
msgstr ""
#: part/templates/part/detail.html:122
msgid "Part stock is not tracked by serial number"
msgstr ""
#: part/templates/part/detail.html:126
msgid "Purchaseable"
msgstr ""
#: part/templates/part/detail.html:129 part/templates/part/detail.html:131
msgid "Part can be purchased from external suppliers"
msgstr ""
#: part/templates/part/detail.html:136
msgid "Sellable"
msgstr ""
#: part/templates/part/detail.html:139
msgid "Part can be sold to customers"
msgstr ""
#: part/templates/part/detail.html:141
msgid "Part cannot be sold to customers"
msgstr ""
#: part/templates/part/detail.html:151
msgid "Notes"
msgstr ""
#: part/views.py:196
#, python-brace-format
msgid "Set category for {n} parts"
msgstr ""
#: part/views.py:773
msgid "No BOM file provided"
msgstr ""
#: part/views.py:1034
msgid "Enter a valid quantity"
msgstr ""
#: part/views.py:1058 part/views.py:1061
msgid "Select valid part"
msgstr ""
#: part/views.py:1067
msgid "Duplicate part selected"
msgstr ""
#: part/views.py:1095
msgid "Select a part"
msgstr ""
#: part/views.py:1099
msgid "Specify quantity"
msgstr ""
#: stock/forms.py:92
msgid "File Format"
msgstr ""
#: stock/forms.py:92
msgid "Select output file format"
msgstr ""
#: stock/forms.py:94
msgid "Include stock items in sub locations"
msgstr ""
#: stock/forms.py:127
msgid "Destination stock location"
msgstr ""
#: stock/forms.py:133
msgid "Confirm movement of stock items"
msgstr ""
#: stock/forms.py:135
msgid "Set the destination as the default location for selected parts"
msgstr ""
#: stock/models.py:201
#, python-brace-format
msgid ""
"A stock item with this serial number already exists for template part {part}"
msgstr ""
#: stock/models.py:206
msgid "A stock item with this serial number already exists"
msgstr ""
#: stock/models.py:225
#, python-brace-format
msgid "Part type ('{pf}') must be {pe}"
msgstr ""
#: stock/models.py:235 stock/models.py:244
msgid "Quantity must be 1 for item with a serial number"
msgstr ""
#: stock/models.py:236
msgid "Serial number cannot be set if quantity greater than 1"
msgstr ""
#: stock/models.py:252
msgid "Stock item cannot be created for a template Part"
msgstr ""
#: stock/models.py:261
msgid "Item cannot belong to itself"
msgstr ""
#: stock/models.py:434
msgid "Quantity must be integer"
msgstr ""
#: stock/models.py:440
#, python-brace-format
msgid "Quantity must not exceed available stock quantity ({n})"
msgstr ""
#: stock/models.py:443 stock/models.py:446
msgid "Serial numbers must be a list of integers"
msgstr ""
#: stock/models.py:449
msgid "Quantity does not match serial numbers"
msgstr ""
#: stock/models.py:459
msgid "Serial numbers already exist: "
msgstr ""
#: stock/models.py:480
msgid "Add serial number"
msgstr ""
#: stock/models.py:483
#, python-brace-format
msgid "Serialized {n} items"
msgstr ""
#: stock/templates/stock/location.html:37
msgid "Location Details"
msgstr ""
#: stock/templates/stock/location.html:40
msgid "Location Path"
msgstr ""
#: stock/templates/stock/location.html:44
msgid "Location Description"
msgstr ""
#: stock/templates/stock/location.html:48
msgid "Sublocations"
msgstr ""
#: stock/templates/stock/location.html:52
#: stock/templates/stock/location.html:64
msgid "Stock Items"
msgstr ""
#: stock/templates/stock/location.html:57
msgid "Stock Details"
msgstr ""
#: stock/templates/stock/location.html:60
msgid "Stock Locations"
msgstr ""
#: stock/views.py:399
msgid "Must enter integer value"
msgstr ""
#: stock/views.py:404
msgid "Quantity must be positive"
msgstr ""
#: stock/views.py:411
#, python-brace-format
msgid "Quantity must not exceed {x}"
msgstr ""
#: stock/views.py:419
msgid "Confirm stock adjustment"
msgstr ""
#: stock/views.py:487
#, python-brace-format
msgid "Added stock to {n} items"
msgstr ""
#: stock/views.py:502
#, python-brace-format
msgid "Removed stock from {n} items"
msgstr ""
#: stock/views.py:515
#, python-brace-format
msgid "Counted stock for {n} items"
msgstr ""
#: stock/views.py:543
msgid "No items were moved"
msgstr ""
#: stock/views.py:546
#, python-brace-format
msgid "Moved {n} items to {dest}"
msgstr ""
#: stock/views.py:813
msgid "Invalid part selection"
msgstr ""
#: stock/views.py:875
msgid "Created new stock item"
msgstr ""

Binary file not shown.

View File

@ -0,0 +1,694 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-27 00:12+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: InvenTree/helpers.py:157 order/models.py:158 order/models.py:203
msgid "Invalid quantity provided"
msgstr ""
#: InvenTree/helpers.py:160
msgid "Empty serial number string"
msgstr ""
#: InvenTree/helpers.py:181 InvenTree/helpers.py:198
#, python-brace-format
msgid "Duplicate serial: {n}"
msgstr ""
#: InvenTree/helpers.py:185 InvenTree/helpers.py:188 InvenTree/helpers.py:191
#: InvenTree/helpers.py:202
#, python-brace-format
msgid "Invalid group: {g}"
msgstr ""
#: InvenTree/helpers.py:208
msgid "No serial numbers found"
msgstr ""
#: InvenTree/helpers.py:212
#, python-brace-format
msgid "Number of unique serial number ({s}) must match quantity ({q})"
msgstr ""
#: InvenTree/settings.py:235
msgid "English"
msgstr ""
#: InvenTree/settings.py:236
msgid "German"
msgstr ""
#: InvenTree/settings.py:237
msgid "French"
msgstr ""
#: InvenTree/settings.py:238
msgid "Polish"
msgstr ""
#: InvenTree/status_codes.py:27 InvenTree/status_codes.py:82
msgid "Pending"
msgstr ""
#: InvenTree/status_codes.py:28
msgid "Placed"
msgstr ""
#: InvenTree/status_codes.py:29 InvenTree/status_codes.py:85
msgid "Complete"
msgstr ""
#: InvenTree/status_codes.py:30 InvenTree/status_codes.py:84
msgid "Cancelled"
msgstr ""
#: InvenTree/status_codes.py:31 InvenTree/status_codes.py:62
msgid "Lost"
msgstr ""
#: InvenTree/status_codes.py:32
msgid "Returned"
msgstr ""
#: InvenTree/status_codes.py:58
msgid "OK"
msgstr ""
#: InvenTree/status_codes.py:59
msgid "Attention needed"
msgstr ""
#: InvenTree/status_codes.py:60
msgid "Damaged"
msgstr ""
#: InvenTree/status_codes.py:61
msgid "Destroyed"
msgstr ""
#: InvenTree/status_codes.py:83
msgid "Allocated"
msgstr ""
#: InvenTree/validators.py:35
msgid "Invalid character in part name"
msgstr ""
#: InvenTree/validators.py:44
#, python-brace-format
msgid "Illegal character in name ({x})"
msgstr ""
#: InvenTree/validators.py:63 InvenTree/validators.py:79
msgid "Overage value must not be negative"
msgstr ""
#: InvenTree/validators.py:81
msgid "Overage must not exceed 100%"
msgstr ""
#: InvenTree/validators.py:88
msgid "Overage must be an integer value or a percentage"
msgstr ""
#: build/forms.py:36
msgid "Confirm"
msgstr ""
#: build/forms.py:53 stock/forms.py:34
msgid "Enter unique serial numbers (or leave blank)"
msgstr ""
#: build/forms.py:55
msgid "Confirm build completion"
msgstr ""
#: build/models.py:381
#, python-brace-format
msgid "Selected stock item not found in BOM for part '{p}'"
msgstr ""
#: build/models.py:384
#, python-brace-format
msgid "Allocated quantity ({n}) must not exceed available quantity ({q})"
msgstr ""
#: build/views.py:289 stock/views.py:834
#, python-brace-format
msgid "The following serial numbers already exist: ({sn})"
msgstr ""
#: common/models.py:65
msgid "Settings key (must be unique - case insensitive"
msgstr ""
#: common/models.py:67
msgid "Settings value"
msgstr ""
#: common/models.py:69
msgid "Settings description"
msgstr ""
#: common/models.py:82
msgid "Key string must be unique"
msgstr ""
#: common/models.py:103
msgid "Currency Symbol e.g. $"
msgstr ""
#: common/models.py:105
msgid "Currency Suffix e.g. AUD"
msgstr ""
#: common/models.py:107
msgid "Currency Description"
msgstr ""
#: common/models.py:109
msgid "Currency Value"
msgstr ""
#: common/models.py:111
msgid "Use this currency as the base currency"
msgstr ""
#: order/forms.py:21
msgid "Place order"
msgstr ""
#: order/forms.py:32
msgid "Cancel order"
msgstr ""
#: order/forms.py:43
msgid "Receive parts to this location"
msgstr ""
#: order/models.py:62
msgid "Order reference"
msgstr ""
#: order/models.py:64
msgid "Order description"
msgstr ""
#: order/models.py:66
msgid "Link to external page"
msgstr ""
#: order/models.py:83
msgid "Order notes"
msgstr ""
#: order/models.py:125
msgid "Company"
msgstr ""
#: order/models.py:156 order/models.py:201 part/views.py:1032
#: stock/models.py:437
msgid "Quantity must be greater than zero"
msgstr ""
#: order/models.py:161
msgid "Part supplier must match PO supplier"
msgstr ""
#: order/models.py:196
msgid "Lines can only be received against an order marked as 'Placed'"
msgstr ""
#: order/models.py:245
msgid "Item quantity"
msgstr ""
#: order/models.py:247
msgid "Line item reference"
msgstr ""
#: order/models.py:249
msgid "Line item notes"
msgstr ""
#: order/models.py:275
msgid "Purchase Order"
msgstr ""
#: order/models.py:284
msgid "Supplier part"
msgstr ""
#: order/models.py:287
msgid "Number of items received"
msgstr ""
#: order/views.py:140
msgid "Confirm order cancellation"
msgstr ""
#: order/views.py:173
msgid "Confirm order placement"
msgstr ""
#: order/views.py:695
msgid "Invalid Purchase Order"
msgstr ""
#: order/views.py:703
msgid "Supplier must match for Part and Order"
msgstr ""
#: order/views.py:708
msgid "Invalid SupplierPart selection"
msgstr ""
#: part/bom.py:107
#, python-brace-format
msgid "Unsupported file format: {f}"
msgstr ""
#: part/bom.py:112
msgid "Error reading BOM file (invalid data)"
msgstr ""
#: part/bom.py:114
msgid "Error reading BOM file (incorrect row size)"
msgstr ""
#: part/forms.py:37
msgid "Confirm that the BOM is correct"
msgstr ""
#: part/forms.py:49
msgid "Select BOM file to upload"
msgstr ""
#: part/forms.py:73
msgid "Select part category"
msgstr ""
#: part/forms.py:81
msgid "Perform 'deep copy' which will duplicate all BOM data for this part"
msgstr ""
#: part/forms.py:86
msgid "Confirm part creation"
msgstr ""
#: part/forms.py:173
msgid "Input quantity for price calculation"
msgstr ""
#: part/forms.py:176
msgid "Select currency for price calculation"
msgstr ""
#: part/models.py:308
msgid "Part must be unique for name, IPN and revision"
msgstr ""
#: part/models.py:322
msgid "Part cannot be a template part if it is a variant of another part"
msgstr ""
#: part/models.py:323
msgid "Part cannot be a variant of another part if it is already a template"
msgstr ""
#: part/models.py:992
msgid "Parameter template name must be unique"
msgstr ""
#: part/models.py:1141
msgid "Part cannot be added to its own Bill of Materials"
msgstr ""
#: part/models.py:1148
#, python-brace-format
msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)"
msgstr ""
#: part/templates/part/category.html:13 part/templates/part/category.html:69
msgid "Part Categories"
msgstr ""
#: part/templates/part/category.html:14
msgid "All parts"
msgstr ""
#: part/templates/part/category.html:34
msgid "Category Details"
msgstr ""
#: part/templates/part/category.html:37
msgid "Category Path"
msgstr ""
#: part/templates/part/category.html:41
msgid "Category Description"
msgstr ""
#: part/templates/part/category.html:46 part/templates/part/detail.html:63
msgid "Default Location"
msgstr ""
#: part/templates/part/category.html:52 part/templates/part/detail.html:43
msgid "Keywords"
msgstr ""
#: part/templates/part/category.html:57
msgid "Subcategories"
msgstr ""
#: part/templates/part/category.html:61
msgid "Parts (Including subcategories)"
msgstr ""
#: part/templates/part/category.html:66 part/templates/part/detail.html:8
msgid "Part Details"
msgstr ""
#: part/templates/part/category.html:73
msgid "Parts"
msgstr ""
#: part/templates/part/detail.html:16
msgid "Part name"
msgstr ""
#: part/templates/part/detail.html:21
msgid "IPN"
msgstr ""
#: part/templates/part/detail.html:27
msgid "Revision"
msgstr ""
#: part/templates/part/detail.html:32
msgid "Description"
msgstr ""
#: part/templates/part/detail.html:37
msgid "Variant Of"
msgstr ""
#: part/templates/part/detail.html:49
msgid "URL"
msgstr ""
#: part/templates/part/detail.html:54
msgid "Category"
msgstr ""
#: part/templates/part/detail.html:69
msgid "Default Supplier"
msgstr ""
#: part/templates/part/detail.html:76
msgid "Units"
msgstr ""
#: part/templates/part/detail.html:81
msgid "Minimum Stock"
msgstr ""
#: part/templates/part/detail.html:90
msgid "Virtual"
msgstr ""
#: part/templates/part/detail.html:93
msgid "Part is virtual (not a physical part)"
msgstr ""
#: part/templates/part/detail.html:95
msgid "Part is not a virtual part"
msgstr ""
#: part/templates/part/detail.html:99
msgid "Assembly"
msgstr ""
#: part/templates/part/detail.html:102
msgid "Part can be assembled from other parts"
msgstr ""
#: part/templates/part/detail.html:104
msgid "Part cannot be assembled from other parts"
msgstr ""
#: part/templates/part/detail.html:108
msgid "Component"
msgstr ""
#: part/templates/part/detail.html:111
msgid "Part can be used in assemblies"
msgstr ""
#: part/templates/part/detail.html:113
msgid "Part cannot be used in assemblies"
msgstr ""
#: part/templates/part/detail.html:117
msgid "Trackable"
msgstr ""
#: part/templates/part/detail.html:120
msgid "Part stock is tracked by serial number"
msgstr ""
#: part/templates/part/detail.html:122
msgid "Part stock is not tracked by serial number"
msgstr ""
#: part/templates/part/detail.html:126
msgid "Purchaseable"
msgstr ""
#: part/templates/part/detail.html:129 part/templates/part/detail.html:131
msgid "Part can be purchased from external suppliers"
msgstr ""
#: part/templates/part/detail.html:136
msgid "Sellable"
msgstr ""
#: part/templates/part/detail.html:139
msgid "Part can be sold to customers"
msgstr ""
#: part/templates/part/detail.html:141
msgid "Part cannot be sold to customers"
msgstr ""
#: part/templates/part/detail.html:151
msgid "Notes"
msgstr ""
#: part/views.py:196
#, python-brace-format
msgid "Set category for {n} parts"
msgstr ""
#: part/views.py:773
msgid "No BOM file provided"
msgstr ""
#: part/views.py:1034
msgid "Enter a valid quantity"
msgstr ""
#: part/views.py:1058 part/views.py:1061
msgid "Select valid part"
msgstr ""
#: part/views.py:1067
msgid "Duplicate part selected"
msgstr ""
#: part/views.py:1095
msgid "Select a part"
msgstr ""
#: part/views.py:1099
msgid "Specify quantity"
msgstr ""
#: stock/forms.py:92
msgid "File Format"
msgstr ""
#: stock/forms.py:92
msgid "Select output file format"
msgstr ""
#: stock/forms.py:94
msgid "Include stock items in sub locations"
msgstr ""
#: stock/forms.py:127
msgid "Destination stock location"
msgstr ""
#: stock/forms.py:133
msgid "Confirm movement of stock items"
msgstr ""
#: stock/forms.py:135
msgid "Set the destination as the default location for selected parts"
msgstr ""
#: stock/models.py:201
#, python-brace-format
msgid ""
"A stock item with this serial number already exists for template part {part}"
msgstr ""
#: stock/models.py:206
msgid "A stock item with this serial number already exists"
msgstr ""
#: stock/models.py:225
#, python-brace-format
msgid "Part type ('{pf}') must be {pe}"
msgstr ""
#: stock/models.py:235 stock/models.py:244
msgid "Quantity must be 1 for item with a serial number"
msgstr ""
#: stock/models.py:236
msgid "Serial number cannot be set if quantity greater than 1"
msgstr ""
#: stock/models.py:252
msgid "Stock item cannot be created for a template Part"
msgstr ""
#: stock/models.py:261
msgid "Item cannot belong to itself"
msgstr ""
#: stock/models.py:434
msgid "Quantity must be integer"
msgstr ""
#: stock/models.py:440
#, python-brace-format
msgid "Quantity must not exceed available stock quantity ({n})"
msgstr ""
#: stock/models.py:443 stock/models.py:446
msgid "Serial numbers must be a list of integers"
msgstr ""
#: stock/models.py:449
msgid "Quantity does not match serial numbers"
msgstr ""
#: stock/models.py:459
msgid "Serial numbers already exist: "
msgstr ""
#: stock/models.py:480
msgid "Add serial number"
msgstr ""
#: stock/models.py:483
#, python-brace-format
msgid "Serialized {n} items"
msgstr ""
#: stock/templates/stock/location.html:37
msgid "Location Details"
msgstr ""
#: stock/templates/stock/location.html:40
msgid "Location Path"
msgstr ""
#: stock/templates/stock/location.html:44
msgid "Location Description"
msgstr ""
#: stock/templates/stock/location.html:48
msgid "Sublocations"
msgstr ""
#: stock/templates/stock/location.html:52
#: stock/templates/stock/location.html:64
msgid "Stock Items"
msgstr ""
#: stock/templates/stock/location.html:57
msgid "Stock Details"
msgstr ""
#: stock/templates/stock/location.html:60
msgid "Stock Locations"
msgstr ""
#: stock/views.py:399
msgid "Must enter integer value"
msgstr ""
#: stock/views.py:404
msgid "Quantity must be positive"
msgstr ""
#: stock/views.py:411
#, python-brace-format
msgid "Quantity must not exceed {x}"
msgstr ""
#: stock/views.py:419
msgid "Confirm stock adjustment"
msgstr ""
#: stock/views.py:487
#, python-brace-format
msgid "Added stock to {n} items"
msgstr ""
#: stock/views.py:502
#, python-brace-format
msgid "Removed stock from {n} items"
msgstr ""
#: stock/views.py:515
#, python-brace-format
msgid "Counted stock for {n} items"
msgstr ""
#: stock/views.py:543
msgid "No items were moved"
msgstr ""
#: stock/views.py:546
#, python-brace-format
msgid "Moved {n} items to {dest}"
msgstr ""
#: stock/views.py:813
msgid "Invalid part selection"
msgstr ""
#: stock/views.py:875
msgid "Created new stock item"
msgstr ""

View File

@ -1,5 +1,6 @@
{% extends "part/part_app_base.html" %}
{% load static %}
{% load i18n %}
{% block content %}
@ -9,8 +10,8 @@
<h3>{{ category.name }}</h3>
<p>{{ category.description }}</p>
{% else %}
<h3>Part Categories</h3>
<p>All parts</p>
<h3>{% trans "Part Categories" %}</h3>
<p>{% trans "All parts" %}</p>
{% endif %}
<p>
<div class='btn-group'>
@ -30,37 +31,49 @@
</div>
<div class='col-sm-6'>
{% if category %}
<h3>Category Details</h3>
<h3>{% trans "Category Details" %}</h3>
<table class='table table-condensed table-striped'>
<tr>
<td>Category Path</td>
<td>{% trans "Category Path" %}</td>
<td>{{ category.pathstring }}</td>
</tr>
<tr>
<td>Category Description</td>
<td>{% trans "Category Description" %}</td>
<td>{{ category.description }}</td>
</tr>
{% if category.default_location %}
<tr>
<td>Default Location</td>
<td>{% trans "Default Location" %}</td>
<td><a href="{% url 'stock-location-detail' category.default_location.pk %}">{{ category.default_location.pathstring }}</a></td>
</tr>
{% endif %}
{% if category.default_keywords %}
<tr>
<td>Keywords</td>
<td>{% trans "Keywords" %}</td>
<td>{{ category.default_keywords }}</td>
</tr>
{% endif %}
<tr>
<td>Subcategories</td>
<td>{% trans "Subcategories" %}</td>
<td>{{ category.children.count }}</td>
</tr>
<tr>
<td>Parts (Including subcategories)</td>
<td>{% trans "Parts (Including subcategories)" %}</td>
<td>{{ category.partcount }}</td>
</tr>
</table>
{% else %}
<h3>{% trans "Part Details" %}</h3>
<table class='table table-striped table-condensed'>
<tr>
<td>{% trans "Part Categories" %}</td>
<td>{{ category_count }}</td>
</tr>
<tr>
<td>{% trans "Parts" %}</td>
<td>{{ part_count }}</td>
</tr>
</table>
{% endif %}
</div>
</div>

View File

@ -1,10 +1,11 @@
{% extends "part/part_base.html" %}
{% load static %}
{% load i18n %}
{% block details %}
{% include 'part/tabs.html' with tab='detail' %}
<h4>Part Details</h4>
<h4>{% trans "Part Details" %}</h4>
<hr>
@ -12,45 +13,45 @@
<div class='col-sm-6'>
<table class='table table-striped'>
<tr>
<td><b>Part name</b></td>
<td><b>{% trans "Part name" %}</b></td>
<td>{{ part.name }}</td>
</tr>
{% if part.IPN %}
<tr>
<td><b>IPN</b></td>
<td><b>{% trans "IPN" %}</b></td>
<td>{{ part.IPN }}</td>
</tr>
{% endif %}
{% if part.revision %}
<tr>
<td><b>Revision</b></td>
<td><b>{% trans "Revision" %}</b></td>
<td>{{ part.revision }}</td>
</tr>
{% endif %}
<tr>
<td><b>Description</b></td>
<td><b>{% trans "Description" %}</b></td>
<td>{{ part.description }}</td>
</tr>
{% if part.variant_of %}
<tr>
<td><b>Variant Of</b></td>
<td><b>{% trans "Variant Of" %}</b></td>
<td><a href="{% url 'part-detail' part.variant_of.id %}">{{ part.variant_of.full_name }}</a></td>
</tr>
{% endif %}
{% if part.keywords %}
<tr>
<td><b>Keywords</b></td>
<td><b>{% trans "Keywords" %}</b></td>
<td>{{ part.keywords }}</td>
</tr>
{% endif %}
{% if part.URL %}
<tr>
<td><b>URL</b></td>
<td><b>{% trans "URL" %}</b></td>
<td><a href="{{ part.URL }}">{{ part.URL }}</a></td>
</tr>
{% endif %}
<tr>
<td><b>Category</b></td>
<td><b>{% trans "Category" %}</b></td>
<td>
{% if part.category %}
<a href="{% url 'category-detail' part.category.id %}">{{ part.category.pathstring }}</a>
@ -59,25 +60,25 @@
</tr>
{% if part.default_location %}
<tr>
<td><b>Default Location</b></td>
<td><b>{% trans "Default Location" %}</b></td>
<td><a href="{% url 'stock-location-detail' part.default_location.id %}">{{ part.default_location.pathstring }}</a></td>
</tr>
{% endif %}
{% if part.default_supplier %}
<tr>
<td><b>Default Supplier</b></td>
<td><b>{% trans "Default Supplier" %}</b></td>
<td><a href="{% url 'supplier-part-detail' part.default_supplier.id %}">
{{ part.default_supplier.supplier.name }} | {{ part.default_supplier.SKU }}
</a></td>
</tr>
{% endif %}
<tr>
<td><b>Units</b></td>
<td><b>{% trans "Units" %}</b></td>
<td>{{ part.units }}</td>
</tr>
{% if part.minimum_stock > 0 %}
<tr>
<td><b>Minimum Stock</b></td>
<td><b>{% trans "Minimum Stock" %}</b></td>
<td>{{ part.minimum_stock }}</td>
</tr>
{% endif %}
@ -86,58 +87,58 @@
<div class='col-sm-6'>
<table class='table table-striped'>
<tr>
<td><b>Virtual</b></td>
<td><b>{% trans "Virtual" %}</b></td>
<td>{% include "slide.html" with state=part.virtual field='virtual' %}</td>
{% if part.virtual %}
<td>Part is virtual (not a physical part)</td>
<td>{% trans "Part is virtual (not a physical part)" %}</td>
{% else %}
<td><i>Part is not a virtual part</i></td>
<td><i>{% trans "Part is not a virtual part" %}</i></td>
{% endif %}
</tr>
<tr>
<td><b>Assembly</b></td>
<td><b>{% trans "Assembly" %}</b></td>
<td>{% include "slide.html" with state=part.assembly field='assembly' %}</td>
{% if part.assembly %}
<td>Part can be assembled from other parts</td>
<td>{% trans "Part can be assembled from other parts" %}</td>
{% else %}
<td><i>Part cannot be assembled from other parts</i></td>
<td><i>{% trans "Part cannot be assembled from other parts" %}</i></td>
{% endif %}
</tr>
<tr>
<td><b>Component</b></td>
<td><b>{% trans "Component" %}</b></td>
<td>{% include "slide.html" with state=part.component field='component' %}</td>
{% if part.component %}
<td>Part can be used in assemblies</td>
<td>{% trans "Part can be used in assemblies" %}</td>
{% else %}
<td><i>Part cannot be used in assemblies</i></td>
<td><i>{% trans "Part cannot be used in assemblies" %}</i></td>
{% endif %}
</tr>
<tr>
<td><b>Trackable</b></td>
<td><b>{% trans "Trackable" %}</b></td>
<td>{% include "slide.html" with state=part.trackable field='trackable' %}</td>
{% if part.trackable %}
<td>Part stock is tracked by serial number</td>
<td>{% trans "Part stock is tracked by serial number" %}</td>
{% else %}
<td><i>Part stock is not tracked by serial number</i></td>
<td><i>{% trans "Part stock is not tracked by serial number" %}</i></td>
{% endif %}
</tr>
<tr>
<td><b>Purchaseable</b></td>
<td><b>{% trans "Purchaseable" %}</b></td>
<td>{% include "slide.html" with state=part.purchaseable field='purchaseable' %}</td>
{% if part.purchaseable %}
<td>Part can be purchased from external suppliers</td>
<td>{% trans "Part can be purchased from external suppliers" %}</td>
{% else %}
<td><i>Part can be purchased from external suppliers</i></td>
<td><i>{% trans "Part can be purchased from external suppliers" %}</i></td>
{% endif %}
</tr>
{% if 0 %}
<tr>
<td><b>Sellable</b></td>
<td><b>{% trans "Sellable" %}</b></td>
<td>{% include "slide.html" with state=part.salable field='salable' %}</td>
{% if part.salable %}
<td>Part can be sold to customers</td>
<td>{% trans "Part can be sold to customers" %}</td>
{% else %}
<td><i>Part cannot be sold to customers</i></td>
<td><i>{% trans "Part cannot be sold to customers" %}</i></td>
{% endif %}
</tr>
{% endif %}
@ -147,7 +148,7 @@
{% if part.notes %}
<div class="panel panel-default">
<div class="panel-heading"><b>Notes</b></div>
<div class="panel-heading"><b>{% trans "Notes" %}</b></div>
<div class="panel-body">{{ part.notes }}</div>
</div>
{% endif %}

View File

@ -56,6 +56,8 @@ class PartIndex(ListView):
children = PartCategory.objects.filter(parent=None)
context['children'] = children
context['category_count'] = PartCategory.objects.count()
context['part_count'] = Part.objects.count()
return context

View File

@ -1,5 +1,6 @@
{% extends "stock/stock_app_base.html" %}
{% load static %}
{% load i18n %}
{% block content %}
<div class='row'>
@ -33,25 +34,37 @@
</div>
<div class='col-sm-6'>
{% if location %}
<h3>Location Details</h3>
<h3>{% trans "Location Details" %}</h3>
<table class='table table-striped table-condensed'>
<tr>
<td>Location Path</td>
<td>{% trans "Location Path" %}</td>
<td>{{ location.pathstring }}</td>
</tr>
<tr>
<td>Location Description</td>
<td>{% trans "Location Description" %}</td>
<td>{{ location.description }}</td>
</tr>
<tr>
<td>Sublocations</td>
<td>{% trans "Sublocations" %}</td>
<td>{{ location.children.count }}</td>
</tr>
<tr>
<td>Stock Items</td>
<td>{% trans "Stock Items" %}</td>
<td>{{ location.item_count }}</td>
</tr>
</table>
{% else %}
<h3>{% trans "Stock Details" %}</h3>
<table class='table table-striped table-condensed'>
<tr>
<td>{% trans "Stock Locations" %}</td>
<td>{{ loc_count }}</td>
</tr>
<tr>
<td>{% trans "Stock Items" %}</td>
<td>{{ stock_count }}</td>
</tr>
</table>
{% endif %}
</div>
</h3>

View File

@ -53,6 +53,9 @@ class StockIndex(ListView):
context['locations'] = locations
context['items'] = StockItem.objects.all()
context['loc_count'] = StockLocation.objects.count()
context['stock_count'] = StockItem.objects.count()
return context

View File

@ -113,14 +113,8 @@ $(document).ready(function () {
{% block js_ready %}
{% endblock %}
/* Run document-ready scripts.
* Ref: static/script/inventree/inventree.js
*/
inventreeDocReady();
/* Display any cached alert messages
* Ref: static/script/inventree/notification.js
*/
showCachedAlerts();
});
</script>

View File

@ -39,6 +39,11 @@ postgresql:
apt-get install postgresql postgresql-contrib libpq-dev
pip3 install psycopg2
# Update translation files
translate:
cd InvenTree && python3 manage.py makemessages
cd InvenTree && python3 manage.py compilemessages
# Run PEP style checks against source code
style:
flake8 InvenTree
@ -67,4 +72,4 @@ backup:
cd InvenTree && python3 manage.py dbbackup
cd InvenTree && python3 manage.py mediabackup
.PHONY: clean migrate superuser install mysql postgresql static style test coverage docreqs docs backup update
.PHONY: clean migrate superuser install mysql postgresql translate static style test coverage docreqs docs backup update

View File

@ -13,9 +13,9 @@ However, powerful business logic works in the background to ensure that stock tr
For InvenTree documentation, refer to the [user documentation](https://inventree.github.io).
## Code Documentation
## Developer Documentation
For project code documentation, refer to the [developer documentation](http://inventree.readthedocs.io/en/latest/) (auto-generated)
For site administrator and project code documentation, refer to the [developer documentation](http://inventree.readthedocs.io/en/latest/). This includes auto-generated documentation of the InvenTree python codebase.
## Getting Started

30
ci/check_locale_files.py Normal file
View File

@ -0,0 +1,30 @@
""" Check that there are no database migration files which have not been committed. """
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import sys
import subprocess
print("Checking for uncommitted locale files...")
cmd = ['git', 'status']
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()
locales = []
for line in str(out.decode()).split('\n'):
# Check for any compiled translation files that have not been committed
if 'modified:' in line and '/locale/' in line and 'django.po' in line:
locales.append(line)
if len(locales) > 0:
print("There are {n} unstaged locale files:".format(n=len(locales)))
for l in locales:
print(" - {l}".format(l=l))
sys.exit(len(locales))

View File

@ -6,6 +6,8 @@ from __future__ import unicode_literals
import sys
import subprocess
print("Checking for unstaged migration files...")
cmd = ['git', 'ls-files', '--exclude-standard', '--others']
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

View File

@ -12,6 +12,7 @@ InvenTree Source Documentation
Deployment<deploy>
Migrate Data<migrate>
Update InvenTree<update>
Translations<translate>
Backup and Restore<backup>
Modal Forms<forms>
Tables<tables>

View File

@ -17,9 +17,11 @@ Requirements
To install InvenTree you will need the following system components installed:
* python3
* python3-pip
* python3-pip (pip3)
* make
Each of these programs need to be installed (e.g. using apt or similar) before running the ``make install`` script.
Installation
------------
@ -88,6 +90,7 @@ Other shorthand functions are provided for the development and testing process:
* ``make migrate`` - Perform database migrations
* ``make mysql`` - Install packages required for MySQL database backend
* ``make postgresql`` - Install packages required for PostgreSQL database backend
* ``make translate`` - Compile language translation files (requires gettext system package)
* ``make backup`` - Backup database tables and media files
* ``make test`` - Run all unit tests
* ``make coverage`` - Run all unit tests and generate code coverage report

16
docs/translate.rst Normal file
View File

@ -0,0 +1,16 @@
Translations
============
.. toctree::
:titlesonly:
:maxdepth: 2
:caption: Language Translation
:hidden:
InvenTree supports multi-language translation using the `Django Translation Framework <https://docs.djangoproject.com/en/2.2/topics/i18n/translation/>`_
Translation strings are located in the `InvenTree/locales/` directory, and translation files can be easily added here.
To set the default language, change the `language` setting in the `config.yaml` settings file.
To recompile the translation files (after adding new translation strings), run the command ``make translate`` from the root directory.