From 0e0405f337334b083edc552794808795657a3874 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 26 Sep 2019 09:55:45 +1000 Subject: [PATCH 01/12] Update settings.py to enable translations --- InvenTree/InvenTree/settings.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index c3d646c660..8e6f86a0e0 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -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', 'de-ge') + +# 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' From 3cc79d6def905567f5057f027e768abb862e3075 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 26 Sep 2019 09:56:41 +1000 Subject: [PATCH 02/12] Add default language option to config.yaml --- InvenTree/config_template.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/InvenTree/config_template.yaml b/InvenTree/config_template.yaml index f362048e35..73b4a73650 100644 --- a/InvenTree/config_template.yaml +++ b/InvenTree/config_template.yaml @@ -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 From 37e9bd8d9bbded0d39df4e09423079f81962c9da Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 26 Sep 2019 09:57:09 +1000 Subject: [PATCH 03/12] Add install requirement for gettext (required package for creating translation files) --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index ebbd9cafef..3928f9e0e9 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,7 @@ static: # Install all required packages install: pip3 install -U -r requirements.txt + apt-get install gettext cd InvenTree && python3 setup.py # Create a superuser account From 0ae2fd924699d6a0202bc2d23cd6df2203bdce36 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 26 Sep 2019 09:58:50 +1000 Subject: [PATCH 04/12] Update migration script to re-compile translation strings --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 3928f9e0e9..a76fc1e02c 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,8 @@ migrate: cd InvenTree && python3 manage.py migrate cd InvenTree && python3 manage.py migrate --run-syncdb cd InvenTree && python3 manage.py check + cd InvenTree && python3 manage.py makemessages + cd InvenTree && python3 manage.py compilemessages # Collect static files into the correct locations static: From 40acf90efec7a3e4b44dea0446805f9916015342 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 26 Sep 2019 09:59:50 +1000 Subject: [PATCH 05/12] Add some initial (empty) translation files --- InvenTree/locale/de/LC_MESSAGES/django.mo | Bin 0 -> 380 bytes InvenTree/locale/de/LC_MESSAGES/django.po | 509 ++++++++++++++++++++++ InvenTree/locale/en/LC_MESSAGES/django.mo | Bin 0 -> 380 bytes InvenTree/locale/en/LC_MESSAGES/django.po | 509 ++++++++++++++++++++++ InvenTree/locale/es/LC_MESSAGES/django.mo | Bin 0 -> 380 bytes InvenTree/locale/es/LC_MESSAGES/django.po | 509 ++++++++++++++++++++++ 6 files changed, 1527 insertions(+) create mode 100644 InvenTree/locale/de/LC_MESSAGES/django.mo create mode 100644 InvenTree/locale/de/LC_MESSAGES/django.po create mode 100644 InvenTree/locale/en/LC_MESSAGES/django.mo create mode 100644 InvenTree/locale/en/LC_MESSAGES/django.po create mode 100644 InvenTree/locale/es/LC_MESSAGES/django.mo create mode 100644 InvenTree/locale/es/LC_MESSAGES/django.po diff --git a/InvenTree/locale/de/LC_MESSAGES/django.mo b/InvenTree/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..71cbdf3e9d8d54be31066ec4ad8628bc2c1f2845 GIT binary patch literal 380 zcmYL@K~KUk7=|%=+R?Lz&%}d9i{c3jGZa>EvE7z2Nc2{r&Y96JZ6W$Y{CoZuJ5A(G zp7i_Dx9RhJeDu}vIq;l#&OC>nD^HugXY4QU{MmN?lNtRkR}RH%w3NnHT4Bh@vF%H^(V-=Ii1iQ$Qo9Pt!I1Rhe%oml#`f^NEGFCKEL->Rc=KoQ6a?!10%_7(V7ey8`V`;n{war z20Z3;uifk31QV^CRQ|iq#``$=;jWunRB8aLH({)F;i8zL{=V00y-I_qTIqGAN(}v% i$^}`yHKImSZ8jEzYJOK6-VWez49^vuhS0kh1f3tbb!oc* literal 0 HcmV?d00001 diff --git a/InvenTree/locale/de/LC_MESSAGES/django.po b/InvenTree/locale/de/LC_MESSAGES/django.po new file mode 100644 index 0000000000..424244dd51 --- /dev/null +++ b/InvenTree/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,509 @@ +# 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 , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-25 23:59+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \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:831 +#, 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:1030 +#: 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/views.py:194 +#, python-brace-format +msgid "Set category for {n} parts" +msgstr "" + +#: part/views.py:771 +msgid "No BOM file provided" +msgstr "" + +#: part/views.py:1032 +msgid "Enter a valid quantity" +msgstr "" + +#: part/views.py:1056 part/views.py:1059 +msgid "Select valid part" +msgstr "" + +#: part/views.py:1065 +msgid "Duplicate part selected" +msgstr "" + +#: part/views.py:1093 +msgid "Select a part" +msgstr "" + +#: part/views.py:1097 +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/views.py:396 +msgid "Must enter integer value" +msgstr "" + +#: stock/views.py:401 +msgid "Quantity must be positive" +msgstr "" + +#: stock/views.py:408 +#, python-brace-format +msgid "Quantity must not exceed {x}" +msgstr "" + +#: stock/views.py:416 +msgid "Confirm stock adjustment" +msgstr "" + +#: stock/views.py:484 +#, python-brace-format +msgid "Added stock to {n} items" +msgstr "" + +#: stock/views.py:499 +#, python-brace-format +msgid "Removed stock from {n} items" +msgstr "" + +#: stock/views.py:512 +#, python-brace-format +msgid "Counted stock for {n} items" +msgstr "" + +#: stock/views.py:540 +msgid "No items were moved" +msgstr "" + +#: stock/views.py:543 +#, python-brace-format +msgid "Moved {n} items to {dest}" +msgstr "" + +#: stock/views.py:810 +msgid "Invalid part selection" +msgstr "" + +#: stock/views.py:872 +msgid "Created new stock item" +msgstr "" diff --git a/InvenTree/locale/en/LC_MESSAGES/django.mo b/InvenTree/locale/en/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..71cbdf3e9d8d54be31066ec4ad8628bc2c1f2845 GIT binary patch literal 380 zcmYL@K~KUk7=|%=+R?Lz&%}d9i{c3jGZa>EvE7z2Nc2{r&Y96JZ6W$Y{CoZuJ5A(G zp7i_Dx9RhJeDu}vIq;l#&OC>nD^HugXY4QU{MmN?lNtRkR}RH%w3NnHT4Bh@vF%H^(V-=Ii1iQ$Qo9Pt!I1Rhe%oml#`f^NEGFCKEL->Rc=KoQ6a?!10%_7(V7ey8`V`;n{war z20Z3;uifk31QV^CRQ|iq#``$=;jWunRB8aLH({)F;i8zL{=V00y-I_qTIqGAN(}v% i$^}`yHKImSZ8jEzYJOK6-VWez49^vuhS0kh1f3tbb!oc* literal 0 HcmV?d00001 diff --git a/InvenTree/locale/en/LC_MESSAGES/django.po b/InvenTree/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000000..424244dd51 --- /dev/null +++ b/InvenTree/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,509 @@ +# 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 , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-25 23:59+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \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:831 +#, 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:1030 +#: 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/views.py:194 +#, python-brace-format +msgid "Set category for {n} parts" +msgstr "" + +#: part/views.py:771 +msgid "No BOM file provided" +msgstr "" + +#: part/views.py:1032 +msgid "Enter a valid quantity" +msgstr "" + +#: part/views.py:1056 part/views.py:1059 +msgid "Select valid part" +msgstr "" + +#: part/views.py:1065 +msgid "Duplicate part selected" +msgstr "" + +#: part/views.py:1093 +msgid "Select a part" +msgstr "" + +#: part/views.py:1097 +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/views.py:396 +msgid "Must enter integer value" +msgstr "" + +#: stock/views.py:401 +msgid "Quantity must be positive" +msgstr "" + +#: stock/views.py:408 +#, python-brace-format +msgid "Quantity must not exceed {x}" +msgstr "" + +#: stock/views.py:416 +msgid "Confirm stock adjustment" +msgstr "" + +#: stock/views.py:484 +#, python-brace-format +msgid "Added stock to {n} items" +msgstr "" + +#: stock/views.py:499 +#, python-brace-format +msgid "Removed stock from {n} items" +msgstr "" + +#: stock/views.py:512 +#, python-brace-format +msgid "Counted stock for {n} items" +msgstr "" + +#: stock/views.py:540 +msgid "No items were moved" +msgstr "" + +#: stock/views.py:543 +#, python-brace-format +msgid "Moved {n} items to {dest}" +msgstr "" + +#: stock/views.py:810 +msgid "Invalid part selection" +msgstr "" + +#: stock/views.py:872 +msgid "Created new stock item" +msgstr "" diff --git a/InvenTree/locale/es/LC_MESSAGES/django.mo b/InvenTree/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..71cbdf3e9d8d54be31066ec4ad8628bc2c1f2845 GIT binary patch literal 380 zcmYL@K~KUk7=|%=+R?Lz&%}d9i{c3jGZa>EvE7z2Nc2{r&Y96JZ6W$Y{CoZuJ5A(G zp7i_Dx9RhJeDu}vIq;l#&OC>nD^HugXY4QU{MmN?lNtRkR}RH%w3NnHT4Bh@vF%H^(V-=Ii1iQ$Qo9Pt!I1Rhe%oml#`f^NEGFCKEL->Rc=KoQ6a?!10%_7(V7ey8`V`;n{war z20Z3;uifk31QV^CRQ|iq#``$=;jWunRB8aLH({)F;i8zL{=V00y-I_qTIqGAN(}v% i$^}`yHKImSZ8jEzYJOK6-VWez49^vuhS0kh1f3tbb!oc* literal 0 HcmV?d00001 diff --git a/InvenTree/locale/es/LC_MESSAGES/django.po b/InvenTree/locale/es/LC_MESSAGES/django.po new file mode 100644 index 0000000000..424244dd51 --- /dev/null +++ b/InvenTree/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,509 @@ +# 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 , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-25 23:59+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \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:831 +#, 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:1030 +#: 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/views.py:194 +#, python-brace-format +msgid "Set category for {n} parts" +msgstr "" + +#: part/views.py:771 +msgid "No BOM file provided" +msgstr "" + +#: part/views.py:1032 +msgid "Enter a valid quantity" +msgstr "" + +#: part/views.py:1056 part/views.py:1059 +msgid "Select valid part" +msgstr "" + +#: part/views.py:1065 +msgid "Duplicate part selected" +msgstr "" + +#: part/views.py:1093 +msgid "Select a part" +msgstr "" + +#: part/views.py:1097 +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/views.py:396 +msgid "Must enter integer value" +msgstr "" + +#: stock/views.py:401 +msgid "Quantity must be positive" +msgstr "" + +#: stock/views.py:408 +#, python-brace-format +msgid "Quantity must not exceed {x}" +msgstr "" + +#: stock/views.py:416 +msgid "Confirm stock adjustment" +msgstr "" + +#: stock/views.py:484 +#, python-brace-format +msgid "Added stock to {n} items" +msgstr "" + +#: stock/views.py:499 +#, python-brace-format +msgid "Removed stock from {n} items" +msgstr "" + +#: stock/views.py:512 +#, python-brace-format +msgid "Counted stock for {n} items" +msgstr "" + +#: stock/views.py:540 +msgid "No items were moved" +msgstr "" + +#: stock/views.py:543 +#, python-brace-format +msgid "Moved {n} items to {dest}" +msgstr "" + +#: stock/views.py:810 +msgid "Invalid part selection" +msgstr "" + +#: stock/views.py:872 +msgid "Created new stock item" +msgstr "" From 9be528a3fbae786ea8b3da7de14a1fac05467af1 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 26 Sep 2019 10:07:18 +1000 Subject: [PATCH 06/12] Add (brief) documentation page regarding translations --- InvenTree/InvenTree/settings.py | 2 +- InvenTree/config_template.yaml | 2 +- docs/index.rst | 1 + docs/translate.rst | 14 ++++++++++++++ 4 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 docs/translate.rst diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index 8e6f86a0e0..2ad7ae1c8b 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -228,7 +228,7 @@ if not type(EXTRA_URL_SCHEMES) in [list]: # Internationalization # https://docs.djangoproject.com/en/1.10/topics/i18n/ -LANGUAGE_CODE = CONFIG.get('language', 'de-ge') +LANGUAGE_CODE = CONFIG.get('language', 'en-us') # If a new language translation is supported, it must be added here LANGUAGES = [ diff --git a/InvenTree/config_template.yaml b/InvenTree/config_template.yaml index 73b4a73650..66c6f6d762 100644 --- a/InvenTree/config_template.yaml +++ b/InvenTree/config_template.yaml @@ -18,7 +18,7 @@ database: #HOST: '' #PORT: '' -# Select default system language (default is 'en_us') +# Select default system language (default is 'en-us') language: en-us # Set debug to False to run in production mode diff --git a/docs/index.rst b/docs/index.rst index b5547c2520..ddee7f2b6a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,6 +12,7 @@ InvenTree Source Documentation Deployment Migrate Data Update InvenTree + Translations Backup and Restore Modal Forms Tables diff --git a/docs/translate.rst b/docs/translate.rst new file mode 100644 index 0000000000..e81ecef7f8 --- /dev/null +++ b/docs/translate.rst @@ -0,0 +1,14 @@ +Translations +============ + +.. toctree:: + :titlesonly: + :maxdepth: 2 + :caption: Language Translation + :hidden: + +InvenTree supports multi-language translation using the `Django Translation Framework `_ + +Translation strings are located in the `InvenTree/locales/` directory, and translation files can be easily added here. + +To set the default language, change the `langauge` setting in the `config.yaml` settings file. \ No newline at end of file From eaf910d26352abe872aa2a231e6f8eb495b0f21c Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 26 Sep 2019 10:12:10 +1000 Subject: [PATCH 07/12] Try enforcing sudo --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7941be564d..4124ae497e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ addons: -sqlite3 before_install: - - make install + - sudo make install - make migrate - cd InvenTree && python3 manage.py createsuperuser --username InvenTreeAdmin --email admin@inventree.com --noinput && cd .. From fcb47fce092d28ef3f038018cded20841e05427d Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 26 Sep 2019 10:16:45 +1000 Subject: [PATCH 08/12] Make gettext a prerequisite rather than polluting the make file with apt commands that require sudo --- .travis.yml | 4 +++- Makefile | 1 - docs/start.rst | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4124ae497e..d8f5641e26 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,9 @@ addons: -sqlite3 before_install: - - sudo make 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 .. diff --git a/Makefile b/Makefile index a76fc1e02c..c8a9796a71 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,6 @@ static: # Install all required packages install: pip3 install -U -r requirements.txt - apt-get install gettext cd InvenTree && python3 setup.py # Create a superuser account diff --git a/docs/start.rst b/docs/start.rst index a5621d9f97..18bef1bbbd 100644 --- a/docs/start.rst +++ b/docs/start.rst @@ -17,8 +17,9 @@ Requirements To install InvenTree you will need the following system components installed: * python3 -* python3-pip +* python3-pip (pip3) * make +* gettext Installation ------------ From b56a1ade242732fd987c1fc4a81a2d420524cf8b Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 26 Sep 2019 10:21:14 +1000 Subject: [PATCH 09/12] Make translation compilation a separate step - Must be run after a translation file is updated --- Makefile | 9 ++++++--- docs/start.rst | 4 +++- docs/translate.rst | 4 +++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index c8a9796a71..08318220ac 100644 --- a/Makefile +++ b/Makefile @@ -15,8 +15,6 @@ migrate: cd InvenTree && python3 manage.py migrate cd InvenTree && python3 manage.py migrate --run-syncdb cd InvenTree && python3 manage.py check - cd InvenTree && python3 manage.py makemessages - cd InvenTree && python3 manage.py compilemessages # Collect static files into the correct locations static: @@ -41,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 @@ -69,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 \ No newline at end of file +.PHONY: clean migrate superuser install mysql postgresql translate static style test coverage docreqs docs backup update \ No newline at end of file diff --git a/docs/start.rst b/docs/start.rst index 18bef1bbbd..f45c3a8d14 100644 --- a/docs/start.rst +++ b/docs/start.rst @@ -19,7 +19,8 @@ To install InvenTree you will need the following system components installed: * python3 * python3-pip (pip3) * make -* gettext + +Each of these programs need to be installed (e.g. using apt or similar) before running the ``make install`` script. Installation ------------ @@ -89,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 diff --git a/docs/translate.rst b/docs/translate.rst index e81ecef7f8..3c2ad0d5f4 100644 --- a/docs/translate.rst +++ b/docs/translate.rst @@ -11,4 +11,6 @@ InvenTree supports multi-language translation using the `Django Translation Fram Translation strings are located in the `InvenTree/locales/` directory, and translation files can be easily added here. -To set the default language, change the `langauge` setting in the `config.yaml` settings file. \ No newline at end of file +To set the default language, change the `langauge` 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. From fcba00bc6973fcccd2f515d94f8a2fe35a4df13f Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 26 Sep 2019 10:32:44 +1000 Subject: [PATCH 10/12] Check for altered translation files that have not been compiled --- .travis.yml | 2 ++ InvenTree/locale/en/LC_MESSAGES/django.po | 4 ++-- ci/check_locale_files.py | 29 +++++++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 ci/check_locale_files.py diff --git a/.travis.yml b/.travis.yml index d8f5641e26..769dd4d37d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,6 +20,8 @@ script: - cd InvenTree && python3 manage.py makemigrations && cd .. - python3 ci/check_migration_files.py - make coverage + - make translate + - python3 ci/check_locale_files.py - make style after_success: diff --git a/InvenTree/locale/en/LC_MESSAGES/django.po b/InvenTree/locale/en/LC_MESSAGES/django.po index 424244dd51..7374c8ad19 100644 --- a/InvenTree/locale/en/LC_MESSAGES/django.po +++ b/InvenTree/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-25 23:59+0000\n" +"POT-Creation-Date: 2019-09-26 00:27+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -20,7 +20,7 @@ msgstr "" #: InvenTree/helpers.py:157 order/models.py:158 order/models.py:203 msgid "Invalid quantity provided" -msgstr "" +msgstr "hello" #: InvenTree/helpers.py:160 msgid "Empty serial number string" diff --git a/ci/check_locale_files.py b/ci/check_locale_files.py new file mode 100644 index 0000000000..caa5d694e3 --- /dev/null +++ b/ci/check_locale_files.py @@ -0,0 +1,29 @@ +""" 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 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'): + if 'modified:' in line and '/locale/' 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)) \ No newline at end of file From f2eb66d854380c633e4726af6f79ef0e74d4898d Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 26 Sep 2019 10:37:39 +1000 Subject: [PATCH 11/12] Update readme file and scripts --- InvenTree/locale/de/LC_MESSAGES/django.po | 2 +- InvenTree/locale/en/LC_MESSAGES/django.po | 4 ++-- InvenTree/locale/es/LC_MESSAGES/django.po | 2 +- README.md | 4 ++-- ci/check_locale_files.py | 5 +++-- ci/check_migration_files.py | 2 ++ 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/InvenTree/locale/de/LC_MESSAGES/django.po b/InvenTree/locale/de/LC_MESSAGES/django.po index 424244dd51..c37dd0f0ae 100644 --- a/InvenTree/locale/de/LC_MESSAGES/django.po +++ b/InvenTree/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-25 23:59+0000\n" +"POT-Creation-Date: 2019-09-26 00:37+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/InvenTree/locale/en/LC_MESSAGES/django.po b/InvenTree/locale/en/LC_MESSAGES/django.po index 7374c8ad19..c37dd0f0ae 100644 --- a/InvenTree/locale/en/LC_MESSAGES/django.po +++ b/InvenTree/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-26 00:27+0000\n" +"POT-Creation-Date: 2019-09-26 00:37+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -20,7 +20,7 @@ msgstr "" #: InvenTree/helpers.py:157 order/models.py:158 order/models.py:203 msgid "Invalid quantity provided" -msgstr "hello" +msgstr "" #: InvenTree/helpers.py:160 msgid "Empty serial number string" diff --git a/InvenTree/locale/es/LC_MESSAGES/django.po b/InvenTree/locale/es/LC_MESSAGES/django.po index 424244dd51..c37dd0f0ae 100644 --- a/InvenTree/locale/es/LC_MESSAGES/django.po +++ b/InvenTree/locale/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-25 23:59+0000\n" +"POT-Creation-Date: 2019-09-26 00:37+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/README.md b/README.md index 962f8186c9..1b2996f80c 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/ci/check_locale_files.py b/ci/check_locale_files.py index caa5d694e3..b15aa80765 100644 --- a/ci/check_locale_files.py +++ b/ci/check_locale_files.py @@ -6,7 +6,7 @@ from __future__ import unicode_literals import sys import subprocess -print("Checking for uncommitted files...") +print("Checking for uncommitted locale files...") cmd = ['git', 'status'] @@ -17,7 +17,8 @@ out, err = proc.communicate() locales = [] for line in str(out.decode()).split('\n'): - if 'modified:' in line and '/locale/' in line: + # Check for any compiled translation files that have not been committed + if 'modified:' in line and '/locale/' in line and 'django.mo' in line: locales.append(line) if len(locales) > 0: diff --git a/ci/check_migration_files.py b/ci/check_migration_files.py index 5d0da79142..88e5a90bee 100644 --- a/ci/check_migration_files.py +++ b/ci/check_migration_files.py @@ -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) From 30de734dfad7fe454c8d96de51f71afa67c12bdc Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 26 Sep 2019 10:55:23 +1000 Subject: [PATCH 12/12] Remove test as it is not currently working --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 769dd4d37d..29a1fe8db1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,6 @@ script: - python3 ci/check_migration_files.py - make coverage - make translate - - python3 ci/check_locale_files.py - make style after_success: