Compare commits

...

97 Commits

Author SHA1 Message Date
jonaswinkler
cd43bc1f66 changelog 2021-08-22 17:15:14 +02:00
jonaswinkler
1b24136590 version bump 2021-08-22 17:11:36 +02:00
jonaswinkler
e8d5b549de documentation 2021-08-22 17:10:10 +02:00
jonaswinkler
3866a77d68 Merge branch 'master' into dev 2021-08-22 17:03:58 +02:00
jonaswinkler
360fe68f92 fix whitespace 2021-08-22 17:03:45 +02:00
Jonas Winkler
c9229f9c80 Merge pull request #1066 from holzhannes/patch-3
Info for The input device is not a TTY Errors
2021-08-22 17:02:08 +02:00
Jonas Winkler
e5b92d895d Update docs/administration.rst
Co-authored-by: Stéphane Brunner <stephane.brunner@camptocamp.com>
2021-08-22 17:00:36 +02:00
jonaswinkler
a7643c1c29 Merge branch 'master' into dev 2021-08-22 16:27:59 +02:00
jonaswinkler
45fd4e8565 fix whitespace 2021-08-22 16:27:44 +02:00
jonaswinkler
211a9d720a changelog 2021-08-22 16:26:58 +02:00
Jonas Winkler
da9c2735b4 Merge pull request #1201 from pewter77/patch-1
update configuration docs for languages
2021-08-22 16:26:27 +02:00
jonaswinkler
d31baca442 downgrade numpy due to armv7 issues 2021-08-19 16:18:49 +02:00
jonaswinkler
499d6f79aa Merge remote-tracking branch 'origin/master' into dev 2021-08-19 00:06:47 +02:00
jonaswinkler
49e049f1c5 Merge branch 'dev' of github.com:jonaswinkler/paperless-ng into dev 2021-08-19 00:06:37 +02:00
jonaswinkler
7411d7c1e2 update dependencies 2021-08-19 00:06:23 +02:00
Jonas Winkler
3f5d3d15fd Merge pull request #1209 from Unkn0wnCat/patch-1
Add Doxie Q to scanners.rst
2021-08-18 23:53:14 +02:00
Jonas Winkler
68fb85ceca Merge pull request #1221 from AlD/master
Make ignores configurable
2021-08-18 22:41:27 +02:00
Daniel Albers
3ebe6d5aef Make ignores configurable
Adds config file setting PAPERLESS_CONSUMER_IGNORE_PATTERNS.
2021-08-18 22:23:18 +02:00
jonaswinkler
566b3ed53d Merge branch 'dev' of github.com:jonaswinkler/paperless-ng into dev 2021-08-18 22:03:31 +02:00
Jonas Winkler
a688c747d7 New Crowdin updates (#1198) 2021-08-18 21:56:59 +02:00
jonaswinkler
83b90e1416 install required dependency for building paperless-ng on GitHub CI 2021-08-18 18:40:27 +02:00
jonaswinkler
23c6f849d6 fix bug with DPI calculation 2021-08-18 18:33:33 +02:00
jonaswinkler
ba6843df83 update python dependencies 2021-08-18 18:21:41 +02:00
jonaswinkler
0b90e69119 update dockerfile 2021-08-18 18:21:31 +02:00
jonaswinkler
dbe820323e switch to python 3.9 2021-08-18 17:47:53 +02:00
Kevin Kandlbinder
47d95d5b0a Add Doxie Q to scanners.rst
The Doxie Q / Q2 is a budget-scanner I've been using for my paperless-usage. It has POST-Support to a custom endpoint like paperless over WiFi and has a rather open API (See https://help.getdoxie.com/doxieq/wifi/api/).
2021-08-04 15:23:12 +02:00
pewter77
971192f6f3 update configuration docs for languages
Due to tesseract naming scheme, packages use '-' but the internal OCR uses '_' . This is to clarify in the documentation that this is the case for new users.
2021-07-30 23:21:22 +08:00
Jonas Winkler
fbfc7df593 Merge pull request #1173 from mweimerskirch/feature/l10n-lb_LU
Added support for Luxembourgish (lb_LU) as an interface language
2021-07-18 21:42:58 +02:00
Jonas Winkler
3c7644ce79 Merge pull request #1153 from jonaswinkler/l10n_dev
New Crowdin updates
2021-07-18 17:36:14 +02:00
Jonas Winkler
4e4a8bcca8 New translations messages.xlf (Luxembourgish)
[ci skip]
2021-07-16 17:20:14 +02:00
Michel Weimerskirch
dc5586b16d Added support for Luxembourgish (lb_LU) as an interface language 2021-07-16 16:43:55 +02:00
Jonas Winkler
1d87b48471 New translations messages.xlf (Luxembourgish)
[ci skip]
2021-07-16 16:22:10 +02:00
Jonas Winkler
353a3432df New translations django.po (Luxembourgish)
[ci skip]
2021-07-16 16:22:08 +02:00
Jonas Winkler
efe94bbf18 New translations messages.xlf (Luxembourgish)
[ci skip]
2021-07-16 15:01:08 +02:00
Jonas Winkler
cea6ec09bc New translations django.po (Luxembourgish)
[ci skip]
2021-07-16 15:01:07 +02:00
Jonas Winkler
4a3276f69c New translations messages.xlf (Luxembourgish)
[ci skip]
2021-07-16 13:47:43 +02:00
Jonas Winkler
f164def2ed New translations django.po (Luxembourgish)
[ci skip]
2021-07-16 13:47:42 +02:00
Jonas Winkler
511c76ae7a New translations messages.xlf (Luxembourgish)
[ci skip]
2021-07-15 10:58:18 +02:00
Jonas Winkler
bfa6dda0de New translations django.po (Luxembourgish)
[ci skip]
2021-07-15 10:58:16 +02:00
Jonas Winkler
54af734971 New translations django.po (Luxembourgish)
[ci skip]
2021-07-15 09:42:47 +02:00
Jonas Winkler
5b9763ecb4 New translations messages.xlf (Luxembourgish)
[ci skip]
2021-07-14 18:00:31 +02:00
Jonas Winkler
438bad23e8 New translations django.po (Luxembourgish)
[ci skip]
2021-07-14 18:00:29 +02:00
Jonas Winkler
ae5a205ba3 New translations django.po (Luxembourgish)
[ci skip]
2021-07-14 10:42:55 +02:00
Jonas Winkler
19b683e7b0 New translations messages.xlf (Luxembourgish)
[ci skip]
2021-07-13 23:45:12 +02:00
Jonas Winkler
0c92027414 New translations django.po (Luxembourgish)
[ci skip]
2021-07-13 23:45:11 +02:00
Jonas Winkler
c4e3b2ca2f New translations messages.xlf (Luxembourgish)
[ci skip]
2021-07-13 22:18:15 +02:00
Jonas Winkler
ba67b89db7 New translations django.po (Luxembourgish)
[ci skip]
2021-07-13 22:18:14 +02:00
Jonas Winkler
06f308ede3 New translations messages.xlf (Spanish)
[ci skip]
2021-07-11 12:20:36 +02:00
Jonas Winkler
214fb8204b New translations messages.xlf (Spanish)
[ci skip]
2021-07-11 10:29:21 +02:00
Jonas Winkler
2a2d7be9f9 New translations django.po (Spanish)
[ci skip]
2021-07-11 10:29:20 +02:00
Jonas Winkler
23304c3746 New translations django.po (Spanish)
[ci skip]
2021-07-11 09:21:44 +02:00
Jonas Winkler
20829c90b2 New translations django.po (German)
[ci skip]
2021-07-05 13:17:50 +02:00
Jonas Winkler
33cc3ce7e0 Merge pull request #1127 from jonaswinkler/l10n_dev
New Crowdin updates
2021-07-04 12:47:07 +02:00
Jonas Winkler
3487b23e88 New translations django.po (English, United Kingdom)
[ci skip]
2021-06-19 23:20:13 +02:00
Jonas Winkler
4718fe13c2 Merge pull request #1116 from ytzelf/patch-1
Update scanners.rst
2021-06-14 18:18:57 +02:00
ytzelf
8592acf6b8 Update scanners.rst
Added ADS-1100w which has FTP (and only FTP) capabilities but is quite cheap
2021-06-14 18:11:06 +02:00
jonaswinkler
88042d7072 fix wording 2021-06-13 21:30:20 +02:00
jonaswinkler
bf92e52d5c update dependencies 2021-06-13 21:21:56 +02:00
jonaswinkler
419580b3be changelog, versions 2021-06-13 19:17:29 +02:00
jonaswinkler
5ee1f6b82b Merge branch 'normalize-whitespace' into dev 2021-06-13 19:06:08 +02:00
Michael Lynch
410bb6a84e Fix trailing newlines in configuration.rst 2021-06-13 10:57:58 -04:00
Michael Lynch
af2b5fef13 Add checkout step to whitespace CI job 2021-06-13 10:57:40 -04:00
Michael Lynch
372ac3a40c Normalize whitespace in source files
Ensure that no source files have trailing whitespace at end of lines and ensure that all files end with a single trailing newline.

This also adds Github Actions to enforce whitespace conventions.
2021-06-13 10:57:40 -04:00
jonaswinkler
a1507d6079 update django-q 2021-06-13 16:36:05 +02:00
jonaswinkler
9242a8901a update django-q 2021-06-13 15:43:32 +02:00
jonaswinkler
1d4f25f930 update datepipe implementation due to interface change 2021-06-13 15:27:04 +02:00
jonaswinkler
7323ec8d16 update angular devkit 2021-06-13 15:18:23 +02:00
jonaswinkler
39d45367d0 replace ng-bootstrap with ngx-bootstrap 2021-06-13 15:12:56 +02:00
jonaswinkler
a6521952b0 update to Angular 11 2021-06-13 15:08:56 +02:00
jonaswinkler
7148c10f1b update docker entrypoint 2021-06-13 12:54:24 +02:00
jonaswinkler
4a1a66248d update requirements.txt 2021-06-13 12:40:28 +02:00
Jonas Winkler
67d0773231 Merge pull request #933 from sbrunner/suggest
Add suggest
2021-06-13 12:20:34 +02:00
jonaswinkler
ff370172b5 fix pycodestyle 2021-06-13 12:18:21 +02:00
jonaswinkler
1f707e86cc fix logging getting spammed with pdfminer warnings on JPG files 2021-06-13 12:09:16 +02:00
jonaswinkler
a3dae02cfb write classifier model to temporary file before copying to final location 2021-06-13 12:03:20 +02:00
jonaswinkler
3eae8a2210 update dependencies 2021-06-13 12:02:49 +02:00
Jonas Winkler
0f18fe1853 Merge pull request #1107 from MJWcodr/patch-1
Update setup.rst
2021-06-13 11:34:03 +02:00
Jonas Winkler
513c61eb79 Merge pull request #1113 from magnetic6/master
Document specification of the expected creation date order
2021-06-13 11:33:43 +02:00
Peter M
4031233fd4 Document specification of the expected creation date order 2021-06-12 10:15:51 -04:00
Matthias J. Wünsch
76ff6100a3 Update setup.rst 2021-06-09 16:46:53 +02:00
Jonas Winkler
05c36f91cf Merge pull request #1105 from mtlynch/single-install-cmd
Simplify installation command
2021-06-07 00:48:29 +02:00
Michael Lynch
6625f8962a Simplify installation command
The installation for docker is currently three separate commands, but it can be a single command if the user simply pipes to the sh interpreter directly. I know there are some who object to piping to sh from a URL, but the current method has no security benefit over piping directly to sh.
2021-06-06 18:02:23 -04:00
Jonas Winkler
63402b70d2 Merge pull request #1057 from muued/patch-6
adjust ansible README to installation instructions
2021-06-03 15:14:36 +02:00
Stéphane Brunner
2ae4a7806d Add suggest 2021-05-30 14:50:29 +02:00
Jonas Winkler
fcc4ecd007 Merge pull request #1068 from servusoft/dev
Solving issue with search criteria 'maximum age' for some mail server
2021-05-29 19:13:10 +02:00
Jonas Winkler
45497250cd Merge pull request #1074 from sbrunner/scan-to-paperless
Add Scan to Paperless as affiliated project
2021-05-29 19:12:46 +02:00
Stéphane Brunner
7dd957140e Add Scan to Paperless as affiliated project 2021-05-29 16:38:16 +02:00
servusoft
4cd772a39e Solving issue with search criteria maximum age for some mail server
Some mail servers (mail.ru) do not support search criteria for the maximum age. By setting the maximum age to 0, it is possible to hide the search criteria. This PR solves that problem.
2021-05-27 18:30:57 +02:00
HolzHannes
b3906e7bc1 Corrected position of info 2021-05-27 10:01:30 +02:00
HolzHannes
e5009b4cd2 Info for The input device is not a TTY Errors 2021-05-27 08:30:21 +02:00
Fabian Ohler
10bf9fd1f8 Adjusted paperlessng_version variable explanation 2021-05-26 08:30:17 +02:00
Jonas Winkler
bd8e68692e New translations django.po (Dutch) (#1048) 2021-05-25 00:01:38 +02:00
Jonas Winkler
b8386a1531 Merge pull request #1052 from muued/patch-5
Use ansible-galaxy during updates
2021-05-25 00:01:20 +02:00
Fabian Ohler
61534fb29d Apply suggestions from code review
Co-authored-by: Fabian Koller <C0nsultant@users.noreply.github.com>
2021-05-24 15:27:11 +02:00
Fabian Ohler
9ad81be38c adjust ansible README to installation instructions
and fix some typos
2021-05-24 15:10:41 +02:00
Fabian Ohler
cf7048e336 Use ansible-galaxy during updates
This mechanism is already used for the installation process.
2021-05-22 23:29:44 +02:00
jonaswinkler
a6105b3ad3 update frontend dependencies 2021-05-21 15:27:10 +02:00
99 changed files with 25039 additions and 5444 deletions

2
.env
View File

@@ -1 +1 @@
COMPOSE_PROJECT_NAME=paperless
COMPOSE_PROJECT_NAME=paperless

View File

@@ -0,0 +1,37 @@
#!/bin/bash
# Verify that all text files end in a trailing newline.
# Exit on first failing command.
set -e
# Exit on unset variable.
set -u
success=0
function is_plaintext_file() {
local file="$1"
if [[ $file == *.svg ]]; then
echo ""
return
fi
file --brief "${file}" | grep text
}
# Split strings on newlines.
IFS='
'
for file in $(git ls-files)
do
if [[ -z $(is_plaintext_file "${file}") ]]; then
continue
fi
if ! [[ -z "$(tail -c 1 "${file}")" ]]; then
printf "File must end in a trailing newline: %s\n" "${file}" >&2
success=255
fi
done
exit "${success}"

View File

@@ -0,0 +1,26 @@
#!/bin/bash
# Check for trailing whitespace at end of lines.
# Exit on first failing command.
set -e
# Exit on unset variable.
set -u
FOUND_TRAILING_WHITESPACE=0
while read -r line; do
if grep \
"\s$" \
--line-number \
--with-filename \
--binary-files=without-match \
--exclude="*.svg" \
--exclude="*.eps" \
"${line}"; then
echo "ERROR: Found trailing whitespace" >&2;
FOUND_TRAILING_WHITESPACE=1
fi
done < <(git ls-files)
exit "${FOUND_TRAILING_WHITESPACE}"

View File

@@ -20,7 +20,7 @@ jobs:
name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.7
python-version: 3.9
-
name: Get pip cache dir
id: pip-cache
@@ -59,7 +59,7 @@ jobs:
name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.7
python-version: 3.9
-
name: Get pip cache dir
id: pip-cache
@@ -81,12 +81,26 @@ jobs:
run: |
cd src/
pycodestyle
whitespace:
runs-on: ubuntu-20.04
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Ensure there are no trailing spaces
run: |
.github/workflow-scripts/check-trailing-whitespace
-
name: Ensure all text files end with a trailing newline
run: |
.github/workflow-scripts/check-trailing-whitespace
tests:
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: ['3.6', '3.7', '3.8', '3.9']
python-version: ['3.7', '3.8', '3.9']
fail-fast: false
steps:
-
@@ -122,7 +136,7 @@ jobs:
pytest
-
name: Publish coverage results
if: matrix.python-version == '3.8'
if: matrix.python-version == '3.9'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# https://github.com/coveralls-clients/coveralls-python/issues/251
@@ -158,7 +172,7 @@ jobs:
path: src/documents/static/frontend/
build-release:
needs: [frontend, documentation, tests, codestyle]
needs: [frontend, documentation, tests, whitespace, codestyle]
runs-on: ubuntu-20.04
steps:
-
@@ -168,7 +182,7 @@ jobs:
name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.7
python-version: 3.9
-
name: Install dependencies
run: |
@@ -268,7 +282,7 @@ jobs:
build-docker-image:
if: github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/ng-'))
runs-on: ubuntu-latest
needs: [frontend, tests, codestyle]
needs: [frontend, tests, whitespace, codestyle]
steps:
-
name: Prepare

View File

@@ -8,7 +8,7 @@ RUN git clone https://github.com/agl/jbig2enc .
RUN ./autogen.sh
RUN ./configure && make
FROM python:3.7-slim
FROM python:3.9-slim-bullseye
# Binary dependencies
RUN apt-get update \
@@ -33,16 +33,11 @@ RUN apt-get update \
zlib1g \
ghostscript \
icc-profiles-free \
&& echo "deb http://deb.debian.org/debian bullseye main" > /etc/apt/sources.list.d/bullseye.list \
&& apt-get update \
&& apt-get -y --no-install-recommends install \
# fixes sudo / gosu issues
libseccomp2 \
# Mime type detection
# Mime type detection
file \
libmagic-dev \
media-types \
# OCRmyPDF dependencies
# OCRmyPDF dependencies
liblept5 \
qpdf \
tesseract-ocr \

16
Pipfile
View File

@@ -14,15 +14,14 @@ django = "~=3.2"
django-cors-headers = "*"
django-extensions = "*"
django-filter = "~=2.4.0"
django-q = "==1.3.4"
django-q = "~=1.3.4"
djangorestframework = "~=3.12.2"
filelock = "*"
fuzzywuzzy = {extras = ["speedup"], version = "*"}
gunicorn = "*"
imap-tools = "*"
langdetect = "*"
# numpy 1.20.0 drops python 3.6 support
numpy = "~=1.19.5"
numpy = "~=1.20.0"
pathvalidate = "*"
pillow = "~=8.1"
pikepdf = "~=2.5"
@@ -34,13 +33,11 @@ psycopg2-binary = "*"
redis = "*"
# Pinned because aarch64 wheels and updates cause warnings when loading the classifier model.
scikit-learn="==0.24.0"
# Prevent scipy updates because 1.6 is incompatible with python 3.6
scipy="~=1.5.4"
whitenoise = "~=5.2.0"
watchdog = "~=1.0.0"
whitenoise = "~=5.3.0"
watchdog = "~=2.1.0"
whoosh="~=2.7.4"
inotifyrecursive = "~=0.3.4"
ocrmypdf = "~=12.0"
ocrmypdf = "~=12.3"
tqdm = "*"
tika = "*"
# TODO: This will sadly also install daphne+dependencies,
@@ -50,9 +47,10 @@ channels-redis = "*"
uvicorn = {extras = ["standard"], version = "*"}
concurrent-log-handler = "*"
# uvloop 0.15+ incompatible with python 3.6
uvloop = "~=0.14.0"
uvloop = "~=0.15"
cryptography = "~=3.4"
"pdfminer.six" = "*"
"backports.zoneinfo" = "*"
[dev-packages]
coveralls = "*"

1213
Pipfile.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -100,6 +100,7 @@ Paperless has been around a while now, and people are starting to build stuff on
* [Paperless App](https://github.com/bauerj/paperless_app): An Android/iOS app for Paperless. Updated to work with paperless-ng.
* [Paperless Share](https://github.com/qcasey/paperless_share). Share any files from your Android application with paperless. Very simple, but works with all of the mobile scanning apps out there that allow you to share scanned documents.
* [Scan to Paperless](https://github.com/sbrunner/scan-to-paperless): Scan and prepare (crop, deskew, OCR, ...) your documents for Paperless.
These projects also exist, but their status and compatibility with paperless-ng is unknown.

View File

@@ -12,27 +12,29 @@ Note that this role requires root access, so either run it in a playbook with a
- hosts: all
roles:
- role: ansible
- role: paperless-ng
become: yes
Role Variables
--------------
Most configuration variables from paperless-ng itself are available and accept their respective arguments.
Every `PAPERLESS_*` configuration varaible is lowercased and instead prefixed with `paperlessng_*` in `defaults/main.yml`.
Every `PAPERLESS_*` configuration variable is lowercased and instead prefixed with `paperlessng_*` in `defaults/main.yml`.
For a full listing including explainations and allowed values, see the current [documentation](https://paperless-ng.readthedocs.io/en/ng-0.9.14/configuration.html).
For a full listing including explanations and allowed values, see the current [documentation](https://paperless-ng.readthedocs.io/en/latest/configuration.html).
Additional variables available in this role are listed below, along with default values:
paperlessng_version: 0.9.14
paperlessng_version: latest
The [release](https://github.com/jonaswinkler/paperless-ng/releases) archive version of paperless-ng to install.
`latest` stands for the latest release of paperless-ng.
To install a specific version of paperless-ng, use the tag name of the release, e. g. `ng-1.4.4`, or specify a branch or commit id.
paperlessng_redis_host: localhost
paperlessng_redis_port: 6379
Seperate configuration values that combine into `PAPERLESS_REDIS`.
Separate configuration values that combine into `PAPERLESS_REDIS`.
paperlessng_db_type: sqlite
@@ -96,11 +98,11 @@ Example Playbook
- hosts: all
become: yes
vars_files:
- vars/main.yml
- vars/paperless-ng.yml
roles:
- ansible
- paperless-ng
`vars/main.yml`:
`vars/paperless-ng.yml`:
paperlessng_media_root: /mnt/media/smbshare

View File

@@ -1 +1 @@
COMPOSE_PROJECT_NAME=paperless
COMPOSE_PROJECT_NAME=paperless

View File

@@ -29,13 +29,9 @@ initialize() {
mkdir -p /tmp/paperless
set +e
CURRENT_USER=$(stat -c '%U' ../)
CURRENT_GROUP=$(stat -c '%G' ../)
if [[ ${CURRENT_USER} != "paperless" || ${CURRENT_GROUP} != "paperless" ]] ; then
echo "Adjusting permissions of paperless files. This may take a while."
chown -R paperless:paperless ../
fi
echo "Adjusting permissions of paperless files. This may take a while."
chown -R paperless:paperless /tmp/paperless
find .. -not \( -user paperless -and -group paperless \) -exec chown paperless:paperless {} +
set -e
gosu paperless /sbin/docker-prepare.sh

View File

@@ -149,22 +149,15 @@ Ansible Route
Most of the update process is automated when using the ansible role.
1. Backup your defined role variables file outside the paperless source-tree:
1. Update the role to the target release tag to make sure the ansible scripts are compatible:
.. code:: shell-session
$ cp ansible/vars.yml ~/vars.yml.old
$ ansible-galaxy install git+https://github.com/jonaswinkler/paperless-ng.git,master --force
2. Pull the release tag you want to update to:
2. Update the role variable definitions ``vars/paperless-ng.yml`` (where appropriate).
.. code:: shell-session
$ git fetch --all
$ git checkout ng-0.9.14
3. Update the role variable definitions ``ansible/vars.yml`` (where appropriate).
4. Run the ansible playbook you created created during :ref:`installation <setup-ansible>` again:
3. Run the ansible playbook you created created during :ref:`installation <setup-ansible>` again:
.. note::
@@ -247,6 +240,8 @@ Document exporter
The document exporter exports all your data from paperless into a folder for
backup or migration to another DMS.
If you use the document exporter within a cronjob to backup your data you might use the ``-T`` flag behind exec to suppress "The input device is not a TTY" errors. For example: ``docker-compose exec -T webserver document_exporter ../export``
.. code::
document_exporter target [-c] [-f] [-d]

View File

@@ -5,6 +5,30 @@
Changelog
*********
paperless-ng 1.5.0
##################
Support for Python 3.6 was dropped.
* Updated python dependencies.
* Base image of the docker image changed from Debian Buster to Debian Bullseye due to its recent release.
* The docker image now uses python 3.9.
* Added the Luxembourgish locale. Thanks for translating!
* `Daniel Albers`_ added support for making the files and folders ignored by the paperless consume folder scanner configurable. See ``PAPERLESS_CONSUMER_IGNORE_PATTERNS``.
paperless-ng 1.4.5
##################
This is a maintenance release.
* Updated Python and Angular dependencies.
* Changed the algorithm that changes permissions during startup. This is still fast,
and will hopefully cause less issues.
* Fixed an issue that would sometimes cause paperless to write an incomplete
classification model file to disk.
* Fixed an issue with the OCRmyPDF parser that would always try to extract text
with PDFminer even from non-PDF files.
paperless-ng 1.4.4
##################
@@ -25,7 +49,7 @@ paperless-ng 1.4.3
* `Michael Shamoon`_ added dark mode for the login and logout pages.
* `Alexander Menk`_ added additional stylesheets for printing. You can now print any page of paperless and the print result will hide the page header, sidebar, and action buttons.
* Added support for sorting when using full text search.
* Fixes
* `puuu`_ fixed ``PAPERLESS_FORCE_SCRIPT_NAME``. You can now host paperless on sub paths such as ``https://localhost:8000/paperless/``.
@@ -85,17 +109,6 @@ paperless-ng 1.4.0
To do this, execute the ``document_index reindex`` management command
(see :ref:`administration-index`).
.. note::
Some packages that paperless depends on are slowly dropping Python 3.6
support one after another, including the web server. Supporting Python
3.6 means that I cannot update these packages anymore.
At some point, paperless will drop Python 3.6 support. If using a bare
metal installation and you're still on Python 3.6, upgrade to 3.7 or newer.
If using docker, this does not affect you.
paperless-ng 1.3.2
##################
@@ -1469,6 +1482,7 @@ bulk of the work on this big change.
.. _JOKer: https://github.com/MasterofJOKers
.. _Brian Cribbs: https://github.com/cribbstechnolog
.. _Brendan M. Sleight: https://github.com/bmsleight
.. _Daniel Albers: https://github.com/AlD
.. _#20: https://github.com/the-paperless-project/paperless/issues/20
.. _#44: https://github.com/the-paperless-project/paperless/issues/44

View File

@@ -174,11 +174,11 @@ PAPERLESS_AUTO_LOGIN_USERNAME=<username>
Defaults to none, which disables this feature.
PAPERLESS_ADMIN_USER=<username>
If this environment variable is specified, Paperless automatically creates
a superuser with the provided username at start. This is useful in cases
where you can not run the `createsuperuser` command seperately, such as Kubernetes
If this environment variable is specified, Paperless automatically creates
a superuser with the provided username at start. This is useful in cases
where you can not run the `createsuperuser` command seperately, such as Kubernetes
or AWS ECS.
Requires `PAPERLESS_ADMIN_PASSWORD` to be set.
.. note::
@@ -188,7 +188,7 @@ PAPERLESS_ADMIN_USER=<username>
the lifecycle of the containers.
PAPERLESS_ADMIN_MAIL=<email>
(Optional) Specify superuser email address. Only used when
(Optional) Specify superuser email address. Only used when
`PAPERLESS_ADMIN_USER` is set.
Defaults to ``root@localhost``.
@@ -222,17 +222,17 @@ PAPERLESS_ENABLE_HTTP_REMOTE_USER=<bool>
Also see the warning `in the official documentation <https://docs.djangoproject.com/en/3.1/howto/auth-remote-user/#configuration>`.
Defaults to `false` which disables this feature.
PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME=<str>
If `PAPERLESS_ENABLE_HTTP_REMOTE_USER` is enabled, this property allows to
customize the name of the HTTP header from which the authenticated username
If `PAPERLESS_ENABLE_HTTP_REMOTE_USER` is enabled, this property allows to
customize the name of the HTTP header from which the authenticated username
is extracted. Values are in terms of
[HttpRequest.META](https://docs.djangoproject.com/en/3.1/ref/request-response/#django.http.HttpRequest.META).
Thus, the configured value must start with `HTTP_` followed by the
Thus, the configured value must start with `HTTP_` followed by the
normalized actual header name.
Defaults to `HTTP_REMOTE_USER`.
.. _configuration-ocr:
OCR settings
@@ -258,6 +258,8 @@ PAPERLESS_OCR_LANGUAGE=<lang>
Defaults to "eng".
Note: If your language contains a '-' such as chi-sim, you must use chi_sim
PAPERLESS_OCR_MODE=<mode>
Tell paperless when and how to perform ocr on your documents. Four modes
are available:
@@ -622,6 +624,20 @@ PAPERLESS_IGNORE_DATES=<string>
Defaults to an empty string to not ignore any dates.
PAPERLESS_DATE_ORDER=<format>
Paperless will try to determine the document creation date from its contents.
Specify the date format Paperless should expect to see within your documents.
This option defaults to DMY which translates to day first, month second, and year
last order. Characters D, M, or Y can be shuffled to meet the required order.
PAPERLESS_CONSUMER_IGNORE_PATTERNS=<json>
By default, paperless ignores certain files and folders in the consumption
directory, such as system files created by the Mac OS.
This can be adjusted by configuring a custom json array with patterns to exclude.
Defautls to ``[".DS_STORE/*", "._*", ".stfolder/*"]``.
Binaries
########

View File

@@ -6,7 +6,7 @@ Contributing to Paperless
.. warning::
This section is not updated to paperless-ng yet.
Maybe you've been using Paperless for a while and want to add a feature or two,
or maybe you've come across a bug that you have some ideas how to solve. The
beauty of Free software is that you can see what's wrong and help to get it

View File

@@ -23,10 +23,10 @@ Apart from that, the folder structure is as follows:
* ``scripts/`` - Various scripts that help with different parts of development.
* ``docker/`` - Files required to build the docker image.
Initial setup and first start
Initial setup and first start
=============================
After you forked and cloned the code from github you need to perform a first-time setup.
After you forked and cloned the code from github you need to perform a first-time setup.
To do the setup you need to perform the steps from the following chapters in a certain order:
1. Install prerequisites + pipenv as mentioned in :ref:`Bare metal route <setup-bare_metal>`
@@ -35,19 +35,19 @@ To do the setup you need to perform the steps from the following chapters in a c
.. code:: shell-session
$ npm install -g @angular/cli
$ npm install -g @angular/cli
4. Create ``consume`` and ``media`` folders in the cloned root folder.
.. code:: shell-session
mkdir -p consume media
5. You can now either ...
* install redis or
* install redis or
* use the included scripts/start-services.sh to use docker to fire up a redis instance (and some other services such as tika, gotenberg and a postgresql server) or
* spin up a bare redis container
* spin up a bare redis container
.. code:: shell-session
@@ -79,7 +79,7 @@ To do the setup you need to perform the steps from the following chapters in a c
python3 manage.py runserver & python3 manage.py document_consumer & python3 manage.py qcluster
10. Login with the superuser credentials provided in step 8 at ``http://localhost:8000`` to create a session that enables you to use the backend.
Backend development environment is now ready, to start Frontend development go to ``/src-ui`` and run ``ng serve``. From there you can use ``http://localhost:4200`` for a preview.
Back end development
@@ -207,7 +207,7 @@ Adding new languages requires adding the translated files in the "src-ui/src/loc
// Add your new language here
]
}
``dateInputFormat`` is a special string that defines the behavior of the date input fields and absolutely needs to contain "dd", "mm" and "yyyy".
3. Import and register the Angular data for this locale in "src-ui/src/app/app.module.ts":
@@ -320,7 +320,7 @@ methods ``parse`` and ``get_thumbnail``. You can provide your own implementation
# The content of the document.
self.text = "content"
# Optional: path to a PDF document that you created from the original.
self.archive_path = os.path.join(self.tempdir, "archived.pdf")

View File

@@ -68,10 +68,10 @@ reuse the text. The web interface is a lot snappier, since it runs
in your browser and paperless has to do much less work to serve the data.
.. note::
You can adjust some of the settings so that paperless uses less processing
power. See :ref:`setup-less_powerful_devices` for details.
**Q:** *How do I install paperless-ng on Raspberry Pi?*

View File

@@ -49,7 +49,7 @@ resources in the documentation:
paperless-ng.
* Paperless is now integrated with a
:ref:`task processing queue <setup-task_processor>` that tells you
at a glance when and why something is not working.
at a glance when and why something is not working.
* The :ref:`changelog <paperless_changelog>` contains a detailed list of all changes
in paperless-ng.

View File

@@ -13,42 +13,48 @@ that works right for you based on recommendations from other Paperless users.
Physical scanners
=================
+---------+----------------+-----+-----+-----+------+----------------+
| Brand | Model | Supports | Recommended By |
+---------+----------------+-----+-----+-----+------+----------------+
| | | FTP | NFS | SMB | SMTP | |
+=========+================+=====+=====+=====+======+================+
| Brother | `ADS-1700W`_ | yes | no | yes | yes |`holzhannes`_ |
+---------+----------------+-----+-----+-----+------+----------------+
| Brother | `ADS-1600W`_ | yes | no | yes | yes |`holzhannes`_ |
+---------+----------------+-----+-----+-----+------+----------------+
| Brother | `ADS-1500W`_ | yes | no | yes | yes |`danielquinn`_ |
+---------+----------------+-----+-----+-----+------+----------------+
| Brother | `MFC-J6930DW`_ | yes | | | |`ayounggun`_ |
+---------+----------------+-----+-----+-----+------+----------------+
| Brother | `MFC-L5850DW`_ | yes | | | yes |`holzhannes`_ |
+---------+----------------+-----+-----+-----+------+----------------+
| Brother | `MFC-J5910DW`_ | yes | | | |`bmsleight`_ |
+---------+----------------+-----+-----+-----+------+----------------+
| Brother | `MFC-9142CDN`_ | yes | | yes | |`REOLDEV`_ |
+---------+----------------+-----+-----+-----+------+----------------+
| Fujitsu | `ix500`_ | yes | | yes | |`eonist`_ |
+---------+----------------+-----+-----+-----+------+----------------+
| Epson | `WF-7710DWF`_ | yes | | yes | |`Skylinar`_ |
+---------+----------------+-----+-----+-----+------+----------------+
| Fujitsu | `S1300i`_ | yes | | yes | |`jonaswinkler`_ |
+---------+----------------+-----+-----+-----+------+----------------+
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brand | Model | Supports | Recommended By |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| | | FTP | NFS | SMB | SMTP | API [1]_ | |
+=========+================+=====+=====+=====+======+==========+================+
| Brother | `ADS-1700W`_ | yes | no | yes | yes | |`holzhannes`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `ADS-1600W`_ | yes | no | yes | yes | |`holzhannes`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `ADS-1500W`_ | yes | no | yes | yes | |`danielquinn`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `ADS-1100W`_ | yes | no | no | no | |`ytzelf`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `MFC-J6930DW`_ | yes | | | | |`ayounggun`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `MFC-L5850DW`_ | yes | | | yes | |`holzhannes`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `MFC-J5910DW`_ | yes | | | | |`bmsleight`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Brother | `MFC-9142CDN`_ | yes | | yes | | |`REOLDEV`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Fujitsu | `ix500`_ | yes | | yes | | |`eonist`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Epson | `WF-7710DWF`_ | yes | | yes | | |`Skylinar`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Fujitsu | `S1300i`_ | yes | | yes | | |`jonaswinkler`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
| Doxie | `Q2`_ | no | no | no | no | yes |`Unkn0wnCat`_ |
+---------+----------------+-----+-----+-----+------+----------+----------------+
.. _MFC-L5850DW: https://www.brother-usa.com/products/mfcl5850dw
.. _ADS-1700W: https://www.brother-usa.com/products/ads1700w
.. _ADS-1600W: https://www.brother-usa.com/products/ads1600w
.. _ADS-1500W: https://www.brother.ca/en/p/ads1500w
.. _ADS-1100W: https://support.brother.com/g/b/downloadtop.aspx?c=fr&lang=fr&prod=ads1100w_eu_as_cn
.. _MFC-J6930DW: https://www.brother.ca/en/p/MFCJ6930DW
.. _MFC-J5910DW: https://www.brother.co.uk/printers/inkjet-printers/mfcj5910dw
.. _MFC-9142CDN: https://www.brother.co.uk/printers/laser-printers/mfc9140cdn
.. _ix500: http://www.fujitsu.com/us/products/computing/peripheral/scanners/scansnap/ix500/
.. _WF-7710DWF: https://www.epson.de/en/products/printers/inkjet-printers/for-home/workforce-wf-7710dwf
.. _S1300i: https://www.fujitsu.com/global/products/computing/peripheral/scanners/soho/s1300i/
.. _Q2: https://www.getdoxie.com/product/doxie-q/
.. _danielquinn: https://github.com/danielquinn
@@ -59,6 +65,10 @@ Physical scanners
.. _Skylinar: https://github.com/Skylinar
.. _jonaswinkler: https://github.com/jonaswinkler
.. _holzhannes: https://github.com/holzhannes
.. _ytzelf: https://github.com/ytzelf
.. _Unkn0wnCat: https://github.com/Unkn0wnCat
.. [1] Scanners with API Integration allow to push scanned documents directly to :ref:`Paperless API <api-file_uploads>`, sometimes referred to as Webhook or Document POST.
Mobile phone software
=====================

View File

@@ -116,9 +116,7 @@ performs all the steps described in :ref:`setup-docker_hub` automatically.
.. code:: shell-session
$ wget https://raw.githubusercontent.com/jonaswinkler/paperless-ng/master/install-paperless-ng.sh
$ chmod +x install-paperless-ng.sh
$ ./install-paperless-ng.sh
$ curl -L https://raw.githubusercontent.com/jonaswinkler/paperless-ng/master/install-paperless-ng.sh | bash
.. _setup-docker_hub:
@@ -286,7 +284,7 @@ writing. Windows is not and will never be supported.
Use this list for your preferred package management:
.. code::
.. code::
python3 python3-pip python3-dev imagemagick fonts-liberation optipng gnupg libpq-dev libmagic-dev mime-support
@@ -305,7 +303,7 @@ writing. Windows is not and will never be supported.
Use this list for your preferred package management:
.. code::
.. code::
unpaper ghostscript icc-profiles-free qpdf liblept5 libxml2 pngquant zlib1g tesseract-ocr
@@ -361,7 +359,7 @@ writing. Windows is not and will never be supported.
8. Install python requirements from the ``requirements.txt`` file.
It is up to you if you wish to use a virtual environment or not. First you should update your pip, so it gets the actual packages.
.. code:: shell-session
sudo -Hu paperless pip3 install --upgrade pip

View File

@@ -81,7 +81,7 @@ UserWarning in sklearn on every single document
You may encounter warnings like this:
.. code::
/usr/local/lib/python3.7/site-packages/sklearn/base.py:315:
UserWarning: Trying to unpickle estimator CountVectorizer from version 0.23.2 when using version 0.24.0.
This might lead to breaking code or invalid results. Use at your own risk.
@@ -200,13 +200,13 @@ This might have multiple reasons.
File "/usr/local/lib/python3.7/site-packages/gunicorn/http/wsgi.py", line 386, in sendfile
sent += os.sendfile(sockno, fileno, offset + sent, count)
OSError: [Errno 22] Invalid argument
To fix this issue, add
.. code::
SENDFILE=0
to your `docker-compose.env` file.
Error while reading metadata

View File

@@ -71,7 +71,7 @@ your documents:
This process can be configured to fit your needs. If you don't want paperless
to create archived versions for digital documents, you can configure that by
configuring ``PAPERLESS_OCR_MODE=skip_noarchive``. Please read the
configuring ``PAPERLESS_OCR_MODE=skip_noarchive``. Please read the
:ref:`relevant section in the documentation <configuration-ocr>`.
.. note::
@@ -289,7 +289,7 @@ Matching specific tags, correspondents or types:
Matching dates:
.. code::
created:[2005 to 2009]
added:yesterday
modified:today
@@ -306,11 +306,11 @@ Matching inexact words:
auto complete and query correction.
All of these constructs can be combined as you see fit.
If you want to learn more about the query language used by paperless, paperless uses Whoosh's default query language.
If you want to learn more about the query language used by paperless, paperless uses Whoosh's default query language.
Head over to `Whoosh query language <https://whoosh.readthedocs.io/en/latest/querylang.html>`_.
For details on what date parsing utilities are available, see
`Date parsing <https://whoosh.readthedocs.io/en/latest/dates.html#parsing-date-queries>`_.
.. _usage-recommended_workflow:
@@ -385,7 +385,7 @@ Once you have scanned in a document, proceed in paperless as follows.
6. Remove inbox tags from the documents.
.. hint::
You can setup manual matching rules for your correspondents and tags and
paperless will assign them automatically. After consuming a couple documents,
you can even ask paperless to *learn* when to assign tags and correspondents

View File

@@ -57,6 +57,7 @@
#PAPERLESS_CONSUMER_POLLING=10
#PAPERLESS_CONSUMER_DELETE_DUPLICATES=false
#PAPERLESS_CONSUMER_RECURSIVE=false
#PAPERLESS_CONSUMER_IGNORE_PATTERNS=[".DS_STORE/*", "._*", ".stfolder/*"]
#PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS=false
#PAPERLESS_OPTIMIZE_THUMBNAILS=true
#PAPERLESS_POST_CONSUME_SCRIPT=/path/to/an/arbitrary/script.sh

View File

@@ -8,42 +8,44 @@
-i https://pypi.python.org/simple
--extra-index-url https://www.piwheels.org/simple
aioredis==1.3.1
arrow==1.1.0; python_version >= '3.6'
asgiref==3.3.4; python_version >= '3.6'
arrow==1.1.1; python_version >= '3.6'
asgiref==3.4.1; python_version >= '3.6'
async-timeout==3.0.1; python_full_version >= '3.5.3'
attrs==21.2.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
autobahn==21.3.1; python_version >= '3.7'
automat==20.2.0
blessed==1.18.0
certifi==2020.12.5
cffi==1.14.5
channels-redis==3.2.0
channels==3.0.3
backports.zoneinfo==0.2.1
blessed==1.18.1; python_version >= '2.7'
certifi==2021.5.30
cffi==1.14.6
channels-redis==3.3.0
channels==3.0.4
chardet==4.0.0; python_version >= '3.1'
click==7.1.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
coloredlogs==15.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
charset-normalizer==2.0.4; python_version >= '3'
click==8.0.1; python_version >= '3.6'
coloredlogs==15.0.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
concurrent-log-handler==0.9.19
constantly==15.1.0
cryptography==3.4.7
daphne==3.0.2; python_version >= '3.6'
dateparser==1.0.0
django-cors-headers==3.7.0
django-cors-headers==3.8.0
django-extensions==3.1.3
django-filter==2.4.0
django-picklefield==3.0.1; python_version >= '3'
django-q==1.3.4
django==3.2.3
django-q==1.3.9
django==3.2.6
djangorestframework==3.12.4
filelock==3.0.12
fuzzywuzzy[speedup]==0.18.0
gunicorn==20.1.0
h11==0.12.0; python_version >= '3.6'
hiredis==2.0.0; python_version >= '3.6'
httptools==0.1.2
humanfriendly==9.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
httptools==0.2.0
humanfriendly==9.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
hyperlink==21.0.0
idna==2.10; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
imap-tools==0.41.0
idna==3.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
imap-tools==0.46.0
img2pdf==0.4.1
incremental==21.3.0
inotify-simple==1.3.5; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
@@ -52,49 +54,50 @@ joblib==1.0.1; python_version >= '3.6'
langdetect==1.0.9
lxml==4.6.3; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
msgpack==1.0.2
numpy==1.19.5
ocrmypdf==12.0.1
numpy==1.20.3
ocrmypdf==12.3.2
pathvalidate==2.4.1
pdfminer.six==20201018
pikepdf==2.12.0
pillow==8.2.0
pikepdf==2.16.1
pillow==8.3.1
pluggy==0.13.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
portalocker==2.3.0; python_version >= '3'
psycopg2-binary==2.8.6
psycopg2-binary==2.9.1
pyasn1-modules==0.2.8
pyasn1==0.4.8
pycparser==2.20; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
pyopenssl==20.0.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
python-dateutil==2.8.1
python-dotenv==0.17.1
python-dateutil==2.8.2
python-dotenv==0.19.0
python-gnupg==0.4.7
python-levenshtein==0.12.2
python-magic==0.4.22
python-magic==0.4.24
pytz==2021.1
pyyaml==5.4.1
redis==3.5.3
regex==2021.4.4
reportlab==3.5.67; python_version >= '2.7' and python_version < '4'
requests==2.25.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
regex==2021.8.3
reportlab==3.6.1; python_version >= '2.7' and python_version < '4'
requests==2.26.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'
scikit-learn==0.24.0
scipy==1.5.4
scipy==1.7.1; python_version < '3.10' and python_version >= '3.7'
service-identity==21.1.0
six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
sortedcontainers==2.3.0
sortedcontainers==2.4.0
sqlparse==0.4.1; python_version >= '3.5'
threadpoolctl==2.1.0; python_version >= '3.5'
threadpoolctl==2.2.0; python_version >= '3.6'
tika==1.24
tqdm==4.60.0
twisted[tls]==21.2.0; python_full_version >= '3.5.4'
tqdm==4.62.1
twisted[tls]==21.7.0; python_full_version >= '3.6.7'
txaio==21.2.1; python_version >= '3.6'
tzlocal==2.1
urllib3==1.26.4; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'
uvicorn[standard]==0.13.4
uvloop==0.14.0
watchdog==1.0.2
typing-extensions==3.10.0.0
tzlocal==3.0; python_version >= '3.6'
urllib3==1.26.6; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'
uvicorn[standard]==0.15.0
uvloop==0.16.0
watchdog==2.1.3
watchgod==0.7
wcwidth==0.2.5
websockets==8.1
whitenoise==5.2.0
websockets==9.1
whitenoise==5.3.0
whoosh==2.7.4
zope.interface==5.4.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'

View File

@@ -27,7 +27,8 @@
"ru-RU": "src/locale/messages.ru_RU.xlf",
"es-ES": "src/locale/messages.es_ES.xlf",
"pl-PL": "src/locale/messages.pl_PL.xlf",
"sv-SE": "src/locale/messages.sv_SE.xlf"
"sv-SE": "src/locale/messages.sv_SE.xlf",
"lb-LU": "src/locale/messages.lb_LU.xlf"
}
},
"architect": {
@@ -72,7 +73,6 @@
"optimization": true,
"outputHashing": "none",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,

View File

@@ -33,4 +33,4 @@ exports.config = {
}
}));
}
};
};

25149
src-ui/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -11,41 +11,41 @@
},
"private": true,
"dependencies": {
"@angular/animations": "~10.1.5",
"@angular/common": "~10.1.5",
"@angular/compiler": "~10.1.5",
"@angular/core": "~10.1.5",
"@angular/forms": "~10.1.5",
"@angular/localize": "~10.1.5",
"@angular/platform-browser": "~10.1.5",
"@angular/platform-browser-dynamic": "~10.1.5",
"@angular/router": "~10.1.5",
"@ng-bootstrap/ng-bootstrap": "^8.0.4",
"@ng-select/ng-select": "^5.0.9",
"@angular/animations": "~11.2.14",
"@angular/common": "~11.2.14",
"@angular/compiler": "~11.2.14",
"@angular/core": "~11.2.14",
"@angular/forms": "~11.2.14",
"@angular/localize": "~11.2.14",
"@angular/platform-browser": "~11.2.14",
"@angular/platform-browser-dynamic": "~11.2.14",
"@angular/router": "~11.2.14",
"@ng-bootstrap/ng-bootstrap": "^9.1.2",
"@ng-select/ng-select": "^7.0.0",
"bootstrap": "^4.5.0",
"file-saver": "^2.0.5",
"ng-bootstrap": "^1.6.3",
"ng2-pdf-viewer": "^6.3.2",
"ngx-bootstrap": "^6.2.0",
"ngx-color": "^6.2.0",
"ngx-cookie-service": "^10.1.1",
"ngx-file-drop": "^10.0.0",
"ngx-file-drop": "^11.1.0",
"ngx-infinite-scroll": "^9.1.0",
"rxjs": "~6.6.0",
"tslib": "^2.0.0",
"uuid": "^8.3.1",
"zone.js": "~0.10.2"
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.1002.0",
"@angular/cli": "~10.1.5",
"@angular/compiler-cli": "~10.1.5",
"@types/jasmine": "~3.5.0",
"@angular-devkit/build-angular": "~0.1102.13",
"@angular/cli": "~11.2.14",
"@angular/compiler-cli": "~11.2.14",
"@types/jasmine": "~3.6.0",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1",
"codelyzer": "^6.0.0",
"jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~5.0.0",
"karma": "~6.3.3",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~3.0.2",
"karma-jasmine": "~4.0.0",
@@ -53,6 +53,6 @@
"protractor": "~7.0.0",
"ts-node": "~8.3.0",
"tslint": "~6.1.0",
"typescript": "~4.0.2"
"typescript": "~4.1.5"
}
}

View File

@@ -33,7 +33,7 @@ const routes: Routes = [
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
imports: [RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' })],
exports: [RouterModule]
})
export class AppRoutingModule { }

View File

@@ -1,3 +1,3 @@
<app-toasts></app-toasts>
<router-outlet></router-outlet>
<router-outlet></router-outlet>

View File

@@ -45,7 +45,7 @@ export class AppComponent implements OnInit, OnDestroy {
ngOnInit(): void {
this.consumerStatusService.connect()
this.successSubscription = this.consumerStatusService.onDocumentConsumptionFinished().subscribe(status => {
if (this.showNotification(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUCCESS)) {
this.toastService.show({title: $localize`Document added`, delay: 10000, content: $localize`Document ${status.filename} was added to paperless.`, actionName: $localize`Open document`, action: () => {

View File

@@ -76,6 +76,7 @@ import localeRu from '@angular/common/locales/ru';
import localeEs from '@angular/common/locales/es';
import localePl from '@angular/common/locales/pl';
import localeSv from '@angular/common/locales/sv';
import localeLb from '@angular/common/locales/lb';
registerLocaleData(localeFr)
@@ -90,6 +91,7 @@ registerLocaleData(localeRu)
registerLocaleData(localeEs)
registerLocaleData(localePl)
registerLocaleData(localeSv)
registerLocaleData(localeLb)
@NgModule({
declarations: [

View File

@@ -30,7 +30,7 @@ export class ConfirmDialogComponent implements OnInit {
@Input()
buttonsEnabled = true
confirmButtonEnabled = true
seconds = 0

View File

@@ -55,7 +55,7 @@
</button>
</div>
</div>
</div>
</div>
</div>

View File

@@ -83,7 +83,7 @@ export class FilterableDropdownSelectionModel {
if (fireEvent) {
this.changed.next(this)
}
}
private getNonTemporary(id: number) {

View File

@@ -10,7 +10,7 @@
<path d="M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8z"/>
</svg>
</ng-container>
</div>
<div class="mr-1">
<app-tag *ngIf="isTag; else displayName" [tag]="item" [clickable]="true" linkTitle="Filter by tag"></app-tag>

View File

@@ -11,7 +11,7 @@ export class AbstractInputComponent<T> implements OnInit, ControlValueAccessor {
constructor() { }
onChange = (newValue: T) => {};
onTouched = () => {};
writeValue(newValue: any): void {

View File

@@ -2,4 +2,4 @@
<input type="checkbox" class="custom-control-input" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" (blur)="onTouched()" [disabled]="disabled">
<label class="custom-control-label" [for]="inputId">{{title}}</label>
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
</div>
</div>

View File

@@ -15,7 +15,7 @@ import { AbstractInputComponent } from '../abstract-input';
})
export class CheckComponent extends AbstractInputComponent<boolean> {
constructor() {
constructor() {
super()
}

View File

@@ -5,12 +5,12 @@
<div class="input-group-prepend">
<span class="input-group-text" [style.background-color]="value">&nbsp;&nbsp;&nbsp;</span>
</div>
<ng-template #popContent>
<div style="min-width: 200px;" class="pb-3">
<color-slider [color]="value" (onChangeComplete)="colorChanged($event.color.hex)"></color-slider>
</div>
</ng-template>
<input class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [autoClose]="'outside'" [ngbPopover]="popContent" placement="bottom" popoverClass="shadow">
@@ -30,4 +30,4 @@
<div class="invalid-feedback">
{{error}}
</div>
</div>
</div>

View File

@@ -11,4 +11,4 @@
</div>
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
</div>
</div>

View File

@@ -5,4 +5,4 @@
<div class="invalid-feedback">
{{error}}
</div>
</div>
</div>

View File

@@ -12,4 +12,4 @@
<div class="modal-footer">
<button type="button" class="btn btn-outline-dark" (click)="cancelClicked()" i18n>Cancel</button>
<button type="button" class="btn btn-primary" (click)="selectClicked.emit(selected)" i18n>Select</button>
</div>
</div>

View File

@@ -1,2 +1,2 @@
<span *ngIf="!clickable" class="badge" [style.background]="tag.color" [style.color]="tag.text_color">{{tag.name}}</span>
<a [routerLink]="" [title]="linkTitle" *ngIf="clickable" class="badge" [style.background]="tag.color" [style.color]="tag.text_color">{{tag.name}}</a>
<a [routerLink]="" [title]="linkTitle" *ngIf="clickable" class="badge" [style.background]="tag.color" [style.color]="tag.text_color">{{tag.name}}</a>

View File

@@ -23,7 +23,7 @@ export class StatisticsWidgetComponent implements OnInit, OnDestroy {
statistics: Statistics = {}
subscription: Subscription
private getStatistics(): Observable<Statistics> {
return this.http.get(`${environment.apiBaseUrl}statistics/`)
}

View File

@@ -13,4 +13,4 @@
<p i18n>Consult the documentation on how to use these features. The section on basic usage also has some information on how to use paperless in general.</p>
</ng-container>
</app-widget-frame>
</app-widget-frame>

View File

@@ -4,9 +4,9 @@
<h5 class="card-title mb-0">{{title}}</h5>
<ng-content select ="[header-buttons]"></ng-content>
</div>
</div>
<div class="card-body text-dark">
<ng-content select ="[content]"></ng-content>
</div>
</div>
</div>

View File

@@ -20,4 +20,4 @@
</tr>
</tbody>
</table>
</div>
</div>

View File

@@ -1,3 +1,3 @@
.metadata-column {
overflow-wrap: anywhere;
}
}

View File

@@ -64,4 +64,4 @@
span ::ng-deep .match {
color: black;
background-color: rgb(255, 211, 66);
}
}

View File

@@ -3,7 +3,7 @@
<div class="form-inline d-flex align-items-center">
<div class="input-group input-group-sm flex-fill w-auto">
<div class="input-group-prepend" ngbDropdown>
<button class="btn btn-outline-primary" ngbDropdownToggle>{{textFilterTargetName}}</button>
<button class="btn btn-outline-primary" ngbDropdownToggle>{{textFilterTargetName}}</button>
<div class="dropdown-menu shadow" ngbDropdownMenu>
<button *ngFor="let t of textFilterTargets" ngbDropdownItem [class.active]="textFilterTarget == t.id" (click)="changeTextFilterTarget(t.id)">{{t.name}}</button>
</div>

View File

@@ -32,6 +32,6 @@ export class CorrespondentEditDialogComponent extends EditDialogComponent<Paperl
match: new FormControl(""),
is_insensitive: new FormControl(true)
})
}
}
}

View File

@@ -18,7 +18,7 @@ export class CorrespondentListComponent extends GenericListComponent<PaperlessCo
constructor(correspondentsService: CorrespondentService, modalService: NgbModal,
private list: DocumentListViewService,
toastService: ToastService
) {
) {
super(correspondentsService,modalService,CorrespondentEditDialogComponent, toastService)
}

View File

@@ -13,7 +13,7 @@ import { ToastService } from 'src/app/services/toast.service';
})
export class DocumentTypeEditDialogComponent extends EditDialogComponent<PaperlessDocumentType> {
constructor(service: DocumentTypeService, activeModal: NgbActiveModal, toastService: ToastService) {
constructor(service: DocumentTypeService, activeModal: NgbActiveModal, toastService: ToastService) {
super(service, activeModal, toastService)
}

View File

@@ -49,4 +49,4 @@
</td>
</tr>
</tbody>
</table>
</table>

View File

@@ -52,4 +52,4 @@
</td>
</tr>
</tbody>
</table>
</table>

View File

@@ -5,4 +5,4 @@
<path d="M7 6.5C7 7.328 6.552 8 6 8s-1-.672-1-1.5S5.448 5 6 5s1 .672 1 1.5zm4 0c0 .828-.448 1.5-1 1.5s-1-.672-1-1.5S9.448 5 10 5s1 .672 1 1.5z"/>
</svg>
<h1 i18n>404 Not Found</h1>
</div>
</div>

View File

@@ -6,7 +6,7 @@ export function cloneFilterRules(filterRules: FilterRule[]): FilterRule[] {
for (let rule of filterRules) {
newRules.push({rule_type: rule.rule_type, value: rule.value})
}
return newRules
return newRules
} else {
return null
}
@@ -19,4 +19,4 @@ export function isFullTextFilterRule(filterRules: FilterRule[]): boolean {
export interface FilterRule {
rule_type: number
value: string
}
}

View File

@@ -1,7 +1,7 @@
import { MatchingModel } from './matching-model';
export interface PaperlessCorrespondent extends MatchingModel {
last_correspondence?: Date
}

View File

@@ -1,5 +1,5 @@
export interface PaperlessDocumentMetadata {
original_checksum?: string
archived_checksum?: string
@@ -10,4 +10,4 @@ export interface PaperlessDocumentMetadata {
has_archive_version?: boolean
}
}

View File

@@ -6,4 +6,4 @@ export interface PaperlessDocumentSuggestions {
document_types?: number[]
}
}

View File

@@ -15,4 +15,4 @@ export interface PaperlessSavedView extends ObjectWithId {
filter_rules: FilterRule[]
}
}

View File

@@ -3,5 +3,5 @@ export interface Results<T> {
count: number
results: T[]
}

View File

@@ -8,4 +8,4 @@ export interface WebsocketConsumerStatusMessage {
message?: string
document_id: number
}
}

View File

@@ -19,7 +19,7 @@ export class ApiVersionInterceptor implements HttpInterceptor {
'Accept': `application/json; version=${environment.apiVersion}`
}
})
return next.handle(request);
}
}

View File

@@ -20,7 +20,7 @@ export class CsrfInterceptor implements HttpInterceptor {
let prefix = ""
if (this.meta.getTag('name=cookie_prefix')) {
prefix = this.meta.getTag('name=cookie_prefix').content
}
}
let csrfToken = this.cookieService.get(`${prefix?prefix:''}csrftoken`)
if (csrfToken) {
request = request.clone({

View File

@@ -11,12 +11,11 @@ const FORMAT_TO_ISO_FORMAT = {
@Pipe({
name: 'customDate'
})
export class CustomDatePipe extends DatePipe implements PipeTransform {
export class CustomDatePipe implements PipeTransform {
private defaultLocale: string
constructor(@Inject(LOCALE_ID) locale: string, private settings: SettingsService) {
super(locale)
constructor(@Inject(LOCALE_ID) locale: string, private datePipe: DatePipe, private settings: SettingsService) {
this.defaultLocale = locale
}
@@ -24,9 +23,9 @@ export class CustomDatePipe extends DatePipe implements PipeTransform {
let l = locale || this.settings.get(SETTINGS_KEYS.DATE_LOCALE) || this.defaultLocale
let f = format || this.settings.get(SETTINGS_KEYS.DATE_FORMAT)
if (l == "iso-8601") {
return super.transform(value, FORMAT_TO_ISO_FORMAT[f], timezone)
return this.datePipe.transform(value, FORMAT_TO_ISO_FORMAT[f], timezone)
} else {
return super.transform(value, format || this.settings.get(SETTINGS_KEYS.DATE_FORMAT), timezone, l)
return this.datePipe.transform(value, format || this.settings.get(SETTINGS_KEYS.DATE_FORMAT), timezone, l)
}
}

View File

@@ -1,6 +1,6 @@
/**
* https://gist.github.com/JonCatmull/ecdf9441aaa37336d9ae2c7f9cb7289a
*
*
* @license
* Copyright (c) 2019 Jonathan Catmull.
*

View File

@@ -16,4 +16,4 @@ export class SafePipe implements PipeTransform {
}
}
}
}

View File

@@ -10,7 +10,7 @@ export class OpenDocumentsService {
private MAX_OPEN_DOCUMENTS = 5
constructor(private documentService: DocumentService) {
constructor(private documentService: DocumentService) {
if (sessionStorage.getItem(OPEN_DOCUMENT_SERVICE.DOCUMENTS)) {
try {
this.openDocuments = JSON.parse(sessionStorage.getItem(OPEN_DOCUMENT_SERVICE.DOCUMENTS))

View File

@@ -44,7 +44,7 @@ export class SavedViewService extends AbstractPaperlessService<PaperlessSavedVie
tap(() => this.reload())
)
}
patchMany(objects: PaperlessSavedView[]): Observable<PaperlessSavedView[]> {
return combineLatest(objects.map(o => super.patch(o))).pipe(
tap(() => this.reload())

View File

@@ -10,10 +10,10 @@ import { DocumentService } from './document.service';
providedIn: 'root'
})
export class SearchService {
constructor(private http: HttpClient) { }
autocomplete(term: string): Observable<string[]> {
return this.http.get<string[]>(`${environment.apiBaseUrl}search/autocomplete/`, {params: new HttpParams().set('term', term)})
}
}
}

View File

@@ -99,7 +99,8 @@ export class SettingsService {
{code: "ru-ru", name: $localize`Russian`, englishName: "Russian", dateInputFormat: "dd.mm.yyyy"},
{code: "es-es", name: $localize`Spanish`, englishName: "Spanish", dateInputFormat: "dd/mm/yyyy"},
{code: "pl-pl", name: $localize`Polish`, englishName: "Polish", dateInputFormat: "dd.mm.yyyy"},
{code: "sv-se", name: $localize`Swedish`, englishName: "Swedish", dateInputFormat: "yyyy-mm-dd"}
{code: "sv-se", name: $localize`Swedish`, englishName: "Swedish", dateInputFormat: "yyyy-mm-dd"},
{code: "lb-lu", name: $localize`Luxembourgish`, englishName: "Luxembourgish", dateInputFormat: "dd.mm.yyyy"}
]
}

View File

@@ -6,7 +6,7 @@ function componentToHex(c) {
/**
* https://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
*
*
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes h, s, and l are contained in the set [0, 1] and
@@ -45,4 +45,4 @@ function hslToRgb(h, s, l){
export function randomColor() {
let rgb = hslToRgb(Math.random(), 0.6, Math.random() * 0.4 + 0.4)
return `#${componentToHex(rgb[0])}${componentToHex(rgb[1])}${componentToHex(rgb[2])}`
}
}

View File

@@ -56,4 +56,4 @@ export class LocalizedDateParserFormatter extends NgbDateParserFormatter {
return null
}
}
}
}

View File

@@ -5,7 +5,7 @@ export const environment = {
apiBaseUrl: document.baseURI + "api/",
apiVersion: "2",
appTitle: "Paperless-ng",
version: "1.4.4",
version: "1.5.0",
webSocketHost: window.location.host,
webSocketProtocol: (window.location.protocol == "https:" ? "wss:" : "ws:"),
webSocketBaseUrl: base_url.pathname + "ws/",

View File

@@ -176,7 +176,7 @@
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">117</context>
</context-group>
<target state="translated">Tipo de documento</target>
<target state="translated">Correspondencia</target>
</trans-unit>
<trans-unit id="fdf7cbdc140d0aab0f0b6c06065a0fd448ed6a2e" datatype="html">
<source>Title</source>
@@ -208,7 +208,7 @@
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">141</context>
</context-group>
<target state="translated">Aggregado</target>
<target state="translated">Añadido</target>
</trans-unit>
<trans-unit id="9021887951960049161" datatype="html">
<source>Confirm delete</source>
@@ -1201,7 +1201,7 @@
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
<context context-type="linenumber">61</context>
</context-group>
<target state="translated">ASN: <x id="PH" equiv-text="rule.value"/></target>
<target state="translated">NSA: <x id="PH" equiv-text="rule.value"/></target>
</trans-unit>
<trans-unit id="5701618810648052610" datatype="html">
<source>Title</source>
@@ -1233,7 +1233,7 @@
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
<context context-type="linenumber">91</context>
</context-group>
<target state="needs-translation">Advanced search</target>
<target state="translated">Búsqueda avanzada</target>
</trans-unit>
<trans-unit id="2649431021108393503" datatype="html">
<source>More like</source>
@@ -1241,7 +1241,7 @@
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
<context context-type="linenumber">94</context>
</context-group>
<target state="needs-translation">More like</target>
<target state="translated">Más parecido</target>
</trans-unit>
<trans-unit id="02d184c288f567825a1fcbf83bcd3099a10853d5" datatype="html">
<source>Filter tags</source>
@@ -1386,7 +1386,7 @@
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<context context-type="linenumber">43</context>
</context-group>
<target state="needs-translation">Created: <x id="INTERPOLATION" equiv-text="{{ document.created | customDate}}"/></target>
<target state="translated">Creado: <x id="INTERPOLATION" equiv-text="{{ document.created | customDate}}"/></target>
</trans-unit>
<trans-unit id="0f5d856cb63c69fde44fbfc653ec0655f9040865" datatype="html">
<source>Added: <x id="INTERPOLATION" equiv-text="{{ document.added | customDate}}"/></source>
@@ -1394,7 +1394,7 @@
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<context context-type="linenumber">44</context>
</context-group>
<target state="needs-translation">Added: <x id="INTERPOLATION" equiv-text="{{ document.added | customDate}}"/></target>
<target state="translated">Añadido: <x id="INTERPOLATION" equiv-text="{{ document.added | customDate}}"/></target>
</trans-unit>
<trans-unit id="a205126adef6251fc63305f1a6228d07bc2795a8" datatype="html">
<source>Modified: <x id="INTERPOLATION" equiv-text="{{ document.modified | customDate}}"/></source>
@@ -1402,7 +1402,7 @@
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<context context-type="linenumber">45</context>
</context-group>
<target state="needs-translation">Modified: <x id="INTERPOLATION" equiv-text="{{ document.modified | customDate}}"/></target>
<target state="translated">Modificado: <x id="INTERPOLATION" equiv-text="{{ document.modified | customDate}}"/></target>
</trans-unit>
<trans-unit id="7985804062689412812" datatype="html">
<source>Error executing bulk operation: <x id="PH" equiv-text="JSON.stringify(error.error)"/></source>
@@ -1614,7 +1614,7 @@
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="needs-translation">Add item</target>
<target state="translated">Añadir elemento</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
@@ -1638,7 +1638,7 @@
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="needs-translation">Add tag</target>
<target state="translated">Añadir etiqueta</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
@@ -1872,7 +1872,7 @@
<context context-type="sourcefile">src/app/components/document-asn/document-asn.component.html</context>
<context context-type="linenumber">1</context>
</context-group>
<target state="needs-translation">Searching document with asn <x id="INTERPOLATION" equiv-text="{{asn}}"/></target>
<target state="translated">Buscando documento con NSA <x id="INTERPOLATION" equiv-text="{{asn}}"/></target>
</trans-unit>
<trans-unit id="2807800733729323332" datatype="html">
<source>Yes</source>
@@ -1944,7 +1944,7 @@
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">95</context>
</context-group>
<target state="needs-translation">Portuguese</target>
<target state="translated">Portugués</target>
</trans-unit>
<trans-unit id="9184513005098760425" datatype="html">
<source>Portuguese (Brazil)</source>
@@ -1992,7 +1992,7 @@
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">101</context>
</context-group>
<target state="needs-translation">Polish</target>
<target state="translated">Polaco</target>
</trans-unit>
<trans-unit id="499386805970351976" datatype="html">
<source>Swedish</source>
@@ -2000,7 +2000,7 @@
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">102</context>
</context-group>
<target state="needs-translation">Swedish</target>
<target state="translated">Sueco</target>
</trans-unit>
<trans-unit id="4912706592792948707" datatype="html">
<source>ISO 8601</source>
@@ -2181,7 +2181,7 @@
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="needs-translation">Search score</target>
<target state="translated">Puntuación de búsqueda</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>

File diff suppressed because it is too large Load Diff

View File

@@ -1614,7 +1614,7 @@
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="needs-translation">Add item</target>
<target state="translated">Dodaj element</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
@@ -1638,7 +1638,7 @@
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="needs-translation">Add tag</target>
<target state="translated">Dodaj tag</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
@@ -2000,7 +2000,7 @@
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">102</context>
</context-group>
<target state="needs-translation">Swedish</target>
<target state="translated">Szwedzki</target>
</trans-unit>
<trans-unit id="4912706592792948707" datatype="html">
<source>ISO 8601</source>
@@ -2181,7 +2181,7 @@
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="needs-translation">Search score</target>
<target state="translated">Dopasowanie</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>

View File

@@ -1614,7 +1614,7 @@
<context context-type="linenumber">11</context>
</context-group>
<note priority="1" from="description">Used for both types and correspondents</note>
<target state="needs-translation">Add item</target>
<target state="translated">Adaugă element</target>
</trans-unit>
<trans-unit id="a1e6c11f20d4bf6e8e6b43e3c6d2561b2080645e" datatype="html">
<source>Suggestions:</source>
@@ -1638,7 +1638,7 @@
<context context-type="sourcefile">src/app/components/common/input/tags/tags.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
<target state="needs-translation">Add tag</target>
<target state="translated">Adaugă etichetă</target>
</trans-unit>
<trans-unit id="4eb84de23219c85432e38fb4fbdeb6c0f103ff8b" datatype="html">
<source>Show all</source>
@@ -2181,7 +2181,7 @@
<context context-type="linenumber">28</context>
</context-group>
<note priority="1" from="description">Score is a value returned by the full text search engine and specifies how well a result matches the given query</note>
<target state="needs-translation">Search score</target>
<target state="translated">Scor de căutare</target>
</trans-unit>
<trans-unit id="4561076822163447092" datatype="html">
<source>Create new item</source>

View File

@@ -3,6 +3,7 @@ import logging
import os
import pickle
import re
import shutil
from django.conf import settings
@@ -96,7 +97,10 @@ class DocumentClassifier(object):
raise ClassifierModelCorruptError()
def save(self):
with open(settings.MODEL_FILE, "wb") as f:
target_file = settings.MODEL_FILE
target_file_temp = settings.MODEL_FILE + ".part"
with open(target_file_temp, "wb") as f:
pickle.dump(self.FORMAT_VERSION, f)
pickle.dump(self.data_hash, f)
pickle.dump(self.data_vectorizer, f)
@@ -107,6 +111,10 @@ class DocumentClassifier(object):
pickle.dump(self.correspondent_classifier, f)
pickle.dump(self.document_type_classifier, f)
if os.path.isfile(target_file):
os.unlink(target_file)
shutil.move(target_file_temp, target_file)
def train(self):
data = list()

View File

@@ -1,6 +1,6 @@
import logging
import os
from pathlib import Path
from pathlib import Path, PurePath
from threading import Thread
from time import sleep
@@ -36,15 +36,11 @@ def _tags_from_path(filepath):
return tag_ids
def _is_ignored(filepath):
# https://github.com/jonaswinkler/paperless-ng/discussions/1037
basename = os.path.basename(filepath)
if basename == ".DS_STORE":
return True
if basename.startswith("._"):
return True
return False
def _is_ignored(filepath: str) -> bool:
filepath_relative = PurePath(filepath).relative_to(
settings.CONSUMPTION_DIR)
return any(
filepath_relative.match(p) for p in settings.CONSUMER_IGNORE_PATTERNS)
def _consume(filepath):

View File

@@ -63,8 +63,20 @@ class Command(BaseCommand):
action="store_true",
help="If set, the progress bar will not be shown"
)
parser.add_argument(
"--suggest",
default=False,
action="store_true",
help="Return the suggestion, don't change anything."
)
parser.add_argument(
"--base-url",
help="The base URL to use to build the link to the documents."
)
def handle(self, *args, **options):
# Detect if we support color
color = self.style.ERROR("test") != "test"
if options["inbox_only"]:
queryset = Document.objects.filter(tags__is_inbox_tag=True)
@@ -85,18 +97,27 @@ class Command(BaseCommand):
document=document,
classifier=classifier,
replace=options['overwrite'],
use_first=options['use_first'])
use_first=options['use_first'],
suggest=options['suggest'],
base_url=options['base_url'],
color=color)
if options['document_type']:
set_document_type(sender=None,
document=document,
classifier=classifier,
replace=options['overwrite'],
use_first=options['use_first'])
use_first=options['use_first'],
suggest=options['suggest'],
base_url=options['base_url'],
color=color)
if options['tags']:
set_tags(
sender=None,
document=document,
classifier=classifier,
replace=options['overwrite'])
replace=options['overwrite'],
suggest=options['suggest'],
base_url=options['base_url'],
color=color)

View File

@@ -1,6 +1,7 @@
import logging
import os
from django.utils import termcolors
from django.conf import settings
from django.contrib.admin.models import ADDITION, LogEntry
from django.contrib.auth.models import User
@@ -8,14 +9,14 @@ from django.contrib.contenttypes.models import ContentType
from django.db import models, DatabaseError
from django.db.models import Q
from django.dispatch import receiver
from django.utils import timezone
from django.utils import termcolors, timezone
from filelock import FileLock
from .. import matching
from ..file_handling import delete_empty_directories, \
create_source_path_directory, \
generate_unique_filename
from ..models import Document, Tag
from ..models import Document, Tag, MatchingModel
logger = logging.getLogger("paperless.handlers")
@@ -32,6 +33,9 @@ def set_correspondent(sender,
classifier=None,
replace=False,
use_first=True,
suggest=False,
base_url=None,
color=False,
**kwargs):
if document.correspondent and not replace:
return
@@ -60,13 +64,31 @@ def set_correspondent(sender,
return
if selected or replace:
logger.info(
f"Assigning correspondent {selected} to {document}",
extra={'group': logging_group}
)
if suggest:
if base_url:
print(
termcolors.colorize(str(document), fg='green')
if color
else str(document)
)
print(f"{base_url}/documents/{document.pk}")
else:
print(
(
termcolors.colorize(str(document), fg='green')
if color
else str(document)
) + f" [{document.pk}]"
)
print(f"Suggest correspondent {selected}")
else:
logger.info(
f"Assigning correspondent {selected} to {document}",
extra={'group': logging_group}
)
document.correspondent = selected
document.save(update_fields=("correspondent",))
document.correspondent = selected
document.save(update_fields=("correspondent",))
def set_document_type(sender,
@@ -75,6 +97,9 @@ def set_document_type(sender,
classifier=None,
replace=False,
use_first=True,
suggest=False,
base_url=None,
color=False,
**kwargs):
if document.document_type and not replace:
return
@@ -104,13 +129,31 @@ def set_document_type(sender,
return
if selected or replace:
logger.info(
f"Assigning document type {selected} to {document}",
extra={'group': logging_group}
)
if suggest:
if base_url:
print(
termcolors.colorize(str(document), fg='green')
if color
else str(document)
)
print(f"{base_url}/documents/{document.pk}")
else:
print(
(
termcolors.colorize(str(document), fg='green')
if color
else str(document)
) + f" [{document.pk}]"
)
print(f"Sugest document type {selected}")
else:
logger.info(
f"Assigning document type {selected} to {document}",
extra={'group': logging_group}
)
document.document_type = selected
document.save(update_fields=("document_type",))
document.document_type = selected
document.save(update_fields=("document_type",))
def set_tags(sender,
@@ -118,6 +161,9 @@ def set_tags(sender,
logging_group=None,
classifier=None,
replace=False,
suggest=False,
base_url=None,
color=False,
**kwargs):
if replace:
@@ -132,16 +178,48 @@ def set_tags(sender,
relevant_tags = set(matched_tags) - current_tags
if not relevant_tags:
return
if suggest:
extra_tags = current_tags - set(matched_tags)
extra_tags = [
t for t in extra_tags
if t.matching_algorithm == MatchingModel.MATCH_AUTO
]
if not relevant_tags and not extra_tags:
return
if base_url:
print(
termcolors.colorize(str(document), fg='green')
if color
else str(document)
)
print(f"{base_url}/documents/{document.pk}")
else:
print(
(
termcolors.colorize(str(document), fg='green')
if color
else str(document)
) + f" [{document.pk}]"
)
if relevant_tags:
print(
"Suggest tags: " + ", ".join([t.name for t in relevant_tags])
)
if extra_tags:
print("Extra tags: " + ", ".join([t.name for t in extra_tags]))
else:
if not relevant_tags:
return
message = 'Tagging "{}" with "{}"'
logger.info(
message.format(document, ", ".join([t.name for t in relevant_tags])),
extra={'group': logging_group}
)
message = 'Tagging "{}" with "{}"'
logger.info(
message.format(
document, ", ".join([t.name for t in relevant_tags])
),
extra={'group': logging_group}
)
document.tags.add(*relevant_tags)
document.tags.add(*relevant_tags)
@receiver(models.signals.post_delete, sender=Document)

File diff suppressed because one or more lines are too long

View File

@@ -222,6 +222,22 @@ class TestConsumer(DirectoriesMixin, ConsumerMixin, TransactionTestCase):
fnames = [os.path.basename(args[1]) for args, _ in self.task_mock.call_args_list]
self.assertCountEqual(fnames, ["my_file.pdf", "my_second_file.pdf"])
def test_is_ignored(self):
test_paths = [
(os.path.join(self.dirs.consumption_dir, "foo.pdf"), False),
(os.path.join(self.dirs.consumption_dir, "foo","bar.pdf"), False),
(os.path.join(self.dirs.consumption_dir, ".DS_STORE", "foo.pdf"), True),
(os.path.join(self.dirs.consumption_dir, "foo", ".DS_STORE", "bar.pdf"), True),
(os.path.join(self.dirs.consumption_dir, ".stfolder", "foo.pdf"), True),
(os.path.join(self.dirs.consumption_dir, "._foo.pdf"), True),
(os.path.join(self.dirs.consumption_dir, "._foo", "bar.pdf"), False),
]
for file_path, expected_ignored in test_paths:
self.assertEqual(
expected_ignored,
document_consumer._is_ignored(file_path),
f'_is_ignored("{file_path}") != {expected_ignored}')
@override_settings(CONSUMER_POLLING=1, CONSUMER_POLLING_DELAY=1, CONSUMER_POLLING_RETRY_COUNT=20)
class TestConsumerPolling(TestConsumer):

View File

@@ -11,14 +11,17 @@ class TestRetagger(DirectoriesMixin, TestCase):
self.d1 = Document.objects.create(checksum="A", title="A", content="first document")
self.d2 = Document.objects.create(checksum="B", title="B", content="second document")
self.d3 = Document.objects.create(checksum="C", title="C", content="unrelated document")
self.d4 = Document.objects.create(checksum="D", title="D", content="auto document")
self.tag_first = Tag.objects.create(name="tag1", match="first", matching_algorithm=Tag.MATCH_ANY)
self.tag_second = Tag.objects.create(name="tag2", match="second", matching_algorithm=Tag.MATCH_ANY)
self.tag_inbox = Tag.objects.create(name="test", is_inbox_tag=True)
self.tag_no_match = Tag.objects.create(name="test2")
self.tag_auto = Tag.objects.create(name="tagauto", matching_algorithm=Tag.MATCH_AUTO)
self.d3.tags.add(self.tag_inbox)
self.d3.tags.add(self.tag_no_match)
self.d4.tags.add(self.tag_auto)
self.correspondent_first = Correspondent.objects.create(
@@ -32,7 +35,8 @@ class TestRetagger(DirectoriesMixin, TestCase):
name="dt2", match="second", matching_algorithm=DocumentType.MATCH_ANY)
def get_updated_docs(self):
return Document.objects.get(title="A"), Document.objects.get(title="B"), Document.objects.get(title="C")
return Document.objects.get(title="A"), Document.objects.get(title="B"), \
Document.objects.get(title="C"), Document.objects.get(title="D")
def setUp(self) -> None:
super(TestRetagger, self).setUp()
@@ -40,25 +44,26 @@ class TestRetagger(DirectoriesMixin, TestCase):
def test_add_tags(self):
call_command('document_retagger', '--tags')
d_first, d_second, d_unrelated = self.get_updated_docs()
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.tags.count(), 1)
self.assertEqual(d_second.tags.count(), 1)
self.assertEqual(d_unrelated.tags.count(), 2)
self.assertEqual(d_auto.tags.count(), 1)
self.assertEqual(d_first.tags.first(), self.tag_first)
self.assertEqual(d_second.tags.first(), self.tag_second)
def test_add_type(self):
call_command('document_retagger', '--document_type')
d_first, d_second, d_unrelated = self.get_updated_docs()
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.document_type, self.doctype_first)
self.assertEqual(d_second.document_type, self.doctype_second)
def test_add_correspondent(self):
call_command('document_retagger', '--correspondent')
d_first, d_second, d_unrelated = self.get_updated_docs()
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.correspondent, self.correspondent_first)
self.assertEqual(d_second.correspondent, self.correspondent_second)
@@ -68,11 +73,55 @@ class TestRetagger(DirectoriesMixin, TestCase):
call_command('document_retagger', '--tags', '--overwrite')
d_first, d_second, d_unrelated = self.get_updated_docs()
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertIsNotNone(Tag.objects.get(id=self.tag_second.id))
self.assertCountEqual([tag.id for tag in d_first.tags.all()], [self.tag_first.id])
self.assertCountEqual([tag.id for tag in d_second.tags.all()], [self.tag_second.id])
self.assertCountEqual([tag.id for tag in d_unrelated.tags.all()], [self.tag_inbox.id, self.tag_no_match.id])
self.assertEqual(d_auto.tags.count(), 0)
def test_add_tags_suggest(self):
call_command('document_retagger', '--tags', '--suggest')
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.tags.count(), 0)
self.assertEqual(d_second.tags.count(), 0)
self.assertEqual(d_auto.tags.count(), 1)
def test_add_type_suggest(self):
call_command('document_retagger', '--document_type', '--suggest')
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.document_type, None)
self.assertEqual(d_second.document_type, None)
def test_add_correspondent_suggest(self):
call_command('document_retagger', '--correspondent', '--suggest')
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.correspondent, None)
self.assertEqual(d_second.correspondent, None)
def test_add_tags_suggest_url(self):
call_command('document_retagger', '--tags', '--suggest', '--base-url=http://localhost')
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.tags.count(), 0)
self.assertEqual(d_second.tags.count(), 0)
self.assertEqual(d_auto.tags.count(), 1)
def test_add_type_suggest_url(self):
call_command('document_retagger', '--document_type', '--suggest', '--base-url=http://localhost')
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.document_type, None)
self.assertEqual(d_second.document_type, None)
def test_add_correspondent_suggest_url(self):
call_command('document_retagger', '--correspondent', '--suggest', '--base-url=http://localhost')
d_first, d_second, d_unrelated, d_auto = self.get_updated_docs()
self.assertEqual(d_first.correspondent, None)
self.assertEqual(d_second.correspondent, None)

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-05-16 09:38+0000\n"
"PO-Revision-Date: 2021-05-16 11:15\n"
"PO-Revision-Date: 2021-07-05 11:17\n"
"Last-Translator: \n"
"Language-Team: German\n"
"Language: de_DE\n"
@@ -35,7 +35,7 @@ msgstr "Exakte Übereinstimmung"
#: documents/models.py:35
msgid "Regular expression"
msgstr "Regulärer Ausdruck"
msgstr "Regular expression / Reguläre Ausdrücke"
#: documents/models.py:36
msgid "Fuzzy word"

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-05-16 09:38+0000\n"
"PO-Revision-Date: 2021-05-16 10:09\n"
"PO-Revision-Date: 2021-06-19 21:20\n"
"Last-Translator: \n"
"Language-Team: English, United Kingdom\n"
"Language: en_GB\n"
@@ -470,11 +470,11 @@ msgstr "Paperless-ng administration"
#: paperless_mail/admin.py:15
msgid "Authentication"
msgstr ""
msgstr "Authentication"
#: paperless_mail/admin.py:18
msgid "Advanced settings"
msgstr ""
msgstr "Advanced settings"
#: paperless_mail/admin.py:37
msgid "Filter"

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-05-16 09:38+0000\n"
"PO-Revision-Date: 2021-05-16 10:09\n"
"PO-Revision-Date: 2021-07-29 20:57\n"
"Last-Translator: \n"
"Language-Team: Spanish\n"
"Language: es_ES\n"
@@ -64,11 +64,11 @@ msgstr "es insensible"
#: documents/models.py:74 documents/models.py:120
msgid "correspondent"
msgstr "Tipo de documento"
msgstr "interlocutor"
#: documents/models.py:75
msgid "correspondents"
msgstr "Tipos de documento"
msgstr "interlocutores"
#: documents/models.py:81
msgid "color"
@@ -100,15 +100,15 @@ msgstr "tipos de documento"
#: documents/models.py:110
msgid "Unencrypted"
msgstr "Sin encriptar"
msgstr "Sin cifrar"
#: documents/models.py:111
msgid "Encrypted with GNU Privacy Guard"
msgstr "Encriptado con GNU Privacy Guard"
msgstr "Cifrado con GNU Privacy Guard"
#: documents/models.py:124
msgid "title"
msgstr "titulo"
msgstr "título"
#: documents/models.py:137
msgid "content"
@@ -256,7 +256,7 @@ msgstr "ordenar al revés"
#: documents/models.py:373
msgid "title contains"
msgstr "el titulo contiene"
msgstr "el título contiene"
#: documents/models.py:374
msgid "content contains"
@@ -268,7 +268,7 @@ msgstr "ASN es"
#: documents/models.py:376
msgid "correspondent is"
msgstr "tipo de documento es"
msgstr "interlocutor es"
#: documents/models.py:377
msgid "document type is"
@@ -336,11 +336,11 @@ msgstr "el título o cuerpo contiene"
#: documents/models.py:393
msgid "fulltext query"
msgstr ""
msgstr "consulta de texto completo"
#: documents/models.py:394
msgid "more like this"
msgstr ""
msgstr "más contenido similar"
#: documents/models.py:405
msgid "rule type"
@@ -438,7 +438,7 @@ msgstr "Portugués (Brasil)"
#: paperless/settings.py:309
msgid "Portuguese"
msgstr ""
msgstr "Portugués"
#: paperless/settings.py:310
msgid "Italian"
@@ -458,11 +458,11 @@ msgstr "Español"
#: paperless/settings.py:314
msgid "Polish"
msgstr ""
msgstr "Polaco"
#: paperless/settings.py:315
msgid "Swedish"
msgstr ""
msgstr "Sueco"
#: paperless/urls.py:120
msgid "Paperless-ng administration"
@@ -470,11 +470,11 @@ msgstr "Paperless-ng Administración"
#: paperless_mail/admin.py:15
msgid "Authentication"
msgstr ""
msgstr "Autentificación"
#: paperless_mail/admin.py:18
msgid "Advanced settings"
msgstr ""
msgstr "Configuración avanzada"
#: paperless_mail/admin.py:37
msgid "Filter"
@@ -490,7 +490,7 @@ msgstr "Acciones"
#: paperless_mail/admin.py:51
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 "La acción aplicada al correo. Esta acción solo se realiza cuando los documentos se consumen del correo. Los correos sin archivos adjuntos permanecerán totalmente intactos."
msgstr "La acción se aplicó al correo. Esta acción sólo se realiza cuando los documentos se consumen desde el correo. Los correos sin archivos adjuntos permanecerán totalmente intactos."
#: paperless_mail/admin.py:58
msgid "Metadata"
@@ -498,7 +498,7 @@ msgstr "Metadatos"
#: paperless_mail/admin.py:60
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 "Asignar metadatos a documentos consumidos por esta regla automáticamente. Si no asigna etiquetas, o ipos aquí, paperless procesará igualmente todas las reglas que haya definido."
msgstr "Asignar metadatos a documentos consumidos por esta regla automáticamente. Si no asigna etiquetas, tipos o interlocutores aquí, paperless procesará igualmente todas las reglas que haya definido."
#: paperless_mail/apps.py:9
msgid "Paperless mail"
@@ -550,11 +550,11 @@ msgstr "contraseña"
#: paperless_mail/models.py:54
msgid "character set"
msgstr ""
msgstr "conjunto de caracteres"
#: paperless_mail/models.py:57
msgid "The character set to use when communicating with the mail server, such as 'UTF-8' or 'US-ASCII'."
msgstr ""
msgstr "El conjunto de caracteres a usar al comunicarse con el servidor de correo, como 'UTF-8' o 'US-ASCII'."
#: paperless_mail/models.py:68
msgid "mail rule"
@@ -590,7 +590,7 @@ msgstr "Borrar"
#: paperless_mail/models.py:96
msgid "Use subject as title"
msgstr "Usar asunto como titulo"
msgstr "Usar asunto como título"
#: paperless_mail/models.py:97
msgid "Use attachment filename as title"
@@ -598,7 +598,7 @@ msgstr "Usar nombre del fichero adjunto como título"
#: paperless_mail/models.py:107
msgid "Do not assign a correspondent"
msgstr "No asignar un tipo de documento"
msgstr "No asignar interlocutor"
#: paperless_mail/models.py:109
msgid "Use mail address"
@@ -606,11 +606,11 @@ msgstr "Usar dirección de correo"
#: paperless_mail/models.py:111
msgid "Use name (or mail address if not available)"
msgstr "Usar nombre (o dirección de correo si no está disponible)"
msgstr "Usar nombre (o dirección de correo sino está disponible)"
#: paperless_mail/models.py:113
msgid "Use correspondent selected below"
msgstr "Usar el tipo seleccionado debajo"
msgstr "Usar el interlocutor seleccionado a continuación"
#: paperless_mail/models.py:121
msgid "order"
@@ -626,7 +626,7 @@ msgstr "carpeta"
#: paperless_mail/models.py:134
msgid "Subfolders must be separated by dots."
msgstr ""
msgstr "Las subcarpetas deben estar separadas por puntos."
#: paperless_mail/models.py:138
msgid "filter from"
@@ -674,11 +674,11 @@ msgstr "parámetro de acción"
#: paperless_mail/models.py:177
msgid "Additional parameter for the action selected above, i.e., the target folder of the move to folder action. Subfolders must be separated by dots."
msgstr ""
msgstr "Parámetro adicional para la acción seleccionada arriba. Ej. la carpeta de destino de la acción \"mover a carpeta\". Las subcarpetas deben estar separadas por puntos."
#: paperless_mail/models.py:184
msgid "assign title from"
msgstr "asignar titulo desde"
msgstr "asignar título desde"
#: paperless_mail/models.py:194
msgid "assign this tag"
@@ -690,9 +690,9 @@ msgstr "asignar este tipo de documento"
#: paperless_mail/models.py:206
msgid "assign correspondent from"
msgstr "Asignar tipo de documento desde"
msgstr "asignar interlocutor desde"
#: paperless_mail/models.py:216
msgid "assign this correspondent"
msgstr "asignar este tipo de documento"
msgstr "asignar este interlocutor"

View File

@@ -0,0 +1,698 @@
msgid ""
msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-05-16 09:38+0000\n"
"PO-Revision-Date: 2021-07-16 14:22\n"
"Last-Translator: \n"
"Language-Team: Luxembourgish\n"
"Language: lb_LU\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: paperless-ng\n"
"X-Crowdin-Project-ID: 434940\n"
"X-Crowdin-Language: lb\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 "Dokumenter"
#: documents/models.py:32
msgid "Any word"
msgstr "Iergendee Wuert"
#: documents/models.py:33
msgid "All words"
msgstr "All d'Wierder"
#: documents/models.py:34
msgid "Exact match"
msgstr "Exakten Treffer"
#: documents/models.py:35
msgid "Regular expression"
msgstr "Regulären Ausdrock"
#: documents/models.py:36
msgid "Fuzzy word"
msgstr "Ongenaut Wuert"
#: documents/models.py:37
msgid "Automatic"
msgstr "Automatesch"
#: documents/models.py:41 documents/models.py:350 paperless_mail/models.py:25
#: paperless_mail/models.py:117
msgid "name"
msgstr "Numm"
#: documents/models.py:45
msgid "match"
msgstr "Zouweisungsmuster"
#: documents/models.py:49
msgid "matching algorithm"
msgstr "Zouweisungsalgorithmus"
#: documents/models.py:55
msgid "is insensitive"
msgstr "Grouss-/Klengschreiwung ignoréieren"
#: documents/models.py:74 documents/models.py:120
msgid "correspondent"
msgstr "Korrespondent"
#: documents/models.py:75
msgid "correspondents"
msgstr "Korrespondenten"
#: documents/models.py:81
msgid "color"
msgstr "Faarf"
#: documents/models.py:87
msgid "is inbox tag"
msgstr "Postaganks-Etikett"
#: documents/models.py:89
msgid "Marks this tag as an inbox tag: All newly consumed documents will be tagged with inbox tags."
msgstr "Dës Etikett als Postaganks-Etikett markéieren: All nei importéiert Dokumenter kréien ëmmer dës Etikett zougewisen."
#: documents/models.py:94
msgid "tag"
msgstr "Etikett"
#: documents/models.py:95 documents/models.py:151
msgid "tags"
msgstr "Etiketten"
#: documents/models.py:101 documents/models.py:133
msgid "document type"
msgstr "Dokumententyp"
#: documents/models.py:102
msgid "document types"
msgstr "Dokumententypen"
#: documents/models.py:110
msgid "Unencrypted"
msgstr "Onverschlësselt"
#: documents/models.py:111
msgid "Encrypted with GNU Privacy Guard"
msgstr "Verschlësselt mat GNU Privacy Guard"
#: documents/models.py:124
msgid "title"
msgstr "Titel"
#: documents/models.py:137
msgid "content"
msgstr "Inhalt"
#: documents/models.py:139
msgid "The raw, text-only data of the document. This field is primarily used for searching."
msgstr "De réien Textinhalt vum Dokument. Dëst Feld gëtt primär fir d'Sich benotzt."
#: documents/models.py:144
msgid "mime type"
msgstr "MIME-Typ"
#: documents/models.py:155
msgid "checksum"
msgstr "Préifzomm"
#: documents/models.py:159
msgid "The checksum of the original document."
msgstr "D'Préifzomm vum Original-Dokument."
#: documents/models.py:163
msgid "archive checksum"
msgstr "Archiv-Préifzomm"
#: documents/models.py:168
msgid "The checksum of the archived document."
msgstr "D'Préifzomm vum archivéierten Dokument."
#: documents/models.py:172 documents/models.py:328
msgid "created"
msgstr "erstallt"
#: documents/models.py:176
msgid "modified"
msgstr "verännert"
#: documents/models.py:180
msgid "storage type"
msgstr "Späichertyp"
#: documents/models.py:188
msgid "added"
msgstr "derbäigesat"
#: documents/models.py:192
msgid "filename"
msgstr "Fichiersnumm"
#: documents/models.py:198
msgid "Current filename in storage"
msgstr "Aktuellen Dateinumm am Späicher"
#: documents/models.py:202
msgid "archive filename"
msgstr "Archiv-Dateinumm"
#: documents/models.py:208
msgid "Current archive filename in storage"
msgstr "Aktuellen Dateinumm am Archiv"
#: documents/models.py:212
msgid "archive serial number"
msgstr "Archiv-Seriennummer"
#: documents/models.py:217
msgid "The position of this document in your physical document archive."
msgstr "D'Positioun vun dësem Dokument am physeschen Dokumentenarchiv."
#: documents/models.py:223
msgid "document"
msgstr "Dokument"
#: documents/models.py:224
msgid "documents"
msgstr "Dokumenter"
#: documents/models.py:311
msgid "debug"
msgstr "Fehlersiich"
#: documents/models.py:312
msgid "information"
msgstr "Informatioun"
#: documents/models.py:313
msgid "warning"
msgstr "Warnung"
#: documents/models.py:314
msgid "error"
msgstr "Feeler"
#: documents/models.py:315
msgid "critical"
msgstr "kritesch"
#: documents/models.py:319
msgid "group"
msgstr "Grupp"
#: documents/models.py:322
msgid "message"
msgstr "Message"
#: documents/models.py:325
msgid "level"
msgstr "Niveau"
#: documents/models.py:332
msgid "log"
msgstr "Protokoll"
#: documents/models.py:333
msgid "logs"
msgstr "Protokoller"
#: documents/models.py:344 documents/models.py:401
msgid "saved view"
msgstr "Gespäichert Usiicht"
#: documents/models.py:345
msgid "saved views"
msgstr "Gespäichert Usiichten"
#: documents/models.py:348
msgid "user"
msgstr "Benotzer"
#: documents/models.py:354
msgid "show on dashboard"
msgstr "Op der Startsäit uweisen"
#: documents/models.py:357
msgid "show in sidebar"
msgstr "An der Säiteleescht uweisen"
#: documents/models.py:361
msgid "sort field"
msgstr "Zortéierfeld"
#: documents/models.py:367
msgid "sort reverse"
msgstr "ëmgedréint zortéieren"
#: documents/models.py:373
msgid "title contains"
msgstr "Titel enthält"
#: documents/models.py:374
msgid "content contains"
msgstr "Inhalt enthält"
#: documents/models.py:375
msgid "ASN is"
msgstr "ASN ass"
#: documents/models.py:376
msgid "correspondent is"
msgstr "Korrespondent ass"
#: documents/models.py:377
msgid "document type is"
msgstr "Dokumententyp ass"
#: documents/models.py:378
msgid "is in inbox"
msgstr "ass am Postagank"
#: documents/models.py:379
msgid "has tag"
msgstr "huet Etikett"
#: documents/models.py:380
msgid "has any tag"
msgstr "huet iergendeng Etikett"
#: documents/models.py:381
msgid "created before"
msgstr "erstallt virun"
#: documents/models.py:382
msgid "created after"
msgstr "erstallt no"
#: documents/models.py:383
msgid "created year is"
msgstr "Erstellungsjoer ass"
#: documents/models.py:384
msgid "created month is"
msgstr "Erstellungsmount ass"
#: documents/models.py:385
msgid "created day is"
msgstr "Erstellungsdag ass"
#: documents/models.py:386
msgid "added before"
msgstr "dobäigesat virun"
#: documents/models.py:387
msgid "added after"
msgstr "dobäigesat no"
#: documents/models.py:388
msgid "modified before"
msgstr "verännert virun"
#: documents/models.py:389
msgid "modified after"
msgstr "verännert no"
#: documents/models.py:390
msgid "does not have tag"
msgstr "huet dës Etikett net"
#: documents/models.py:391
msgid "does not have ASN"
msgstr "huet keng ASN"
#: documents/models.py:392
msgid "title or content contains"
msgstr "Titel oder Inhalt enthalen"
#: documents/models.py:393
msgid "fulltext query"
msgstr "Volltextsich"
#: documents/models.py:394
msgid "more like this"
msgstr "ähnlech Dokumenter"
#: documents/models.py:405
msgid "rule type"
msgstr "Reegeltyp"
#: documents/models.py:409
msgid "value"
msgstr "Wäert"
#: documents/models.py:415
msgid "filter rule"
msgstr "Filterreegel"
#: documents/models.py:416
msgid "filter rules"
msgstr "Filterreegelen"
#: documents/serialisers.py:53
#, python-format
msgid "Invalid regular expression: %(error)s"
msgstr "Ongëltege regulären Ausdrock: %(error)s"
#: documents/serialisers.py:177
msgid "Invalid color."
msgstr "Ongëlteg Faarf."
#: documents/serialisers.py:451
#, python-format
msgid "File type %(type)s not supported"
msgstr "Fichierstyp %(type)s net ënnerstëtzt"
#: documents/templates/index.html:22
msgid "Paperless-ng is loading..."
msgstr "Paperless-ng gëtt gelueden..."
#: documents/templates/registration/logged_out.html:14
msgid "Paperless-ng signed out"
msgstr "Paperless-ng ofgemellt"
#: documents/templates/registration/logged_out.html:45
msgid "You have been successfully logged out. Bye!"
msgstr "Dir hutt Iech erfollegräich ofgemellt. Bis geschwënn!"
#: documents/templates/registration/logged_out.html:46
msgid "Sign in again"
msgstr "Nees umellen"
#: documents/templates/registration/login.html:15
msgid "Paperless-ng sign in"
msgstr "Umeldung bei Paperless-ng"
#: documents/templates/registration/login.html:47
msgid "Please sign in."
msgstr "W. e. g. umellen."
#: documents/templates/registration/login.html:50
msgid "Your username and password didn't match. Please try again."
msgstr "Äre Benotzernumm a Passwuert stëmmen net iwwereneen. Probéiert w. e. g. nach emol."
#: documents/templates/registration/login.html:53
msgid "Username"
msgstr "Benotzernumm"
#: documents/templates/registration/login.html:54
msgid "Password"
msgstr "Passwuert"
#: documents/templates/registration/login.html:59
msgid "Sign in"
msgstr "Umellen"
#: paperless/settings.py:303
msgid "English (US)"
msgstr "Englesch (USA)"
#: paperless/settings.py:304
msgid "English (GB)"
msgstr "Englesch (GB)"
#: paperless/settings.py:305
msgid "German"
msgstr "Däitsch"
#: paperless/settings.py:306
msgid "Dutch"
msgstr "Hollännesch"
#: paperless/settings.py:307
msgid "French"
msgstr "Franséisch"
#: paperless/settings.py:308
msgid "Portuguese (Brazil)"
msgstr "Portugisesch (Brasilien)"
#: paperless/settings.py:309
msgid "Portuguese"
msgstr "Portugisesch"
#: paperless/settings.py:310
msgid "Italian"
msgstr "Italienesch"
#: paperless/settings.py:311
msgid "Romanian"
msgstr "Rumänesch"
#: paperless/settings.py:312
msgid "Russian"
msgstr "Russesch"
#: paperless/settings.py:313
msgid "Spanish"
msgstr "Spuenesch"
#: paperless/settings.py:314
msgid "Polish"
msgstr "Polnesch"
#: paperless/settings.py:315
msgid "Swedish"
msgstr "Schwedesch"
#: paperless/urls.py:120
msgid "Paperless-ng administration"
msgstr "Paperless-ng-Administratioun"
#: paperless_mail/admin.py:15
msgid "Authentication"
msgstr "Authentifizéierung"
#: paperless_mail/admin.py:18
msgid "Advanced settings"
msgstr "Erweidert Astellungen"
#: paperless_mail/admin.py:37
msgid "Filter"
msgstr "Filter"
#: paperless_mail/admin.py:39
msgid "Paperless will only process mails that match ALL of the filters given below."
msgstr "Paperless wäert nëmmen E-Maile veraarbechten, fir déi all déi hei definéiert Filteren zoutreffen."
#: paperless_mail/admin.py:49
msgid "Actions"
msgstr "Aktiounen"
#: paperless_mail/admin.py:51
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 "D'Aktioun, déi op E-Mailen applizéiert sill ginn. Dës Aktioun gëtt just ausgefouert, wann Dokumenter aus der E-Mail veraarbecht goufen. E-Mailen ouni Unhank bleiwe komplett onberéiert."
#: paperless_mail/admin.py:58
msgid "Metadata"
msgstr "Metadaten"
#: paperless_mail/admin.py:60
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 "Den Dokumenter, déi iwwer dës Reegel veraarbecht ginn, automatesch Metadaten zouweisen. Wann hei keng Etiketten, Typen oder Korrespondenten zougewise ginn, veraarbecht Paperless-ng trotzdeem all zoutreffend Reegelen déi definéiert sinn."
#: paperless_mail/apps.py:9
msgid "Paperless mail"
msgstr "Paperless E-Mail"
#: paperless_mail/models.py:11
msgid "mail account"
msgstr "Mailkont"
#: paperless_mail/models.py:12
msgid "mail accounts"
msgstr "Mailkonten"
#: paperless_mail/models.py:19
msgid "No encryption"
msgstr "Keng Verschlësselung"
#: paperless_mail/models.py:20
msgid "Use SSL"
msgstr "SSL benotzen"
#: paperless_mail/models.py:21
msgid "Use STARTTLS"
msgstr "STARTTLS benotzen"
#: paperless_mail/models.py:29
msgid "IMAP server"
msgstr "IMAP-Server"
#: paperless_mail/models.py:33
msgid "IMAP port"
msgstr "IMAP-Port"
#: paperless_mail/models.py:36
msgid "This is usually 143 for unencrypted and STARTTLS connections, and 993 for SSL connections."
msgstr "Dëst ass normalerweis 143 fir onverschësselt oder STARTTLS-Connectiounen an 993 fir SSL-Connectiounen."
#: paperless_mail/models.py:40
msgid "IMAP security"
msgstr "IMAP-Sécherheet"
#: paperless_mail/models.py:46
msgid "username"
msgstr "Benotzernumm"
#: paperless_mail/models.py:50
msgid "password"
msgstr "Passwuert"
#: paperless_mail/models.py:54
msgid "character set"
msgstr "Zeechesaz"
#: paperless_mail/models.py:57
msgid "The character set to use when communicating with the mail server, such as 'UTF-8' or 'US-ASCII'."
msgstr "Den Zeechesaz dee benotzt gëtt wa mam Mailserver kommunizéiert gëtt, wéi beispillsweis 'UTF-8' oder 'US-ASCII'."
#: paperless_mail/models.py:68
msgid "mail rule"
msgstr "E-Mail-Reegel"
#: paperless_mail/models.py:69
msgid "mail rules"
msgstr "E-Mail-Reegelen"
#: paperless_mail/models.py:75
msgid "Only process attachments."
msgstr "Just Unhäng veraarbechten."
#: paperless_mail/models.py:76
msgid "Process all files, including 'inline' attachments."
msgstr "All d'Fichiere veraarbechten, inklusiv \"inline\"-Unhäng."
#: paperless_mail/models.py:86
msgid "Mark as read, don't process read mails"
msgstr "Als gelies markéieren, gelies Mailen net traitéieren"
#: paperless_mail/models.py:87
msgid "Flag the mail, don't process flagged mails"
msgstr "Als wichteg markéieren, markéiert E-Mailen net veraarbechten"
#: paperless_mail/models.py:88
msgid "Move to specified folder"
msgstr "An e virdefinéierten Dossier réckelen"
#: paperless_mail/models.py:89
msgid "Delete"
msgstr "Läschen"
#: paperless_mail/models.py:96
msgid "Use subject as title"
msgstr "Sujet als TItel notzen"
#: paperless_mail/models.py:97
msgid "Use attachment filename as title"
msgstr "Numm vum Dateiunhank als Titel benotzen"
#: paperless_mail/models.py:107
msgid "Do not assign a correspondent"
msgstr "Kee Korrespondent zouweisen"
#: paperless_mail/models.py:109
msgid "Use mail address"
msgstr "E-Mail-Adress benotzen"
#: paperless_mail/models.py:111
msgid "Use name (or mail address if not available)"
msgstr "Numm benotzen (oder E-Mail-Adress falls den Numm net disponibel ass)"
#: paperless_mail/models.py:113
msgid "Use correspondent selected below"
msgstr "Korrespondent benotzen deen hei drënner ausgewielt ass"
#: paperless_mail/models.py:121
msgid "order"
msgstr "Reiefolleg"
#: paperless_mail/models.py:128
msgid "account"
msgstr "Kont"
#: paperless_mail/models.py:132
msgid "folder"
msgstr "Dossier"
#: paperless_mail/models.py:134
msgid "Subfolders must be separated by dots."
msgstr "Ënnerdossiere mussen duerch Punkte getrennt ginn."
#: paperless_mail/models.py:138
msgid "filter from"
msgstr "Ofsenderfilter"
#: paperless_mail/models.py:141
msgid "filter subject"
msgstr "Sujets-Filter"
#: paperless_mail/models.py:144
msgid "filter body"
msgstr "Contenu-Filter"
#: paperless_mail/models.py:148
msgid "filter attachment filename"
msgstr "Filter fir den Numm vum Unhank"
#: paperless_mail/models.py:150
msgid "Only consume documents which entirely match this filename if specified. Wildcards such as *.pdf or *invoice* are allowed. Case insensitive."
msgstr "Just Dokumenter traitéieren, déi exakt dësen Dateinumm hunn (falls definéiert). Platzhalter wéi *.pdf oder *invoice* sinn erlaabt. D'Grouss-/Klengschreiwung gëtt ignoréiert."
#: paperless_mail/models.py:156
msgid "maximum age"
msgstr "Maximalen Alter"
#: paperless_mail/models.py:158
msgid "Specified in days."
msgstr "An Deeg."
#: paperless_mail/models.py:161
msgid "attachment type"
msgstr "Fichierstyp vum Unhank"
#: paperless_mail/models.py:164
msgid "Inline attachments include embedded images, so it's best to combine this option with a filename filter."
msgstr "\"Inline\"-Unhänk schléissen och agebonne Biller mat an, dofir sollt dës Astellung mat engem Filter fir den Numm vum Unhank kombinéiert ginn."
#: paperless_mail/models.py:169
msgid "action"
msgstr "Aktioun"
#: paperless_mail/models.py:175
msgid "action parameter"
msgstr "Parameter fir Aktioun"
#: paperless_mail/models.py:177
msgid "Additional parameter for the action selected above, i.e., the target folder of the move to folder action. Subfolders must be separated by dots."
msgstr "Zousätzleche Parameter fir d'Aktioun déi hei driwwer ausgewielt ass, zum Beispill den Numm vum Zildossier fir d'Aktioun \"An e virdefinéierten Dossier réckelen\". Ënnerdossiere musse mat Punkte getrennt ginn."
#: paperless_mail/models.py:184
msgid "assign title from"
msgstr "Titel zouweisen aus"
#: paperless_mail/models.py:194
msgid "assign this tag"
msgstr "dës Etikett zouweisen"
#: paperless_mail/models.py:202
msgid "assign this document type"
msgstr "Dësen Dokumententyp zouweisen"
#: paperless_mail/models.py:206
msgid "assign correspondent from"
msgstr "Korrespondent zouweisen aus"
#: paperless_mail/models.py:216
msgid "assign this correspondent"
msgstr "Dëse Korrespondent zouweisen"

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-05-16 09:38+0000\n"
"PO-Revision-Date: 2021-05-19 20:48\n"
"PO-Revision-Date: 2021-05-22 10:12\n"
"Last-Translator: \n"
"Language-Team: Dutch\n"
"Language: nl_NL\n"
@@ -674,7 +674,7 @@ msgstr "actie parameters"
#: paperless_mail/models.py:177
msgid "Additional parameter for the action selected above, i.e., the target folder of the move to folder action. Subfolders must be separated by dots."
msgstr "Extra parameter voor de hierboven geselecteerde actie, bijvoorbeeld: de doelmap voor de verplaats naar map actie. Submappen moeten gescheiden worden door punten."
msgstr "Extra parameter voor de hierboven geselecteerde actie, bijvoorbeeld: de doelmap voor de \"verplaats naar map\"-actie. Submappen moeten gescheiden worden door punten."
#: paperless_mail/models.py:184
msgid "assign title from"

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-05-16 09:38+0000\n"
"PO-Revision-Date: 2021-05-16 10:09\n"
"PO-Revision-Date: 2021-08-07 13:02\n"
"Last-Translator: \n"
"Language-Team: Polish\n"
"Language: pl_PL\n"
@@ -462,7 +462,7 @@ msgstr "Polski"
#: paperless/settings.py:315
msgid "Swedish"
msgstr ""
msgstr "Szwedzki"
#: paperless/urls.py:120
msgid "Paperless-ng administration"
@@ -470,11 +470,11 @@ msgstr "Administracja Paperless-ng"
#: paperless_mail/admin.py:15
msgid "Authentication"
msgstr ""
msgstr "Uwierzytelnianie"
#: paperless_mail/admin.py:18
msgid "Advanced settings"
msgstr ""
msgstr "Ustawienia zaawansowane"
#: paperless_mail/admin.py:37
msgid "Filter"
@@ -550,11 +550,11 @@ msgstr "hasło"
#: paperless_mail/models.py:54
msgid "character set"
msgstr ""
msgstr "Kodowanie"
#: paperless_mail/models.py:57
msgid "The character set to use when communicating with the mail server, such as 'UTF-8' or 'US-ASCII'."
msgstr ""
msgstr "Zestaw znaków używany podczas komunikowania się z serwerem poczty, np. \"UTF-8\" lub \"US-ASCII\"."
#: paperless_mail/models.py:68
msgid "mail rule"
@@ -626,7 +626,7 @@ msgstr "folder"
#: paperless_mail/models.py:134
msgid "Subfolders must be separated by dots."
msgstr ""
msgstr "Podfoldery muszą być oddzielone kropkami."
#: paperless_mail/models.py:138
msgid "filter from"
@@ -674,7 +674,7 @@ msgstr "parametr akcji"
#: paperless_mail/models.py:177
msgid "Additional parameter for the action selected above, i.e., the target folder of the move to folder action. Subfolders must be separated by dots."
msgstr ""
msgstr "Dodatkowy parametr dla akcji wybranej powyżej, tj. docelowy folder akcji \"Przenieś do określonego folderu\". Podfoldery muszą być oddzielone kropkami."
#: paperless_mail/models.py:184
msgid "assign title from"

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-05-16 09:38+0000\n"
"PO-Revision-Date: 2021-05-16 10:09\n"
"PO-Revision-Date: 2021-08-16 09:06\n"
"Last-Translator: \n"
"Language-Team: Romanian\n"
"Language: ro_RO\n"
@@ -470,11 +470,11 @@ msgstr "Administrare Paperless-ng"
#: paperless_mail/admin.py:15
msgid "Authentication"
msgstr ""
msgstr "Autentificare"
#: paperless_mail/admin.py:18
msgid "Advanced settings"
msgstr ""
msgstr "Setări avansate"
#: paperless_mail/admin.py:37
msgid "Filter"
@@ -550,11 +550,11 @@ msgstr "parolă"
#: paperless_mail/models.py:54
msgid "character set"
msgstr ""
msgstr "Set de caractere"
#: paperless_mail/models.py:57
msgid "The character set to use when communicating with the mail server, such as 'UTF-8' or 'US-ASCII'."
msgstr ""
msgstr "Setul de caractere folosit la comunicarea cu serverul de e-mail, cum ar fi \"UTF-8\" sau \"US-ASCII\"."
#: paperless_mail/models.py:68
msgid "mail rule"
@@ -626,7 +626,7 @@ msgstr "director"
#: paperless_mail/models.py:134
msgid "Subfolders must be separated by dots."
msgstr ""
msgstr "Subdosarele trebuie separate prin puncte."
#: paperless_mail/models.py:138
msgid "filter from"
@@ -674,7 +674,7 @@ msgstr "parametru acțiune"
#: paperless_mail/models.py:177
msgid "Additional parameter for the action selected above, i.e., the target folder of the move to folder action. Subfolders must be separated by dots."
msgstr ""
msgstr "Parametru adițional pentru acțiunea definită mai sus (ex. directorul în care să se realizeze o mutare). Subdosarele trebuie separate prin puncte."
#: paperless_mail/models.py:184
msgid "assign title from"

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: paperless-ng\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-05-16 09:38+0000\n"
"PO-Revision-Date: 2021-05-16 11:15\n"
"PO-Revision-Date: 2021-07-30 18:02\n"
"Last-Translator: \n"
"Language-Team: Swedish\n"
"Language: sv_SE\n"
@@ -39,7 +39,7 @@ msgstr "Reguljära uttryck"
#: documents/models.py:36
msgid "Fuzzy word"
msgstr "Fuzzy word"
msgstr "Ungefärligt ord"
#: documents/models.py:37
msgid "Automatic"
@@ -76,19 +76,19 @@ msgstr "färg"
#: documents/models.py:87
msgid "is inbox tag"
msgstr "är inkorgstagg"
msgstr "är inkorgsetikett"
#: documents/models.py:89
msgid "Marks this tag as an inbox tag: All newly consumed documents will be tagged with inbox tags."
msgstr "Markerar denna tagg som en inkorgstagg: Alla nyligen konsumerade dokument kommer att taggas med inkorgstaggar."
msgstr "Markerar denna etikett som en inkorgsetikett: Alla nyligen konsumerade dokument kommer att märkas med inkorgsetiketter."
#: documents/models.py:94
msgid "tag"
msgstr "tagg"
msgstr "etikett"
#: documents/models.py:95 documents/models.py:151
msgid "tags"
msgstr "taggar"
msgstr "etiketter"
#: documents/models.py:101 documents/models.py:133
msgid "document type"
@@ -116,7 +116,7 @@ msgstr "innehåll"
#: documents/models.py:139
msgid "The raw, text-only data of the document. This field is primarily used for searching."
msgstr "Dokumentets råa, enbart text data. Detta fält används främst för sökning."
msgstr "Dokumentets obearbetade textdata. Detta fält används främst för sökning."
#: documents/models.py:144
msgid "mime type"
@@ -136,7 +136,7 @@ msgstr "arkivera kontrollsumma"
#: documents/models.py:168
msgid "The checksum of the archived document."
msgstr "Kontrollsumman för arkiverat dokument."
msgstr "Kontrollsumman för det arkiverade dokumentet."
#: documents/models.py:172 documents/models.py:328
msgid "created"
@@ -148,7 +148,7 @@ msgstr "ändrad"
#: documents/models.py:180
msgid "storage type"
msgstr "Lagringstyp"
msgstr "lagringstyp"
#: documents/models.py:188
msgid "added"
@@ -160,7 +160,7 @@ msgstr "filnamn"
#: documents/models.py:198
msgid "Current filename in storage"
msgstr "Nuvarande filnamn i lagring"
msgstr "Nuvarande filnamn i lagringsutrymmet"
#: documents/models.py:202
msgid "archive filename"
@@ -168,11 +168,11 @@ msgstr "arkivfilnamn"
#: documents/models.py:208
msgid "Current archive filename in storage"
msgstr "Nuvarande arkivfilnamn i lagring"
msgstr "Nuvarande arkivfilnamn i lagringsutrymmet"
#: documents/models.py:212
msgid "archive serial number"
msgstr "arkivets serienummer"
msgstr "serienummer (arkivering)"
#: documents/models.py:217
msgid "The position of this document in your physical document archive."
@@ -240,7 +240,7 @@ msgstr "användare"
#: documents/models.py:354
msgid "show on dashboard"
msgstr "visa på instrumentpanelen"
msgstr "visa på kontrollpanelen"
#: documents/models.py:357
msgid "show in sidebar"
@@ -252,7 +252,7 @@ msgstr "sortera fält"
#: documents/models.py:367
msgid "sort reverse"
msgstr "sortera omvänd"
msgstr "sortera omvänt"
#: documents/models.py:373
msgid "title contains"
@@ -280,11 +280,11 @@ msgstr "är i inkorgen"
#: documents/models.py:379
msgid "has tag"
msgstr "har tagg"
msgstr "har etikett"
#: documents/models.py:380
msgid "has any tag"
msgstr "har någon tagg"
msgstr "har någon etikett"
#: documents/models.py:381
msgid "created before"
@@ -324,7 +324,7 @@ msgstr "ändrad efter"
#: documents/models.py:390
msgid "does not have tag"
msgstr "har inte tagg"
msgstr "har inte etikett"
#: documents/models.py:391
msgid "does not have ASN"
@@ -332,7 +332,7 @@ msgstr "har inte ASN"
#: documents/models.py:392
msgid "title or content contains"
msgstr "titeln eller innehållet innehåller"
msgstr "titel eller innehåll innehåller"
#: documents/models.py:393
msgid "fulltext query"
@@ -382,7 +382,7 @@ msgstr "Paperless-ng utloggad"
#: documents/templates/registration/logged_out.html:45
msgid "You have been successfully logged out. Bye!"
msgstr "Du är nu utloggad!"
msgstr "Du är nu utloggad. Hejdå!"
#: documents/templates/registration/logged_out.html:46
msgid "Sign in again"
@@ -398,7 +398,7 @@ msgstr "Vänligen logga in."
#: documents/templates/registration/login.html:50
msgid "Your username and password didn't match. Please try again."
msgstr "Ditt användarnamn och lösenord stämde inte. Försök igen."
msgstr "Ditt användarnamn och lösenord matchade inte. Vänligen försök igen."
#: documents/templates/registration/login.html:53
msgid "Username"
@@ -498,7 +498,7 @@ msgstr "Metadata"
#: paperless_mail/admin.py:60
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 "Tilldela metadata till dokument som konsumeras från denna regel automatiskt. Om du inte tilldelar taggar, typer eller korrespondenter här kommer paperless fortfarande att behandla alla matchande regler som du har definierat."
msgstr "Tilldela metadata till dokument som konsumeras från denna regel automatiskt. Om du inte tilldelar etiketter, typer eller korrespondenter här kommer paperless fortfarande att behandla alla matchande regler som du har definierat."
#: paperless_mail/apps.py:9
msgid "Paperless mail"
@@ -530,7 +530,7 @@ msgstr "IMAP-server"
#: paperless_mail/models.py:33
msgid "IMAP port"
msgstr "IMAP port"
msgstr "IMAP-port"
#: paperless_mail/models.py:36
msgid "This is usually 143 for unencrypted and STARTTLS connections, and 993 for SSL connections."
@@ -538,7 +538,7 @@ msgstr "Detta är vanligtvis 143 för okrypterade och STARTTLS-anslutningar, och
#: paperless_mail/models.py:40
msgid "IMAP security"
msgstr "IMAP säkerhet"
msgstr "IMAP-säkerhet"
#: paperless_mail/models.py:46
msgid "username"
@@ -570,7 +570,7 @@ msgstr "Behandla endast bilagor."
#: paperless_mail/models.py:76
msgid "Process all files, including 'inline' attachments."
msgstr "Behandla alla filer, inklusive \"inline\" bilagor."
msgstr "Behandla alla filer, inklusive infogade bilagor."
#: paperless_mail/models.py:86
msgid "Mark as read, don't process read mails"
@@ -578,7 +578,7 @@ msgstr "Markera som läst, bearbeta inte lästa meddelanden"
#: paperless_mail/models.py:87
msgid "Flag the mail, don't process flagged mails"
msgstr "Flagga mailet, bearbeta inte flaggade mail"
msgstr "Flagga meddelandet, bearbeta inte flaggade meddelanden"
#: paperless_mail/models.py:88
msgid "Move to specified folder"
@@ -646,11 +646,11 @@ msgstr "filtrera filnamn för bilaga"
#: paperless_mail/models.py:150
msgid "Only consume documents which entirely match this filename if specified. Wildcards such as *.pdf or *invoice* are allowed. Case insensitive."
msgstr "Konsumera endast dokument som helt och hållet matchar detta filnamn om det anges. Wildcards som *.pdf eller *faktura* är tillåtna. Ej skiftlägeskänsliga."
msgstr "Konsumera endast dokument som matchar exakt detta filnamn, om det är angivet. Jokertecken som *.pdf eller *faktura* är tillåtna. Ej skiftlägeskänsligt."
#: paperless_mail/models.py:156
msgid "maximum age"
msgstr "maximal ålder"
msgstr "högsta ålder"
#: paperless_mail/models.py:158
msgid "Specified in days."
@@ -662,7 +662,7 @@ msgstr "typ av bilaga"
#: paperless_mail/models.py:164
msgid "Inline attachments include embedded images, so it's best to combine this option with a filename filter."
msgstr "Bifogade bilagor inkluderar inbäddade bilder, så det är bäst att kombinera detta alternativ med ett filnamnsfilter."
msgstr "Infogade bilagor inkluderar inbäddade bilder, så det är bäst att kombinera detta alternativ med ett filnamnsfilter."
#: paperless_mail/models.py:169
msgid "action"
@@ -674,7 +674,7 @@ msgstr "åtgärdsparameter"
#: paperless_mail/models.py:177
msgid "Additional parameter for the action selected above, i.e., the target folder of the move to folder action. Subfolders must be separated by dots."
msgstr "Ytterligare parametrar för åtgärden som valts ovan, d.v.s. målmappen för flytten till mapp-åtgärder. Undermappar måste vara separerade med punkter."
msgstr "Ytterligare parametrar för åtgärden som valts ovan, d.v.s. målmappen för åtgärden \"flytta till angiven mapp\". Undermappar måste vara separerade med punkter."
#: paperless_mail/models.py:184
msgid "assign title from"
@@ -682,7 +682,7 @@ msgstr "tilldela titel från"
#: paperless_mail/models.py:194
msgid "assign this tag"
msgstr "tilldela denna tagg"
msgstr "tilldela denna etikett"
#: paperless_mail/models.py:202
msgid "assign this document type"

View File

@@ -313,6 +313,7 @@ LANGUAGES = [
("es-es", _("Spanish")),
("pl-pl", _("Polish")),
("sv-se", _("Swedish")),
("lb-lu", _("Luxembourgish")),
]
LOCALE_PATHS = [
@@ -420,6 +421,8 @@ Q_CLUSTER = {
'name': 'paperless',
'catch_up': False,
'recycle': 1,
'retry': 1800,
'timeout': 1800,
'workers': TASK_WORKERS,
'redis': os.getenv("PAPERLESS_REDIS", "redis://localhost:6379")
}
@@ -455,6 +458,12 @@ CONSUMER_DELETE_DUPLICATES = __get_boolean("PAPERLESS_CONSUMER_DELETE_DUPLICATES
CONSUMER_RECURSIVE = __get_boolean("PAPERLESS_CONSUMER_RECURSIVE")
# Ignore glob patterns, relative to PAPERLESS_CONSUMPTION_DIR
CONSUMER_IGNORE_PATTERNS = list(
json.loads(
os.getenv("PAPERLESS_CONSUMER_IGNORE_PATTERNS",
'[".DS_STORE/*", "._*", ".stfolder/*"]')))
CONSUMER_SUBDIRS_AS_TAGS = __get_boolean("PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS")
OPTIMIZE_THUMBNAILS = __get_boolean("PAPERLESS_OPTIMIZE_THUMBNAILS", "true")

View File

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

View File

@@ -75,9 +75,9 @@ def get_rule_action(rule):
def make_criterias(rule):
maximum_age = date.today() - timedelta(days=rule.maximum_age)
criterias = {
"date_gte": maximum_age
}
criterias = {}
if rule.maximum_age > 0:
criterias["date_gte"] = maximum_age
if rule.filter_from:
criterias["from_"] = rule.filter_from
if rule.filter_subject:

View File

@@ -70,7 +70,7 @@ class RasterisedDocumentParser(DocumentParser):
try:
with Image.open(image) as im:
x, y = im.info['dpi']
return x
return round(x)
except Exception as e:
self.log(
'warning',
@@ -214,8 +214,12 @@ class RasterisedDocumentParser(DocumentParser):
# This forces tesseract to use one core per page.
os.environ['OMP_THREAD_LIMIT'] = "1"
text_original = self.extract_text(None, document_path)
original_has_text = text_original and len(text_original) > 50
if mime_type == "application/pdf":
text_original = self.extract_text(None, document_path)
original_has_text = text_original and len(text_original) > 50
else:
text_original = None
original_has_text = False
if settings.OCR_MODE == "skip_noarchive" and original_has_text:
self.log("debug",