Merge branch 'dev' into feature/superuser-manager

This commit is contained in:
jonaswinkler
2021-04-17 14:01:42 +02:00
109 changed files with 7029 additions and 3698 deletions

View File

@@ -64,9 +64,9 @@ class Consumer(LoggingMixin):
{'type': 'status_update',
'data': payload})
def _fail(self, message, log_message=None):
def _fail(self, message, log_message=None, exc_info=None):
self._send_progress(100, 100, 'FAILED', message)
self.log("error", log_message or message)
self.log("error", log_message or message, exc_info=exc_info)
raise ConsumerError(f"{self.filename}: {log_message or message}")
def __init__(self):
@@ -115,12 +115,16 @@ class Consumer(LoggingMixin):
f"Configured pre-consume script "
f"{settings.PRE_CONSUME_SCRIPT} does not exist.")
self.log("info",
f"Executing pre-consume script {settings.PRE_CONSUME_SCRIPT}")
try:
Popen((settings.PRE_CONSUME_SCRIPT, self.path)).wait()
except Exception as e:
self._fail(
MESSAGE_PRE_CONSUME_SCRIPT_ERROR,
f"Error while executing pre-consume script: {e}"
f"Error while executing pre-consume script: {e}",
exc_info=True
)
def run_post_consume_script(self, document):
@@ -134,6 +138,11 @@ class Consumer(LoggingMixin):
f"{settings.POST_CONSUME_SCRIPT} does not exist."
)
self.log(
"info",
f"Executing post-consume script {settings.POST_CONSUME_SCRIPT}"
)
try:
Popen((
settings.POST_CONSUME_SCRIPT,
@@ -150,7 +159,8 @@ class Consumer(LoggingMixin):
except Exception as e:
self._fail(
MESSAGE_POST_CONSUME_SCRIPT_ERROR,
f"Error while executing post-consume script: {e}"
f"Error while executing post-consume script: {e}",
exc_info=True
)
def try_consume_file(self,
@@ -255,7 +265,8 @@ class Consumer(LoggingMixin):
document_parser.cleanup()
self._fail(
str(e),
f"Error while consuming document {self.filename}: {e}"
f"Error while consuming document {self.filename}: {e}",
exc_info=True
)
# Prepare the document classifier.
@@ -326,7 +337,8 @@ class Consumer(LoggingMixin):
self._fail(
str(e),
f"The following error occured while consuming "
f"{self.filename}: {e}"
f"{self.filename}: {e}",
exc_info=True
)
finally:
document_parser.cleanup()

View File

@@ -2,75 +2,70 @@ import logging
import os
from contextlib import contextmanager
import math
from dateutil.parser import isoparse
from django.conf import settings
from whoosh import highlight, classify, query
from whoosh.fields import Schema, TEXT, NUMERIC, KEYWORD, DATETIME
from whoosh.highlight import Formatter, get_text
from whoosh.fields import Schema, TEXT, NUMERIC, KEYWORD, DATETIME, BOOLEAN
from whoosh.highlight import Formatter, get_text, HtmlFormatter
from whoosh.index import create_in, exists_in, open_dir
from whoosh.qparser import MultifieldParser
from whoosh.qparser.dateparse import DateParserPlugin
from whoosh.searching import ResultsPage, Searcher
from whoosh.writing import AsyncWriter
from documents.models import Document
logger = logging.getLogger("paperless.index")
class JsonFormatter(Formatter):
def __init__(self):
self.seen = {}
def format_token(self, text, token, replace=False):
ttext = self._text(get_text(text, token, replace))
return {'text': ttext, 'highlight': 'true'}
def format_fragment(self, fragment, replace=False):
output = []
index = fragment.startchar
text = fragment.text
amend_token = None
for t in fragment.matches:
if t.startchar is None:
continue
if t.startchar < index:
continue
if t.startchar > index:
text_inbetween = text[index:t.startchar]
if amend_token and t.startchar - index < 10:
amend_token['text'] += text_inbetween
else:
output.append({'text': text_inbetween,
'highlight': False})
amend_token = None
token = self.format_token(text, t, replace)
if amend_token:
amend_token['text'] += token['text']
else:
output.append(token)
amend_token = token
index = t.endchar
if index < fragment.endchar:
output.append({'text': text[index:fragment.endchar],
'highlight': False})
return output
def format(self, fragments, replace=False):
output = []
for fragment in fragments:
output.append(self.format_fragment(fragment, replace=replace))
return output
def get_schema():
return Schema(
id=NUMERIC(stored=True, unique=True, numtype=int),
title=TEXT(stored=True),
id=NUMERIC(
stored=True,
unique=True
),
title=TEXT(
sortable=True
),
content=TEXT(),
correspondent=TEXT(stored=True),
tag=KEYWORD(stored=True, commas=True, scorable=True, lowercase=True),
type=TEXT(stored=True),
created=DATETIME(stored=True, sortable=True),
modified=DATETIME(stored=True, sortable=True),
added=DATETIME(stored=True, sortable=True),
asn=NUMERIC(
sortable=True
),
correspondent=TEXT(
sortable=True
),
correspondent_id=NUMERIC(),
has_correspondent=BOOLEAN(),
tag=KEYWORD(
commas=True,
scorable=True,
lowercase=True
),
tag_id=KEYWORD(
commas=True,
scorable=True
),
has_tag=BOOLEAN(),
type=TEXT(
sortable=True
),
type_id=NUMERIC(),
has_type=BOOLEAN(),
created=DATETIME(
sortable=True
),
modified=DATETIME(
sortable=True
),
added=DATETIME(
sortable=True
),
)
@@ -87,11 +82,8 @@ def open_index(recreate=False):
@contextmanager
def open_index_writer(ix=None, optimize=False):
if ix:
writer = AsyncWriter(ix)
else:
writer = AsyncWriter(open_index())
def open_index_writer(optimize=False):
writer = AsyncWriter(open_index())
try:
yield writer
@@ -102,17 +94,35 @@ def open_index_writer(ix=None, optimize=False):
writer.commit(optimize=optimize)
@contextmanager
def open_index_searcher():
searcher = open_index().searcher()
try:
yield searcher
finally:
searcher.close()
def update_document(writer, doc):
tags = ",".join([t.name for t in doc.tags.all()])
tags_ids = ",".join([str(t.id) for t in doc.tags.all()])
writer.update_document(
id=doc.pk,
title=doc.title,
content=doc.content,
correspondent=doc.correspondent.name if doc.correspondent else None,
correspondent_id=doc.correspondent.id if doc.correspondent else None,
has_correspondent=doc.correspondent is not None,
tag=tags if tags else None,
tag_id=tags_ids if tags_ids else None,
has_tag=len(tags) > 0,
type=doc.document_type.name if doc.document_type else None,
type_id=doc.document_type.id if doc.document_type else None,
has_type=doc.document_type is not None,
created=doc.created,
added=doc.added,
asn=doc.archive_serial_number,
modified=doc.modified,
)
@@ -135,50 +145,137 @@ def remove_document_from_index(document):
remove_document(writer, document)
@contextmanager
def query_page(ix, page, querystring, more_like_doc_id, more_like_doc_content):
searcher = ix.searcher()
try:
if querystring:
qp = MultifieldParser(
["content", "title", "correspondent", "tag", "type"],
ix.schema)
qp.add_plugin(DateParserPlugin())
str_q = qp.parse(querystring)
corrected = searcher.correct_query(str_q, querystring)
else:
str_q = None
corrected = None
class DelayedQuery:
if more_like_doc_id:
docnum = searcher.document_number(id=more_like_doc_id)
kts = searcher.key_terms_from_text(
'content', more_like_doc_content, numterms=20,
model=classify.Bo1Model, normalize=False)
more_like_q = query.Or(
[query.Term('content', word, boost=weight)
for word, weight in kts])
result_page = searcher.search_page(
more_like_q, page, filter=str_q, mask={docnum})
elif str_q:
result_page = searcher.search_page(str_q, page)
else:
raise ValueError(
"Either querystring or more_like_doc_id is required."
)
@property
def _query(self):
raise NotImplementedError()
result_page.results.fragmenter = highlight.ContextFragmenter(
@property
def _query_filter(self):
criterias = []
for k, v in self.query_params.items():
if k == 'correspondent__id':
criterias.append(query.Term('correspondent_id', v))
elif k == 'tags__id__all':
for tag_id in v.split(","):
criterias.append(query.Term('tag_id', tag_id))
elif k == 'document_type__id':
criterias.append(query.Term('type_id', v))
elif k == 'correspondent__isnull':
criterias.append(query.Term("has_correspondent", v == "false"))
elif k == 'is_tagged':
criterias.append(query.Term("has_tag", v == "true"))
elif k == 'document_type__isnull':
criterias.append(query.Term("has_type", v == "false"))
elif k == 'created__date__lt':
criterias.append(
query.DateRange("created", start=None, end=isoparse(v)))
elif k == 'created__date__gt':
criterias.append(
query.DateRange("created", start=isoparse(v), end=None))
elif k == 'added__date__gt':
criterias.append(
query.DateRange("added", start=isoparse(v), end=None))
elif k == 'added__date__lt':
criterias.append(
query.DateRange("added", start=None, end=isoparse(v)))
if len(criterias) > 0:
return query.And(criterias)
else:
return None
@property
def _query_sortedby(self):
# if not 'ordering' in self.query_params:
return None, False
# o: str = self.query_params['ordering']
# if o.startswith('-'):
# return o[1:], True
# else:
# return o, False
def __init__(self, searcher: Searcher, query_params, page_size):
self.searcher = searcher
self.query_params = query_params
self.page_size = page_size
self.saved_results = dict()
self.first_score = None
def __len__(self):
page = self[0:1]
return len(page)
def __getitem__(self, item):
if item.start in self.saved_results:
return self.saved_results[item.start]
q, mask = self._query
sortedby, reverse = self._query_sortedby
page: ResultsPage = self.searcher.search_page(
q,
mask=mask,
filter=self._query_filter,
pagenum=math.floor(item.start / self.page_size) + 1,
pagelen=self.page_size,
sortedby=sortedby,
reverse=reverse
)
page.results.fragmenter = highlight.ContextFragmenter(
surround=50)
result_page.results.formatter = JsonFormatter()
page.results.formatter = HtmlFormatter(tagname="span", between=" ... ")
if corrected and corrected.query != str_q:
if not self.first_score and len(page.results) > 0:
self.first_score = page.results[0].score
if self.first_score:
page.results.top_n = list(map(
lambda hit: (hit[0] / self.first_score, hit[1]),
page.results.top_n
))
self.saved_results[item.start] = page
return page
class DelayedFullTextQuery(DelayedQuery):
@property
def _query(self):
q_str = self.query_params['query']
qp = MultifieldParser(
["content", "title", "correspondent", "tag", "type"],
self.searcher.ixreader.schema)
qp.add_plugin(DateParserPlugin())
q = qp.parse(q_str)
corrected = self.searcher.correct_query(q, q_str)
if corrected.query != q:
corrected_query = corrected.string
else:
corrected_query = None
yield result_page, corrected_query
finally:
searcher.close()
return q, None
class DelayedMoreLikeThisQuery(DelayedQuery):
@property
def _query(self):
more_like_doc_id = int(self.query_params['more_like_id'])
content = Document.objects.get(id=more_like_doc_id).content
docnum = self.searcher.document_number(id=more_like_doc_id)
kts = self.searcher.key_terms_from_text(
'content', content, numterms=20,
model=classify.Bo1Model, normalize=False)
q = query.Or(
[query.Term('content', word, boost=weight)
for word, weight in kts])
mask = {docnum}
return q, mask
def autocomplete(ix, term, limit=10):

View File

@@ -6,15 +6,18 @@ import time
import tqdm
from django.conf import settings
from django.contrib.auth.models import User
from django.core import serializers
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from filelock import FileLock
from documents.models import Document, Correspondent, Tag, DocumentType
from documents.models import Document, Correspondent, Tag, DocumentType, \
SavedView, SavedViewFilterRule
from documents.settings import EXPORTER_FILE_NAME, EXPORTER_THUMBNAIL_NAME, \
EXPORTER_ARCHIVE_NAME
from paperless.db import GnuPG
from paperless_mail.models import MailAccount, MailRule
from ...file_handling import generate_filename, delete_empty_directories
@@ -105,6 +108,21 @@ class Command(BaseCommand):
serializers.serialize("json", documents))
manifest += document_manifest
manifest += json.loads(serializers.serialize(
"json", MailAccount.objects.all()))
manifest += json.loads(serializers.serialize(
"json", MailRule.objects.all()))
manifest += json.loads(serializers.serialize(
"json", SavedView.objects.all()))
manifest += json.loads(serializers.serialize(
"json", SavedViewFilterRule.objects.all()))
manifest += json.loads(serializers.serialize(
"json", User.objects.all()))
# 3. Export files from each document
for index, document_dict in tqdm.tqdm(enumerate(document_manifest),
total=len(document_manifest)):

View File

@@ -1,5 +1,6 @@
import logging
import tqdm
from django.core.management.base import BaseCommand
from documents.classifier import load_classifier
@@ -67,9 +68,7 @@ class Command(BaseCommand):
classifier = load_classifier()
for document in documents:
logger.info(
f"Processing document {document.title}")
for document in tqdm.tqdm(documents):
if options['correspondent']:
set_correspondent(

View File

@@ -90,7 +90,7 @@ def matches(matching_model, document):
elif matching_model.matching_algorithm == MatchingModel.MATCH_LITERAL:
result = bool(re.search(
rf"\b{matching_model.match}\b",
rf"\b{re.escape(matching_model.match)}\b",
document_content,
**search_kwargs
))
@@ -161,6 +161,9 @@ def _split_match(matching_model):
findterms = re.compile(r'"([^"]+)"|(\S+)').findall
normspace = re.compile(r"\s+").sub
return [
normspace(" ", (t[0] or t[1]).strip()).replace(" ", r"\s+")
# normspace(" ", (t[0] or t[1]).strip()).replace(" ", r"\s+")
re.escape(
normspace(" ", (t[0] or t[1]).strip())
).replace(r"\ ", r"\s+")
for t in findterms(matching_model.match)
]

View File

@@ -0,0 +1,29 @@
# Generated by Django 3.1.7 on 2021-04-04 18:28
import logging
from django.db import migrations
logger = logging.getLogger("paperless.migrations")
def remove_null_characters(apps, schema_editor):
Document = apps.get_model('documents', 'Document')
for doc in Document.objects.all():
content: str = doc.content
if '\0' in content:
logger.info(f"Removing null characters from document {doc}...")
doc.content = content.replace('\0', ' ')
doc.save()
class Migration(migrations.Migration):
dependencies = [
('documents', '1014_auto_20210228_1614'),
]
operations = [
migrations.RunPython(remove_null_characters, migrations.RunPython.noop)
]

View File

@@ -0,0 +1,23 @@
# Generated by Django 3.1.7 on 2021-03-17 12:51
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('documents', '1015_remove_null_characters'),
]
operations = [
migrations.AlterField(
model_name='savedview',
name='sort_field',
field=models.CharField(blank=True, max_length=128, null=True, verbose_name='sort field'),
),
migrations.AlterField(
model_name='savedviewfilterrule',
name='rule_type',
field=models.PositiveIntegerField(choices=[(0, 'title contains'), (1, 'content contains'), (2, 'ASN is'), (3, 'correspondent is'), (4, 'document type is'), (5, 'is in inbox'), (6, 'has tag'), (7, 'has any tag'), (8, 'created before'), (9, 'created after'), (10, 'created year is'), (11, 'created month is'), (12, 'created day is'), (13, 'added before'), (14, 'added after'), (15, 'modified before'), (16, 'modified after'), (17, 'does not have tag'), (18, 'does not have ASN'), (19, 'title or content contains'), (20, 'fulltext query'), (21, 'more like this')], verbose_name='rule type'),
),
]

View File

@@ -359,7 +359,10 @@ class SavedView(models.Model):
sort_field = models.CharField(
_("sort field"),
max_length=128)
max_length=128,
null=True,
blank=True
)
sort_reverse = models.BooleanField(
_("sort reverse"),
default=False)
@@ -387,6 +390,8 @@ class SavedViewFilterRule(models.Model):
(17, _("does not have tag")),
(18, _("does not have ASN")),
(19, _("title or content contains")),
(20, _("fulltext query")),
(21, _("more like this"))
]
saved_view = models.ForeignKey(

View File

@@ -46,13 +46,13 @@ def set_correspondent(sender,
selected = None
if potential_count > 1:
if use_first:
logger.info(
logger.debug(
f"Detected {potential_count} potential correspondents, "
f"so we've opted for {selected}",
extra={'group': logging_group}
)
else:
logger.info(
logger.debug(
f"Detected {potential_count} potential correspondents, "
f"not assigning any correspondent",
extra={'group': logging_group}

View File

@@ -27,7 +27,7 @@ class TestDocumentAdmin(DirectoriesMixin, TestCase):
doc.title = "new title"
self.doc_admin.save_model(None, doc, None, None)
self.assertEqual(Document.objects.get(id=doc.id).title, "new title")
self.assertEqual(self.get_document_from_index(doc)['title'], "new title")
self.assertEqual(self.get_document_from_index(doc)['id'], doc.id)
def test_delete_model(self):
doc = Document.objects.create(title="test")

View File

@@ -7,6 +7,7 @@ import tempfile
import zipfile
from unittest import mock
import pytest
from django.conf import settings
from django.contrib.auth.models import User
from django.test import override_settings
@@ -294,12 +295,6 @@ class TestDocumentApi(DirectoriesMixin, APITestCase):
results = response.data['results']
self.assertEqual(len(results), 0)
def test_search_no_query(self):
response = self.client.get("/api/search/")
results = response.data['results']
self.assertEqual(len(results), 0)
def test_search(self):
d1=Document.objects.create(title="invoice", content="the thing i bought at a shop and paid with bank account", checksum="A", pk=1)
d2=Document.objects.create(title="bank statement 1", content="things i paid for in august", pk=2, checksum="B")
@@ -311,32 +306,24 @@ class TestDocumentApi(DirectoriesMixin, APITestCase):
index.update_document(writer, d1)
index.update_document(writer, d2)
index.update_document(writer, d3)
response = self.client.get("/api/search/?query=bank")
response = self.client.get("/api/documents/?query=bank")
results = response.data['results']
self.assertEqual(response.data['count'], 3)
self.assertEqual(response.data['page'], 1)
self.assertEqual(response.data['page_count'], 1)
self.assertEqual(len(results), 3)
response = self.client.get("/api/search/?query=september")
response = self.client.get("/api/documents/?query=september")
results = response.data['results']
self.assertEqual(response.data['count'], 1)
self.assertEqual(response.data['page'], 1)
self.assertEqual(response.data['page_count'], 1)
self.assertEqual(len(results), 1)
response = self.client.get("/api/search/?query=statement")
response = self.client.get("/api/documents/?query=statement")
results = response.data['results']
self.assertEqual(response.data['count'], 2)
self.assertEqual(response.data['page'], 1)
self.assertEqual(response.data['page_count'], 1)
self.assertEqual(len(results), 2)
response = self.client.get("/api/search/?query=sfegdfg")
response = self.client.get("/api/documents/?query=sfegdfg")
results = response.data['results']
self.assertEqual(response.data['count'], 0)
self.assertEqual(response.data['page'], 0)
self.assertEqual(response.data['page_count'], 0)
self.assertEqual(len(results), 0)
def test_search_multi_page(self):
@@ -349,53 +336,34 @@ class TestDocumentApi(DirectoriesMixin, APITestCase):
seen_ids = []
for i in range(1, 6):
response = self.client.get(f"/api/search/?query=content&page={i}")
response = self.client.get(f"/api/documents/?query=content&page={i}&page_size=10")
results = response.data['results']
self.assertEqual(response.data['count'], 55)
self.assertEqual(response.data['page'], i)
self.assertEqual(response.data['page_count'], 6)
self.assertEqual(len(results), 10)
for result in results:
self.assertNotIn(result['id'], seen_ids)
seen_ids.append(result['id'])
response = self.client.get(f"/api/search/?query=content&page=6")
response = self.client.get(f"/api/documents/?query=content&page=6&page_size=10")
results = response.data['results']
self.assertEqual(response.data['count'], 55)
self.assertEqual(response.data['page'], 6)
self.assertEqual(response.data['page_count'], 6)
self.assertEqual(len(results), 5)
for result in results:
self.assertNotIn(result['id'], seen_ids)
seen_ids.append(result['id'])
response = self.client.get(f"/api/search/?query=content&page=7")
results = response.data['results']
self.assertEqual(response.data['count'], 55)
self.assertEqual(response.data['page'], 6)
self.assertEqual(response.data['page_count'], 6)
self.assertEqual(len(results), 5)
def test_search_invalid_page(self):
with AsyncWriter(index.open_index()) as writer:
for i in range(15):
doc = Document.objects.create(checksum=str(i), pk=i+1, title=f"Document {i+1}", content="content")
index.update_document(writer, doc)
first_page = self.client.get(f"/api/search/?query=content&page=1").data
second_page = self.client.get(f"/api/search/?query=content&page=2").data
should_be_first_page_1 = self.client.get(f"/api/search/?query=content&page=0").data
should_be_first_page_2 = self.client.get(f"/api/search/?query=content&page=dgfd").data
should_be_first_page_3 = self.client.get(f"/api/search/?query=content&page=").data
should_be_first_page_4 = self.client.get(f"/api/search/?query=content&page=-7868").data
self.assertDictEqual(first_page, should_be_first_page_1)
self.assertDictEqual(first_page, should_be_first_page_2)
self.assertDictEqual(first_page, should_be_first_page_3)
self.assertDictEqual(first_page, should_be_first_page_4)
self.assertNotEqual(len(first_page['results']), len(second_page['results']))
response = self.client.get(f"/api/documents/?query=content&page=0&page_size=10")
self.assertEqual(response.status_code, 404)
response = self.client.get(f"/api/documents/?query=content&page=3&page_size=10")
self.assertEqual(response.status_code, 404)
@mock.patch("documents.index.autocomplete")
def test_search_autocomplete(self, m):
@@ -419,6 +387,7 @@ class TestDocumentApi(DirectoriesMixin, APITestCase):
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data), 10)
@pytest.mark.skip(reason="Not implemented yet")
def test_search_spelling_correction(self):
with AsyncWriter(index.open_index()) as writer:
for i in range(55):
@@ -444,7 +413,7 @@ class TestDocumentApi(DirectoriesMixin, APITestCase):
index.update_document(writer, d2)
index.update_document(writer, d3)
response = self.client.get(f"/api/search/?more_like={d2.id}")
response = self.client.get(f"/api/documents/?more_like_id={d2.id}")
self.assertEqual(response.status_code, 200)
@@ -454,6 +423,54 @@ class TestDocumentApi(DirectoriesMixin, APITestCase):
self.assertEqual(results[0]['id'], d3.id)
self.assertEqual(results[1]['id'], d1.id)
def test_search_filtering(self):
t = Tag.objects.create(name="tag")
t2 = Tag.objects.create(name="tag2")
c = Correspondent.objects.create(name="correspondent")
dt = DocumentType.objects.create(name="type")
d1 = Document.objects.create(checksum="1", correspondent=c, content="test")
d2 = Document.objects.create(checksum="2", document_type=dt, content="test")
d3 = Document.objects.create(checksum="3", content="test")
d3.tags.add(t)
d3.tags.add(t2)
d4 = Document.objects.create(checksum="4", created=datetime.datetime(2020, 7, 13), content="test")
d4.tags.add(t2)
d5 = Document.objects.create(checksum="5", added=datetime.datetime(2020, 7, 13), content="test")
d6 = Document.objects.create(checksum="6", content="test2")
with AsyncWriter(index.open_index()) as writer:
for doc in Document.objects.all():
index.update_document(writer, doc)
def search_query(q):
r = self.client.get("/api/documents/?query=test" + q)
self.assertEqual(r.status_code, 200)
return [hit['id'] for hit in r.data['results']]
self.assertCountEqual(search_query(""), [d1.id, d2.id, d3.id, d4.id, d5.id])
self.assertCountEqual(search_query("&is_tagged=true"), [d3.id, d4.id])
self.assertCountEqual(search_query("&is_tagged=false"), [d1.id, d2.id, d5.id])
self.assertCountEqual(search_query("&correspondent__id=" + str(c.id)), [d1.id])
self.assertCountEqual(search_query("&document_type__id=" + str(dt.id)), [d2.id])
self.assertCountEqual(search_query("&correspondent__isnull"), [d2.id, d3.id, d4.id, d5.id])
self.assertCountEqual(search_query("&document_type__isnull"), [d1.id, d3.id, d4.id, d5.id])
self.assertCountEqual(search_query("&tags__id__all=" + str(t.id) + "," + str(t2.id)), [d3.id])
self.assertCountEqual(search_query("&tags__id__all=" + str(t.id)), [d3.id])
self.assertCountEqual(search_query("&tags__id__all=" + str(t2.id)), [d3.id, d4.id])
self.assertIn(d4.id, search_query("&created__date__lt=" + datetime.datetime(2020, 9, 2).strftime("%Y-%m-%d")))
self.assertNotIn(d4.id, search_query("&created__date__gt=" + datetime.datetime(2020, 9, 2).strftime("%Y-%m-%d")))
self.assertNotIn(d4.id, search_query("&created__date__lt=" + datetime.datetime(2020, 1, 2).strftime("%Y-%m-%d")))
self.assertIn(d4.id, search_query("&created__date__gt=" + datetime.datetime(2020, 1, 2).strftime("%Y-%m-%d")))
self.assertIn(d5.id, search_query("&added__date__lt=" + datetime.datetime(2020, 9, 2).strftime("%Y-%m-%d")))
self.assertNotIn(d5.id, search_query("&added__date__gt=" + datetime.datetime(2020, 9, 2).strftime("%Y-%m-%d")))
self.assertNotIn(d5.id, search_query("&added__date__lt=" + datetime.datetime(2020, 1, 2).strftime("%Y-%m-%d")))
self.assertIn(d5.id, search_query("&added__date__gt=" + datetime.datetime(2020, 1, 2).strftime("%Y-%m-%d")))
def test_statistics(self):
doc1 = Document.objects.create(title="none1", checksum="A")
@@ -1375,8 +1392,7 @@ class TestApiAuth(APITestCase):
self.assertEqual(self.client.get("/api/logs/").status_code, 401)
self.assertEqual(self.client.get("/api/saved_views/").status_code, 401)
self.assertEqual(self.client.get("/api/search/").status_code, 401)
self.assertEqual(self.client.get("/api/search/auto_complete/").status_code, 401)
self.assertEqual(self.client.get("/api/search/autocomplete/").status_code, 401)
self.assertEqual(self.client.get("/api/documents/bulk_edit/").status_code, 401)
self.assertEqual(self.client.get("/api/documents/bulk_download/").status_code, 401)
self.assertEqual(self.client.get("/api/documents/selection_data/").status_code, 401)

View File

@@ -1,20 +1,10 @@
from django.test import TestCase
from documents import index
from documents.index import JsonFormatter
from documents.models import Document
from documents.tests.utils import DirectoriesMixin
class JsonFormatterTest(TestCase):
def setUp(self) -> None:
self.formatter = JsonFormatter()
def test_empty_fragments(self):
self.assertListEqual(self.formatter.format([]), [])
class TestAutoComplete(DirectoriesMixin, TestCase):
def test_auto_complete(self):

View File

@@ -69,7 +69,7 @@ class TestExportImport(DirectoriesMixin, TestCase):
manifest = self._do_export(use_filename_format=use_filename_format)
self.assertEqual(len(manifest), 7)
self.assertEqual(len(manifest), 8)
self.assertEqual(len(list(filter(lambda e: e['model'] == 'documents.document', manifest))), 4)
self.assertTrue(os.path.exists(os.path.join(self.target, "manifest.json")))

View File

@@ -0,0 +1,15 @@
from documents.tests.utils import DirectoriesMixin, TestMigrations
class TestMigrateNullCharacters(DirectoriesMixin, TestMigrations):
migrate_from = '1014_auto_20210228_1614'
migrate_to = '1015_remove_null_characters'
def setUpBeforeMigration(self, apps):
Document = apps.get_model("documents", "Document")
self.doc = Document.objects.create(content="aaa\0bbb")
def testMimeTypesMigrated(self):
Document = self.apps.get_model('documents', 'Document')
self.assertNotIn("\0", Document.objects.get(id=self.doc.id).content)

View File

@@ -17,7 +17,9 @@ from django_filters.rest_framework import DjangoFilterBackend
from django_q.tasks import async_task
from rest_framework import parsers
from rest_framework.decorators import action
from rest_framework.exceptions import NotFound
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import (
DestroyModelMixin,
ListModelMixin,
@@ -326,6 +328,70 @@ class DocumentViewSet(RetrieveModelMixin,
raise Http404()
class SearchResultSerializer(DocumentSerializer):
def to_representation(self, instance):
doc = Document.objects.get(id=instance['id'])
r = super(SearchResultSerializer, self).to_representation(doc)
r['__search_hit__'] = {
"score": instance.score,
"highlights": instance.highlights("content",
text=doc.content) if doc else None, # NOQA: E501
"rank": instance.rank
}
return r
class UnifiedSearchViewSet(DocumentViewSet):
def __init__(self, *args, **kwargs):
super(UnifiedSearchViewSet, self).__init__(*args, **kwargs)
self.searcher = None
def get_serializer_class(self):
if self._is_search_request():
return SearchResultSerializer
else:
return DocumentSerializer
def _is_search_request(self):
return ("query" in self.request.query_params or
"more_like_id" in self.request.query_params)
def filter_queryset(self, queryset):
if self._is_search_request():
from documents import index
if "query" in self.request.query_params:
query_class = index.DelayedFullTextQuery
elif "more_like_id" in self.request.query_params:
query_class = index.DelayedMoreLikeThisQuery
else:
raise ValueError()
return query_class(
self.searcher,
self.request.query_params,
self.paginator.get_page_size(self.request))
else:
return super(UnifiedSearchViewSet, self).filter_queryset(queryset)
def list(self, request, *args, **kwargs):
if self._is_search_request():
from documents import index
try:
with index.open_index_searcher() as s:
self.searcher = s
return super(UnifiedSearchViewSet, self).list(request)
except NotFound:
raise
except Exception as e:
return HttpResponseBadRequest(str(e))
else:
return super(UnifiedSearchViewSet, self).list(request)
class LogViewSet(ViewSet):
permission_classes = (IsAuthenticated,)
@@ -366,23 +432,12 @@ class SavedViewViewSet(ModelViewSet):
serializer.save(user=self.request.user)
class BulkEditView(APIView):
class BulkEditView(GenericAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = BulkEditSerializer
parser_classes = (parsers.JSONParser,)
def get_serializer_context(self):
return {
'request': self.request,
'format': self.format_kwarg,
'view': self
}
def get_serializer(self, *args, **kwargs):
kwargs['context'] = self.get_serializer_context()
return self.serializer_class(*args, **kwargs)
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
@@ -399,23 +454,12 @@ class BulkEditView(APIView):
return HttpResponseBadRequest(str(e))
class PostDocumentView(APIView):
class PostDocumentView(GenericAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = PostDocumentSerializer
parser_classes = (parsers.MultiPartParser,)
def get_serializer_context(self):
return {
'request': self.request,
'format': self.format_kwarg,
'view': self
}
def get_serializer(self, *args, **kwargs):
kwargs['context'] = self.get_serializer_context()
return self.serializer_class(*args, **kwargs)
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
@@ -453,23 +497,12 @@ class PostDocumentView(APIView):
return Response("OK")
class SelectionDataView(APIView):
class SelectionDataView(GenericAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = DocumentListSerializer
parser_classes = (parsers.MultiPartParser, parsers.JSONParser)
def get_serializer_context(self):
return {
'request': self.request,
'format': self.format_kwarg,
'view': self
}
def get_serializer(self, *args, **kwargs):
kwargs['context'] = self.get_serializer_context()
return self.serializer_class(*args, **kwargs)
def post(self, request, format=None):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
@@ -510,74 +543,6 @@ class SelectionDataView(APIView):
return r
class SearchView(APIView):
permission_classes = (IsAuthenticated,)
def add_infos_to_hit(self, r):
try:
doc = Document.objects.get(id=r['id'])
except Document.DoesNotExist:
logger.warning(
f"Search index returned a non-existing document: "
f"id: {r['id']}, title: {r['title']}. "
f"Search index needs reindex."
)
doc = None
return {'id': r['id'],
'highlights': r.highlights("content", text=doc.content) if doc else None, # NOQA: E501
'score': r.score,
'rank': r.rank,
'document': DocumentSerializer(doc).data if doc else None,
'title': r['title']
}
def get(self, request, format=None):
from documents import index
if 'query' in request.query_params:
query = request.query_params['query']
else:
query = None
if 'more_like' in request.query_params:
more_like_id = request.query_params['more_like']
more_like_content = Document.objects.get(id=more_like_id).content
else:
more_like_id = None
more_like_content = None
if not query and not more_like_id:
return Response({
'count': 0,
'page': 0,
'page_count': 0,
'corrected_query': None,
'results': []})
try:
page = int(request.query_params.get('page', 1))
except (ValueError, TypeError):
page = 1
if page < 1:
page = 1
ix = index.open_index()
try:
with index.query_page(ix, page, query, more_like_id, more_like_content) as (result_page, corrected_query): # NOQA: E501
return Response(
{'count': len(result_page),
'page': result_page.pagenum,
'page_count': result_page.pagecount,
'corrected_query': corrected_query,
'results': list(map(self.add_infos_to_hit, result_page))})
except Exception as e:
return HttpResponseBadRequest(str(e))
class SearchAutoCompleteView(APIView):
permission_classes = (IsAuthenticated,)
@@ -620,23 +585,12 @@ class StatisticsView(APIView):
})
class BulkDownloadView(APIView):
class BulkDownloadView(GenericAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = BulkDownloadSerializer
parser_classes = (parsers.JSONParser,)
def get_serializer_context(self):
return {
'request': self.request,
'format': self.format_kwarg,
'view': self
}
def get_serializer(self, *args, **kwargs):
kwargs['context'] = self.get_serializer_context()
return self.serializer_class(*args, **kwargs)
def post(self, request, format=None):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-14 13:33+0100\n"
"PO-Revision-Date: 2021-03-14 13:58\n"
"POT-Creation-Date: 2021-04-05 22:05+0200\n"
"PO-Revision-Date: 2021-04-05 20:20\n"
"Last-Translator: \n"
"Language-Team: Czech\n"
"Language: cs_CZ\n"
@@ -226,7 +226,7 @@ msgstr "záznam"
msgid "logs"
msgstr "záznamy"
#: documents/models.py:344 documents/models.py:396
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr "uložený pohled"
@@ -250,103 +250,111 @@ msgstr "zobrazit v postranním menu"
msgid "sort field"
msgstr "pole na řazení"
#: documents/models.py:364
#: documents/models.py:367
msgid "sort reverse"
msgstr "třídit opačně"
#: documents/models.py:370
#: documents/models.py:373
msgid "title contains"
msgstr "titulek obsahuje"
#: documents/models.py:371
#: documents/models.py:374
msgid "content contains"
msgstr "obsah obsahuje"
#: documents/models.py:372
#: documents/models.py:375
msgid "ASN is"
msgstr "ASN je"
#: documents/models.py:373
#: documents/models.py:376
msgid "correspondent is"
msgstr "korespondent je"
#: documents/models.py:374
#: documents/models.py:377
msgid "document type is"
msgstr "typ dokumentu je"
#: documents/models.py:375
#: documents/models.py:378
msgid "is in inbox"
msgstr "je v příchozích"
#: documents/models.py:376
#: documents/models.py:379
msgid "has tag"
msgstr "má tag"
#: documents/models.py:377
#: documents/models.py:380
msgid "has any tag"
msgstr "má jakýkoliv tag"
#: documents/models.py:378
#: documents/models.py:381
msgid "created before"
msgstr "vytvořeno před"
#: documents/models.py:379
#: documents/models.py:382
msgid "created after"
msgstr "vytvořeno po"
#: documents/models.py:380
#: documents/models.py:383
msgid "created year is"
msgstr "rok vytvoření je"
#: documents/models.py:381
#: documents/models.py:384
msgid "created month is"
msgstr "měsíc vytvoření je"
#: documents/models.py:382
#: documents/models.py:385
msgid "created day is"
msgstr "den vytvoření je"
#: documents/models.py:383
#: documents/models.py:386
msgid "added before"
msgstr "přidáno před"
#: documents/models.py:384
#: documents/models.py:387
msgid "added after"
msgstr "přidáno po"
#: documents/models.py:385
#: documents/models.py:388
msgid "modified before"
msgstr "upraveno před"
#: documents/models.py:386
#: documents/models.py:389
msgid "modified after"
msgstr "upraveno po"
#: documents/models.py:387
#: documents/models.py:390
msgid "does not have tag"
msgstr "nemá tag"
#: documents/models.py:388
#: documents/models.py:391
msgid "does not have ASN"
msgstr ""
#: documents/models.py:389
#: documents/models.py:392
msgid "title or content contains"
msgstr ""
#: documents/models.py:400
#: documents/models.py:393
msgid "fulltext query"
msgstr ""
#: documents/models.py:394
msgid "more like this"
msgstr ""
#: documents/models.py:405
msgid "rule type"
msgstr "typ pravidla"
#: documents/models.py:404
#: documents/models.py:409
msgid "value"
msgstr "hodnota"
#: documents/models.py:410
#: documents/models.py:415
msgid "filter rule"
msgstr "filtrovací pravidlo"
#: documents/models.py:411
#: documents/models.py:416
msgid "filter rules"
msgstr "filtrovací pravidla"
@@ -429,22 +437,26 @@ msgid "Portuguese (Brazil)"
msgstr ""
#: paperless/settings.py:304
msgid "Italian"
msgid "Portuguese"
msgstr ""
#: paperless/settings.py:305
msgid "Romanian"
msgid "Italian"
msgstr ""
#: paperless/settings.py:306
msgid "Russian"
msgid "Romanian"
msgstr ""
#: paperless/settings.py:307
msgid "Russian"
msgstr ""
#: paperless/settings.py:308
msgid "Spanish"
msgstr ""
#: paperless/urls.py:118
#: paperless/urls.py:113
msgid "Paperless-ng administration"
msgstr "Správa Paperless-ng"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-14 13:33+0100\n"
"PO-Revision-Date: 2021-03-14 13:58\n"
"POT-Creation-Date: 2021-04-05 22:05+0200\n"
"PO-Revision-Date: 2021-04-11 15:29\n"
"Last-Translator: \n"
"Language-Team: German\n"
"Language: de_DE\n"
@@ -226,7 +226,7 @@ msgstr "Protokoll"
msgid "logs"
msgstr "Protokoll"
#: documents/models.py:344 documents/models.py:396
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr "Gespeicherte Ansicht"
@@ -250,103 +250,111 @@ msgstr "In Seitenleiste zeigen"
msgid "sort field"
msgstr "Sortierfeld"
#: documents/models.py:364
#: documents/models.py:367
msgid "sort reverse"
msgstr "Umgekehrte Sortierung"
#: documents/models.py:370
#: documents/models.py:373
msgid "title contains"
msgstr "Titel enthält"
#: documents/models.py:371
#: documents/models.py:374
msgid "content contains"
msgstr "Inhalt enthält"
#: documents/models.py:372
#: documents/models.py:375
msgid "ASN is"
msgstr "ASN ist"
#: documents/models.py:373
#: documents/models.py:376
msgid "correspondent is"
msgstr "Korrespondent ist"
#: documents/models.py:374
#: documents/models.py:377
msgid "document type is"
msgstr "Dokumenttyp ist"
#: documents/models.py:375
#: documents/models.py:378
msgid "is in inbox"
msgstr "Ist im Posteingang"
#: documents/models.py:376
#: documents/models.py:379
msgid "has tag"
msgstr "Hat Tag"
#: documents/models.py:377
#: documents/models.py:380
msgid "has any tag"
msgstr "Hat irgendein Tag"
#: documents/models.py:378
#: documents/models.py:381
msgid "created before"
msgstr "Ausgestellt vor"
#: documents/models.py:379
#: documents/models.py:382
msgid "created after"
msgstr "Ausgestellt nach"
#: documents/models.py:380
#: documents/models.py:383
msgid "created year is"
msgstr "Ausgestellt im Jahr"
#: documents/models.py:381
#: documents/models.py:384
msgid "created month is"
msgstr "Ausgestellt im Monat"
#: documents/models.py:382
#: documents/models.py:385
msgid "created day is"
msgstr "Ausgestellt am Tag"
#: documents/models.py:383
#: documents/models.py:386
msgid "added before"
msgstr "Hinzugefügt vor"
#: documents/models.py:384
#: documents/models.py:387
msgid "added after"
msgstr "Hinzugefügt nach"
#: documents/models.py:385
#: documents/models.py:388
msgid "modified before"
msgstr "Geändert vor"
#: documents/models.py:386
#: documents/models.py:389
msgid "modified after"
msgstr "Geändert nach"
#: documents/models.py:387
#: documents/models.py:390
msgid "does not have tag"
msgstr "Hat nicht folgendes Tag"
#: documents/models.py:388
#: documents/models.py:391
msgid "does not have ASN"
msgstr "Dokument hat keine ASN"
#: documents/models.py:389
#: documents/models.py:392
msgid "title or content contains"
msgstr "Titel oder Inhalt enthält"
#: documents/models.py:400
#: documents/models.py:393
msgid "fulltext query"
msgstr "Volltextsuche"
#: documents/models.py:394
msgid "more like this"
msgstr "Ähnliche Dokumente"
#: documents/models.py:405
msgid "rule type"
msgstr "Regeltyp"
#: documents/models.py:404
#: documents/models.py:409
msgid "value"
msgstr "Wert"
#: documents/models.py:410
#: documents/models.py:415
msgid "filter rule"
msgstr "Filterregel"
#: documents/models.py:411
#: documents/models.py:416
msgid "filter rules"
msgstr "Filterregeln"
@@ -429,22 +437,26 @@ msgid "Portuguese (Brazil)"
msgstr "Portugiesisch (Brasilien)"
#: paperless/settings.py:304
msgid "Portuguese"
msgstr "Portugiesisch"
#: paperless/settings.py:305
msgid "Italian"
msgstr "Italienisch"
#: paperless/settings.py:305
#: paperless/settings.py:306
msgid "Romanian"
msgstr "Rumänisch"
#: paperless/settings.py:306
#: paperless/settings.py:307
msgid "Russian"
msgstr "Russisch"
#: paperless/settings.py:307
#: paperless/settings.py:308
msgid "Spanish"
msgstr "Spanisch"
#: paperless/urls.py:118
#: paperless/urls.py:113
msgid "Paperless-ng administration"
msgstr "Paperless-ng Administration"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-14 13:33+0100\n"
"PO-Revision-Date: 2021-03-14 13:57\n"
"POT-Creation-Date: 2021-04-05 22:05+0200\n"
"PO-Revision-Date: 2021-04-05 20:20\n"
"Last-Translator: \n"
"Language-Team: English, United Kingdom\n"
"Language: en_GB\n"
@@ -226,7 +226,7 @@ msgstr "log"
msgid "logs"
msgstr "logs"
#: documents/models.py:344 documents/models.py:396
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr "saved view"
@@ -250,103 +250,111 @@ msgstr "show in sidebar"
msgid "sort field"
msgstr "sort field"
#: documents/models.py:364
#: documents/models.py:367
msgid "sort reverse"
msgstr "sort reverse"
#: documents/models.py:370
#: documents/models.py:373
msgid "title contains"
msgstr "title contains"
#: documents/models.py:371
#: documents/models.py:374
msgid "content contains"
msgstr "content contains"
#: documents/models.py:372
#: documents/models.py:375
msgid "ASN is"
msgstr "ASN is"
#: documents/models.py:373
#: documents/models.py:376
msgid "correspondent is"
msgstr "correspondent is"
#: documents/models.py:374
#: documents/models.py:377
msgid "document type is"
msgstr "document type is"
#: documents/models.py:375
#: documents/models.py:378
msgid "is in inbox"
msgstr "is in inbox"
#: documents/models.py:376
#: documents/models.py:379
msgid "has tag"
msgstr "has tag"
#: documents/models.py:377
#: documents/models.py:380
msgid "has any tag"
msgstr "has any tag"
#: documents/models.py:378
#: documents/models.py:381
msgid "created before"
msgstr "created before"
#: documents/models.py:379
#: documents/models.py:382
msgid "created after"
msgstr "created after"
#: documents/models.py:380
#: documents/models.py:383
msgid "created year is"
msgstr "created year is"
#: documents/models.py:381
#: documents/models.py:384
msgid "created month is"
msgstr "created month is"
#: documents/models.py:382
#: documents/models.py:385
msgid "created day is"
msgstr "created day is"
#: documents/models.py:383
#: documents/models.py:386
msgid "added before"
msgstr "added before"
#: documents/models.py:384
#: documents/models.py:387
msgid "added after"
msgstr "added after"
#: documents/models.py:385
#: documents/models.py:388
msgid "modified before"
msgstr "modified before"
#: documents/models.py:386
#: documents/models.py:389
msgid "modified after"
msgstr "modified after"
#: documents/models.py:387
#: documents/models.py:390
msgid "does not have tag"
msgstr "does not have tag"
#: documents/models.py:388
#: documents/models.py:391
msgid "does not have ASN"
msgstr "does not have ASN"
#: documents/models.py:389
#: documents/models.py:392
msgid "title or content contains"
msgstr "title or content contains"
#: documents/models.py:400
#: documents/models.py:393
msgid "fulltext query"
msgstr ""
#: documents/models.py:394
msgid "more like this"
msgstr ""
#: documents/models.py:405
msgid "rule type"
msgstr "rule type"
#: documents/models.py:404
#: documents/models.py:409
msgid "value"
msgstr "value"
#: documents/models.py:410
#: documents/models.py:415
msgid "filter rule"
msgstr "filter rule"
#: documents/models.py:411
#: documents/models.py:416
msgid "filter rules"
msgstr "filter rules"
@@ -429,22 +437,26 @@ msgid "Portuguese (Brazil)"
msgstr "Portuguese (Brazil)"
#: paperless/settings.py:304
msgid "Portuguese"
msgstr "Portuguese"
#: paperless/settings.py:305
msgid "Italian"
msgstr "Italian"
#: paperless/settings.py:305
#: paperless/settings.py:306
msgid "Romanian"
msgstr "Romanian"
#: paperless/settings.py:306
#: paperless/settings.py:307
msgid "Russian"
msgstr "Russian"
#: paperless/settings.py:307
#: paperless/settings.py:308
msgid "Spanish"
msgstr ""
msgstr "Spanish"
#: paperless/urls.py:118
#: paperless/urls.py:113
msgid "Paperless-ng administration"
msgstr "Paperless-ng administration"

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-14 13:33+0100\n"
"POT-Creation-Date: 2021-04-17 13:41+0200\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"
@@ -230,7 +230,7 @@ msgstr ""
msgid "logs"
msgstr ""
#: documents/models.py:344 documents/models.py:396
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr ""
@@ -254,103 +254,111 @@ msgstr ""
msgid "sort field"
msgstr ""
#: documents/models.py:364
#: documents/models.py:367
msgid "sort reverse"
msgstr ""
#: documents/models.py:370
#: documents/models.py:373
msgid "title contains"
msgstr ""
#: documents/models.py:371
#: documents/models.py:374
msgid "content contains"
msgstr ""
#: documents/models.py:372
#: documents/models.py:375
msgid "ASN is"
msgstr ""
#: documents/models.py:373
#: documents/models.py:376
msgid "correspondent is"
msgstr ""
#: documents/models.py:374
#: documents/models.py:377
msgid "document type is"
msgstr ""
#: documents/models.py:375
#: documents/models.py:378
msgid "is in inbox"
msgstr ""
#: documents/models.py:376
#: documents/models.py:379
msgid "has tag"
msgstr ""
#: documents/models.py:377
#: documents/models.py:380
msgid "has any tag"
msgstr ""
#: documents/models.py:378
#: documents/models.py:381
msgid "created before"
msgstr ""
#: documents/models.py:379
#: documents/models.py:382
msgid "created after"
msgstr ""
#: documents/models.py:380
#: documents/models.py:383
msgid "created year is"
msgstr ""
#: documents/models.py:381
#: documents/models.py:384
msgid "created month is"
msgstr ""
#: documents/models.py:382
#: documents/models.py:385
msgid "created day is"
msgstr ""
#: documents/models.py:383
#: documents/models.py:386
msgid "added before"
msgstr ""
#: documents/models.py:384
#: documents/models.py:387
msgid "added after"
msgstr ""
#: documents/models.py:385
#: documents/models.py:388
msgid "modified before"
msgstr ""
#: documents/models.py:386
#: documents/models.py:389
msgid "modified after"
msgstr ""
#: documents/models.py:387
#: documents/models.py:390
msgid "does not have tag"
msgstr ""
#: documents/models.py:388
#: documents/models.py:391
msgid "does not have ASN"
msgstr ""
#: documents/models.py:389
#: documents/models.py:392
msgid "title or content contains"
msgstr ""
#: documents/models.py:400
#: documents/models.py:393
msgid "fulltext query"
msgstr ""
#: documents/models.py:394
msgid "more like this"
msgstr ""
#: documents/models.py:405
msgid "rule type"
msgstr ""
#: documents/models.py:404
#: documents/models.py:409
msgid "value"
msgstr ""
#: documents/models.py:410
#: documents/models.py:415
msgid "filter rule"
msgstr ""
#: documents/models.py:411
#: documents/models.py:416
msgid "filter rules"
msgstr ""
@@ -433,22 +441,30 @@ msgid "Portuguese (Brazil)"
msgstr ""
#: paperless/settings.py:304
msgid "Italian"
msgid "Portuguese"
msgstr ""
#: paperless/settings.py:305
msgid "Romanian"
msgid "Italian"
msgstr ""
#: paperless/settings.py:306
msgid "Russian"
msgid "Romanian"
msgstr ""
#: paperless/settings.py:307
msgid "Russian"
msgstr ""
#: paperless/settings.py:308
msgid "Spanish"
msgstr ""
#: paperless/urls.py:118
#: paperless/settings.py:309
msgid "Polish"
msgstr ""
#: paperless/urls.py:113
msgid "Paperless-ng administration"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-14 13:33+0100\n"
"PO-Revision-Date: 2021-03-14 13:58\n"
"POT-Creation-Date: 2021-04-05 22:05+0200\n"
"PO-Revision-Date: 2021-04-05 20:20\n"
"Last-Translator: \n"
"Language-Team: Spanish\n"
"Language: es_ES\n"
@@ -226,7 +226,7 @@ msgstr "log"
msgid "logs"
msgstr "logs"
#: documents/models.py:344 documents/models.py:396
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr "vista guardada"
@@ -250,103 +250,111 @@ msgstr "mostrar en barra lateral"
msgid "sort field"
msgstr "campo de ordenación"
#: documents/models.py:364
#: documents/models.py:367
msgid "sort reverse"
msgstr "ordenar al revés"
#: documents/models.py:370
#: documents/models.py:373
msgid "title contains"
msgstr "el titulo contiene"
#: documents/models.py:371
#: documents/models.py:374
msgid "content contains"
msgstr "el contenido contiene"
#: documents/models.py:372
#: documents/models.py:375
msgid "ASN is"
msgstr "ASN es"
#: documents/models.py:373
#: documents/models.py:376
msgid "correspondent is"
msgstr "tipo de documento es"
#: documents/models.py:374
#: documents/models.py:377
msgid "document type is"
msgstr "el tipo de documento es"
#: documents/models.py:375
#: documents/models.py:378
msgid "is in inbox"
msgstr "está en la bandeja de entrada"
#: documents/models.py:376
#: documents/models.py:379
msgid "has tag"
msgstr "tiene la etiqueta"
#: documents/models.py:377
#: documents/models.py:380
msgid "has any tag"
msgstr "tiene cualquier etiqueta"
#: documents/models.py:378
#: documents/models.py:381
msgid "created before"
msgstr "creado antes"
#: documents/models.py:379
#: documents/models.py:382
msgid "created after"
msgstr "creado después"
#: documents/models.py:380
#: documents/models.py:383
msgid "created year is"
msgstr "el año de creación es"
#: documents/models.py:381
#: documents/models.py:384
msgid "created month is"
msgstr "el mes de creación es"
#: documents/models.py:382
#: documents/models.py:385
msgid "created day is"
msgstr "creado el día"
#: documents/models.py:383
#: documents/models.py:386
msgid "added before"
msgstr "agregado antes de"
#: documents/models.py:384
#: documents/models.py:387
msgid "added after"
msgstr "agregado después de"
#: documents/models.py:385
#: documents/models.py:388
msgid "modified before"
msgstr "modificado después de"
#: documents/models.py:386
#: documents/models.py:389
msgid "modified after"
msgstr "modificado antes de"
#: documents/models.py:387
#: documents/models.py:390
msgid "does not have tag"
msgstr "no tiene la etiqueta"
#: documents/models.py:388
#: documents/models.py:391
msgid "does not have ASN"
msgstr "no tiene ASN"
#: documents/models.py:389
#: documents/models.py:392
msgid "title or content contains"
msgstr "el título o cuerpo contiene"
#: documents/models.py:400
#: documents/models.py:393
msgid "fulltext query"
msgstr ""
#: documents/models.py:394
msgid "more like this"
msgstr ""
#: documents/models.py:405
msgid "rule type"
msgstr "tipo de regla"
#: documents/models.py:404
#: documents/models.py:409
msgid "value"
msgstr "valor"
#: documents/models.py:410
#: documents/models.py:415
msgid "filter rule"
msgstr "regla de filtrado"
#: documents/models.py:411
#: documents/models.py:416
msgid "filter rules"
msgstr "reglas de filtrado"
@@ -429,22 +437,26 @@ msgid "Portuguese (Brazil)"
msgstr "Portugués (Brasil)"
#: paperless/settings.py:304
msgid "Portuguese"
msgstr ""
#: paperless/settings.py:305
msgid "Italian"
msgstr "Italiano"
#: paperless/settings.py:305
#: paperless/settings.py:306
msgid "Romanian"
msgstr "Rumano"
#: paperless/settings.py:306
#: paperless/settings.py:307
msgid "Russian"
msgstr "Ruso"
#: paperless/settings.py:307
#: paperless/settings.py:308
msgid "Spanish"
msgstr ""
msgstr "Español"
#: paperless/urls.py:118
#: paperless/urls.py:113
msgid "Paperless-ng administration"
msgstr "Paperless-ng Administración"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-14 13:33+0100\n"
"PO-Revision-Date: 2021-03-14 13:58\n"
"POT-Creation-Date: 2021-04-05 22:05+0200\n"
"PO-Revision-Date: 2021-04-06 12:03\n"
"Last-Translator: \n"
"Language-Team: French\n"
"Language: fr_FR\n"
@@ -226,7 +226,7 @@ msgstr "journal"
msgid "logs"
msgstr "journaux"
#: documents/models.py:344 documents/models.py:396
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr "vue enregistrée"
@@ -250,103 +250,111 @@ msgstr "montrer dans la barre latérale"
msgid "sort field"
msgstr "champ de tri"
#: documents/models.py:364
#: documents/models.py:367
msgid "sort reverse"
msgstr "tri inverse"
#: documents/models.py:370
#: documents/models.py:373
msgid "title contains"
msgstr "le titre contient"
#: documents/models.py:371
#: documents/models.py:374
msgid "content contains"
msgstr "le contenu contient"
#: documents/models.py:372
#: documents/models.py:375
msgid "ASN is"
msgstr "le NSA est"
#: documents/models.py:373
#: documents/models.py:376
msgid "correspondent is"
msgstr "le correspondant est"
#: documents/models.py:374
#: documents/models.py:377
msgid "document type is"
msgstr "le type de document est"
#: documents/models.py:375
#: documents/models.py:378
msgid "is in inbox"
msgstr "est dans la boîte de réception"
#: documents/models.py:376
#: documents/models.py:379
msgid "has tag"
msgstr "porte l'étiquette"
#: documents/models.py:377
#: documents/models.py:380
msgid "has any tag"
msgstr "porte l'une des étiquettes"
#: documents/models.py:378
#: documents/models.py:381
msgid "created before"
msgstr "créé avant"
#: documents/models.py:379
#: documents/models.py:382
msgid "created after"
msgstr "créé après"
#: documents/models.py:380
#: documents/models.py:383
msgid "created year is"
msgstr "l'année de création est"
#: documents/models.py:381
#: documents/models.py:384
msgid "created month is"
msgstr "le mois de création est"
#: documents/models.py:382
#: documents/models.py:385
msgid "created day is"
msgstr "le jour de création est"
#: documents/models.py:383
#: documents/models.py:386
msgid "added before"
msgstr "ajouté avant"
#: documents/models.py:384
#: documents/models.py:387
msgid "added after"
msgstr "ajouté après"
#: documents/models.py:385
#: documents/models.py:388
msgid "modified before"
msgstr "modifié avant"
#: documents/models.py:386
#: documents/models.py:389
msgid "modified after"
msgstr "modifié après"
#: documents/models.py:387
#: documents/models.py:390
msgid "does not have tag"
msgstr "ne porte pas d'étiquette"
#: documents/models.py:388
#: documents/models.py:391
msgid "does not have ASN"
msgstr "ne porte pas de NSA"
#: documents/models.py:389
#: documents/models.py:392
msgid "title or content contains"
msgstr "le titre ou le contenu contient"
#: documents/models.py:400
#: documents/models.py:393
msgid "fulltext query"
msgstr "recherche en texte intégral"
#: documents/models.py:394
msgid "more like this"
msgstr "documents relatifs"
#: documents/models.py:405
msgid "rule type"
msgstr "type de règle"
#: documents/models.py:404
#: documents/models.py:409
msgid "value"
msgstr "valeur"
#: documents/models.py:410
#: documents/models.py:415
msgid "filter rule"
msgstr "règle de filtrage"
#: documents/models.py:411
#: documents/models.py:416
msgid "filter rules"
msgstr "règles de filtrage"
@@ -429,22 +437,26 @@ msgid "Portuguese (Brazil)"
msgstr "Portugais (Brésil)"
#: paperless/settings.py:304
msgid "Portuguese"
msgstr "Portugais"
#: paperless/settings.py:305
msgid "Italian"
msgstr "Italien"
#: paperless/settings.py:305
#: paperless/settings.py:306
msgid "Romanian"
msgstr "Roumain"
#: paperless/settings.py:306
#: paperless/settings.py:307
msgid "Russian"
msgstr "Russe"
#: paperless/settings.py:307
#: paperless/settings.py:308
msgid "Spanish"
msgstr ""
msgstr "Espagnol"
#: paperless/urls.py:118
#: paperless/urls.py:113
msgid "Paperless-ng administration"
msgstr "Administration de Paperless-ng"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-14 13:33+0100\n"
"PO-Revision-Date: 2021-03-14 13:57\n"
"POT-Creation-Date: 2021-04-05 22:05+0200\n"
"PO-Revision-Date: 2021-04-05 20:20\n"
"Last-Translator: \n"
"Language-Team: Hungarian\n"
"Language: hu_HU\n"
@@ -226,7 +226,7 @@ msgstr ""
msgid "logs"
msgstr ""
#: documents/models.py:344 documents/models.py:396
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr ""
@@ -250,103 +250,111 @@ msgstr ""
msgid "sort field"
msgstr ""
#: documents/models.py:364
#: documents/models.py:367
msgid "sort reverse"
msgstr ""
#: documents/models.py:370
#: documents/models.py:373
msgid "title contains"
msgstr ""
#: documents/models.py:371
#: documents/models.py:374
msgid "content contains"
msgstr ""
#: documents/models.py:372
#: documents/models.py:375
msgid "ASN is"
msgstr ""
#: documents/models.py:373
#: documents/models.py:376
msgid "correspondent is"
msgstr ""
#: documents/models.py:374
#: documents/models.py:377
msgid "document type is"
msgstr ""
#: documents/models.py:375
#: documents/models.py:378
msgid "is in inbox"
msgstr ""
#: documents/models.py:376
#: documents/models.py:379
msgid "has tag"
msgstr ""
#: documents/models.py:377
#: documents/models.py:380
msgid "has any tag"
msgstr ""
#: documents/models.py:378
#: documents/models.py:381
msgid "created before"
msgstr ""
#: documents/models.py:379
#: documents/models.py:382
msgid "created after"
msgstr ""
#: documents/models.py:380
#: documents/models.py:383
msgid "created year is"
msgstr ""
#: documents/models.py:381
#: documents/models.py:384
msgid "created month is"
msgstr ""
#: documents/models.py:382
#: documents/models.py:385
msgid "created day is"
msgstr ""
#: documents/models.py:383
#: documents/models.py:386
msgid "added before"
msgstr ""
#: documents/models.py:384
#: documents/models.py:387
msgid "added after"
msgstr ""
#: documents/models.py:385
#: documents/models.py:388
msgid "modified before"
msgstr ""
#: documents/models.py:386
#: documents/models.py:389
msgid "modified after"
msgstr ""
#: documents/models.py:387
#: documents/models.py:390
msgid "does not have tag"
msgstr ""
#: documents/models.py:388
#: documents/models.py:391
msgid "does not have ASN"
msgstr ""
#: documents/models.py:389
#: documents/models.py:392
msgid "title or content contains"
msgstr ""
#: documents/models.py:400
#: documents/models.py:393
msgid "fulltext query"
msgstr ""
#: documents/models.py:394
msgid "more like this"
msgstr ""
#: documents/models.py:405
msgid "rule type"
msgstr ""
#: documents/models.py:404
#: documents/models.py:409
msgid "value"
msgstr ""
#: documents/models.py:410
#: documents/models.py:415
msgid "filter rule"
msgstr ""
#: documents/models.py:411
#: documents/models.py:416
msgid "filter rules"
msgstr ""
@@ -429,22 +437,26 @@ msgid "Portuguese (Brazil)"
msgstr ""
#: paperless/settings.py:304
msgid "Italian"
msgid "Portuguese"
msgstr ""
#: paperless/settings.py:305
msgid "Romanian"
msgid "Italian"
msgstr ""
#: paperless/settings.py:306
msgid "Russian"
msgid "Romanian"
msgstr ""
#: paperless/settings.py:307
msgid "Russian"
msgstr ""
#: paperless/settings.py:308
msgid "Spanish"
msgstr ""
#: paperless/urls.py:118
#: paperless/urls.py:113
msgid "Paperless-ng administration"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-14 13:33+0100\n"
"PO-Revision-Date: 2021-03-14 13:57\n"
"POT-Creation-Date: 2021-04-05 22:05+0200\n"
"PO-Revision-Date: 2021-04-05 21:31\n"
"Last-Translator: \n"
"Language-Team: Italian\n"
"Language: it_IT\n"
@@ -226,7 +226,7 @@ msgstr "log"
msgid "logs"
msgstr "log"
#: documents/models.py:344 documents/models.py:396
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr "vista salvata"
@@ -250,103 +250,111 @@ msgstr "mostra nella barra laterale"
msgid "sort field"
msgstr "campo di ordinamento"
#: documents/models.py:364
#: documents/models.py:367
msgid "sort reverse"
msgstr "ordine invertito"
#: documents/models.py:370
#: documents/models.py:373
msgid "title contains"
msgstr "il titolo contiene"
#: documents/models.py:371
#: documents/models.py:374
msgid "content contains"
msgstr "il contenuto contiene"
#: documents/models.py:372
#: documents/models.py:375
msgid "ASN is"
msgstr "ASN è"
#: documents/models.py:373
#: documents/models.py:376
msgid "correspondent is"
msgstr "la corrispondenza è"
#: documents/models.py:374
#: documents/models.py:377
msgid "document type is"
msgstr "il tipo di documento è"
#: documents/models.py:375
#: documents/models.py:378
msgid "is in inbox"
msgstr "è in arrivo"
#: documents/models.py:376
#: documents/models.py:379
msgid "has tag"
msgstr "ha etichetta"
#: documents/models.py:377
#: documents/models.py:380
msgid "has any tag"
msgstr "ha qualsiasi etichetta"
#: documents/models.py:378
#: documents/models.py:381
msgid "created before"
msgstr "creato prima del"
#: documents/models.py:379
#: documents/models.py:382
msgid "created after"
msgstr "creato dopo il"
#: documents/models.py:380
#: documents/models.py:383
msgid "created year is"
msgstr "l'anno di creazione è"
#: documents/models.py:381
#: documents/models.py:384
msgid "created month is"
msgstr "il mese di creazione è"
#: documents/models.py:382
#: documents/models.py:385
msgid "created day is"
msgstr "il giorno di creazione è"
#: documents/models.py:383
#: documents/models.py:386
msgid "added before"
msgstr "aggiunto prima del"
#: documents/models.py:384
#: documents/models.py:387
msgid "added after"
msgstr "aggiunto dopo il"
#: documents/models.py:385
#: documents/models.py:388
msgid "modified before"
msgstr "modificato prima del"
#: documents/models.py:386
#: documents/models.py:389
msgid "modified after"
msgstr "modificato dopo"
#: documents/models.py:387
#: documents/models.py:390
msgid "does not have tag"
msgstr "non ha tag"
#: documents/models.py:388
#: documents/models.py:391
msgid "does not have ASN"
msgstr "non ha ASN"
#: documents/models.py:389
#: documents/models.py:392
msgid "title or content contains"
msgstr "il titolo o il contenuto contiene"
#: documents/models.py:400
#: documents/models.py:393
msgid "fulltext query"
msgstr "query fulltext"
#: documents/models.py:394
msgid "more like this"
msgstr "altro come questo"
#: documents/models.py:405
msgid "rule type"
msgstr "tipo di regola"
#: documents/models.py:404
#: documents/models.py:409
msgid "value"
msgstr "valore"
#: documents/models.py:410
#: documents/models.py:415
msgid "filter rule"
msgstr "regola filtro"
#: documents/models.py:411
#: documents/models.py:416
msgid "filter rules"
msgstr "regole filtro"
@@ -366,7 +374,7 @@ msgstr "Il tipo di file %(type)s non è supportato"
#: documents/templates/index.html:21
msgid "Paperless-ng is loading..."
msgstr "Paperless-ng si sta caricando..."
msgstr "Paperless-ng è in caricamento..."
#: documents/templates/registration/logged_out.html:13
msgid "Paperless-ng signed out"
@@ -374,11 +382,11 @@ msgstr "Paperless-ng è uscito"
#: documents/templates/registration/logged_out.html:41
msgid "You have been successfully logged out. Bye!"
msgstr "Vi siete disconnessi. Ciao!"
msgstr "Ti sei disconnesso. A presto!"
#: documents/templates/registration/logged_out.html:42
msgid "Sign in again"
msgstr "Rientra nuovamente"
msgstr "Accedi nuovamente"
#: documents/templates/registration/login.html:13
msgid "Paperless-ng sign in"
@@ -429,22 +437,26 @@ msgid "Portuguese (Brazil)"
msgstr "Portoghese (Brasile)"
#: paperless/settings.py:304
msgid "Portuguese"
msgstr "Portoghese"
#: paperless/settings.py:305
msgid "Italian"
msgstr "Italiano"
#: paperless/settings.py:305
#: paperless/settings.py:306
msgid "Romanian"
msgstr "Rumeno"
#: paperless/settings.py:306
#: paperless/settings.py:307
msgid "Russian"
msgstr "Russo"
#: paperless/settings.py:307
#: paperless/settings.py:308
msgid "Spanish"
msgstr ""
msgstr "Spagnolo"
#: paperless/urls.py:118
#: paperless/urls.py:113
msgid "Paperless-ng administration"
msgstr "Amministrazione di Paperless-ng"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-14 13:33+0100\n"
"PO-Revision-Date: 2021-03-14 13:57\n"
"POT-Creation-Date: 2021-04-05 22:05+0200\n"
"PO-Revision-Date: 2021-04-06 12:03\n"
"Last-Translator: \n"
"Language-Team: Dutch\n"
"Language: nl_NL\n"
@@ -226,7 +226,7 @@ msgstr "bericht"
msgid "logs"
msgstr "berichten"
#: documents/models.py:344 documents/models.py:396
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr "opgeslagen view"
@@ -250,103 +250,111 @@ msgstr "weergeven in zijbalk"
msgid "sort field"
msgstr "sorteerveld"
#: documents/models.py:364
#: documents/models.py:367
msgid "sort reverse"
msgstr "omgekeerd sorteren"
#: documents/models.py:370
#: documents/models.py:373
msgid "title contains"
msgstr "titel bevat"
#: documents/models.py:371
#: documents/models.py:374
msgid "content contains"
msgstr "inhoud bevat"
#: documents/models.py:372
#: documents/models.py:375
msgid "ASN is"
msgstr "ASN is"
#: documents/models.py:373
#: documents/models.py:376
msgid "correspondent is"
msgstr "correspondent is"
#: documents/models.py:374
#: documents/models.py:377
msgid "document type is"
msgstr "documenttype is"
#: documents/models.py:375
#: documents/models.py:378
msgid "is in inbox"
msgstr "zit in \"Postvak in\""
#: documents/models.py:376
#: documents/models.py:379
msgid "has tag"
msgstr "heeft etiket"
#: documents/models.py:377
#: documents/models.py:380
msgid "has any tag"
msgstr "heeft één van de etiketten"
#: documents/models.py:378
#: documents/models.py:381
msgid "created before"
msgstr "aangemaakt voor"
#: documents/models.py:379
#: documents/models.py:382
msgid "created after"
msgstr "aangemaakt na"
#: documents/models.py:380
#: documents/models.py:383
msgid "created year is"
msgstr "aangemaakt jaar is"
#: documents/models.py:381
#: documents/models.py:384
msgid "created month is"
msgstr "aangemaakte maand is"
#: documents/models.py:382
#: documents/models.py:385
msgid "created day is"
msgstr "aangemaakte dag is"
#: documents/models.py:383
#: documents/models.py:386
msgid "added before"
msgstr "toegevoegd voor"
#: documents/models.py:384
#: documents/models.py:387
msgid "added after"
msgstr "toegevoegd na"
#: documents/models.py:385
#: documents/models.py:388
msgid "modified before"
msgstr "gewijzigd voor"
#: documents/models.py:386
#: documents/models.py:389
msgid "modified after"
msgstr "gewijzigd na"
#: documents/models.py:387
#: documents/models.py:390
msgid "does not have tag"
msgstr "heeft geen etiket"
#: documents/models.py:388
#: documents/models.py:391
msgid "does not have ASN"
msgstr "heeft geen ASN"
#: documents/models.py:389
#: documents/models.py:392
msgid "title or content contains"
msgstr "titel of inhoud bevat"
#: documents/models.py:400
#: documents/models.py:393
msgid "fulltext query"
msgstr "inhoud doorzoeken"
#: documents/models.py:394
msgid "more like this"
msgstr "meer zoals dit"
#: documents/models.py:405
msgid "rule type"
msgstr "type regel"
#: documents/models.py:404
#: documents/models.py:409
msgid "value"
msgstr "waarde"
#: documents/models.py:410
#: documents/models.py:415
msgid "filter rule"
msgstr "filterregel"
#: documents/models.py:411
#: documents/models.py:416
msgid "filter rules"
msgstr "filterregels"
@@ -429,22 +437,26 @@ msgid "Portuguese (Brazil)"
msgstr "Portugees (Brazilië)"
#: paperless/settings.py:304
msgid "Portuguese"
msgstr "Portugees"
#: paperless/settings.py:305
msgid "Italian"
msgstr "Italiaans"
#: paperless/settings.py:305
#: paperless/settings.py:306
msgid "Romanian"
msgstr "Roemeens"
#: paperless/settings.py:306
#: paperless/settings.py:307
msgid "Russian"
msgstr "Russisch"
#: paperless/settings.py:307
#: paperless/settings.py:308
msgid "Spanish"
msgstr ""
msgstr "Spaans"
#: paperless/urls.py:118
#: paperless/urls.py:113
msgid "Paperless-ng administration"
msgstr "Paperless-ng administratie"

View File

@@ -0,0 +1,670 @@
msgid ""
msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-04-05 22:05+0200\n"
"PO-Revision-Date: 2021-04-11 21:03\n"
"Last-Translator: \n"
"Language-Team: Polish\n"
"Language: pl_PL\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
"X-Crowdin-Project: paperless-ng\n"
"X-Crowdin-Project-ID: 434940\n"
"X-Crowdin-Language: pl\n"
"X-Crowdin-File: /dev/src/locale/en_US/LC_MESSAGES/django.po\n"
"X-Crowdin-File-ID: 54\n"
#: documents/apps.py:10
msgid "Documents"
msgstr "Dokumenty"
#: documents/models.py:32
msgid "Any word"
msgstr "Dowolne słowo"
#: documents/models.py:33
msgid "All words"
msgstr "Wszystkie słowa"
#: documents/models.py:34
msgid "Exact match"
msgstr "Dokładne dopasowanie"
#: documents/models.py:35
msgid "Regular expression"
msgstr "Wyrażenie regularne"
#: documents/models.py:36
msgid "Fuzzy word"
msgstr "Dopasowanie rozmyte"
#: documents/models.py:37
msgid "Automatic"
msgstr "Automatyczny"
#: documents/models.py:41 documents/models.py:350 paperless_mail/models.py:25
#: paperless_mail/models.py:109
msgid "name"
msgstr "nazwa"
#: documents/models.py:45
msgid "match"
msgstr "dopasowanie"
#: documents/models.py:49
msgid "matching algorithm"
msgstr "algorytm dopasowania"
#: documents/models.py:55
msgid "is insensitive"
msgstr "bez rozróżniania wielkości liter"
#: documents/models.py:74 documents/models.py:120
msgid "correspondent"
msgstr "korespondent"
#: documents/models.py:75
msgid "correspondents"
msgstr "korespondenci"
#: documents/models.py:81
msgid "color"
msgstr "kolor"
#: documents/models.py:87
msgid "is inbox tag"
msgstr "jest tagiem skrzynki odbiorczej"
#: documents/models.py:89
msgid "Marks this tag as an inbox tag: All newly consumed documents will be tagged with inbox tags."
msgstr "Zaznacza ten tag jako tag skrzynki odbiorczej: Wszystkie nowo przetworzone dokumenty będą oznaczone tagami skrzynki odbiorczej."
#: documents/models.py:94
msgid "tag"
msgstr "tag"
#: documents/models.py:95 documents/models.py:151
msgid "tags"
msgstr "tagi"
#: documents/models.py:101 documents/models.py:133
msgid "document type"
msgstr "typ dokumentu"
#: documents/models.py:102
msgid "document types"
msgstr "typy dokumentów"
#: documents/models.py:110
msgid "Unencrypted"
msgstr "Niezaszyfrowane"
#: documents/models.py:111
msgid "Encrypted with GNU Privacy Guard"
msgstr "Zaszyfrowane przy użyciu GNU Privacy Guard"
#: documents/models.py:124
msgid "title"
msgstr "tytuł"
#: documents/models.py:137
msgid "content"
msgstr "zawartość"
#: documents/models.py:139
msgid "The raw, text-only data of the document. This field is primarily used for searching."
msgstr "Surowe, tekstowe dane dokumentu. To pole jest używane głównie do wyszukiwania."
#: documents/models.py:144
msgid "mime type"
msgstr "typ mime"
#: documents/models.py:155
msgid "checksum"
msgstr "suma kontrolna"
#: documents/models.py:159
msgid "The checksum of the original document."
msgstr "Suma kontrolna oryginalnego dokumentu."
#: documents/models.py:163
msgid "archive checksum"
msgstr "suma kontrolna archiwum"
#: documents/models.py:168
msgid "The checksum of the archived document."
msgstr "Suma kontrolna zarchiwizowanego dokumentu."
#: documents/models.py:172 documents/models.py:328
msgid "created"
msgstr "utworzono"
#: documents/models.py:176
msgid "modified"
msgstr "zmodyfikowano"
#: documents/models.py:180
msgid "storage type"
msgstr "typ przechowywania"
#: documents/models.py:188
msgid "added"
msgstr "dodano"
#: documents/models.py:192
msgid "filename"
msgstr "nazwa pliku"
#: documents/models.py:198
msgid "Current filename in storage"
msgstr "Aktualna nazwa pliku w pamięci"
#: documents/models.py:202
msgid "archive filename"
msgstr "nazwa pliku archiwum"
#: documents/models.py:208
msgid "Current archive filename in storage"
msgstr "Aktualna nazwa pliku archiwum w pamięci"
#: documents/models.py:212
msgid "archive serial number"
msgstr "numer seryjny archiwum"
#: documents/models.py:217
msgid "The position of this document in your physical document archive."
msgstr "Pozycja tego dokumentu w archiwum dokumentów fizycznych."
#: documents/models.py:223
msgid "document"
msgstr "dokument"
#: documents/models.py:224
msgid "documents"
msgstr "dokumenty"
#: documents/models.py:311
msgid "debug"
msgstr "debug"
#: documents/models.py:312
msgid "information"
msgstr "informacja"
#: documents/models.py:313
msgid "warning"
msgstr "ostrzeżenie"
#: documents/models.py:314
msgid "error"
msgstr "błąd"
#: documents/models.py:315
msgid "critical"
msgstr "krytyczne"
#: documents/models.py:319
msgid "group"
msgstr "grupa"
#: documents/models.py:322
msgid "message"
msgstr "wiadomość"
#: documents/models.py:325
msgid "level"
msgstr "poziom"
#: documents/models.py:332
msgid "log"
msgstr "log"
#: documents/models.py:333
msgid "logs"
msgstr "logi"
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr "zapisany widok"
#: documents/models.py:345
msgid "saved views"
msgstr "zapisane widoki"
#: documents/models.py:348
msgid "user"
msgstr "użytkownik"
#: documents/models.py:354
msgid "show on dashboard"
msgstr "pokaż na pulpicie"
#: documents/models.py:357
msgid "show in sidebar"
msgstr "pokaż na pasku bocznym"
#: documents/models.py:361
msgid "sort field"
msgstr "pole sortowania"
#: documents/models.py:367
msgid "sort reverse"
msgstr "sortuj malejąco"
#: documents/models.py:373
msgid "title contains"
msgstr "tytuł zawiera"
#: documents/models.py:374
msgid "content contains"
msgstr "zawartość zawiera"
#: documents/models.py:375
msgid "ASN is"
msgstr "numer archiwum jest"
#: documents/models.py:376
msgid "correspondent is"
msgstr "korespondentem jest"
#: documents/models.py:377
msgid "document type is"
msgstr "typ dokumentu jest"
#: documents/models.py:378
msgid "is in inbox"
msgstr "jest w skrzynce odbiorczej"
#: documents/models.py:379
msgid "has tag"
msgstr "ma tag"
#: documents/models.py:380
msgid "has any tag"
msgstr "ma dowolny tag"
#: documents/models.py:381
msgid "created before"
msgstr "utworzony przed"
#: documents/models.py:382
msgid "created after"
msgstr "utworzony po"
#: documents/models.py:383
msgid "created year is"
msgstr "rok utworzenia to"
#: documents/models.py:384
msgid "created month is"
msgstr "miesiąc utworzenia to"
#: documents/models.py:385
msgid "created day is"
msgstr "dzień utworzenia to"
#: documents/models.py:386
msgid "added before"
msgstr "dodany przed"
#: documents/models.py:387
msgid "added after"
msgstr "dodany po"
#: documents/models.py:388
msgid "modified before"
msgstr "zmodyfikowany przed"
#: documents/models.py:389
msgid "modified after"
msgstr "zmodyfikowany po"
#: documents/models.py:390
msgid "does not have tag"
msgstr "nie ma tagu"
#: documents/models.py:391
msgid "does not have ASN"
msgstr "nie ma numeru archiwum"
#: documents/models.py:392
msgid "title or content contains"
msgstr "tytuł lub zawartość zawiera"
#: documents/models.py:393
msgid "fulltext query"
msgstr "zapytanie pełnotekstowe"
#: documents/models.py:394
msgid "more like this"
msgstr "podobne dokumenty"
#: documents/models.py:405
msgid "rule type"
msgstr "typ reguły"
#: documents/models.py:409
msgid "value"
msgstr "wartość"
#: documents/models.py:415
msgid "filter rule"
msgstr "reguła filtrowania"
#: documents/models.py:416
msgid "filter rules"
msgstr "reguły filtrowania"
#: documents/serialisers.py:53
#, python-format
msgid "Invalid regular expression: %(error)s"
msgstr "Nieprawidłowe wyrażenie regularne: %(error)s"
#: documents/serialisers.py:177
msgid "Invalid color."
msgstr "Nieprawidłowy kolor."
#: documents/serialisers.py:451
#, python-format
msgid "File type %(type)s not supported"
msgstr "Typ pliku %(type)s nie jest obsługiwany"
#: documents/templates/index.html:21
msgid "Paperless-ng is loading..."
msgstr "Ładowanie Paperless-ng..."
#: documents/templates/registration/logged_out.html:13
msgid "Paperless-ng signed out"
msgstr "Wylogowano z Paperless-ng"
#: documents/templates/registration/logged_out.html:41
msgid "You have been successfully logged out. Bye!"
msgstr "Poprawnie wylogowano. Do zobaczenia!"
#: documents/templates/registration/logged_out.html:42
msgid "Sign in again"
msgstr "Zaloguj się ponownie"
#: documents/templates/registration/login.html:13
msgid "Paperless-ng sign in"
msgstr "Logowanie do Paperless-ng"
#: documents/templates/registration/login.html:42
msgid "Please sign in."
msgstr "Proszę się zalogować."
#: documents/templates/registration/login.html:45
msgid "Your username and password didn't match. Please try again."
msgstr "Twoja nazwa użytkownika i hasło nie są zgodne. Spróbuj ponownie."
#: documents/templates/registration/login.html:48
msgid "Username"
msgstr "Użytkownik"
#: documents/templates/registration/login.html:49
msgid "Password"
msgstr "Hasło"
#: documents/templates/registration/login.html:54
msgid "Sign in"
msgstr "Zaloguj się"
#: paperless/settings.py:298
msgid "English (US)"
msgstr "Angielski (USA)"
#: paperless/settings.py:299
msgid "English (GB)"
msgstr "Angielski (Wielka Brytania)"
#: paperless/settings.py:300
msgid "German"
msgstr "Niemiecki"
#: paperless/settings.py:301
msgid "Dutch"
msgstr "Holenderski"
#: paperless/settings.py:302
msgid "French"
msgstr "Francuski"
#: paperless/settings.py:303
msgid "Portuguese (Brazil)"
msgstr "Portugalski (Brazylia)"
#: paperless/settings.py:304
msgid "Portuguese"
msgstr "Portugalski"
#: paperless/settings.py:305
msgid "Italian"
msgstr "Włoski"
#: paperless/settings.py:306
msgid "Romanian"
msgstr "Rumuński"
#: paperless/settings.py:307
msgid "Russian"
msgstr "Rosyjski"
#: paperless/settings.py:308
msgid "Spanish"
msgstr "Hiszpański"
#: paperless/urls.py:113
msgid "Paperless-ng administration"
msgstr "Administracja Paperless-ng"
#: paperless_mail/admin.py:25
msgid "Filter"
msgstr "Filtry"
#: paperless_mail/admin.py:27
msgid "Paperless will only process mails that match ALL of the filters given below."
msgstr "Paperless przetworzy tylko wiadomości pasujące do WSZYSTKICH filtrów podanych poniżej."
#: paperless_mail/admin.py:37
msgid "Actions"
msgstr "Akcje"
#: paperless_mail/admin.py:39
msgid "The action applied to the mail. This action is only performed when documents were consumed from the mail. Mails without attachments will remain entirely untouched."
msgstr "Akcja zastosowana do wiadomości. Ta akcja jest wykonywana tylko wtedy, gdy dokumenty zostały przetworzone z wiadomości. Poczta bez załączników pozostanie całkowicie niezmieniona."
#: paperless_mail/admin.py:46
msgid "Metadata"
msgstr "Metadane"
#: paperless_mail/admin.py:48
msgid "Assign metadata to documents consumed from this rule automatically. If you do not assign tags, types or correspondents here, paperless will still process all matching rules that you have defined."
msgstr "Przypisz metadane do dokumentów zużywanych z tej reguły automatycznie. Jeśli nie przypisujesz tutaj tagów, typów lub korespondentów, Paperless będzie nadal przetwarzał wszystkie zdefiniowane przez Ciebie reguły."
#: paperless_mail/apps.py:9
msgid "Paperless mail"
msgstr "Poczta Paperless"
#: paperless_mail/models.py:11
msgid "mail account"
msgstr "konto pocztowe"
#: paperless_mail/models.py:12
msgid "mail accounts"
msgstr "konta pocztowe"
#: paperless_mail/models.py:19
msgid "No encryption"
msgstr "Brak szyfrowania"
#: paperless_mail/models.py:20
msgid "Use SSL"
msgstr "Użyj SSL"
#: paperless_mail/models.py:21
msgid "Use STARTTLS"
msgstr "Użyj STARTTLS"
#: paperless_mail/models.py:29
msgid "IMAP server"
msgstr "Serwer IMAP"
#: paperless_mail/models.py:33
msgid "IMAP port"
msgstr "Port IMAP"
#: paperless_mail/models.py:36
msgid "This is usually 143 for unencrypted and STARTTLS connections, and 993 for SSL connections."
msgstr "Zwykle jest to 143 dla połączeń niezaszyfrowanych i STARTTLS oraz 993 dla połączeń SSL."
#: paperless_mail/models.py:40
msgid "IMAP security"
msgstr "Zabezpieczenia IMAP"
#: paperless_mail/models.py:46
msgid "username"
msgstr "nazwa użytkownika"
#: paperless_mail/models.py:50
msgid "password"
msgstr "hasło"
#: paperless_mail/models.py:60
msgid "mail rule"
msgstr "reguła wiadomości"
#: paperless_mail/models.py:61
msgid "mail rules"
msgstr "reguły wiadomości"
#: paperless_mail/models.py:67
msgid "Only process attachments."
msgstr "Przetwarzaj tylko załączniki."
#: paperless_mail/models.py:68
msgid "Process all files, including 'inline' attachments."
msgstr "Przetwarzaj wszystkie pliki, łącznie z załącznikami „inline”."
#: paperless_mail/models.py:78
msgid "Mark as read, don't process read mails"
msgstr "Oznacz jako przeczytane, nie przetwarzaj przeczytanych wiadomości"
#: paperless_mail/models.py:79
msgid "Flag the mail, don't process flagged mails"
msgstr "Oznacz wiadomość, nie przetwarzaj oznaczonych wiadomości"
#: paperless_mail/models.py:80
msgid "Move to specified folder"
msgstr "Przenieś do określonego folderu"
#: paperless_mail/models.py:81
msgid "Delete"
msgstr "Usuń"
#: paperless_mail/models.py:88
msgid "Use subject as title"
msgstr "Użyj tematu jako tytułu"
#: paperless_mail/models.py:89
msgid "Use attachment filename as title"
msgstr "Użyj nazwy pliku załącznika jako tytułu"
#: paperless_mail/models.py:99
msgid "Do not assign a correspondent"
msgstr "Nie przypisuj korespondenta"
#: paperless_mail/models.py:101
msgid "Use mail address"
msgstr "Użyj adresu e-mail"
#: paperless_mail/models.py:103
msgid "Use name (or mail address if not available)"
msgstr "Użyj nazwy nadawcy (lub adresu e-mail, jeśli jest niedostępna)"
#: paperless_mail/models.py:105
msgid "Use correspondent selected below"
msgstr "Użyj korespondenta wybranego poniżej"
#: paperless_mail/models.py:113
msgid "order"
msgstr "kolejność"
#: paperless_mail/models.py:120
msgid "account"
msgstr "konto"
#: paperless_mail/models.py:124
msgid "folder"
msgstr "folder"
#: paperless_mail/models.py:128
msgid "filter from"
msgstr "filtruj po nadawcy"
#: paperless_mail/models.py:131
msgid "filter subject"
msgstr "filtruj po temacie"
#: paperless_mail/models.py:134
msgid "filter body"
msgstr "filtruj po treści"
#: paperless_mail/models.py:138
msgid "filter attachment filename"
msgstr "filtruj po nazwie pliku załącznika"
#: paperless_mail/models.py:140
msgid "Only consume documents which entirely match this filename if specified. Wildcards such as *.pdf or *invoice* are allowed. Case insensitive."
msgstr "Przetwarzaj tylko dokumenty, które całkowicie pasują do tej nazwy pliku, jeśli jest podana. Wzorce dopasowania jak *.pdf lub *faktura* są dozwolone. Wielkość liter nie jest rozróżniana."
#: paperless_mail/models.py:146
msgid "maximum age"
msgstr "nie starsze niż"
#: paperless_mail/models.py:148
msgid "Specified in days."
msgstr "dni."
#: paperless_mail/models.py:151
msgid "attachment type"
msgstr "typ załącznika"
#: paperless_mail/models.py:154
msgid "Inline attachments include embedded images, so it's best to combine this option with a filename filter."
msgstr "Załączniki typu \"inline\" zawierają osadzone obrazy, więc najlepiej połączyć tę opcję z filtrem nazwy pliku."
#: paperless_mail/models.py:159
msgid "action"
msgstr "akcja"
#: paperless_mail/models.py:165
msgid "action parameter"
msgstr "parametr akcji"
#: paperless_mail/models.py:167
msgid "Additional parameter for the action selected above, i.e., the target folder of the move to folder action."
msgstr "Dodatkowy parametr dla akcji wybranej powyżej, tj. docelowy folder akcji \"Przenieś do określonego folderu\"."
#: paperless_mail/models.py:173
msgid "assign title from"
msgstr "przypisz tytuł"
#: paperless_mail/models.py:183
msgid "assign this tag"
msgstr "przypisz ten tag"
#: paperless_mail/models.py:191
msgid "assign this document type"
msgstr "przypisz ten typ dokumentu"
#: paperless_mail/models.py:195
msgid "assign correspondent from"
msgstr "przypisz korespondenta z"
#: paperless_mail/models.py:205
msgid "assign this correspondent"
msgstr "przypisz tego korespondenta"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-14 13:33+0100\n"
"PO-Revision-Date: 2021-03-14 13:57\n"
"POT-Creation-Date: 2021-04-05 22:05+0200\n"
"PO-Revision-Date: 2021-04-05 20:20\n"
"Last-Translator: \n"
"Language-Team: Portuguese, Brazilian\n"
"Language: pt_BR\n"
@@ -226,7 +226,7 @@ msgstr "log"
msgid "logs"
msgstr "logs"
#: documents/models.py:344 documents/models.py:396
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr "visualização"
@@ -250,103 +250,111 @@ msgstr "exibir no painel lateral"
msgid "sort field"
msgstr "ordenar campo"
#: documents/models.py:364
#: documents/models.py:367
msgid "sort reverse"
msgstr "odernar reverso"
#: documents/models.py:370
#: documents/models.py:373
msgid "title contains"
msgstr "título contém"
#: documents/models.py:371
#: documents/models.py:374
msgid "content contains"
msgstr "conteúdo contém"
#: documents/models.py:372
#: documents/models.py:375
msgid "ASN is"
msgstr "NSA é"
#: documents/models.py:373
#: documents/models.py:376
msgid "correspondent is"
msgstr "correspondente é"
#: documents/models.py:374
#: documents/models.py:377
msgid "document type is"
msgstr "tipo de documento é"
#: documents/models.py:375
#: documents/models.py:378
msgid "is in inbox"
msgstr "é caixa de entrada"
#: documents/models.py:376
#: documents/models.py:379
msgid "has tag"
msgstr "contém etiqueta"
#: documents/models.py:377
#: documents/models.py:380
msgid "has any tag"
msgstr "contém qualquer etiqueta"
#: documents/models.py:378
#: documents/models.py:381
msgid "created before"
msgstr "criado antes de"
#: documents/models.py:379
#: documents/models.py:382
msgid "created after"
msgstr "criado depois de"
#: documents/models.py:380
#: documents/models.py:383
msgid "created year is"
msgstr "ano de criação é"
#: documents/models.py:381
#: documents/models.py:384
msgid "created month is"
msgstr "mês de criação é"
#: documents/models.py:382
#: documents/models.py:385
msgid "created day is"
msgstr "dia de criação é"
#: documents/models.py:383
#: documents/models.py:386
msgid "added before"
msgstr "adicionado antes de"
#: documents/models.py:384
#: documents/models.py:387
msgid "added after"
msgstr "adicionado depois de"
#: documents/models.py:385
#: documents/models.py:388
msgid "modified before"
msgstr "modificado antes de"
#: documents/models.py:386
#: documents/models.py:389
msgid "modified after"
msgstr "modificado depois de"
#: documents/models.py:387
#: documents/models.py:390
msgid "does not have tag"
msgstr "não tem etiqueta"
#: documents/models.py:388
#: documents/models.py:391
msgid "does not have ASN"
msgstr ""
#: documents/models.py:389
#: documents/models.py:392
msgid "title or content contains"
msgstr "título ou conteúdo contém"
#: documents/models.py:400
#: documents/models.py:393
msgid "fulltext query"
msgstr ""
#: documents/models.py:394
msgid "more like this"
msgstr ""
#: documents/models.py:405
msgid "rule type"
msgstr "tipo de regra"
#: documents/models.py:404
#: documents/models.py:409
msgid "value"
msgstr "valor"
#: documents/models.py:410
#: documents/models.py:415
msgid "filter rule"
msgstr "regra de filtragem"
#: documents/models.py:411
#: documents/models.py:416
msgid "filter rules"
msgstr "regras de filtragem"
@@ -429,22 +437,26 @@ msgid "Portuguese (Brazil)"
msgstr "Português (Brasil)"
#: paperless/settings.py:304
msgid "Portuguese"
msgstr ""
#: paperless/settings.py:305
msgid "Italian"
msgstr "Italiano"
#: paperless/settings.py:305
#: paperless/settings.py:306
msgid "Romanian"
msgstr "Romeno"
#: paperless/settings.py:306
#: paperless/settings.py:307
msgid "Russian"
msgstr ""
#: paperless/settings.py:307
#: paperless/settings.py:308
msgid "Spanish"
msgstr ""
#: paperless/urls.py:118
#: paperless/urls.py:113
msgid "Paperless-ng administration"
msgstr "Administração do Paperless-ng"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-14 13:33+0100\n"
"PO-Revision-Date: 2021-03-14 13:57\n"
"POT-Creation-Date: 2021-04-05 22:05+0200\n"
"PO-Revision-Date: 2021-04-05 21:31\n"
"Last-Translator: \n"
"Language-Team: Portuguese\n"
"Language: pt_PT\n"
@@ -60,7 +60,7 @@ msgstr "algoritmo correspondente"
#: documents/models.py:55
msgid "is insensitive"
msgstr ""
msgstr "é insensível"
#: documents/models.py:74 documents/models.py:120
msgid "correspondent"
@@ -80,7 +80,7 @@ msgstr "é etiqueta de novo"
#: documents/models.py:89
msgid "Marks this tag as an inbox tag: All newly consumed documents will be tagged with inbox tags."
msgstr ""
msgstr "Marca esta etiqueta como uma etiqueta de entrada. Todos os documentos recentemente consumidos serão etiquetados com a etiqueta de entrada."
#: documents/models.py:94
msgid "tag"
@@ -116,27 +116,27 @@ msgstr "conteúdo"
#: documents/models.py:139
msgid "The raw, text-only data of the document. This field is primarily used for searching."
msgstr ""
msgstr "Os dados de texto, em cru, do documento. Este campo é utilizado principalmente para pesquisar."
#: documents/models.py:144
msgid "mime type"
msgstr ""
msgstr "tipo mime"
#: documents/models.py:155
msgid "checksum"
msgstr ""
msgstr "soma de verificação"
#: documents/models.py:159
msgid "The checksum of the original document."
msgstr ""
msgstr "A soma de verificação do documento original."
#: documents/models.py:163
msgid "archive checksum"
msgstr ""
msgstr "arquivar soma de verificação"
#: documents/models.py:168
msgid "The checksum of the archived document."
msgstr ""
msgstr "A soma de verificação do documento arquivado."
#: documents/models.py:172 documents/models.py:328
msgid "created"
@@ -160,23 +160,23 @@ msgstr "nome de ficheiro"
#: documents/models.py:198
msgid "Current filename in storage"
msgstr ""
msgstr "Nome do arquivo atual no armazenamento"
#: documents/models.py:202
msgid "archive filename"
msgstr ""
msgstr "nome do ficheiro de arquivo"
#: documents/models.py:208
msgid "Current archive filename in storage"
msgstr ""
msgstr "Nome do arquivo atual em no armazenamento"
#: documents/models.py:212
msgid "archive serial number"
msgstr ""
msgstr "numero de série de arquivo"
#: documents/models.py:217
msgid "The position of this document in your physical document archive."
msgstr ""
msgstr "A posição do documento no seu arquivo físico de documentos."
#: documents/models.py:223
msgid "document"
@@ -226,13 +226,13 @@ msgstr "registo"
msgid "logs"
msgstr "registos"
#: documents/models.py:344 documents/models.py:396
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr ""
msgstr "vista guardada"
#: documents/models.py:345
msgid "saved views"
msgstr ""
msgstr "vistas guardadas"
#: documents/models.py:348
msgid "user"
@@ -244,165 +244,173 @@ msgstr "exibir no painel de controlo"
#: documents/models.py:357
msgid "show in sidebar"
msgstr ""
msgstr "mostrar na navegação lateral"
#: documents/models.py:361
msgid "sort field"
msgstr ""
msgstr "ordenar campo"
#: documents/models.py:364
#: documents/models.py:367
msgid "sort reverse"
msgstr ""
#: documents/models.py:370
msgid "title contains"
msgstr ""
#: documents/models.py:371
msgid "content contains"
msgstr ""
#: documents/models.py:372
msgid "ASN is"
msgstr ""
msgstr "ordenar inversamente"
#: documents/models.py:373
msgid "correspondent is"
msgstr ""
msgid "title contains"
msgstr "o título contém"
#: documents/models.py:374
msgid "document type is"
msgstr ""
msgid "content contains"
msgstr "o conteúdo contém"
#: documents/models.py:375
msgid "is in inbox"
msgstr ""
msgid "ASN is"
msgstr "O NSA é"
#: documents/models.py:376
msgid "has tag"
msgstr ""
msgid "correspondent is"
msgstr "o correspondente é"
#: documents/models.py:377
msgid "has any tag"
msgstr ""
msgid "document type is"
msgstr "o tipo de documento é"
#: documents/models.py:378
msgid "created before"
msgstr ""
msgid "is in inbox"
msgstr "está na entrada"
#: documents/models.py:379
msgid "created after"
msgstr ""
msgid "has tag"
msgstr "tem etiqueta"
#: documents/models.py:380
msgid "created year is"
msgstr ""
msgid "has any tag"
msgstr "tem qualquer etiqueta"
#: documents/models.py:381
msgid "created month is"
msgstr ""
msgid "created before"
msgstr "criado antes"
#: documents/models.py:382
msgid "created day is"
msgstr ""
msgid "created after"
msgstr "criado depois"
#: documents/models.py:383
msgid "added before"
msgstr ""
msgid "created year is"
msgstr "ano criada é"
#: documents/models.py:384
msgid "added after"
msgstr ""
msgid "created month is"
msgstr "mês criado é"
#: documents/models.py:385
msgid "modified before"
msgstr ""
msgid "created day is"
msgstr "dia criado é"
#: documents/models.py:386
msgid "modified after"
msgstr ""
msgid "added before"
msgstr "adicionada antes"
#: documents/models.py:387
msgid "does not have tag"
msgstr ""
msgid "added after"
msgstr "adicionado depois de"
#: documents/models.py:388
msgid "does not have ASN"
msgstr ""
msgid "modified before"
msgstr "modificado antes de"
#: documents/models.py:389
msgid "modified after"
msgstr "modificado depois de"
#: documents/models.py:390
msgid "does not have tag"
msgstr "não tem etiqueta"
#: documents/models.py:391
msgid "does not have ASN"
msgstr "não possui um NSA"
#: documents/models.py:392
msgid "title or content contains"
msgstr ""
msgstr "título ou conteúdo contém"
#: documents/models.py:400
#: documents/models.py:393
msgid "fulltext query"
msgstr "consulta de texto completo"
#: documents/models.py:394
msgid "more like this"
msgstr "mais como este"
#: documents/models.py:405
msgid "rule type"
msgstr ""
msgstr "tipo de regra"
#: documents/models.py:404
#: documents/models.py:409
msgid "value"
msgstr ""
msgstr "valor"
#: documents/models.py:410
#: documents/models.py:415
msgid "filter rule"
msgstr ""
msgstr "regra de filtragem"
#: documents/models.py:411
#: documents/models.py:416
msgid "filter rules"
msgstr ""
msgstr "regras de filtragem"
#: documents/serialisers.py:53
#, python-format
msgid "Invalid regular expression: %(error)s"
msgstr ""
msgstr "Expressão regular inválida: %(error)s"
#: documents/serialisers.py:177
msgid "Invalid color."
msgstr ""
msgstr "Cor invalida."
#: documents/serialisers.py:451
#, python-format
msgid "File type %(type)s not supported"
msgstr ""
msgstr "Tipo de arquivo %(type)s não suportado"
#: documents/templates/index.html:21
msgid "Paperless-ng is loading..."
msgstr ""
msgstr "O paperless-ng está a carregar..."
#: documents/templates/registration/logged_out.html:13
msgid "Paperless-ng signed out"
msgstr ""
msgstr "Paperless-ng com sessão terminada"
#: documents/templates/registration/logged_out.html:41
msgid "You have been successfully logged out. Bye!"
msgstr ""
msgstr "Terminou a sessão com sucesso. Adeus!"
#: documents/templates/registration/logged_out.html:42
msgid "Sign in again"
msgstr ""
msgstr "Iniciar sessão novamente"
#: documents/templates/registration/login.html:13
msgid "Paperless-ng sign in"
msgstr ""
msgstr "Inicio de sessão Paperless-ng"
#: documents/templates/registration/login.html:42
msgid "Please sign in."
msgstr ""
msgstr "Por favor inicie sessão."
#: documents/templates/registration/login.html:45
msgid "Your username and password didn't match. Please try again."
msgstr ""
msgstr "O utilizador e a senha não correspondem. Tente novamente."
#: documents/templates/registration/login.html:48
msgid "Username"
msgstr ""
msgstr "Nome de utilizador"
#: documents/templates/registration/login.html:49
msgid "Password"
msgstr ""
msgstr "Palavra-passe"
#: documents/templates/registration/login.html:54
msgid "Sign in"
msgstr ""
msgstr "Iniciar sessão"
#: paperless/settings.py:298
msgid "English (US)"
@@ -426,35 +434,39 @@ msgstr "Français"
#: paperless/settings.py:303
msgid "Portuguese (Brazil)"
msgstr ""
msgstr "Português (Brasil)"
#: paperless/settings.py:304
msgid "Italian"
msgstr ""
msgid "Portuguese"
msgstr "Português"
#: paperless/settings.py:305
msgid "Romanian"
msgstr ""
msgid "Italian"
msgstr "Italiano"
#: paperless/settings.py:306
msgid "Romanian"
msgstr "Romeno"
#: paperless/settings.py:307
msgid "Russian"
msgstr "Russo"
#: paperless/settings.py:307
#: paperless/settings.py:308
msgid "Spanish"
msgstr ""
msgstr "Espanhol"
#: paperless/urls.py:118
#: paperless/urls.py:113
msgid "Paperless-ng administration"
msgstr ""
msgstr "Administração do Paperless-ng"
#: paperless_mail/admin.py:25
msgid "Filter"
msgstr ""
msgstr "Filtro"
#: paperless_mail/admin.py:27
msgid "Paperless will only process mails that match ALL of the filters given below."
msgstr ""
msgstr "O Paperless apenas irá processar emails que coincidem com TODOS os filtros dados abaixo."
#: paperless_mail/admin.py:37
msgid "Actions"
@@ -462,7 +474,7 @@ msgstr "Ações"
#: paperless_mail/admin.py:39
msgid "The action applied to the mail. This action is only performed when documents were consumed from the mail. Mails without attachments will remain entirely untouched."
msgstr ""
msgstr "A ação aplicada a correio. Esta ação apenas será efetuada com documentos que tenham sido consumidos através do correio. E-mails sem anexos permanecerão intactos."
#: paperless_mail/admin.py:46
msgid "Metadata"
@@ -470,83 +482,83 @@ msgstr "Metadados"
#: paperless_mail/admin.py:48
msgid "Assign metadata to documents consumed from this rule automatically. If you do not assign tags, types or correspondents here, paperless will still process all matching rules that you have defined."
msgstr ""
msgstr "Atribuir meta-dados aos documentos consumidos automaticamente através desta regra. Se você não atribuir etiquetas, tipos ou correspondentes aqui, o paperless ainda assim processará todas as regras correspondentes que tenha definido."
#: paperless_mail/apps.py:9
msgid "Paperless mail"
msgstr ""
msgstr "Correio Paperless"
#: paperless_mail/models.py:11
msgid "mail account"
msgstr ""
msgstr "conta de email"
#: paperless_mail/models.py:12
msgid "mail accounts"
msgstr ""
msgstr "contas de email"
#: paperless_mail/models.py:19
msgid "No encryption"
msgstr ""
msgstr "Sem encriptação"
#: paperless_mail/models.py:20
msgid "Use SSL"
msgstr ""
msgstr "Utilizar SSL"
#: paperless_mail/models.py:21
msgid "Use STARTTLS"
msgstr ""
msgstr "Utilizar STARTTLS"
#: paperless_mail/models.py:29
msgid "IMAP server"
msgstr ""
msgstr "Servidor IMAP"
#: paperless_mail/models.py:33
msgid "IMAP port"
msgstr ""
msgstr "Porto IMAP"
#: paperless_mail/models.py:36
msgid "This is usually 143 for unencrypted and STARTTLS connections, and 993 for SSL connections."
msgstr ""
msgstr "Por norma é o 143 sem encriptação e conexões STARTTLS, e o 993 para conexões com SSL."
#: paperless_mail/models.py:40
msgid "IMAP security"
msgstr ""
msgstr "Segurança IMAP"
#: paperless_mail/models.py:46
msgid "username"
msgstr ""
msgstr "nome de utilizador"
#: paperless_mail/models.py:50
msgid "password"
msgstr ""
msgstr "palavra-passe"
#: paperless_mail/models.py:60
msgid "mail rule"
msgstr ""
msgstr "regra de correio"
#: paperless_mail/models.py:61
msgid "mail rules"
msgstr ""
msgstr "regras de correio"
#: paperless_mail/models.py:67
msgid "Only process attachments."
msgstr ""
msgstr "Processar anexos apenas."
#: paperless_mail/models.py:68
msgid "Process all files, including 'inline' attachments."
msgstr ""
msgstr "Processar todos os ficheiros, incluindo ficheiros 'embutidos (inline)'."
#: paperless_mail/models.py:78
msgid "Mark as read, don't process read mails"
msgstr ""
msgstr "Marcar como lido, não processar emails lidos"
#: paperless_mail/models.py:79
msgid "Flag the mail, don't process flagged mails"
msgstr ""
msgstr "Marcar o email, não processar emails marcados"
#: paperless_mail/models.py:80
msgid "Move to specified folder"
msgstr ""
msgstr "Mover para uma diretoria específica"
#: paperless_mail/models.py:81
msgid "Delete"
@@ -554,105 +566,105 @@ msgstr "Excluir"
#: paperless_mail/models.py:88
msgid "Use subject as title"
msgstr ""
msgstr "Utilizar o assunto como título"
#: paperless_mail/models.py:89
msgid "Use attachment filename as title"
msgstr ""
msgstr "Utilizar o nome do anexo como título"
#: paperless_mail/models.py:99
msgid "Do not assign a correspondent"
msgstr ""
msgstr "Não atribuir um correspondente"
#: paperless_mail/models.py:101
msgid "Use mail address"
msgstr ""
msgstr "Utilizar o endereço de email"
#: paperless_mail/models.py:103
msgid "Use name (or mail address if not available)"
msgstr ""
msgstr "Utilizar nome (ou endereço de email se não disponível)"
#: paperless_mail/models.py:105
msgid "Use correspondent selected below"
msgstr ""
msgstr "Utilizar o correspondente selecionado abaixo"
#: paperless_mail/models.py:113
msgid "order"
msgstr ""
msgstr "ordem"
#: paperless_mail/models.py:120
msgid "account"
msgstr ""
msgstr "conta"
#: paperless_mail/models.py:124
msgid "folder"
msgstr ""
msgstr "directoria"
#: paperless_mail/models.py:128
msgid "filter from"
msgstr ""
msgstr "filtrar de"
#: paperless_mail/models.py:131
msgid "filter subject"
msgstr ""
msgstr "filtrar assunto"
#: paperless_mail/models.py:134
msgid "filter body"
msgstr ""
msgstr "filtrar corpo"
#: paperless_mail/models.py:138
msgid "filter attachment filename"
msgstr ""
msgstr "filtrar nome do arquivo anexo"
#: paperless_mail/models.py:140
msgid "Only consume documents which entirely match this filename if specified. Wildcards such as *.pdf or *invoice* are allowed. Case insensitive."
msgstr ""
msgstr "Consumir apenas documentos que correspondam inteiramente ao nome de arquivo se especificado. Genéricos como *.pdf ou *fatura* são permitidos. Não é sensível a letras maiúsculas/minúsculas."
#: paperless_mail/models.py:146
msgid "maximum age"
msgstr ""
msgstr "idade máxima"
#: paperless_mail/models.py:148
msgid "Specified in days."
msgstr ""
msgstr "Especificado em dias."
#: paperless_mail/models.py:151
msgid "attachment type"
msgstr ""
msgstr "tipo de anexo"
#: paperless_mail/models.py:154
msgid "Inline attachments include embedded images, so it's best to combine this option with a filename filter."
msgstr ""
msgstr "Anexos embutidos incluem imagens incorporadas, por isso é melhor combinar esta opção com um filtro de nome do arquivo."
#: paperless_mail/models.py:159
msgid "action"
msgstr ""
msgstr "ação"
#: paperless_mail/models.py:165
msgid "action parameter"
msgstr ""
msgstr "parâmetro de ação"
#: paperless_mail/models.py:167
msgid "Additional parameter for the action selected above, i.e., the target folder of the move to folder action."
msgstr ""
msgstr "Parâmetro adicional para a ação selecionada acima, isto é, a diretoria de destino do movimento da ação para a pasta."
#: paperless_mail/models.py:173
msgid "assign title from"
msgstr ""
msgstr "atribuir titulo de"
#: paperless_mail/models.py:183
msgid "assign this tag"
msgstr ""
msgstr "atribuir esta etiqueta"
#: paperless_mail/models.py:191
msgid "assign this document type"
msgstr ""
msgstr "atribuir este tipo de documento"
#: paperless_mail/models.py:195
msgid "assign correspondent from"
msgstr ""
msgstr "atribuir correspondente de"
#: paperless_mail/models.py:205
msgid "assign this correspondent"
msgstr ""
msgstr "atribuir este correspondente"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-14 13:33+0100\n"
"PO-Revision-Date: 2021-03-14 13:57\n"
"POT-Creation-Date: 2021-04-05 22:05+0200\n"
"PO-Revision-Date: 2021-04-05 20:19\n"
"Last-Translator: \n"
"Language-Team: Romanian\n"
"Language: ro_RO\n"
@@ -226,7 +226,7 @@ msgstr "jurnal"
msgid "logs"
msgstr "jurnale"
#: documents/models.py:344 documents/models.py:396
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr "vizualizare"
@@ -250,103 +250,111 @@ msgstr "afișează in bara laterala"
msgid "sort field"
msgstr "sortează camp"
#: documents/models.py:364
#: documents/models.py:367
msgid "sort reverse"
msgstr "sortează invers"
#: documents/models.py:370
#: documents/models.py:373
msgid "title contains"
msgstr "titlul conține"
#: documents/models.py:371
#: documents/models.py:374
msgid "content contains"
msgstr "conținutul conține"
#: documents/models.py:372
#: documents/models.py:375
msgid "ASN is"
msgstr "Avizul prealabil de expediție este"
#: documents/models.py:373
#: documents/models.py:376
msgid "correspondent is"
msgstr "corespondentul este"
#: documents/models.py:374
#: documents/models.py:377
msgid "document type is"
msgstr "tipul documentului este"
#: documents/models.py:375
#: documents/models.py:378
msgid "is in inbox"
msgstr "este în inbox"
#: documents/models.py:376
#: documents/models.py:379
msgid "has tag"
msgstr "are eticheta"
#: documents/models.py:377
#: documents/models.py:380
msgid "has any tag"
msgstr "are orice eticheta"
#: documents/models.py:378
#: documents/models.py:381
msgid "created before"
msgstr "creat înainte de"
#: documents/models.py:379
#: documents/models.py:382
msgid "created after"
msgstr "creat după"
#: documents/models.py:380
#: documents/models.py:383
msgid "created year is"
msgstr "anul creării este"
#: documents/models.py:381
#: documents/models.py:384
msgid "created month is"
msgstr "luna creării este"
#: documents/models.py:382
#: documents/models.py:385
msgid "created day is"
msgstr "ziua creării este"
#: documents/models.py:383
#: documents/models.py:386
msgid "added before"
msgstr "adăugat înainte de"
#: documents/models.py:384
#: documents/models.py:387
msgid "added after"
msgstr "adăugat după"
#: documents/models.py:385
#: documents/models.py:388
msgid "modified before"
msgstr "modificat înainte de"
#: documents/models.py:386
#: documents/models.py:389
msgid "modified after"
msgstr "modificat după"
#: documents/models.py:387
#: documents/models.py:390
msgid "does not have tag"
msgstr "nu are etichetă"
#: documents/models.py:388
#: documents/models.py:391
msgid "does not have ASN"
msgstr "nu are aviz prealabil de expediție"
#: documents/models.py:389
#: documents/models.py:392
msgid "title or content contains"
msgstr "titlul sau conținutul conține"
#: documents/models.py:400
#: documents/models.py:393
msgid "fulltext query"
msgstr ""
#: documents/models.py:394
msgid "more like this"
msgstr ""
#: documents/models.py:405
msgid "rule type"
msgstr "tip de regula"
#: documents/models.py:404
#: documents/models.py:409
msgid "value"
msgstr "valoare"
#: documents/models.py:410
#: documents/models.py:415
msgid "filter rule"
msgstr "regulă de filtrare"
#: documents/models.py:411
#: documents/models.py:416
msgid "filter rules"
msgstr "reguli de filtrare"
@@ -429,22 +437,26 @@ msgid "Portuguese (Brazil)"
msgstr "Portugheză (Brazilia)"
#: paperless/settings.py:304
msgid "Portuguese"
msgstr "Portugheză"
#: paperless/settings.py:305
msgid "Italian"
msgstr "Italiană"
#: paperless/settings.py:305
#: paperless/settings.py:306
msgid "Romanian"
msgstr "Română"
#: paperless/settings.py:306
#: paperless/settings.py:307
msgid "Russian"
msgstr "Rusă"
#: paperless/settings.py:307
#: paperless/settings.py:308
msgid "Spanish"
msgstr ""
msgstr "Spaniolă"
#: paperless/urls.py:118
#: paperless/urls.py:113
msgid "Paperless-ng administration"
msgstr "Administrare Paperless-ng"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-14 13:33+0100\n"
"PO-Revision-Date: 2021-03-14 13:57\n"
"POT-Creation-Date: 2021-04-05 22:05+0200\n"
"PO-Revision-Date: 2021-04-05 21:31\n"
"Last-Translator: \n"
"Language-Team: Russian\n"
"Language: ru_RU\n"
@@ -226,7 +226,7 @@ msgstr "журнал"
msgid "logs"
msgstr "логи"
#: documents/models.py:344 documents/models.py:396
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr "сохранённое представление"
@@ -250,103 +250,111 @@ msgstr "показать в боковой панели"
msgid "sort field"
msgstr "Поле сортировки"
#: documents/models.py:364
#: documents/models.py:367
msgid "sort reverse"
msgstr "обратная сортировка"
#: documents/models.py:370
#: documents/models.py:373
msgid "title contains"
msgstr "заголовок содержит"
#: documents/models.py:371
#: documents/models.py:374
msgid "content contains"
msgstr "содержимое содержит"
#: documents/models.py:372
#: documents/models.py:375
msgid "ASN is"
msgstr "АН"
#: documents/models.py:373
#: documents/models.py:376
msgid "correspondent is"
msgstr "корреспондент"
#: documents/models.py:374
#: documents/models.py:377
msgid "document type is"
msgstr "тип документа"
#: documents/models.py:375
#: documents/models.py:378
msgid "is in inbox"
msgstr "во входящих"
#: documents/models.py:376
#: documents/models.py:379
msgid "has tag"
msgstr "есть тег"
#: documents/models.py:377
#: documents/models.py:380
msgid "has any tag"
msgstr "есть любой тег"
#: documents/models.py:378
#: documents/models.py:381
msgid "created before"
msgstr "создан до"
#: documents/models.py:379
#: documents/models.py:382
msgid "created after"
msgstr "создан после"
#: documents/models.py:380
#: documents/models.py:383
msgid "created year is"
msgstr "год создания"
#: documents/models.py:381
#: documents/models.py:384
msgid "created month is"
msgstr "месяц создания"
#: documents/models.py:382
#: documents/models.py:385
msgid "created day is"
msgstr "день создания"
#: documents/models.py:383
#: documents/models.py:386
msgid "added before"
msgstr "добавлен до"
#: documents/models.py:384
#: documents/models.py:387
msgid "added after"
msgstr "добавлен после"
#: documents/models.py:385
#: documents/models.py:388
msgid "modified before"
msgstr "изменен до"
#: documents/models.py:386
#: documents/models.py:389
msgid "modified after"
msgstr "изменен после"
#: documents/models.py:387
#: documents/models.py:390
msgid "does not have tag"
msgstr "не имеет тега"
#: documents/models.py:388
#: documents/models.py:391
msgid "does not have ASN"
msgstr ""
msgstr "не имеет архивного номера"
#: documents/models.py:389
#: documents/models.py:392
msgid "title or content contains"
msgstr ""
msgstr "Название или содержимое включает"
#: documents/models.py:400
#: documents/models.py:393
msgid "fulltext query"
msgstr "полнотекстовый запрос"
#: documents/models.py:394
msgid "more like this"
msgstr "больше похожих"
#: documents/models.py:405
msgid "rule type"
msgstr "Тип правила"
#: documents/models.py:404
#: documents/models.py:409
msgid "value"
msgstr "значение"
#: documents/models.py:410
#: documents/models.py:415
msgid "filter rule"
msgstr "Правило фильтрации"
#: documents/models.py:411
#: documents/models.py:416
msgid "filter rules"
msgstr "правила фильтрации"
@@ -429,22 +437,26 @@ msgid "Portuguese (Brazil)"
msgstr "Portuguese (Brazil)"
#: paperless/settings.py:304
msgid "Portuguese"
msgstr "Португальский"
#: paperless/settings.py:305
msgid "Italian"
msgstr "Italian"
#: paperless/settings.py:305
#: paperless/settings.py:306
msgid "Romanian"
msgstr "Romanian"
#: paperless/settings.py:306
msgid "Russian"
msgstr ""
#: paperless/settings.py:307
msgid "Spanish"
msgstr ""
msgid "Russian"
msgstr "Русский"
#: paperless/urls.py:118
#: paperless/settings.py:308
msgid "Spanish"
msgstr "Испанский"
#: paperless/urls.py:113
msgid "Paperless-ng administration"
msgstr "Администрирование Paperless-ng"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-14 13:33+0100\n"
"PO-Revision-Date: 2021-03-14 13:57\n"
"POT-Creation-Date: 2021-04-05 22:05+0200\n"
"PO-Revision-Date: 2021-04-05 20:20\n"
"Last-Translator: \n"
"Language-Team: Xhosa\n"
"Language: xh_ZA\n"
@@ -226,7 +226,7 @@ msgstr "crwdns2628:0crwdne2628:0"
msgid "logs"
msgstr "crwdns2630:0crwdne2630:0"
#: documents/models.py:344 documents/models.py:396
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr "crwdns2632:0crwdne2632:0"
@@ -250,103 +250,111 @@ msgstr "crwdns2640:0crwdne2640:0"
msgid "sort field"
msgstr "crwdns2642:0crwdne2642:0"
#: documents/models.py:364
#: documents/models.py:367
msgid "sort reverse"
msgstr "crwdns2644:0crwdne2644:0"
#: documents/models.py:370
#: documents/models.py:373
msgid "title contains"
msgstr "crwdns2646:0crwdne2646:0"
#: documents/models.py:371
#: documents/models.py:374
msgid "content contains"
msgstr "crwdns2648:0crwdne2648:0"
#: documents/models.py:372
#: documents/models.py:375
msgid "ASN is"
msgstr "crwdns2650:0crwdne2650:0"
#: documents/models.py:373
#: documents/models.py:376
msgid "correspondent is"
msgstr "crwdns2652:0crwdne2652:0"
#: documents/models.py:374
#: documents/models.py:377
msgid "document type is"
msgstr "crwdns2654:0crwdne2654:0"
#: documents/models.py:375
#: documents/models.py:378
msgid "is in inbox"
msgstr "crwdns2656:0crwdne2656:0"
#: documents/models.py:376
#: documents/models.py:379
msgid "has tag"
msgstr "crwdns2658:0crwdne2658:0"
#: documents/models.py:377
#: documents/models.py:380
msgid "has any tag"
msgstr "crwdns2660:0crwdne2660:0"
#: documents/models.py:378
#: documents/models.py:381
msgid "created before"
msgstr "crwdns2662:0crwdne2662:0"
#: documents/models.py:379
#: documents/models.py:382
msgid "created after"
msgstr "crwdns2664:0crwdne2664:0"
#: documents/models.py:380
#: documents/models.py:383
msgid "created year is"
msgstr "crwdns2666:0crwdne2666:0"
#: documents/models.py:381
#: documents/models.py:384
msgid "created month is"
msgstr "crwdns2668:0crwdne2668:0"
#: documents/models.py:382
#: documents/models.py:385
msgid "created day is"
msgstr "crwdns2670:0crwdne2670:0"
#: documents/models.py:383
#: documents/models.py:386
msgid "added before"
msgstr "crwdns2672:0crwdne2672:0"
#: documents/models.py:384
#: documents/models.py:387
msgid "added after"
msgstr "crwdns2674:0crwdne2674:0"
#: documents/models.py:385
#: documents/models.py:388
msgid "modified before"
msgstr "crwdns2676:0crwdne2676:0"
#: documents/models.py:386
#: documents/models.py:389
msgid "modified after"
msgstr "crwdns2678:0crwdne2678:0"
#: documents/models.py:387
#: documents/models.py:390
msgid "does not have tag"
msgstr "crwdns2680:0crwdne2680:0"
#: documents/models.py:388
#: documents/models.py:391
msgid "does not have ASN"
msgstr "crwdns3408:0crwdne3408:0"
#: documents/models.py:389
#: documents/models.py:392
msgid "title or content contains"
msgstr "crwdns3410:0crwdne3410:0"
#: documents/models.py:400
#: documents/models.py:393
msgid "fulltext query"
msgstr "crwdns3438:0crwdne3438:0"
#: documents/models.py:394
msgid "more like this"
msgstr "crwdns3440:0crwdne3440:0"
#: documents/models.py:405
msgid "rule type"
msgstr "crwdns2682:0crwdne2682:0"
#: documents/models.py:404
#: documents/models.py:409
msgid "value"
msgstr "crwdns2684:0crwdne2684:0"
#: documents/models.py:410
#: documents/models.py:415
msgid "filter rule"
msgstr "crwdns2686:0crwdne2686:0"
#: documents/models.py:411
#: documents/models.py:416
msgid "filter rules"
msgstr "crwdns2688:0crwdne2688:0"
@@ -429,22 +437,26 @@ msgid "Portuguese (Brazil)"
msgstr "crwdns2726:0crwdne2726:0"
#: paperless/settings.py:304
msgid "Portuguese"
msgstr "crwdns3424:0crwdne3424:0"
#: paperless/settings.py:305
msgid "Italian"
msgstr "crwdns2728:0crwdne2728:0"
#: paperless/settings.py:305
#: paperless/settings.py:306
msgid "Romanian"
msgstr "crwdns2730:0crwdne2730:0"
#: paperless/settings.py:306
#: paperless/settings.py:307
msgid "Russian"
msgstr "crwdns3414:0crwdne3414:0"
#: paperless/settings.py:307
#: paperless/settings.py:308
msgid "Spanish"
msgstr "crwdns3420:0crwdne3420:0"
#: paperless/urls.py:118
#: paperless/urls.py:113
msgid "Paperless-ng administration"
msgstr "crwdns2732:0crwdne2732:0"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-14 13:33+0100\n"
"PO-Revision-Date: 2021-03-14 13:57\n"
"POT-Creation-Date: 2021-04-05 22:05+0200\n"
"PO-Revision-Date: 2021-04-05 20:20\n"
"Last-Translator: \n"
"Language-Team: Chinese Simplified\n"
"Language: zh_CN\n"
@@ -226,7 +226,7 @@ msgstr ""
msgid "logs"
msgstr ""
#: documents/models.py:344 documents/models.py:396
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr ""
@@ -250,103 +250,111 @@ msgstr ""
msgid "sort field"
msgstr ""
#: documents/models.py:364
#: documents/models.py:367
msgid "sort reverse"
msgstr ""
#: documents/models.py:370
#: documents/models.py:373
msgid "title contains"
msgstr ""
#: documents/models.py:371
#: documents/models.py:374
msgid "content contains"
msgstr ""
#: documents/models.py:372
#: documents/models.py:375
msgid "ASN is"
msgstr ""
#: documents/models.py:373
#: documents/models.py:376
msgid "correspondent is"
msgstr ""
#: documents/models.py:374
#: documents/models.py:377
msgid "document type is"
msgstr ""
#: documents/models.py:375
#: documents/models.py:378
msgid "is in inbox"
msgstr ""
#: documents/models.py:376
#: documents/models.py:379
msgid "has tag"
msgstr ""
#: documents/models.py:377
#: documents/models.py:380
msgid "has any tag"
msgstr ""
#: documents/models.py:378
#: documents/models.py:381
msgid "created before"
msgstr ""
#: documents/models.py:379
#: documents/models.py:382
msgid "created after"
msgstr ""
#: documents/models.py:380
#: documents/models.py:383
msgid "created year is"
msgstr ""
#: documents/models.py:381
#: documents/models.py:384
msgid "created month is"
msgstr ""
#: documents/models.py:382
#: documents/models.py:385
msgid "created day is"
msgstr ""
#: documents/models.py:383
#: documents/models.py:386
msgid "added before"
msgstr ""
#: documents/models.py:384
#: documents/models.py:387
msgid "added after"
msgstr ""
#: documents/models.py:385
#: documents/models.py:388
msgid "modified before"
msgstr ""
#: documents/models.py:386
#: documents/models.py:389
msgid "modified after"
msgstr ""
#: documents/models.py:387
#: documents/models.py:390
msgid "does not have tag"
msgstr ""
#: documents/models.py:388
#: documents/models.py:391
msgid "does not have ASN"
msgstr ""
#: documents/models.py:389
#: documents/models.py:392
msgid "title or content contains"
msgstr ""
#: documents/models.py:400
#: documents/models.py:393
msgid "fulltext query"
msgstr ""
#: documents/models.py:394
msgid "more like this"
msgstr ""
#: documents/models.py:405
msgid "rule type"
msgstr ""
#: documents/models.py:404
#: documents/models.py:409
msgid "value"
msgstr ""
#: documents/models.py:410
#: documents/models.py:415
msgid "filter rule"
msgstr ""
#: documents/models.py:411
#: documents/models.py:416
msgid "filter rules"
msgstr ""
@@ -429,22 +437,26 @@ msgid "Portuguese (Brazil)"
msgstr ""
#: paperless/settings.py:304
msgid "Italian"
msgid "Portuguese"
msgstr ""
#: paperless/settings.py:305
msgid "Romanian"
msgid "Italian"
msgstr ""
#: paperless/settings.py:306
msgid "Russian"
msgid "Romanian"
msgstr ""
#: paperless/settings.py:307
msgid "Russian"
msgstr ""
#: paperless/settings.py:308
msgid "Spanish"
msgstr ""
#: paperless/urls.py:118
#: paperless/urls.py:113
msgid "Paperless-ng administration"
msgstr ""

View File

@@ -23,9 +23,12 @@ def path_check(var, directory):
exists_hint.format(directory)
))
else:
test_file = os.path.join(directory, '__paperless_write_test__')
test_file = os.path.join(
directory, f'__paperless_write_test_{os.getpid()}__'
)
try:
open(test_file, 'w')
with open(test_file, 'w'):
pass
except PermissionError:
messages.append(Error(
writeable_message.format(var),
@@ -33,8 +36,9 @@ def path_check(var, directory):
f'\n{stat.filemode(os.stat(directory).st_mode)} '
f'{directory}\n')
))
else:
os.remove(test_file)
finally:
if os.path.isfile(test_file):
os.remove(test_file)
return messages

View File

@@ -301,10 +301,12 @@ LANGUAGES = [
("nl-nl", _("Dutch")),
("fr-fr", _("French")),
("pt-br", _("Portuguese (Brazil)")),
("pt-pt", _("Portuguese")),
("it-it", _("Italian")),
("ro-ro", _("Romanian")),
("ru-ru", _("Russian")),
("es-es", _("Spanish"))
("es-es", _("Spanish")),
("pl-pl", _("Polish"))
]
LOCALE_PATHS = [

View File

@@ -12,11 +12,10 @@ from django.utils.translation import gettext_lazy as _
from paperless.consumers import StatusConsumer
from documents.views import (
CorrespondentViewSet,
DocumentViewSet,
UnifiedSearchViewSet,
LogViewSet,
TagViewSet,
DocumentTypeViewSet,
SearchView,
IndexView,
SearchAutoCompleteView,
StatisticsView,
@@ -31,7 +30,7 @@ from paperless.views import FaviconView
api_router = DefaultRouter()
api_router.register(r"correspondents", CorrespondentViewSet)
api_router.register(r"document_types", DocumentTypeViewSet)
api_router.register(r"documents", DocumentViewSet)
api_router.register(r"documents", UnifiedSearchViewSet)
api_router.register(r"logs", LogViewSet, basename="logs")
api_router.register(r"tags", TagViewSet)
api_router.register(r"saved_views", SavedViewViewSet)
@@ -47,10 +46,6 @@ urlpatterns = [
SearchAutoCompleteView.as_view(),
name="autocomplete"),
re_path(r"^search/",
SearchView.as_view(),
name="search"),
re_path(r"^statistics/",
StatisticsView.as_view(),
name="statistics"),

View File

@@ -1 +1 @@
__version__ = (1, 3, 1)
__version__ = (1, 4, 0)

View File

@@ -104,7 +104,7 @@ class RasterisedDocumentParser(DocumentParser):
# This happens when there's already text in the input file.
# The sidecar file will only contain text for OCR'ed pages.
self.log("debug", "Using text from sidecar file")
return text
return post_process_text(text)
else:
self.log("debug", "Incomplete sidecar file: discarding.")
@@ -113,12 +113,12 @@ class RasterisedDocumentParser(DocumentParser):
if not os.path.isfile(pdf_file):
return None
from pdfminer.high_level import extract_text
from pdfminer.high_level import extract_text as pdfminer_extract_text
from pdfminer.pdftypes import PDFException
try:
text = extract_text(pdf_file)
stripped = strip_excess_whitespace(text)
stripped = post_process_text(pdfminer_extract_text(pdf_file))
self.log("debug", f"Extracted text from PDF file {pdf_file}")
return stripped
except PDFException:
@@ -244,9 +244,9 @@ class RasterisedDocumentParser(DocumentParser):
if original_has_text:
self.text = text_original
except (NoTextFoundException, InputFileError) as e:
self.log("exception",
f"Encountered the following error while running OCR, "
f"attempting force OCR to get the text.")
self.log("warning",
f"Encountered an error while running OCR: {str(e)}. "
f"Attempting force OCR to get the text.")
archive_path_fallback = os.path.join(
self.tempdir, "archive-fallback.pdf")
@@ -294,7 +294,7 @@ class RasterisedDocumentParser(DocumentParser):
self.text = ""
def strip_excess_whitespace(text):
def post_process_text(text):
if not text:
return None
@@ -305,4 +305,6 @@ def strip_excess_whitespace(text):
r"([^\S\n\r]+)$", '', no_leading_whitespace)
# TODO: this needs a rework
return no_trailing_whitespace.strip()
# replace \0 prevents issues with saving to postgres.
# text may contain \0 when this character is present in PDF files.
return no_trailing_whitespace.strip().replace("\0", " ")

View File

@@ -7,7 +7,7 @@ from django.test import TestCase, override_settings
from documents.parsers import ParseError, run_convert
from documents.tests.utils import DirectoriesMixin
from paperless_tesseract.parsers import RasterisedDocumentParser, strip_excess_whitespace
from paperless_tesseract.parsers import RasterisedDocumentParser, post_process_text
image_to_string_calls = []
@@ -32,8 +32,6 @@ class FakeImageFile(ContextManager):
return os.path.basename(self.fname)
class TestParser(DirectoriesMixin, TestCase):
def assertContainsStrings(self, content, strings):
@@ -58,9 +56,9 @@ class TestParser(DirectoriesMixin, TestCase):
)
]
def test_strip_excess_whitespace(self):
def test_post_process_text(self):
for source, result in self.text_cases:
actual_result = strip_excess_whitespace(source)
actual_result = post_process_text(source)
self.assertEqual(
result,
actual_result,