mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	i18n, better error handling
This commit is contained in:
		| @@ -25,6 +25,8 @@ from .signals import ( | ||||
|     document_consumption_started | ||||
| ) | ||||
|  | ||||
| from django.utils.translation import gettext as _ | ||||
|  | ||||
|  | ||||
| class ConsumerError(Exception): | ||||
|     pass | ||||
| @@ -32,10 +34,10 @@ class ConsumerError(Exception): | ||||
|  | ||||
| class Consumer(LoggingMixin): | ||||
|  | ||||
|     def _send_progress(self, filename, current_progress, max_progress, status, | ||||
|     def _send_progress(self, current_progress, max_progress, status, | ||||
|                        message, document_id=None): | ||||
|         payload = { | ||||
|             'filename': os.path.basename(filename), | ||||
|             'filename': os.path.basename(self.filename), | ||||
|             'task_id': self.task_id, | ||||
|             'current_progress': current_progress, | ||||
|             'max_progress': max_progress, | ||||
| @@ -47,10 +49,10 @@ class Consumer(LoggingMixin): | ||||
|                                                      {'type': 'status_update', | ||||
|                                                       'data': payload}) | ||||
|  | ||||
|     def _fail(self, message): | ||||
|         self._send_progress(self.filename, 100, 100, 'FAILED', | ||||
|                             message) | ||||
|         raise ConsumerError(f"{self.filename}: {message}") | ||||
|     def _fail(self, message, log_message=None): | ||||
|         self._send_progress(100, 100, 'FAILED', message) | ||||
|         self.log("error", log_message or message) | ||||
|         raise ConsumerError(f"{self.filename}: {log_message or message}") | ||||
|  | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
| @@ -66,11 +68,10 @@ class Consumer(LoggingMixin): | ||||
|  | ||||
|     def pre_check_file_exists(self): | ||||
|         if not os.path.isfile(self.path): | ||||
|             self.log( | ||||
|                 "error", | ||||
|                 "Cannot consume {}: It is not a file.".format(self.path) | ||||
|             self._fail( | ||||
|                 _("File not found"), | ||||
|                 f"Cannot consume {self.path}: It is not a file." | ||||
|             ) | ||||
|             self._fail("File not found") | ||||
|  | ||||
|     def pre_check_duplicate(self): | ||||
|         with open(self.path, "rb") as f: | ||||
| @@ -78,11 +79,10 @@ class Consumer(LoggingMixin): | ||||
|         if Document.objects.filter(Q(checksum=checksum) | Q(archive_checksum=checksum)).exists():  # NOQA: E501 | ||||
|             if settings.CONSUMER_DELETE_DUPLICATES: | ||||
|                 os.unlink(self.path) | ||||
|             self.log( | ||||
|                 "error", | ||||
|                 "Not consuming {}: It is a duplicate.".format(self.filename) | ||||
|             self._fail( | ||||
|                 _("Document is a duplicate"), | ||||
|                 f"Not consuming {self.filename}: It is a duplicate." | ||||
|             ) | ||||
|             self._fail("Document is a duplicate") | ||||
|  | ||||
|     def pre_check_directories(self): | ||||
|         os.makedirs(settings.SCRATCH_DIR, exist_ok=True) | ||||
| @@ -95,14 +95,16 @@ class Consumer(LoggingMixin): | ||||
|             return | ||||
|  | ||||
|         if not os.path.isfile(settings.PRE_CONSUME_SCRIPT): | ||||
|             raise ConsumerError( | ||||
|             self._fail( | ||||
|                 _("Pre-consume script does not exist."), | ||||
|                 f"Configured pre-consume script " | ||||
|                 f"{settings.PRE_CONSUME_SCRIPT} does not exist.") | ||||
|  | ||||
|         try: | ||||
|             Popen((settings.PRE_CONSUME_SCRIPT, self.path)).wait() | ||||
|         except Exception as e: | ||||
|             raise ConsumerError( | ||||
|             self._fail( | ||||
|                 _("Error while executing pre-consume script"), | ||||
|                 f"Error while executing pre-consume script: {e}" | ||||
|             ) | ||||
|  | ||||
| @@ -111,9 +113,11 @@ class Consumer(LoggingMixin): | ||||
|             return | ||||
|  | ||||
|         if not os.path.isfile(settings.POST_CONSUME_SCRIPT): | ||||
|             raise ConsumerError( | ||||
|             self._fail( | ||||
|                 _("Post-consume script does not exist."), | ||||
|                 f"Configured post-consume script " | ||||
|                 f"{settings.POST_CONSUME_SCRIPT} does not exist.") | ||||
|                 f"{settings.POST_CONSUME_SCRIPT} does not exist." | ||||
|             ) | ||||
|  | ||||
|         try: | ||||
|             Popen(( | ||||
| @@ -129,8 +133,9 @@ class Consumer(LoggingMixin): | ||||
|                     "name", flat=True))) | ||||
|             )).wait() | ||||
|         except Exception as e: | ||||
|             raise ConsumerError( | ||||
|                 f"Error while executing pre-consume script: {e}" | ||||
|             self._fail( | ||||
|                 _("Error while executing post-consume script"), | ||||
|                 f"Error while executing post-consume script: {e}" | ||||
|             ) | ||||
|  | ||||
|     def try_consume_file(self, | ||||
| @@ -153,8 +158,7 @@ class Consumer(LoggingMixin): | ||||
|         self.override_tag_ids = override_tag_ids | ||||
|         self.task_id = task_id or str(uuid.uuid4()) | ||||
|  | ||||
|         self._send_progress(self.filename, 0, 100, 'WORKING', | ||||
|                             'Received new file.') | ||||
|         self._send_progress(0, 100, 'WORKING', _('Received new file')) | ||||
|  | ||||
|         # this is for grouping logging entries for this particular file | ||||
|         # together. | ||||
| @@ -177,10 +181,13 @@ class Consumer(LoggingMixin): | ||||
|  | ||||
|         parser_class = get_parser_class_for_mime_type(mime_type) | ||||
|         if not parser_class: | ||||
|             self._fail(f"Unsupported mime type {mime_type}") | ||||
|             self._fail( | ||||
|                 _("File type %(type)s not supported") % | ||||
|                 {'type': mime_type}, | ||||
|                 f"Unsupported mime type {mime_type}" | ||||
|             ) | ||||
|         else: | ||||
|             self.log("debug", | ||||
|                      f"Parser: {parser_class.__name__}") | ||||
|             self.log("debug", f"Parser: {parser_class.__name__}") | ||||
|  | ||||
|         # Notify all listeners that we're going to do some work. | ||||
|  | ||||
| @@ -195,7 +202,7 @@ class Consumer(LoggingMixin): | ||||
|         def progress_callback(current_progress, max_progress, message): | ||||
|             # recalculate progress to be within 20 and 80 | ||||
|             p = int((current_progress / max_progress) * 50 + 20) | ||||
|             self._send_progress(self.filename, p, 100, "WORKING", message) | ||||
|             self._send_progress(p, 100, "WORKING", message) | ||||
|  | ||||
|         # This doesn't parse the document yet, but gives us a parser. | ||||
|  | ||||
| @@ -206,32 +213,36 @@ class Consumer(LoggingMixin): | ||||
|  | ||||
|         # Parse the document. This may take some time. | ||||
|  | ||||
|         text = None | ||||
|         date = None | ||||
|         thumbnail = None | ||||
|         archive_path = None | ||||
|  | ||||
|         try: | ||||
|             self._send_progress(self.filename, 20, 100, 'WORKING', | ||||
|                                 'Parsing document...') | ||||
|             self._send_progress(20, 100, 'WORKING', _('Parsing document...')) | ||||
|             self.log("debug", "Parsing {}...".format(self.filename)) | ||||
|             document_parser.parse(self.path, mime_type, self.filename) | ||||
|  | ||||
|             self.log("debug", f"Generating thumbnail for {self.filename}...") | ||||
|             self._send_progress(self.filename, 70, 100, 'WORKING', | ||||
|                                 'Generating thumbnail...') | ||||
|             self._send_progress(70, 100, 'WORKING', | ||||
|                                 _('Generating thumbnail...')) | ||||
|             thumbnail = document_parser.get_optimised_thumbnail( | ||||
|                 self.path, mime_type) | ||||
|  | ||||
|             text = document_parser.get_text() | ||||
|             date = document_parser.get_date() | ||||
|             if not date: | ||||
|                 self._send_progress(self.filename, 90, 100, 'WORKING', | ||||
|                                     'Getting date from document...') | ||||
|                 self._send_progress(90, 100, 'WORKING', | ||||
|                                     _('Getting date from document...')) | ||||
|                 date = parse_date(self.filename, text) | ||||
|             archive_path = document_parser.get_archive_path() | ||||
|  | ||||
|         except ParseError as e: | ||||
|             document_parser.cleanup() | ||||
|             self.log( | ||||
|                 "error", | ||||
|                 f"Error while consuming document {self.filename}: {e}") | ||||
|             self._fail(str(e)) | ||||
|             self._fail( | ||||
|                 str(e), | ||||
|                 f"Error while consuming document {self.filename}: {e}" | ||||
|             ) | ||||
|  | ||||
|         # Prepare the document classifier. | ||||
|  | ||||
| @@ -247,8 +258,7 @@ class Consumer(LoggingMixin): | ||||
|                 "warning", | ||||
|                 f"Cannot classify documents: {e}.") | ||||
|             classifier = None | ||||
|         self._send_progress(self.filename, 95, 100, 'WORKING', | ||||
|                             'Storing the document...') | ||||
|         self._send_progress(95, 100, 'WORKING', _('Saving document...')) | ||||
|         # now that everything is done, we can start to store the document | ||||
|         # in the system. This will be a transaction and reasonably fast. | ||||
|         try: | ||||
| @@ -302,12 +312,11 @@ class Consumer(LoggingMixin): | ||||
|                 os.unlink(self.path) | ||||
|  | ||||
|         except Exception as e: | ||||
|             self.log( | ||||
|                 "error", | ||||
|             self._fail( | ||||
|                 str(e), | ||||
|                 f"The following error occured while consuming " | ||||
|                 f"{self.filename}: {e}" | ||||
|             ) | ||||
|             self._fail(str(e)) | ||||
|         finally: | ||||
|             document_parser.cleanup() | ||||
|  | ||||
| @@ -318,8 +327,7 @@ class Consumer(LoggingMixin): | ||||
|             "Document {} consumption finished".format(document) | ||||
|         ) | ||||
|  | ||||
|         self._send_progress(self.filename, 100, 100, 'SUCCESS', | ||||
|                             'Finished.', document.id) | ||||
|         self._send_progress(100, 100, 'SUCCESS', _('Finished.'), document.id) | ||||
|  | ||||
|         return document | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,8 @@ from .models import Correspondent, Tag, Document, Log, DocumentType, \ | ||||
|     SavedView, SavedViewFilterRule | ||||
| from .parsers import is_mime_type_supported | ||||
|  | ||||
| from django.utils.translation import gettext as _ | ||||
|  | ||||
|  | ||||
| # https://www.django-rest-framework.org/api-guide/serializers/#example | ||||
| class DynamicFieldsModelSerializer(serializers.ModelSerializer): | ||||
| @@ -378,7 +380,9 @@ class PostDocumentSerializer(serializers.Serializer): | ||||
|  | ||||
|         if not is_mime_type_supported(mime_type): | ||||
|             raise serializers.ValidationError( | ||||
|                 "This file type is not supported.") | ||||
|                 _("File type %(type)s not supported") % | ||||
|                 {'type': mime_type} | ||||
|             ) | ||||
|  | ||||
|         return document.name, document_data | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: PACKAGE VERSION\n" | ||||
| "Report-Msgid-Bugs-To: \n" | ||||
| "POT-Creation-Date: 2021-01-10 21:41+0000\n" | ||||
| "POT-Creation-Date: 2021-01-26 14:59+0100\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" | ||||
| @@ -21,320 +21,374 @@ msgstr "" | ||||
| msgid "Documents" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:32 | ||||
| msgid "Any word" | ||||
| #: documents/consumer.py:72 | ||||
| msgid "File not found" | ||||
| msgstr "Datei nicht gefunden" | ||||
|  | ||||
| #: documents/consumer.py:83 | ||||
| msgid "Document is a duplicate" | ||||
| msgstr "Dokument existiert bereits" | ||||
|  | ||||
| #: documents/consumer.py:99 | ||||
| msgid "Pre-consume script does not exist." | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/consumer.py:107 | ||||
| msgid "Error while executing pre-consume script" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/consumer.py:117 | ||||
| msgid "Post-consume script does not exist." | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/consumer.py:137 | ||||
| msgid "Error while executing post-consume script" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/consumer.py:161 | ||||
| msgid "Received new file" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/consumer.py:185 documents/serialisers.py:383 | ||||
| #, fuzzy, python-format | ||||
| #| msgid "File type {type} not supported." | ||||
| msgid "File type %(type)s not supported" | ||||
| msgstr "Dateityp {type} wird nicht unterstützt" | ||||
|  | ||||
| #: documents/consumer.py:222 | ||||
| msgid "Parsing document..." | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/consumer.py:228 | ||||
| msgid "Generating thumbnail..." | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/consumer.py:236 | ||||
| msgid "Getting date from document..." | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/consumer.py:261 | ||||
| msgid "Saving document..." | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/consumer.py:330 | ||||
| msgid "Finished." | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:33 | ||||
| msgid "All words" | ||||
| msgid "Any word" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:34 | ||||
| msgid "Exact match" | ||||
| msgid "All words" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:35 | ||||
| msgid "Regular expression" | ||||
| msgid "Exact match" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:36 | ||||
| msgid "Fuzzy word" | ||||
| msgid "Regular expression" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:37 | ||||
| msgid "Fuzzy word" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:38 | ||||
| msgid "Automatic" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:41 documents/models.py:354 paperless_mail/models.py:25 | ||||
| #: documents/models.py:42 documents/models.py:352 paperless_mail/models.py:25 | ||||
| #: paperless_mail/models.py:109 | ||||
| msgid "name" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:45 | ||||
| #: documents/models.py:46 | ||||
| msgid "match" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:49 | ||||
| #: documents/models.py:50 | ||||
| msgid "matching algorithm" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:55 | ||||
| #: documents/models.py:56 | ||||
| msgid "is insensitive" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:80 documents/models.py:140 | ||||
| #: documents/models.py:75 documents/models.py:135 | ||||
| msgid "correspondent" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:81 | ||||
| #: documents/models.py:76 | ||||
| msgid "correspondents" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:103 | ||||
| #: documents/models.py:98 | ||||
| msgid "color" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:107 | ||||
| #: documents/models.py:102 | ||||
| msgid "is inbox tag" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:109 | ||||
| #: documents/models.py:104 | ||||
| msgid "" | ||||
| "Marks this tag as an inbox tag: All newly consumed documents will be tagged " | ||||
| "with inbox tags." | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:114 | ||||
| #: documents/models.py:109 | ||||
| msgid "tag" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:115 documents/models.py:171 | ||||
| #: documents/models.py:110 documents/models.py:166 | ||||
| msgid "tags" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:121 documents/models.py:153 | ||||
| #: documents/models.py:116 documents/models.py:148 | ||||
| msgid "document type" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:122 | ||||
| #: documents/models.py:117 | ||||
| msgid "document types" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:130 | ||||
| #: documents/models.py:125 | ||||
| msgid "Unencrypted" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:131 | ||||
| #: documents/models.py:126 | ||||
| msgid "Encrypted with GNU Privacy Guard" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:144 | ||||
| #: documents/models.py:139 | ||||
| msgid "title" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:157 | ||||
| #: documents/models.py:152 | ||||
| msgid "content" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:159 | ||||
| #: documents/models.py:154 | ||||
| msgid "" | ||||
| "The raw, text-only data of the document. This field is primarily used for " | ||||
| "searching." | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:164 | ||||
| #: documents/models.py:159 | ||||
| msgid "mime type" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:175 | ||||
| #: documents/models.py:170 | ||||
| msgid "checksum" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:179 | ||||
| #: documents/models.py:174 | ||||
| msgid "The checksum of the original document." | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:183 | ||||
| #: documents/models.py:178 | ||||
| msgid "archive checksum" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:188 | ||||
| #: documents/models.py:183 | ||||
| msgid "The checksum of the archived document." | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:192 documents/models.py:332 | ||||
| #: documents/models.py:187 documents/models.py:330 | ||||
| msgid "created" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:196 | ||||
| #: documents/models.py:191 | ||||
| msgid "modified" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:200 | ||||
| #: documents/models.py:195 | ||||
| msgid "storage type" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:208 | ||||
| #: documents/models.py:203 | ||||
| msgid "added" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:212 | ||||
| #: documents/models.py:207 | ||||
| msgid "filename" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:217 | ||||
| #: documents/models.py:212 | ||||
| msgid "Current filename in storage" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:221 | ||||
| #: documents/models.py:216 | ||||
| msgid "archive serial number" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:226 | ||||
| #: documents/models.py:221 | ||||
| msgid "The position of this document in your physical document archive." | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:232 | ||||
| #: documents/models.py:227 | ||||
| msgid "document" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:233 | ||||
| #: documents/models.py:228 | ||||
| msgid "documents" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:315 | ||||
| #: documents/models.py:313 | ||||
| msgid "debug" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:316 | ||||
| #: documents/models.py:314 | ||||
| msgid "information" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:317 | ||||
| #: documents/models.py:315 | ||||
| msgid "warning" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:318 | ||||
| #: documents/models.py:316 | ||||
| msgid "error" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:319 | ||||
| #: documents/models.py:317 | ||||
| msgid "critical" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:323 | ||||
| #: documents/models.py:321 | ||||
| msgid "group" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:326 | ||||
| #: documents/models.py:324 | ||||
| msgid "message" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:329 | ||||
| #: documents/models.py:327 | ||||
| msgid "level" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:336 | ||||
| #: documents/models.py:334 | ||||
| msgid "log" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:337 | ||||
| #: documents/models.py:335 | ||||
| msgid "logs" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:348 documents/models.py:398 | ||||
| #: documents/models.py:346 documents/models.py:396 | ||||
| msgid "saved view" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:349 | ||||
| #: documents/models.py:347 | ||||
| msgid "saved views" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:352 | ||||
| #: documents/models.py:350 | ||||
| msgid "user" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:358 | ||||
| #: documents/models.py:356 | ||||
| msgid "show on dashboard" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:361 | ||||
| #: documents/models.py:359 | ||||
| msgid "show in sidebar" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:365 | ||||
| #: documents/models.py:363 | ||||
| msgid "sort field" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:368 | ||||
| #: documents/models.py:366 | ||||
| msgid "sort reverse" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:374 | ||||
| #: documents/models.py:372 | ||||
| msgid "title contains" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:375 | ||||
| #: documents/models.py:373 | ||||
| msgid "content contains" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:376 | ||||
| #: documents/models.py:374 | ||||
| msgid "ASN is" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:377 | ||||
| #: documents/models.py:375 | ||||
| msgid "correspondent is" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:378 | ||||
| #: documents/models.py:376 | ||||
| msgid "document type is" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:379 | ||||
| #: documents/models.py:377 | ||||
| msgid "is in inbox" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:380 | ||||
| #: documents/models.py:378 | ||||
| msgid "has tag" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:381 | ||||
| #: documents/models.py:379 | ||||
| msgid "has any tag" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:382 | ||||
| #: documents/models.py:380 | ||||
| msgid "created before" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:383 | ||||
| #: documents/models.py:381 | ||||
| msgid "created after" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:384 | ||||
| #: documents/models.py:382 | ||||
| msgid "created year is" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:385 | ||||
| #: documents/models.py:383 | ||||
| msgid "created month is" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:386 | ||||
| #: documents/models.py:384 | ||||
| msgid "created day is" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:387 | ||||
| #: documents/models.py:385 | ||||
| msgid "added before" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:388 | ||||
| #: documents/models.py:386 | ||||
| msgid "added after" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:389 | ||||
| #: documents/models.py:387 | ||||
| msgid "modified before" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:390 | ||||
| #: documents/models.py:388 | ||||
| msgid "modified after" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:391 | ||||
| #: documents/models.py:389 | ||||
| msgid "does not have tag" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:402 | ||||
| #: documents/models.py:400 | ||||
| msgid "rule type" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:406 | ||||
| #: documents/models.py:404 | ||||
| msgid "value" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:412 | ||||
| #: documents/models.py:410 | ||||
| msgid "filter rule" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/models.py:413 | ||||
| #: documents/models.py:411 | ||||
| msgid "filter rules" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -378,23 +432,23 @@ msgstr "" | ||||
| msgid "Sign in" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:268 | ||||
| #: paperless/settings.py:286 | ||||
| msgid "English" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:269 | ||||
| #: paperless/settings.py:287 | ||||
| msgid "German" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:270 | ||||
| #: paperless/settings.py:288 | ||||
| msgid "Dutch" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:271 | ||||
| #: paperless/settings.py:289 | ||||
| msgid "French" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/urls.py:108 | ||||
| #: paperless/urls.py:114 | ||||
| msgid "Paperless-ng administration" | ||||
| msgstr "" | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 jonaswinkler
					jonaswinkler