Compare commits

..

88 Commits

Author SHA1 Message Date
shamoon
3fa4fad811 Merge migrations again 2025-06-28 05:53:41 -07:00
shamoon
8b0e97d3ec Fix merge conflict 2025-06-28 05:53:41 -07:00
shamoon
2ba5c0c391 Merge migrations 2025-06-28 05:53:40 -07:00
shamoon
1367453d2c Add fallback parsing for invalid ai responses 2025-06-28 05:53:40 -07:00
shamoon
f92982217f Truncate similar docs content 2025-06-28 05:53:40 -07:00
shamoon
701b254b86 Fix paperless_ai logging 2025-06-28 05:53:40 -07:00
shamoon
a092dd3ab0 token limiting 2025-06-28 05:53:40 -07:00
shamoon
9fdfdf9b48 Update AI docs 2025-06-28 05:53:40 -07:00
shamoon
81bacec484 Cover app config changes 2025-06-28 05:53:40 -07:00
shamoon
5b13e3594e Mock auto-trigger llm index 2025-06-28 05:53:24 -07:00
shamoon
3f051fb27b Fix / cleanup ai indexing test 2025-06-28 05:53:07 -07:00
shamoon
d1294c4183 Doh, add tests in new module 2025-06-28 05:53:07 -07:00
shamoon
ca87f43262 Coverage for llmindex tasks 2025-06-28 05:53:06 -07:00
shamoon
c20273f46f Cover llmindex in system status 2025-06-28 05:53:06 -07:00
shamoon
48d0315cc4 Add llmindex to systemstatus 2025-06-28 05:53:06 -07:00
shamoon
553bfeb9fc Auto-trigger llmindex rebuild when enabled 2025-06-28 05:53:06 -07:00
shamoon
1b9d775508 Use PaperlessTask for llmindex 2025-06-28 05:51:43 -07:00
shamoon
c75ec8dfc3 Create llmindex if doesnt exist on update run 2025-06-28 05:51:43 -07:00
shamoon
f8890bd14a Move ai to its own module 2025-06-28 05:51:42 -07:00
shamoon
8fc77d92a9 Better respect perms for ai suggestions 2025-06-28 05:51:42 -07:00
shamoon
92837f86c0 Refactor load_or_build_index 2025-06-28 05:51:42 -07:00
shamoon
4b43e39fbb Update chat view decorators 2025-06-28 05:51:42 -07:00
shamoon
51a89b0cde Cover matching 2025-06-28 05:51:42 -07:00
shamoon
6536a9c874 Cover partial indexing 2025-06-28 05:51:42 -07:00
shamoon
1e04ce1e57 Refactor and consolidate rag / embedding and tests 2025-06-28 05:51:42 -07:00
shamoon
199f328999 indexing cleanup and tests 2025-06-28 05:51:41 -07:00
shamoon
495a6fe2fe Use partial reindex for bulk updates 2025-06-28 05:51:41 -07:00
shamoon
03f183712b Unify prompts, cover 2025-06-28 05:51:41 -07:00
shamoon
f8c6989eaf Incremental llm index update, add scheduled llm index task 2025-06-28 05:51:41 -07:00
shamoon
5c0903b6da Some cleanup, typing 2025-06-28 05:51:41 -07:00
shamoon
d49982a5ba Handle doc updates, refactor 2025-06-28 05:51:41 -07:00
shamoon
db0dc337bd Chat coverage 2025-06-28 05:51:41 -07:00
shamoon
fd1554fb96 Tests for rest of RAG 2025-06-28 05:51:41 -07:00
shamoon
404dbae431 Chat component and service coverage 2025-06-28 05:51:40 -07:00
shamoon
0f1aee3a3c Real doc ID updating 2025-06-28 05:51:40 -07:00
shamoon
3f8dbc630a Sweet chat animation, cursor 2025-06-28 05:51:40 -07:00
shamoon
5180651400 Only show chat if enabled 2025-06-28 05:51:40 -07:00
shamoon
f0ac80a08a Fix partial length in chat 2025-06-28 05:51:40 -07:00
shamoon
d439b58aaf Fix gzip breaks streaming and flush stream 2025-06-28 05:51:40 -07:00
shamoon
37745e846d Fix openai api key, config settings saving 2025-06-28 05:51:40 -07:00
shamoon
9c00b48dc7 Try rewriting with httpclient 2025-06-28 05:51:40 -07:00
shamoon
bdaae882a6 Extremely basic chat component 2025-06-28 05:51:39 -07:00
shamoon
37e1290e00 Just use the built-in ollama LLM class of course 2025-06-28 05:51:39 -07:00
shamoon
183d369350 Fix naming 2025-06-28 05:51:39 -07:00
shamoon
d431f1af15 Trim nodes 2025-06-28 05:51:39 -07:00
shamoon
b4ea2b7521 Backend streaming chat 2025-06-28 05:51:39 -07:00
shamoon
46df529c3a Fixup some tests 2025-06-28 05:51:39 -07:00
shamoon
3ed877b301 Just some docs
[ci skip]
2025-06-28 05:51:39 -07:00
shamoon
1e79795fbf Unify, respect perms
[ci skip]
2025-06-28 05:51:38 -07:00
shamoon
cee5a3b62d Individual doc chat
[ci skip]
2025-06-28 05:51:38 -07:00
shamoon
0807e32278 Super basic doc chat
[ci skip]
2025-06-28 05:51:38 -07:00
shamoon
6bdf396083 Better encapsulate backends, use llama_index OpenAI 2025-06-28 05:51:38 -07:00
shamoon
5c88a7207d Add backend settings to frontend config
[ci skip]
2025-06-28 05:51:38 -07:00
shamoon
3e8a9958a5 Tweak ollama timeout, prompt
[ci skip]
2025-06-28 05:51:38 -07:00
shamoon
b1b2d03644 Fix ollama, fix RAG
[ci skip]
2025-06-28 05:51:38 -07:00
shamoon
2c4b8c9afe RAG into suggestions 2025-06-28 05:51:38 -07:00
shamoon
0a19a5500c llamaindex vector index, llmindex mangement command 2025-06-28 05:51:37 -07:00
shamoon
edeb9a7534 Docs 2025-06-28 05:51:37 -07:00
shamoon
06b0817cc2 Use password and select config fields 2025-06-28 05:51:37 -07:00
shamoon
3051ea5fbb Use a frontend config 2025-06-28 05:51:37 -07:00
shamoon
c3175c2cd6 Pass AI enabled to frontend 2025-06-28 05:51:37 -07:00
shamoon
77796ac3f4 Basic handling of non-AI response 2025-06-28 05:51:37 -07:00
shamoon
45451ac110 Cleaner auto-remove 2025-06-28 05:51:37 -07:00
shamoon
2e34223ead Automatically remove suggestions after add 2025-06-28 05:51:36 -07:00
shamoon
c416bca3df Test views, caching 2025-06-28 05:51:36 -07:00
shamoon
b8dc6665dc Invalidate llm suggestion cache on doc save 2025-06-28 05:51:36 -07:00
shamoon
2fe901cd8d Fix 2025-06-28 05:51:36 -07:00
shamoon
199834ee8f Backend tests 2025-06-28 05:51:36 -07:00
shamoon
5849c6fff6 Correct object retrieval 2025-06-28 05:51:36 -07:00
shamoon
de6e43738c Refactor 2025-06-28 05:51:36 -07:00
shamoon
4e23a072d4 Move module 2025-06-28 05:51:35 -07:00
shamoon
b600e27f90 Hook up the add buttons 2025-06-28 05:51:35 -07:00
shamoon
2c83e0d07f Refine the suggestions dropdown ui a bit 2025-06-28 05:51:35 -07:00
shamoon
be327c1b72 Suggestions dropdown 2025-06-28 05:51:35 -07:00
shamoon
4013f15e51 Messing with a suggest button 2025-06-28 05:51:35 -07:00
shamoon
a53014ab89 Rename config 2025-06-28 05:51:35 -07:00
shamoon
214420ba1a Title suggestion ui 2025-06-28 05:51:35 -07:00
shamoon
453dc5062b Just start the frontend
[ci skip]
2025-06-28 05:51:35 -07:00
shamoon
1b6a4a3be4 wow llama3 is bad 2025-06-28 05:51:34 -07:00
shamoon
3d33149f03 Changeup logging 2025-06-28 05:51:34 -07:00
shamoon
455ff068cb Some logging, error handling 2025-06-28 05:51:34 -07:00
shamoon
0b06ded65a Basic start 2025-06-28 05:51:30 -07:00
github-actions[bot]
e1c3124698 Changelog v2.17.1 - GHA (#10229) 2025-06-19 12:40:37 -07:00
shamoon
f2e22e103b Bump version to 2.17.1 2025-06-19 12:07:49 -07:00
github-actions[bot]
dda94f013e New Crowdin translations by GitHub Action (#10228)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-06-19 12:06:52 -07:00
GitHub Actions
caf00e7ead Auto translate strings 2025-06-19 18:52:01 +00:00
shamoon
f214440d2e Fix: correct PAPERLESS_EMPTY_TRASH_DIR to Path (#10227) 2025-06-19 11:50:23 -07:00
github-actions[bot]
240c9ac511 Changelog v2.17.0 - GHA (#10225) 2025-06-19 10:43:13 -07:00
123 changed files with 6919 additions and 1703 deletions

View File

@@ -11,6 +11,7 @@ for command in decrypt_documents \
mail_fetcher \
document_create_classifier \
document_index \
document_llmindex \
document_renamer \
document_retagger \
document_thumbnails \

View File

@@ -0,0 +1,14 @@
#!/command/with-contenv /usr/bin/bash
# shellcheck shell=bash
set -e
cd "${PAPERLESS_SRC_DIR}"
if [[ $(id -u) == 0 ]]; then
s6-setuidgid paperless python3 manage.py document_llmindex "$@"
elif [[ $(id -un) == "paperless" ]]; then
python3 manage.py document_llmindex "$@"
else
echo "Unknown user."
fi

View File

@@ -1,5 +1,64 @@
# Changelog
## paperless-ngx 2.17.1
### Bug Fixes
- Fix: correct PAPERLESS_EMPTY_TRASH_DIR to Path [@shamoon](https://github.com/shamoon) ([#10227](https://github.com/paperless-ngx/paperless-ngx/pull/10227))
### All App Changes
- Fix: correct PAPERLESS_EMPTY_TRASH_DIR to Path [@shamoon](https://github.com/shamoon) ([#10227](https://github.com/paperless-ngx/paperless-ngx/pull/10227))
## paperless-ngx 2.17.0
### Breaking Changes
- Fix: restore expected pre-2.16 scheduled workflow offset behavior [@shamoon](https://github.com/shamoon) ([#10218](https://github.com/paperless-ngx/paperless-ngx/pull/10218))
### Features / Enhancements
- QoL: log version at startup, show backend vs frontend mismatch in system status [@shamoon](https://github.com/shamoon) ([#10214](https://github.com/paperless-ngx/paperless-ngx/pull/10214))
- Feature: add Persian translation [@shamoon](https://github.com/shamoon) ([#10183](https://github.com/paperless-ngx/paperless-ngx/pull/10183))
- Enhancement: support import of zipped export [@kaerbr](https://github.com/kaerbr) ([#10073](https://github.com/paperless-ngx/paperless-ngx/pull/10073))
### Bug Fixes
- Fix: more api fixes [@shamoon](https://github.com/shamoon) ([#10204](https://github.com/paperless-ngx/paperless-ngx/pull/10204))
- Fix: restore expected pre-2.16 scheduled workflow offset behavior [@shamoon](https://github.com/shamoon) ([#10218](https://github.com/paperless-ngx/paperless-ngx/pull/10218))
- Fix: fix some API crashes [@shamoon](https://github.com/shamoon) ([#10196](https://github.com/paperless-ngx/paperless-ngx/pull/10196))
- Fix: remove duplicate base path in websocket urls [@robertmx](https://github.com/robertmx) ([#10194](https://github.com/paperless-ngx/paperless-ngx/pull/10194))
- Fix: use hard delete for custom fields with workflow removal [@shamoon](https://github.com/shamoon) ([#10191](https://github.com/paperless-ngx/paperless-ngx/pull/10191))
- Fix: fix mail account test api schema [@shamoon](https://github.com/shamoon) ([#10164](https://github.com/paperless-ngx/paperless-ngx/pull/10164))
- Fix: correct api schema for mail_account process [@shamoon](https://github.com/shamoon) ([#10157](https://github.com/paperless-ngx/paperless-ngx/pull/10157))
- Fix: correct api schema for next_asn [@shamoon](https://github.com/shamoon) ([#10151](https://github.com/paperless-ngx/paperless-ngx/pull/10151))
- Fix: fix email and notes endpoints api spec [@shamoon](https://github.com/shamoon) ([#10148](https://github.com/paperless-ngx/paperless-ngx/pull/10148))
### Dependencies
- Chore: bump angular/common to 19.12.14 [@shamoon](https://github.com/shamoon) ([#10212](https://github.com/paperless-ngx/paperless-ngx/pull/10212))
### All App Changes
<details>
<summary>14 changes</summary>
- QoL: log version at startup, show backend vs frontend mismatch in system status [@shamoon](https://github.com/shamoon) ([#10214](https://github.com/paperless-ngx/paperless-ngx/pull/10214))
- Fix: more api fixes [@shamoon](https://github.com/shamoon) ([#10204](https://github.com/paperless-ngx/paperless-ngx/pull/10204))
- Fix: restore expected pre-2.16 scheduled workflow offset behavior [@shamoon](https://github.com/shamoon) ([#10218](https://github.com/paperless-ngx/paperless-ngx/pull/10218))
- Chore: switch from os.path to pathlib.Path [@gothicVI](https://github.com/gothicVI) ([#9933](https://github.com/paperless-ngx/paperless-ngx/pull/9933))
- Chore: bump angular/common to 19.12.14 [@shamoon](https://github.com/shamoon) ([#10212](https://github.com/paperless-ngx/paperless-ngx/pull/10212))
- Fix: fix some API crashes [@shamoon](https://github.com/shamoon) ([#10196](https://github.com/paperless-ngx/paperless-ngx/pull/10196))
- Fix: remove duplicate base path in websocket urls [@robertmx](https://github.com/robertmx) ([#10194](https://github.com/paperless-ngx/paperless-ngx/pull/10194))
- Fix: use hard delete for custom fields with workflow removal [@shamoon](https://github.com/shamoon) ([#10191](https://github.com/paperless-ngx/paperless-ngx/pull/10191))
- Feature: add Persian translation [@shamoon](https://github.com/shamoon) ([#10183](https://github.com/paperless-ngx/paperless-ngx/pull/10183))
- Enhancement: support import of zipped export [@kaerbr](https://github.com/kaerbr) ([#10073](https://github.com/paperless-ngx/paperless-ngx/pull/10073))
- Fix: fix mail account test api schema [@shamoon](https://github.com/shamoon) ([#10164](https://github.com/paperless-ngx/paperless-ngx/pull/10164))
- Fix: correct api schema for mail_account process [@shamoon](https://github.com/shamoon) ([#10157](https://github.com/paperless-ngx/paperless-ngx/pull/10157))
- Fix: correct api schema for next_asn [@shamoon](https://github.com/shamoon) ([#10151](https://github.com/paperless-ngx/paperless-ngx/pull/10151))
- Fix: fix email and notes endpoints api spec [@shamoon](https://github.com/shamoon) ([#10148](https://github.com/paperless-ngx/paperless-ngx/pull/10148))
</details>
## paperless-ngx 2.16.3
### Features / Enhancements

View File

@@ -1708,3 +1708,67 @@ password. All of these options come from their similarly-named [Django settings]
#### [`PAPERLESS_EMAIL_USE_SSL=<bool>`](#PAPERLESS_EMAIL_USE_SSL) {#PAPERLESS_EMAIL_USE_SSL}
: Defaults to false.
## AI {#ai}
#### [`PAPERLESS_ENABLE_AI=<bool>`](#PAPERLESS_ENABLE_AI) {#PAPERLESS_ENABLE_AI}
: Enables the AI features in Paperless. This includes the AI-based
suggestions. This setting is required to be set to true in order to use the AI features.
Defaults to false.
#### [`PAPERLESS_LLM_EMBEDDING_BACKEND=<str>`](#PAPERLESS_LLM_EMBEDDING_BACKEND) {#PAPERLESS_LLM_EMBEDDING_BACKEND}
: The embedding backend to use for RAG. This can be either "openai" or "huggingface".
Defaults to None.
#### [`PAPERLESS_LLM_EMBEDDING_MODEL=<str>`](#PAPERLESS_LLM_EMBEDDING_MODEL) {#PAPERLESS_LLM_EMBEDDING_MODEL}
: The model to use for the embedding backend for RAG. This can be set to any of the embedding models supported by the current embedding backend. If not supplied, defaults to "text-embedding-3-small" for OpenAI and "sentence-transformers/all-MiniLM-L6-v2" for Huggingface.
Defaults to None.
#### [`PAPERLESS_AI_BACKEND=<str>`](#PAPERLESS_AI_BACKEND) {#PAPERLESS_AI_BACKEND}
: The AI backend to use. This can be either "openai" or "ollama". If set to "ollama", the AI
features will be run locally on your machine. If set to "openai", the AI features will be run
using the OpenAI API. This setting is required to be set to use the AI features.
Defaults to None.
!!! note
The OpenAI API is a paid service. You will need to set up an OpenAI account and
will be charged for usage incurred by Paperless-ngx features and your document data
will (of course) be sent to the OpenAI API. Paperless-ngx does not endorse the use of the
OpenAI API in any way.
Refer to the OpenAI terms of service, and use at your own risk.
#### [`PAPERLESS_LLM_MODEL=<str>`](#PAPERLESS_LLM_MODEL) {#PAPERLESS_LLM_MODEL}
: The model to use for the AI backend, i.e. "gpt-3.5-turbo", "gpt-4" or any of the models supported by the
current backend. If not supplied, defaults to "gpt-3.5-turbo" for OpenAI and "llama3" for Ollama.
Defaults to None.
#### [`PAPERLESS_LLM_API_KEY=<str>`](#PAPERLESS_LLM_API_KEY) {#PAPERLESS_LLM_API_KEY}
: The API key to use for the AI backend. This is required for the OpenAI backend only.
Defaults to None.
#### [`PAPERLESS_LLM_URL=<str>`](#PAPERLESS_LLM_URL) {#PAPERLESS_LLM_URL}
: The URL to use for the AI backend. This is required for the Ollama backend only.
Defaults to None.
#### [`PAPERLESS_LLM_INDEX_TASK_CRON=<cron expression>`](#PAPERLESS_LLM_INDEX_TASK_CRON) {#PAPERLESS_LLM_INDEX_TASK_CRON}
: Configures the schedule to update the AI embeddings for all documents. Only performed if
AI is enabled and the LLM embedding backend is set.
Defaults to `10 2 * * *`, once per day.

View File

@@ -25,11 +25,12 @@ physical documents into a searchable online archive so you can keep, well, _less
## Features
- **Organize and index** your scanned documents with tags, correspondents, types, and more.
- _Your_ data is stored locally on _your_ server and is never transmitted or shared in any way.
- _Your_ data is stored locally on _your_ server and is never transmitted or shared in any way, unless you explicitly choose to do so.
- Performs **OCR** on your documents, adding searchable and selectable text, even to documents scanned with only images.
- Utilizes the open-source Tesseract engine to recognize more than 100 languages.
- Documents are saved as PDF/A format which is designed for long term storage, alongside the unaltered originals.
- Uses machine-learning to automatically add tags, correspondents and document types to your documents.
- **New**: Paperless-ngx can now leverage AI (Large Language Models or LLMs) for document suggestions. This is an optional feature that can be enabled (and is disabled by default).
- Supports PDF documents, images, plain text files, Office documents (Word, Excel, Powerpoint, and LibreOffice equivalents)[^1] and more.
- Paperless stores your documents plain on disk. Filenames and folders are managed by paperless and their format can be configured freely with different configurations assigned to different documents.
- **Beautiful, modern web application** that features:

View File

@@ -261,6 +261,22 @@ Once setup, navigating to the email settings page in Paperless-ngx will allow yo
You can also submit a document using the REST API, see [POSTing documents](api.md#file-uploads)
for details.
## Document Suggestions
Paperless-ngx can suggest tags, correspondents, document types and storage paths for documents based on the content of the document. This is done using a machine learning model that is trained on the documents in your database. The suggestions are shown in the document detail page and can be accepted or rejected by the user.
## AI Features
Paperless-ngx includes several features that use AI to enhance the document management experience. These features are optional and can be enabled or disabled in the settings. If you are using the AI features, you may want to also enable the "LLM index" feature, which supports Retrieval-Augmented Generation (RAG) designed to improve the quality of AI responses. The LLM index feature is not enabled by default and requires additional configuration.
### Document Chat
Paperless-ngx can use an AI LLM model to answer questions about a document or across multiple documents. Again, this feature works best when RAG is enabled. The chat feature is available in the upper app toolbar and will switch between chatting across multiple documents or a single document based on the current view.
### AI-Enhanced Suggestions
If enabled, Paperless-ngx can use an AI LLM model to suggest document titles, dates, tags, correspondents and document types for documents. This feature will always be "opt-in" and does not disable the existing classifier-based suggestion system. Currently, both remote (via the OpenAI API) and local (via Ollama) models are supported, see [configuration](configuration.md#ai) for details.
## Sharing documents from Paperless-ngx
Paperless-ngx supports sharing documents with other users by assigning them [permissions](#object-permissions)

View File

@@ -1,6 +1,6 @@
[project]
name = "paperless-ngx"
version = "2.17.0"
version = "2.17.1"
description = "A community-supported supercharged version of paperless: scan, index and archive all your physical documents"
readme = "README.md"
requires-python = ">=3.10"
@@ -39,6 +39,7 @@ dependencies = [
"drf-spectacular~=0.28",
"drf-spectacular-sidecar~=2025.4.1",
"drf-writable-nested~=0.7.1",
"faiss-cpu>=1.10",
"filelock~=3.18.0",
"flower~=2.0.1",
"gotenberg-client~=0.10.0",
@@ -47,8 +48,15 @@ dependencies = [
"inotifyrecursive~=0.3",
"jinja2~=3.1.5",
"langdetect~=1.0.9",
"llama-index-core>=0.12.33.post1",
"llama-index-embeddings-huggingface>=0.5.3",
"llama-index-embeddings-openai>=0.3.1",
"llama-index-llms-ollama>=0.5.4",
"llama-index-llms-openai>=0.3.38",
"llama-index-vector-stores-faiss>=0.3",
"nltk~=3.9.1",
"ocrmypdf~=16.10.0",
"openai>=1.76",
"pathvalidate~=3.2.3",
"pdf2image~=1.17.0",
"python-dateutil~=2.9.0",
@@ -60,6 +68,7 @@ dependencies = [
"rapidfuzz~=3.13.0",
"redis[hiredis]~=5.2.1",
"scikit-learn~=1.6.1",
"sentence-transformers>=4.1",
"setproctitle~=1.3.4",
"tika-client~=0.9.0",
"tqdm~=4.67.1",
@@ -240,6 +249,7 @@ testpaths = [
"src/paperless_mail/tests/",
"src/paperless_tesseract/tests/",
"src/paperless_tika/tests",
"src/paperless_ai/tests",
]
addopts = [
"--pythonwarnings=all",

View File

@@ -1,6 +1,6 @@
{
"name": "paperless-ngx-ui",
"version": "2.17.0",
"version": "2.17.1",
"scripts": {
"preinstall": "npx only-allow pnpm",
"ng": "ng",

View File

@@ -35,6 +35,7 @@
@case (ConfigOptionType.String) { <pngx-input-text [formControlName]="option.key" [error]="errors[option.key]"></pngx-input-text> }
@case (ConfigOptionType.JSON) { <pngx-input-text [formControlName]="option.key" [error]="errors[option.key]"></pngx-input-text> }
@case (ConfigOptionType.File) { <pngx-input-file [formControlName]="option.key" (upload)="uploadFile($event, option.key)" [error]="errors[option.key]"></pngx-input-file> }
@case (ConfigOptionType.Password) { <pngx-input-password [formControlName]="option.key" [error]="errors[option.key]"></pngx-input-password> }
}
</div>
</div>

View File

@@ -29,6 +29,7 @@ import { SettingsService } from 'src/app/services/settings.service'
import { ToastService } from 'src/app/services/toast.service'
import { FileComponent } from '../../common/input/file/file.component'
import { NumberComponent } from '../../common/input/number/number.component'
import { PasswordComponent } from '../../common/input/password/password.component'
import { SelectComponent } from '../../common/input/select/select.component'
import { SwitchComponent } from '../../common/input/switch/switch.component'
import { TextComponent } from '../../common/input/text/text.component'
@@ -46,6 +47,7 @@ import { LoadingComponentWithPermissions } from '../../loading-component/loading
TextComponent,
NumberComponent,
FileComponent,
PasswordComponent,
AsyncPipe,
NgbNavModule,
FormsModule,

View File

@@ -314,6 +314,9 @@ describe('SettingsComponent', () => {
sanity_check_status: SystemStatusItemStatus.ERROR,
sanity_check_last_run: new Date().toISOString(),
sanity_check_error: 'Error running sanity check.',
llmindex_status: SystemStatusItemStatus.DISABLED,
llmindex_last_modified: new Date().toISOString(),
llmindex_error: null,
},
}
jest.spyOn(systemStatusService, 'get').mockReturnValue(of(status))

View File

@@ -30,6 +30,9 @@
</div>
</div>
<ul ngbNav class="order-sm-3">
@if (aiEnabled) {
<pngx-chat></pngx-chat>
}
<pngx-toasts-dropdown></pngx-toasts-dropdown>
<li ngbDropdown class="nav-item dropdown">
<button class="btn ps-1 border-0" id="userDropdown" ngbDropdownToggle>

View File

@@ -44,6 +44,7 @@ import { SettingsService } from 'src/app/services/settings.service'
import { TasksService } from 'src/app/services/tasks.service'
import { ToastService } from 'src/app/services/toast.service'
import { environment } from 'src/environments/environment'
import { ChatComponent } from '../chat/chat/chat.component'
import { ProfileEditDialogComponent } from '../common/profile-edit-dialog/profile-edit-dialog.component'
import { DocumentDetailComponent } from '../document-detail/document-detail.component'
import { ComponentWithPermissions } from '../with-permissions/with-permissions.component'
@@ -59,6 +60,7 @@ import { ToastsDropdownComponent } from './toasts-dropdown/toasts-dropdown.compo
DocumentTitlePipe,
IfPermissionsDirective,
ToastsDropdownComponent,
ChatComponent,
RouterModule,
NgClass,
NgbDropdownModule,
@@ -168,6 +170,10 @@ export class AppFrameComponent
})
}
get aiEnabled(): boolean {
return this.settingsService.get(SETTINGS_KEYS.AI_ENABLED)
}
closeMenu() {
this.isMenuCollapsed = true
}

View File

@@ -1,5 +1,5 @@
<li ngbDropdown class="nav-item" (openChange)="onOpenChange($event)">
<li ngbDropdown class="nav-item mx-1" (openChange)="onOpenChange($event)">
@if (toasts.length) {
<span class="badge rounded-pill z-3 pe-none bg-secondary me-2 position-absolute top-0 left-0">{{ toasts.length }}</span>
}

View File

@@ -0,0 +1,35 @@
<li ngbDropdown class="nav-item me-n2" (openChange)="onOpenChange($event)">
<button class="btn border-0" id="chatDropdown" ngbDropdownToggle>
<i-bs width="1.3em" height="1.3em" name="chatSquareDots"></i-bs>
</button>
<div ngbDropdownMenu class="dropdown-menu-end shadow p-3" aria-labelledby="chatDropdown">
<div class="chat-container bg-light p-2">
<div class="chat-messages font-monospace small">
@for (message of messages; track message) {
<div class="message d-flex flex-row small" [class.justify-content-end]="message.role === 'user'">
<span class="p-2 m-2" [class.bg-dark]="message.role === 'user'">
{{ message.content }}
@if (message.isStreaming) { <span class="blinking-cursor">|</span> }
</span>
</div>
}
<div #scrollAnchor></div>
</div>
<form class="chat-input">
<div class="input-group">
<input
#chatInput
class="form-control form-control-sm" name="chatInput" type="text"
[placeholder]="placeholder"
[disabled]="loading"
[(ngModel)]="input"
(keydown)="searchInputKeyDown($event)"
/>
<button class="btn btn-sm btn-secondary" type="button" (click)="sendMessage()" [disabled]="loading">Send</button>
</div>
</form>
</div>
</div>
</li>

View File

@@ -0,0 +1,37 @@
.dropdown-menu {
width: var(--pngx-toast-max-width);
}
.chat-messages {
max-height: 350px;
overflow-y: auto;
}
.dropdown-toggle::after {
display: none;
}
.dropdown-item {
white-space: initial;
}
@media screen and (max-width: 400px) {
:host ::ng-deep .dropdown-menu-end {
right: -3rem;
}
}
.blinking-cursor {
font-weight: bold;
font-size: 1.2em;
animation: blink 1s step-end infinite;
}
@keyframes blink {
from, to {
opacity: 0;
}
50% {
opacity: 1;
}
}

View File

@@ -0,0 +1,132 @@
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
import { provideHttpClientTesting } from '@angular/common/http/testing'
import { ElementRef } from '@angular/core'
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { NavigationEnd, Router } from '@angular/router'
import { allIcons, NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { Subject } from 'rxjs'
import { ChatService } from 'src/app/services/chat.service'
import { ChatComponent } from './chat.component'
describe('ChatComponent', () => {
let component: ChatComponent
let fixture: ComponentFixture<ChatComponent>
let chatService: ChatService
let router: Router
let routerEvents$: Subject<NavigationEnd>
let mockStream$: Subject<string>
beforeEach(async () => {
TestBed.configureTestingModule({
imports: [NgxBootstrapIconsModule.pick(allIcons), ChatComponent],
providers: [
provideHttpClient(withInterceptorsFromDi()),
provideHttpClientTesting(),
],
}).compileComponents()
fixture = TestBed.createComponent(ChatComponent)
router = TestBed.inject(Router)
routerEvents$ = new Subject<any>()
jest
.spyOn(router, 'events', 'get')
.mockReturnValue(routerEvents$.asObservable())
chatService = TestBed.inject(ChatService)
mockStream$ = new Subject<string>()
jest
.spyOn(chatService, 'streamChat')
.mockReturnValue(mockStream$.asObservable())
component = fixture.componentInstance
jest.useFakeTimers()
fixture.detectChanges()
component.scrollAnchor.nativeElement.scrollIntoView = jest.fn()
})
it('should update documentId on initialization', () => {
jest.spyOn(router, 'url', 'get').mockReturnValue('/documents/123')
component.ngOnInit()
expect(component.documentId).toBe(123)
})
it('should update documentId on navigation', () => {
component.ngOnInit()
routerEvents$.next(new NavigationEnd(1, '/documents/456', '/documents/456'))
expect(component.documentId).toBe(456)
})
it('should return correct placeholder based on documentId', () => {
component.documentId = 123
expect(component.placeholder).toBe('Ask a question about this document...')
component.documentId = undefined
expect(component.placeholder).toBe('Ask a question about a document...')
})
it('should send a message and handle streaming response', () => {
component.input = 'Hello'
component.sendMessage()
expect(component.messages.length).toBe(2)
expect(component.messages[0].content).toBe('Hello')
expect(component.loading).toBe(true)
mockStream$.next('Hi')
expect(component.messages[1].content).toBe('H')
mockStream$.next('Hi there')
// advance time to process the typewriter effect
jest.advanceTimersByTime(1000)
expect(component.messages[1].content).toBe('Hi there')
mockStream$.complete()
expect(component.loading).toBe(false)
expect(component.messages[1].isStreaming).toBe(false)
})
it('should handle errors during streaming', () => {
component.input = 'Hello'
component.sendMessage()
mockStream$.error('Error')
expect(component.messages[1].content).toContain(
'⚠️ Error receiving response.'
)
expect(component.loading).toBe(false)
})
it('should enqueue typewriter chunks correctly', () => {
const message = { content: '', role: 'assistant', isStreaming: true }
component.enqueueTypewriter(null, message as any) // coverage for null
component.enqueueTypewriter('Hello', message as any)
expect(component['typewriterBuffer'].length).toBe(4)
})
it('should scroll to bottom after sending a message', () => {
const scrollSpy = jest.spyOn(
ChatComponent.prototype as any,
'scrollToBottom'
)
component.input = 'Test'
component.sendMessage()
expect(scrollSpy).toHaveBeenCalled()
})
it('should focus chat input when dropdown is opened', () => {
const focus = jest.fn()
component.chatInput = {
nativeElement: { focus: focus },
} as unknown as ElementRef<HTMLInputElement>
component.onOpenChange(true)
jest.advanceTimersByTime(15)
expect(focus).toHaveBeenCalled()
})
it('should send message on Enter key press', () => {
jest.spyOn(component, 'sendMessage')
const event = new KeyboardEvent('keydown', { key: 'Enter' })
component.searchInputKeyDown(event)
expect(component.sendMessage).toHaveBeenCalled()
})
})

View File

@@ -0,0 +1,144 @@
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { NavigationEnd, Router } from '@angular/router'
import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { filter, map } from 'rxjs'
import { ChatMessage, ChatService } from 'src/app/services/chat.service'
@Component({
selector: 'pngx-chat',
imports: [
FormsModule,
ReactiveFormsModule,
NgxBootstrapIconsModule,
NgbDropdownModule,
],
templateUrl: './chat.component.html',
styleUrl: './chat.component.scss',
})
export class ChatComponent implements OnInit {
public messages: ChatMessage[] = []
public loading = false
public input: string = ''
public documentId!: number
@ViewChild('scrollAnchor') scrollAnchor!: ElementRef<HTMLDivElement>
@ViewChild('chatInput') chatInput!: ElementRef<HTMLInputElement>
private typewriterBuffer: string[] = []
private typewriterActive = false
public get placeholder(): string {
return this.documentId
? $localize`Ask a question about this document...`
: $localize`Ask a question about a document...`
}
constructor(
private chatService: ChatService,
private router: Router
) {}
ngOnInit(): void {
this.updateDocumentId(this.router.url)
this.router.events
.pipe(
filter((event) => event instanceof NavigationEnd),
map((event) => (event as NavigationEnd).url)
)
.subscribe((url) => {
console.log('URL changed:', url)
this.updateDocumentId(url)
})
}
private updateDocumentId(url: string): void {
const docIdRe = url.match(/^\/documents\/(\d+)/)
this.documentId = docIdRe ? +docIdRe[1] : undefined
}
sendMessage(): void {
if (!this.input.trim()) return
const userMessage: ChatMessage = { role: 'user', content: this.input }
this.messages.push(userMessage)
this.scrollToBottom()
const assistantMessage: ChatMessage = {
role: 'assistant',
content: '',
isStreaming: true,
}
this.messages.push(assistantMessage)
this.loading = true
let lastPartialLength = 0
this.chatService.streamChat(this.documentId, this.input).subscribe({
next: (chunk) => {
const delta = chunk.substring(lastPartialLength)
lastPartialLength = chunk.length
this.enqueueTypewriter(delta, assistantMessage)
},
error: () => {
assistantMessage.content += '\n\n⚠ Error receiving response.'
assistantMessage.isStreaming = false
this.loading = false
},
complete: () => {
assistantMessage.isStreaming = false
this.loading = false
this.scrollToBottom()
},
})
this.input = ''
}
enqueueTypewriter(chunk: string, message: ChatMessage): void {
if (!chunk) return
this.typewriterBuffer.push(...chunk.split(''))
if (!this.typewriterActive) {
this.typewriterActive = true
this.playTypewriter(message)
}
}
playTypewriter(message: ChatMessage): void {
if (this.typewriterBuffer.length === 0) {
this.typewriterActive = false
return
}
const nextChar = this.typewriterBuffer.shift()!
message.content += nextChar
this.scrollToBottom()
setTimeout(() => this.playTypewriter(message), 10) // 10ms per character
}
private scrollToBottom(): void {
setTimeout(() => {
this.scrollAnchor?.nativeElement?.scrollIntoView({ behavior: 'smooth' })
}, 50)
}
public onOpenChange(open: boolean): void {
if (open) {
setTimeout(() => {
this.chatInput.nativeElement.focus()
}, 10)
}
}
public searchInputKeyDown(event: KeyboardEvent) {
if (event.key === 'Enter') {
event.preventDefault()
this.sendMessage()
}
}
}

View File

@@ -1,7 +1,7 @@
<div ngbDropdown #fieldDropdown="ngbDropdown" (openChange)="onOpenClose($event)" [popperOptions]="popperOptions" placement="bottom-end">
<button class="btn btn-sm btn-outline-primary" id="customFieldsDropdown" [disabled]="disabled" ngbDropdownToggle>
<div ngbDropdown #fieldDropdown="ngbDropdown" (openChange)="onOpenClose($event)" [popperOptions]="popperOptions">
<button type="button" class="btn btn-sm btn-outline-primary" id="customFieldsDropdown" [disabled]="disabled" ngbDropdownToggle>
<i-bs name="ui-radios"></i-bs>
<div class="d-none d-sm-inline">&nbsp;<ng-container i18n>Custom Fields</ng-container></div>
<div class="d-none d-lg-inline">&nbsp;<ng-container i18n>Custom Fields</ng-container></div>
</button>
<div ngbDropdownMenu aria-labelledby="customFieldsDropdown" class="shadow custom-fields-dropdown">
<div class="list-group list-group-flush" (keydown)="listKeyDown($event)">

View File

@@ -1,17 +1,24 @@
<div class="mb-3">
<label class="form-label" [for]="inputId">{{title}}</label>
<div class="input-group" [class.is-invalid]="error">
<input #inputField [type]="showReveal && textVisible ? 'text' : 'password'" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (focus)="onFocus()" (focusout)="onFocusOut()" (change)="onChange(value)" [disabled]="disabled" [autocomplete]="autocomplete">
@if (showReveal) {
<button type="button" class="btn btn-outline-secondary" (click)="toggleVisibility()" i18n-title title="Show password" [disabled]="disabled || disableRevealToggle">
<i-bs name="eye"></i-bs>
</button>
<div class="mb-3" [class.pb-3]="error">
<div class="row">
<div class="d-flex align-items-center position-relative hidden-button-container" [class.col-md-3]="horizontal">
@if (title) {
<label class="form-label" [class.mb-md-0]="horizontal" [for]="inputId">{{title}}</label>
}
</div>
<div class="position-relative" [class.col-md-9]="horizontal">
<div class="input-group" [class.is-invalid]="error">
<input #inputField [type]="showReveal && textVisible ? 'text' : 'password'" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (focus)="onFocus()" (focusout)="onFocusOut()" (change)="onChange(value)" [disabled]="disabled" [autocomplete]="autocomplete">
@if (showReveal) {
<button type="button" class="btn btn-outline-secondary" (click)="toggleVisibility()" i18n-title title="Show password" [disabled]="disabled || disableRevealToggle">
<i-bs name="eye"></i-bs>
</button>
}
</div>
<div class="invalid-feedback">
{{error}}
</div>
@if (hint) {
<small class="form-text text-muted" [innerHTML]="hint | safeHtml"></small>
}
</div>
<div class="invalid-feedback">
{{error}}
</div>
@if (hint) {
<small class="form-text text-muted" [innerHTML]="hint | safeHtml"></small>
}
</div>

View File

@@ -15,6 +15,12 @@
@if (hint) {
<small class="form-text text-muted" [innerHTML]="hint | safeHtml"></small>
}
@if (getSuggestion()?.length > 0) {
<small>
<span i18n>Suggestion:</span>&nbsp;
<a (click)="applySuggestion(s)" [routerLink]="[]">{{getSuggestion()}}</a>&nbsp;
</small>
}
<div class="invalid-feedback position-absolute top-100">
{{error}}
</div>

View File

@@ -26,10 +26,20 @@ describe('TextComponent', () => {
it('should support use of input field', () => {
expect(component.value).toBeUndefined()
// TODO: why doesn't this work?
// input.value = 'foo'
// input.dispatchEvent(new Event('change'))
// fixture.detectChanges()
// expect(component.value).toEqual('foo')
input.value = 'foo'
input.dispatchEvent(new Event('input'))
fixture.detectChanges()
expect(component.value).toBe('foo')
})
it('should support suggestion', () => {
component.value = 'foo'
component.suggestion = 'foo'
expect(component.getSuggestion()).toBe('')
component.value = 'bar'
expect(component.getSuggestion()).toBe('foo')
component.applySuggestion()
fixture.detectChanges()
expect(component.value).toBe('foo')
})
})

View File

@@ -4,6 +4,7 @@ import {
NG_VALUE_ACCESSOR,
ReactiveFormsModule,
} from '@angular/forms'
import { RouterLink } from '@angular/router'
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { SafeHtmlPipe } from 'src/app/pipes/safehtml.pipe'
import { AbstractInputComponent } from '../abstract-input'
@@ -24,6 +25,7 @@ import { AbstractInputComponent } from '../abstract-input'
ReactiveFormsModule,
SafeHtmlPipe,
NgxBootstrapIconsModule,
RouterLink,
],
})
export class TextComponent extends AbstractInputComponent<string> {
@@ -33,7 +35,19 @@ export class TextComponent extends AbstractInputComponent<string> {
@Input()
placeholder: string = ''
@Input()
suggestion: string = ''
constructor() {
super()
}
getSuggestion() {
return this.value !== this.suggestion ? this.suggestion : ''
}
applySuggestion() {
this.value = this.suggestion
this.onChange(this.value)
}
}

View File

@@ -0,0 +1,49 @@
<div class="btn-group">
<button type="button" class="btn btn-sm btn-outline-primary" (click)="clickSuggest()" [disabled]="loading || (suggestions && !aiEnabled)">
@if (loading) {
<div class="spinner-border spinner-border-sm" role="status"></div>
} @else {
<i-bs width="1.2em" height="1.2em" name="stars"></i-bs>
}
<span class="d-none d-lg-inline ps-1" i18n>Suggest</span>
@if (totalSuggestions > 0) {
<span class="badge bg-primary ms-2">{{ totalSuggestions }}</span>
}
</button>
@if (aiEnabled) {
<div class="btn-group" ngbDropdown #dropdown="ngbDropdown" [popperOptions]="popperOptions">
<button type="button" class="btn btn-sm btn-outline-primary" ngbDropdownToggle [disabled]="loading || !suggestions" aria-expanded="false" aria-controls="suggestionsDropdown" aria-label="Suggestions dropdown">
<span class="visually-hidden" i18n>Show suggestions</span>
</button>
<div ngbDropdownMenu aria-labelledby="suggestionsDropdown" class="shadow suggestions-dropdown">
<div class="list-group list-group-flush small pb-0">
@if (!suggestions?.suggested_tags && !suggestions?.suggested_document_types && !suggestions?.suggested_correspondents) {
<div class="list-group-item text-muted fst-italic">
<small class="text-muted small fst-italic" i18n>No novel suggestions</small>
</div>
}
@if (suggestions?.suggested_tags.length > 0) {
<small class="list-group-item text-uppercase text-muted small">Tags</small>
@for (tag of suggestions.suggested_tags; track tag) {
<button type="button" class="list-group-item list-group-item-action bg-light" (click)="addTag.emit(tag)" i18n>{{ tag }}</button>
}
}
@if (suggestions?.suggested_document_types.length > 0) {
<div class="list-group-item text-uppercase text-muted small">Document Types</div>
@for (type of suggestions.suggested_document_types; track type) {
<button type="button" class="list-group-item list-group-item-action bg-light" (click)="addDocumentType.emit(type)" i18n>{{ type }}</button>
}
}
@if (suggestions?.suggested_correspondents.length > 0) {
<div class="list-group-item text-uppercase text-muted small">Correspondents</div>
@for (correspondent of suggestions.suggested_correspondents; track correspondent) {
<button type="button" class="list-group-item list-group-item-action bg-light" (click)="addCorrespondent.emit(correspondent)" i18n>{{ correspondent }}</button>
}
}
</div>
</div>
</div>
}
</div>

View File

@@ -0,0 +1,3 @@
.suggestions-dropdown {
min-width: 250px;
}

View File

@@ -0,0 +1,51 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
import { SuggestionsDropdownComponent } from './suggestions-dropdown.component'
describe('SuggestionsDropdownComponent', () => {
let component: SuggestionsDropdownComponent
let fixture: ComponentFixture<SuggestionsDropdownComponent>
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
NgbDropdownModule,
NgxBootstrapIconsModule.pick(allIcons),
SuggestionsDropdownComponent,
],
providers: [],
})
fixture = TestBed.createComponent(SuggestionsDropdownComponent)
component = fixture.componentInstance
fixture.detectChanges()
})
it('should calculate totalSuggestions', () => {
component.suggestions = {
suggested_correspondents: ['John Doe'],
suggested_tags: ['Tag1', 'Tag2'],
suggested_document_types: ['Type1'],
}
expect(component.totalSuggestions).toBe(4)
})
it('should emit getSuggestions when clickSuggest is called and suggestions are null', () => {
jest.spyOn(component.getSuggestions, 'emit')
component.suggestions = null
component.clickSuggest()
expect(component.getSuggestions.emit).toHaveBeenCalled()
})
it('should toggle dropdown when clickSuggest is called and suggestions are not null', () => {
component.aiEnabled = true
fixture.detectChanges()
component.suggestions = {
suggested_correspondents: [],
suggested_tags: [],
suggested_document_types: [],
}
component.clickSuggest()
expect(component.dropdown.open).toBeTruthy()
})
})

View File

@@ -0,0 +1,64 @@
import {
Component,
EventEmitter,
Input,
Output,
ViewChild,
} from '@angular/core'
import { NgbDropdown, NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { DocumentSuggestions } from 'src/app/data/document-suggestions'
import { pngxPopperOptions } from 'src/app/utils/popper-options'
@Component({
selector: 'pngx-suggestions-dropdown',
imports: [NgbDropdownModule, NgxBootstrapIconsModule],
templateUrl: './suggestions-dropdown.component.html',
styleUrl: './suggestions-dropdown.component.scss',
})
export class SuggestionsDropdownComponent {
public popperOptions = pngxPopperOptions
@ViewChild('dropdown') dropdown: NgbDropdown
@Input()
suggestions: DocumentSuggestions = null
@Input()
aiEnabled: boolean = false
@Input()
loading: boolean = false
@Input()
disabled: boolean = false
@Output()
getSuggestions: EventEmitter<SuggestionsDropdownComponent> =
new EventEmitter()
@Output()
addTag: EventEmitter<string> = new EventEmitter()
@Output()
addDocumentType: EventEmitter<string> = new EventEmitter()
@Output()
addCorrespondent: EventEmitter<string> = new EventEmitter()
public clickSuggest(): void {
if (!this.suggestions) {
this.getSuggestions.emit(this)
} else {
this.dropdown?.toggle()
}
}
get totalSuggestions(): number {
return (
this.suggestions?.suggested_correspondents?.length +
this.suggestions?.suggested_tags?.length +
this.suggestions?.suggested_document_types?.length || 0
)
}
}

View File

@@ -254,6 +254,43 @@
<h6><ng-container i18n>Error</ng-container>:</h6> <span class="font-monospace small">{{status.tasks.sanity_check_error}}</span>
}
</ng-template>
@if (aiEnabled) {
<dt i18n>AI Index</dt>
<dd class="d-flex align-items-center">
<button class="btn btn-sm d-flex align-items-center btn-dark text-uppercase small" [ngbPopover]="llmIndexStatus" triggers="click mouseenter:mouseleave">
{{status.tasks.llmindex_status}}
@if (status.tasks.llmindex_status === 'OK') {
@if (isStale(status.tasks.llmindex_last_modified)) {
<i-bs name="exclamation-triangle-fill" class="text-warning ms-2 lh-1"></i-bs>
} @else {
<i-bs name="check-circle-fill" class="text-primary ms-2 lh-1"></i-bs>
}
} @else {
<i-bs name="exclamation-triangle-fill" class="ms-2 lh-1"
[class.text-danger]="status.tasks.llmindex_status === SystemStatusItemStatus.ERROR"
[class.text-warning]="status.tasks.llmindex_status === SystemStatusItemStatus.WARNING"
[class.text-muted]="status.tasks.llmindex_status === SystemStatusItemStatus.DISABLED"></i-bs>
}
</button>
@if (currentUserIsSuperUser) {
@if (isRunning(PaperlessTaskName.LLMIndexUpdate)) {
<div class="spinner-border spinner-border-sm ms-2" role="status"></div>
} @else {
<button class="btn btn-sm d-flex align-items-center btn-dark small ms-2" (click)="runTask(PaperlessTaskName.LLMIndexUpdate)">
<i-bs name="play-fill"></i-bs>&nbsp;
<ng-container i18n>Run Task</ng-container>
</button>
}
}
</dd>
<ng-template #llmIndexStatus>
@if (status.tasks.llmindex_status === 'OK') {
<h6><ng-container i18n>Last Run</ng-container>:</h6> <span class="font-monospace small">{{status.tasks.llmindex_last_modified | customDate:'medium'}}</span>
} @else {
<h6><ng-container i18n>Error</ng-container>:</h6> <span class="font-monospace small">{{status.tasks.llmindex_error}}</span>
}
</ng-template>
}
</dl>
</div>
</div>

View File

@@ -67,6 +67,9 @@ const status: SystemStatus = {
sanity_check_status: SystemStatusItemStatus.OK,
sanity_check_last_run: new Date().toISOString(),
sanity_check_error: null,
llmindex_status: SystemStatusItemStatus.OK,
llmindex_last_modified: new Date().toISOString(),
llmindex_error: null,
},
}

View File

@@ -12,9 +12,11 @@ import {
SystemStatus,
SystemStatusItemStatus,
} from 'src/app/data/system-status'
import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe'
import { FileSizePipe } from 'src/app/pipes/file-size.pipe'
import { PermissionsService } from 'src/app/services/permissions.service'
import { SettingsService } from 'src/app/services/settings.service'
import { SystemStatusService } from 'src/app/services/system-status.service'
import { TasksService } from 'src/app/services/tasks.service'
import { ToastService } from 'src/app/services/toast.service'
@@ -49,13 +51,18 @@ export class SystemStatusDialogComponent implements OnInit {
return this.permissionsService.isSuperUser()
}
get aiEnabled(): boolean {
return this.settingsService.get(SETTINGS_KEYS.AI_ENABLED)
}
constructor(
public activeModal: NgbActiveModal,
private clipboard: Clipboard,
private systemStatusService: SystemStatusService,
private tasksService: TasksService,
private toastService: ToastService,
private permissionsService: PermissionsService
private permissionsService: PermissionsService,
private settingsService: SettingsService
) {}
public ngOnInit() {

View File

@@ -72,16 +72,6 @@
</div>
</div>
<pngx-custom-fields-dropdown
*pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.CustomField }"
[documentId]="documentId"
[disabled]="!userCanEdit"
[existingFields]="document?.custom_fields"
(created)="refreshCustomFields()"
(added)="addField($event)">
</pngx-custom-fields-dropdown>
<div class="ms-auto" ngbDropdown>
<button class="btn btn-sm btn-outline-primary" id="sendDropdown" ngbDropdownToggle>
<i-bs name="send"></i-bs>
@@ -102,7 +92,7 @@
</pngx-page-header>
<div class="row">
<div class="col-md-6 col-xl-4 mb-4">
<div class="col-md-6 col-xl-5 mb-4">
<form [formGroup]='documentForm' (ngSubmit)="save()">
@@ -119,6 +109,32 @@
</button>
</div>
<ng-container *pngxIfPermissions="{ action: PermissionAction.Change, type: PermissionType.Document }">
<div class="btn-group pb-3 ms-auto">
<pngx-suggestions-dropdown *pngxIfPermissions="{ action: PermissionAction.Change, type: PermissionType.Document }"
[disabled]="!userCanEdit || suggestionsLoading"
[loading]="suggestionsLoading"
[suggestions]="suggestions"
[aiEnabled]="aiEnabled"
(getSuggestions)="getSuggestions()"
(addTag)="createTag($event)"
(addDocumentType)="createDocumentType($event)"
(addCorrespondent)="createCorrespondent($event)">
</pngx-suggestions-dropdown>
</div>
<div class="btn-group pb-3 ms-2">
<pngx-custom-fields-dropdown
*pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.CustomField }"
[documentId]="documentId"
[disabled]="!userCanEdit"
[existingFields]="document?.custom_fields"
(created)="refreshCustomFields()"
(added)="addField($event)">
</pngx-custom-fields-dropdown>
</div>
</ng-container>
<ng-container *ngTemplateOutlet="saveButtons"></ng-container>
</div>
@@ -127,7 +143,7 @@
<a ngbNavLink i18n>Details</a>
<ng-template ngbNavContent>
<div>
<pngx-input-text #inputTitle i18n-title title="Title" formControlName="title" [horizontal]="true" (keyup)="titleKeyUp($event)" [error]="error?.title"></pngx-input-text>
<pngx-input-text #inputTitle i18n-title title="Title" formControlName="title" [horizontal]="true" [suggestion]="suggestions?.title" (keyup)="titleKeyUp($event)" [error]="error?.title"></pngx-input-text>
<pngx-input-number i18n-title title="Archive serial number" [error]="error?.archive_serial_number" [horizontal]="true" formControlName='archive_serial_number'></pngx-input-number>
<pngx-input-date i18n-title title="Date created" formControlName="created" [suggestions]="suggestions?.dates" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event)"
[error]="error?.created"></pngx-input-date>
@@ -137,7 +153,7 @@
(createNew)="createDocumentType($event)" [hideAddButton]="createDisabled(DataType.DocumentType)" [suggestions]="suggestions?.document_types" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.DocumentType }"></pngx-input-select>
<pngx-input-select [items]="storagePaths" i18n-title title="Storage path" formControlName="storage_path" [allowNull]="true" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event, DataType.StoragePath)"
(createNew)="createStoragePath($event)" [hideAddButton]="createDisabled(DataType.StoragePath)" [suggestions]="suggestions?.storage_paths" i18n-placeholder placeholder="Default" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.StoragePath }"></pngx-input-select>
<pngx-input-tags formControlName="tags" [suggestions]="suggestions?.tags" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event, DataType.Tag)" [hideAddButton]="createDisabled(DataType.Tag)" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Tag }"></pngx-input-tags>
<pngx-input-tags #tagsInput formControlName="tags" [suggestions]="suggestions?.tags" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event, DataType.Tag)" [hideAddButton]="createDisabled(DataType.Tag)" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Tag }"></pngx-input-tags>
@for (fieldInstance of document?.custom_fields; track fieldInstance.field; let i = $index) {
<div [formGroup]="customFieldFormFields.controls[i]">
@switch (getCustomFieldFromInstance(fieldInstance)?.data_type) {
@@ -351,14 +367,14 @@
</form>
</div>
<div class="col-md-6 col-xl-8 mb-3 d-none d-md-block position-relative" #pdfPreview>
<div class="col-md-6 col-xl-7 mb-3 d-none d-md-block position-relative" #pdfPreview>
<ng-container *ngTemplateOutlet="previewContent"></ng-container>
</div>
</div>
<ng-template #saveButtons>
<div class="btn-group pb-3 ms-auto">
<div class="btn-group pb-3 ms-4">
<ng-container *pngxIfPermissions="{ action: PermissionAction.Change, type: PermissionType.Document }">
<button type="submit" class="order-3 btn btn-sm btn-primary" i18n [disabled]="!userCanEdit || networkActive || (isDirty$ | async) !== true">Save</button>
@if (hasNext()) {

View File

@@ -156,6 +156,16 @@ describe('DocumentDetailComponent', () => {
{
provide: TagService,
useValue: {
getCachedMany: (ids: number[]) =>
of(
ids.map((id) => ({
id,
name: `Tag${id}`,
is_inbox_tag: true,
color: '#ff0000',
text_color: '#000000',
}))
),
listAll: () =>
of({
count: 3,
@@ -382,8 +392,32 @@ describe('DocumentDetailComponent', () => {
currentUserCan = true
})
it('should support creating document type', () => {
it('should support creating tag, remove from suggestions', () => {
initNormally()
component.suggestions = {
suggested_tags: ['Tag1', 'NewTag12'],
}
let openModal: NgbModalRef
modalService.activeInstances.subscribe((modal) => (openModal = modal[0]))
const modalSpy = jest.spyOn(modalService, 'open')
component.createTag('NewTag12')
expect(modalSpy).toHaveBeenCalled()
openModal.componentInstance.succeeded.next({
id: 12,
name: 'NewTag12',
is_inbox_tag: true,
color: '#ff0000',
text_color: '#000000',
})
expect(component.documentForm.get('tags').value).toContain(12)
expect(component.suggestions.suggested_tags).not.toContain('NewTag12')
})
it('should support creating document type, remove from suggestions', () => {
initNormally()
component.suggestions = {
suggested_document_types: ['DocumentType1', 'NewDocType2'],
}
let openModal: NgbModalRef
modalService.activeInstances.subscribe((modal) => (openModal = modal[0]))
const modalSpy = jest.spyOn(modalService, 'open')
@@ -391,10 +425,16 @@ describe('DocumentDetailComponent', () => {
expect(modalSpy).toHaveBeenCalled()
openModal.componentInstance.succeeded.next({ id: 12, name: 'NewDocType12' })
expect(component.documentForm.get('document_type').value).toEqual(12)
expect(component.suggestions.suggested_document_types).not.toContain(
'NewDocType2'
)
})
it('should support creating correspondent', () => {
it('should support creating correspondent, remove from suggestions', () => {
initNormally()
component.suggestions = {
suggested_correspondents: ['Correspondent1', 'NewCorrrespondent12'],
}
let openModal: NgbModalRef
modalService.activeInstances.subscribe((modal) => (openModal = modal[0]))
const modalSpy = jest.spyOn(modalService, 'open')
@@ -405,6 +445,9 @@ describe('DocumentDetailComponent', () => {
name: 'NewCorrrespondent12',
})
expect(component.documentForm.get('correspondent').value).toEqual(12)
expect(component.suggestions.suggested_correspondents).not.toContain(
'NewCorrrespondent12'
)
})
it('should support creating storage path', () => {
@@ -983,7 +1026,7 @@ describe('DocumentDetailComponent', () => {
expect(component.document.custom_fields).toHaveLength(initialLength - 1)
expect(component.customFieldFormFields).toHaveLength(initialLength - 1)
expect(
fixture.debugElement.query(By.css('form')).nativeElement.textContent
fixture.debugElement.query(By.css('form ul')).nativeElement.textContent
).not.toContain('Field 1')
const patchSpy = jest.spyOn(documentService, 'patch')
component.save(true)
@@ -1058,10 +1101,22 @@ describe('DocumentDetailComponent', () => {
it('should get suggestions', () => {
const suggestionsSpy = jest.spyOn(documentService, 'getSuggestions')
suggestionsSpy.mockReturnValue(of({ tags: [42, 43] }))
suggestionsSpy.mockReturnValue(
of({
tags: [42, 43],
suggested_tags: [],
suggested_document_types: [],
suggested_correspondents: [],
})
)
initNormally()
expect(suggestionsSpy).toHaveBeenCalled()
expect(component.suggestions).toEqual({ tags: [42, 43] })
expect(component.suggestions).toEqual({
tags: [42, 43],
suggested_tags: [],
suggested_document_types: [],
suggested_correspondents: [],
})
})
it('should show error if needed for get suggestions', () => {

View File

@@ -74,6 +74,7 @@ import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service
import { DocumentTypeService } from 'src/app/services/rest/document-type.service'
import { DocumentService } from 'src/app/services/rest/document.service'
import { StoragePathService } from 'src/app/services/rest/storage-path.service'
import { TagService } from 'src/app/services/rest/tag.service'
import { UserService } from 'src/app/services/rest/user.service'
import { SettingsService } from 'src/app/services/settings.service'
import { ToastService } from 'src/app/services/toast.service'
@@ -89,6 +90,7 @@ import { CorrespondentEditDialogComponent } from '../common/edit-dialog/correspo
import { DocumentTypeEditDialogComponent } from '../common/edit-dialog/document-type-edit-dialog/document-type-edit-dialog.component'
import { EditDialogMode } from '../common/edit-dialog/edit-dialog.component'
import { StoragePathEditDialogComponent } from '../common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component'
import { TagEditDialogComponent } from '../common/edit-dialog/tag-edit-dialog/tag-edit-dialog.component'
import { EmailDocumentDialogComponent } from '../common/email-document-dialog/email-document-dialog.component'
import { CheckComponent } from '../common/input/check/check.component'
import { DateComponent } from '../common/input/date/date.component'
@@ -102,6 +104,7 @@ import { TextComponent } from '../common/input/text/text.component'
import { UrlComponent } from '../common/input/url/url.component'
import { PageHeaderComponent } from '../common/page-header/page-header.component'
import { ShareLinksDialogComponent } from '../common/share-links-dialog/share-links-dialog.component'
import { SuggestionsDropdownComponent } from '../common/suggestions-dropdown/suggestions-dropdown.component'
import { DocumentHistoryComponent } from '../document-history/document-history.component'
import { DocumentNotesComponent } from '../document-notes/document-notes.component'
import { ComponentWithPermissions } from '../with-permissions/with-permissions.component'
@@ -158,6 +161,7 @@ export enum ZoomSetting {
NumberComponent,
MonetaryComponent,
UrlComponent,
SuggestionsDropdownComponent,
CustomDatePipe,
FileSizePipe,
IfPermissionsDirective,
@@ -179,6 +183,8 @@ export class DocumentDetailComponent
@ViewChild('inputTitle')
titleInput: TextComponent
@ViewChild('tagsInput') tagsInput: TagsComponent
expandOriginalMetadata = false
expandArchivedMetadata = false
@@ -190,6 +196,7 @@ export class DocumentDetailComponent
document: Document
metadata: DocumentMetadata
suggestions: DocumentSuggestions
suggestionsLoading: boolean = false
users: User[]
title: string
@@ -262,6 +269,7 @@ export class DocumentDetailComponent
constructor(
private documentsService: DocumentService,
private route: ActivatedRoute,
private tagService: TagService,
private correspondentService: CorrespondentService,
private documentTypeService: DocumentTypeService,
private router: Router,
@@ -291,6 +299,10 @@ export class DocumentDetailComponent
return this.settings.get(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER)
}
get aiEnabled(): boolean {
return this.settings.get(SETTINGS_KEYS.AI_ENABLED)
}
get archiveContentRenderType(): ContentRenderType {
return this.document?.archived_file_name
? this.getRenderType('application/pdf')
@@ -645,25 +657,12 @@ export class DocumentDetailComponent
PermissionType.Document
)
) {
this.documentsService
.getSuggestions(doc.id)
.pipe(
first(),
takeUntil(this.unsubscribeNotifier),
takeUntil(this.docChangeNotifier)
)
.subscribe({
next: (result) => {
this.suggestions = result
},
error: (error) => {
this.suggestions = null
this.toastService.showError(
$localize`Error retrieving suggestions.`,
error
)
},
})
this.tagService.getCachedMany(doc.tags).subscribe((tags) => {
// only show suggestions if document has inbox tags
if (tags.some((tag) => tag.is_inbox_tag)) {
this.getSuggestions()
}
})
}
this.title = this.documentTitlePipe.transform(doc.title)
const docFormValues = Object.assign({}, doc)
@@ -680,6 +679,56 @@ export class DocumentDetailComponent
return this.documentForm.get('custom_fields') as FormArray
}
getSuggestions() {
this.suggestionsLoading = true
this.documentsService
.getSuggestions(this.documentId)
.pipe(
first(),
takeUntil(this.unsubscribeNotifier),
takeUntil(this.docChangeNotifier)
)
.subscribe({
next: (result) => {
this.suggestions = result
this.suggestionsLoading = false
},
error: (error) => {
this.suggestions = null
this.suggestionsLoading = false
this.toastService.showError(
$localize`Error retrieving suggestions.`,
error
)
},
})
}
createTag(newName: string) {
var modal = this.modalService.open(TagEditDialogComponent, {
backdrop: 'static',
})
modal.componentInstance.dialogMode = EditDialogMode.CREATE
if (newName) modal.componentInstance.object = { name: newName }
modal.componentInstance.succeeded
.pipe(
switchMap((newTag) => {
return this.tagService
.listAll()
.pipe(map((tags) => ({ newTag, tags })))
})
)
.pipe(takeUntil(this.unsubscribeNotifier))
.subscribe(({ newTag, tags }) => {
this.tagsInput.tags = tags.results
this.tagsInput.addTag(newTag.id)
if (this.suggestions) {
this.suggestions.suggested_tags =
this.suggestions.suggested_tags.filter((tag) => tag !== newName)
}
})
}
createDocumentType(newName: string) {
var modal = this.modalService.open(DocumentTypeEditDialogComponent, {
backdrop: 'static',
@@ -699,6 +748,12 @@ export class DocumentDetailComponent
this.documentTypes = documentTypes.results
this.documentForm.get('document_type').setValue(newDocumentType.id)
this.documentForm.get('document_type').markAsDirty()
if (this.suggestions) {
this.suggestions.suggested_document_types =
this.suggestions.suggested_document_types.filter(
(dt) => dt !== newName
)
}
})
}
@@ -723,6 +778,12 @@ export class DocumentDetailComponent
this.correspondents = correspondents.results
this.documentForm.get('correspondent').setValue(newCorrespondent.id)
this.documentForm.get('correspondent').markAsDirty()
if (this.suggestions) {
this.suggestions.suggested_correspondents =
this.suggestions.suggested_correspondents.filter(
(c) => c !== newName
)
}
})
}

View File

@@ -1,11 +1,17 @@
export interface DocumentSuggestions {
title?: string
tags?: number[]
suggested_tags?: string[]
correspondents?: number[]
suggested_correspondents?: string[]
document_types?: number[]
suggested_document_types?: string[]
storage_paths?: number[]
suggested_storage_paths?: string[]
dates?: string[] // ISO-formatted date string e.g. 2022-11-03
}

View File

@@ -44,12 +44,24 @@ export enum ConfigOptionType {
Boolean = 'boolean',
JSON = 'json',
File = 'file',
Password = 'password',
}
export const ConfigCategory = {
General: $localize`General Settings`,
OCR: $localize`OCR Settings`,
Barcode: $localize`Barcode Settings`,
AI: $localize`AI Settings`,
}
export const LLMEmbeddingBackendConfig = {
OPENAI: 'openai',
HUGGINGFACE: 'huggingface',
}
export const LLMBackendConfig = {
OPENAI: 'openai',
OLLAMA: 'ollama',
}
export interface ConfigOption {
@@ -258,6 +270,57 @@ export const PaperlessConfigOptions: ConfigOption[] = [
config_key: 'PAPERLESS_CONSUMER_TAG_BARCODE_MAPPING',
category: ConfigCategory.Barcode,
},
{
key: 'ai_enabled',
title: $localize`AI Enabled`,
type: ConfigOptionType.Boolean,
config_key: 'PAPERLESS_AI_ENABLED',
category: ConfigCategory.AI,
},
{
key: 'llm_embedding_backend',
title: $localize`LLM Embedding Backend`,
type: ConfigOptionType.Select,
choices: mapToItems(LLMEmbeddingBackendConfig),
config_key: 'PAPERLESS_LLM_EMBEDDING_BACKEND',
category: ConfigCategory.AI,
},
{
key: 'llm_embedding_model',
title: $localize`LLM Embedding Model`,
type: ConfigOptionType.String,
config_key: 'PAPERLESS_LLM_EMBEDDING_MODEL',
category: ConfigCategory.AI,
},
{
key: 'llm_backend',
title: $localize`LLM Backend`,
type: ConfigOptionType.Select,
choices: mapToItems(LLMBackendConfig),
config_key: 'PAPERLESS_LLM_BACKEND',
category: ConfigCategory.AI,
},
{
key: 'llm_model',
title: $localize`LLM Model`,
type: ConfigOptionType.String,
config_key: 'PAPERLESS_LLM_MODEL',
category: ConfigCategory.AI,
},
{
key: 'llm_api_key',
title: $localize`LLM API Key`,
type: ConfigOptionType.Password,
config_key: 'PAPERLESS_LLM_API_KEY',
category: ConfigCategory.AI,
},
{
key: 'llm_url',
title: $localize`LLM URL`,
type: ConfigOptionType.String,
config_key: 'PAPERLESS_LLM_URL',
category: ConfigCategory.AI,
},
]
export interface PaperlessConfig extends ObjectWithId {
@@ -287,4 +350,11 @@ export interface PaperlessConfig extends ObjectWithId {
barcode_max_pages: number
barcode_enable_tag: boolean
barcode_tag_mapping: object
ai_enabled: boolean
llm_embedding_backend: string
llm_embedding_model: string
llm_backend: string
llm_model: string
llm_api_key: string
llm_url: string
}

View File

@@ -11,6 +11,7 @@ export enum PaperlessTaskName {
TrainClassifier = 'train_classifier',
SanityCheck = 'check_sanity',
IndexOptimize = 'index_optimize',
LLMIndexUpdate = 'llmindex_update',
}
export enum PaperlessTaskStatus {

View File

@@ -7,6 +7,7 @@ export enum SystemStatusItemStatus {
OK = 'OK',
ERROR = 'ERROR',
WARNING = 'WARNING',
DISABLED = 'DISABLED',
}
export interface SystemStatus {
@@ -43,5 +44,8 @@ export interface SystemStatus {
sanity_check_status: SystemStatusItemStatus
sanity_check_last_run: string // ISO date string
sanity_check_error: string
llmindex_status: SystemStatusItemStatus
llmindex_last_modified: string // ISO date string
llmindex_error: string
}
}

View File

@@ -74,6 +74,7 @@ export const SETTINGS_KEYS = {
GMAIL_OAUTH_URL: 'gmail_oauth_url',
OUTLOOK_OAUTH_URL: 'outlook_oauth_url',
EMAIL_ENABLED: 'email_enabled',
AI_ENABLED: 'ai_enabled',
}
export const SETTINGS: UiSetting[] = [
@@ -282,4 +283,9 @@ export const SETTINGS: UiSetting[] = [
type: 'string',
default: 'page-width', // ZoomSetting from 'document-detail.component'
},
{
key: SETTINGS_KEYS.AI_ENABLED,
type: 'boolean',
default: false,
},
]

View File

@@ -0,0 +1,58 @@
import {
HttpEventType,
provideHttpClient,
withInterceptorsFromDi,
} from '@angular/common/http'
import {
HttpTestingController,
provideHttpClientTesting,
} from '@angular/common/http/testing'
import { TestBed } from '@angular/core/testing'
import { environment } from 'src/environments/environment'
import { ChatService } from './chat.service'
describe('ChatService', () => {
let service: ChatService
let httpMock: HttpTestingController
beforeEach(() => {
TestBed.configureTestingModule({
imports: [],
providers: [
ChatService,
provideHttpClient(withInterceptorsFromDi()),
provideHttpClientTesting(),
],
})
service = TestBed.inject(ChatService)
httpMock = TestBed.inject(HttpTestingController)
})
afterEach(() => {
httpMock.verify()
})
it('should stream chat messages', (done) => {
const documentId = 1
const prompt = 'Hello, world!'
const mockResponse = 'Partial response text'
const apiUrl = `${environment.apiBaseUrl}documents/chat/`
service.streamChat(documentId, prompt).subscribe((chunk) => {
expect(chunk).toBe(mockResponse)
done()
})
const req = httpMock.expectOne(apiUrl)
expect(req.request.method).toBe('POST')
expect(req.request.body).toEqual({
document_id: documentId,
q: prompt,
})
req.event({
type: HttpEventType.DownloadProgress,
partialText: mockResponse,
} as any)
})
})

View File

@@ -0,0 +1,46 @@
import {
HttpClient,
HttpDownloadProgressEvent,
HttpEventType,
} from '@angular/common/http'
import { Injectable } from '@angular/core'
import { filter, map, Observable } from 'rxjs'
import { environment } from 'src/environments/environment'
export interface ChatMessage {
role: 'user' | 'assistant'
content: string
isStreaming?: boolean
}
@Injectable({
providedIn: 'root',
})
export class ChatService {
constructor(private http: HttpClient) {}
streamChat(documentId: number, prompt: string): Observable<string> {
return this.http
.post(
`${environment.apiBaseUrl}documents/chat/`,
{
document_id: documentId,
q: prompt,
},
{
observe: 'events',
reportProgress: true,
responseType: 'text',
withCredentials: true,
}
)
.pipe(
map((event) => {
if (event.type === HttpEventType.DownloadProgress) {
return (event as HttpDownloadProgressEvent).partialText!
}
}),
filter((chunk) => !!chunk)
)
}
}

View File

@@ -6,7 +6,7 @@ export const environment = {
apiVersion: '9', // match src/paperless/settings.py
appTitle: 'Paperless-ngx',
tag: 'prod',
version: '2.17.0',
version: '2.17.1',
webSocketHost: window.location.host,
webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
webSocketBaseUrl: base_url.pathname + 'ws/',

View File

@@ -9,6 +9,7 @@ import { DatePipe, registerLocaleData } from '@angular/common'
import {
HTTP_INTERCEPTORS,
provideHttpClient,
withFetch,
withInterceptorsFromDi,
} from '@angular/common/http'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
@@ -48,6 +49,7 @@ import {
caretDown,
caretUp,
chatLeftText,
chatSquareDots,
check,
check2All,
checkAll,
@@ -118,6 +120,7 @@ import {
sliders2Vertical,
sortAlphaDown,
sortAlphaUpAlt,
stars,
tag,
tagFill,
tags,
@@ -255,6 +258,7 @@ const icons = {
caretDown,
caretUp,
chatLeftText,
chatSquareDots,
check,
check2All,
checkAll,
@@ -325,6 +329,7 @@ const icons = {
sliders2Vertical,
sortAlphaDown,
sortAlphaUpAlt,
stars,
tagFill,
tag,
tags,
@@ -389,6 +394,6 @@ bootstrapApplication(AppComponent, {
CorrespondentNamePipe,
DocumentTypeNamePipe,
StoragePathNamePipe,
provideHttpClient(withInterceptorsFromDi()),
provideHttpClient(withInterceptorsFromDi(), withFetch()),
],
}).catch((err) => console.error(err))

View File

@@ -11,6 +11,7 @@ class DocumentsConfig(AppConfig):
from documents.signals import document_consumption_finished
from documents.signals import document_updated
from documents.signals.handlers import add_inbox_tags
from documents.signals.handlers import add_or_update_document_in_llm_index
from documents.signals.handlers import add_to_index
from documents.signals.handlers import run_workflows_added
from documents.signals.handlers import run_workflows_updated
@@ -26,6 +27,7 @@ class DocumentsConfig(AppConfig):
document_consumption_finished.connect(set_storage_path)
document_consumption_finished.connect(add_to_index)
document_consumption_finished.connect(run_workflows_added)
document_consumption_finished.connect(add_or_update_document_in_llm_index)
document_updated.connect(run_workflows_updated)
import documents.schema # noqa: F401

View File

@@ -115,6 +115,56 @@ def refresh_suggestions_cache(
cache.touch(doc_key, timeout)
def get_llm_suggestion_cache(
document_id: int,
backend: str,
) -> SuggestionCacheData | None:
doc_key = get_suggestion_cache_key(document_id)
data: SuggestionCacheData = cache.get(doc_key)
if data and data.classifier_hash == backend:
return data
return None
def set_llm_suggestions_cache(
document_id: int,
suggestions: dict,
*,
backend: str,
timeout: int = CACHE_50_MINUTES,
) -> None:
"""
Cache LLM-generated suggestions using a backend-specific identifier (e.g. 'openai:gpt-4').
"""
from documents.caching import SuggestionCacheData
doc_key = get_suggestion_cache_key(document_id)
cache.set(
doc_key,
SuggestionCacheData(
classifier_version=1000, # Unique marker for LLM-based suggestion
classifier_hash=backend,
suggestions=suggestions,
),
timeout,
)
def invalidate_llm_suggestions_cache(
document_id: int,
) -> None:
"""
Invalidate the LLM suggestions cache for a specific document and backend.
"""
doc_key = get_suggestion_cache_key(document_id)
data: SuggestionCacheData = cache.get(doc_key)
if data:
cache.delete(doc_key)
def get_metadata_cache_key(document_id: int) -> str:
"""
Returns the basic key for a document's metadata

View File

@@ -0,0 +1,22 @@
from django.core.management import BaseCommand
from django.db import transaction
from documents.management.commands.mixins import ProgressBarMixin
from documents.tasks import llmindex_index
class Command(ProgressBarMixin, BaseCommand):
help = "Manages the LLM-based vector index for Paperless."
def add_arguments(self, parser):
parser.add_argument("command", choices=["rebuild", "update"])
self.add_argument_progress_bar_mixin(parser)
def handle(self, *args, **options):
self.handle_progress_bar_mixin(**options)
with transaction.atomic():
llmindex_index(
progress_bar_disable=self.no_progress_bar,
rebuild=options["command"] == "rebuild",
scheduled=False,
)

View File

@@ -0,0 +1,30 @@
# Generated by Django 5.1.8 on 2025-04-30 02:38
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
dependencies = [
("documents", "1068_alter_document_created"),
]
operations = [
migrations.AlterField(
model_name="paperlesstask",
name="task_name",
field=models.CharField(
choices=[
("consume_file", "Consume File"),
("train_classifier", "Train Classifier"),
("check_sanity", "Check Sanity"),
("index_optimize", "Index Optimize"),
("llmindex_update", "LLM Index Update"),
],
help_text="Name of the task that was run",
max_length=255,
null=True,
verbose_name="Task Name",
),
),
]

View File

@@ -543,6 +543,7 @@ class PaperlessTask(ModelWithOwner):
TRAIN_CLASSIFIER = ("train_classifier", _("Train Classifier"))
CHECK_SANITY = ("check_sanity", _("Check Sanity"))
INDEX_OPTIMIZE = ("index_optimize", _("Index Optimize"))
LLMINDEX_UPDATE = ("llmindex_update", _("LLM Index Update"))
task_id = models.CharField(
max_length=255,

View File

@@ -26,6 +26,7 @@ from guardian.shortcuts import remove_perm
from documents import matching
from documents.caching import clear_document_caches
from documents.caching import invalidate_llm_suggestions_cache
from documents.file_handling import create_source_path_directory
from documents.file_handling import delete_empty_directories
from documents.file_handling import generate_unique_filename
@@ -47,6 +48,7 @@ from documents.models import WorkflowTrigger
from documents.permissions import get_objects_for_user_owner_aware
from documents.permissions import set_permissions_for_object
from documents.templating.workflows import parse_w_workflow_placeholders
from paperless.config import AIConfig
if TYPE_CHECKING:
from pathlib import Path
@@ -331,9 +333,8 @@ def cleanup_document_deletion(sender, instance, **kwargs):
(old_filebase, old_fileext) = os.path.splitext(old_filename)
while True:
new_file_path = os.path.join(
settings.EMPTY_TRASH_DIR,
old_filebase + (f"_{counter:02}" if counter else "") + old_fileext,
new_file_path = settings.EMPTY_TRASH_DIR / (
old_filebase + (f"_{counter:02}" if counter else "") + old_fileext
)
if os.path.exists(new_file_path):
@@ -526,6 +527,15 @@ def update_filename_and_move_files(
)
@receiver(models.signals.post_save, sender=Document)
def update_llm_suggestions_cache(sender, instance, **kwargs):
"""
Invalidate the LLM suggestions cache when a document is saved.
"""
# Invalidate the cache for the document
invalidate_llm_suggestions_cache(instance.pk)
# should be disabled in /src/documents/management/commands/document_importer.py handle
@receiver(models.signals.post_save, sender=CustomField)
def check_paths_and_prune_custom_fields(sender, instance: CustomField, **kwargs):
@@ -1440,3 +1450,26 @@ def task_failure_handler(
task_instance.save()
except Exception: # pragma: no cover
logger.exception("Updating PaperlessTask failed")
def add_or_update_document_in_llm_index(sender, document, **kwargs):
"""
Add or update a document in the LLM index when it is created or updated.
"""
ai_config = AIConfig()
if ai_config.llm_index_enabled():
from documents.tasks import update_document_in_llm_index
update_document_in_llm_index.delay(document)
@receiver(models.signals.post_delete, sender=Document)
def delete_document_from_llm_index(sender, instance: Document, **kwargs):
"""
Delete a document from the LLM index when it is deleted.
"""
ai_config = AIConfig()
if ai_config.llm_index_enabled():
from documents.tasks import remove_document_from_llm_index
remove_document_from_llm_index.delay(instance)

View File

@@ -54,6 +54,10 @@ from documents.sanity_checker import SanityCheckFailedException
from documents.signals import document_updated
from documents.signals.handlers import cleanup_document_deletion
from documents.signals.handlers import run_workflows
from paperless.config import AIConfig
from paperless_ai.indexing import llm_index_add_or_update_document
from paperless_ai.indexing import llm_index_remove_document
from paperless_ai.indexing import update_llm_index
if settings.AUDIT_LOG_ENABLED:
from auditlog.models import LogEntry
@@ -242,6 +246,13 @@ def bulk_update_documents(document_ids):
for doc in documents:
index.update_document(writer, doc)
ai_config = AIConfig()
if ai_config.llm_index_enabled():
update_llm_index(
progress_bar_disable=True,
rebuild=False,
)
@shared_task
def update_document_content_maybe_archive_file(document_id):
@@ -341,6 +352,10 @@ def update_document_content_maybe_archive_file(document_id):
with index.open_index_writer() as writer:
index.update_document(writer, document)
ai_config = AIConfig()
if ai_config.llm_index_enabled:
llm_index_add_or_update_document(document)
clear_document_caches(document.pk)
except Exception:
@@ -517,3 +532,53 @@ def check_scheduled_workflows():
workflow_to_run=workflow,
document=document,
)
@shared_task
def llmindex_index(
*,
progress_bar_disable=True,
rebuild=False,
scheduled=True,
auto=False,
):
ai_config = AIConfig()
if ai_config.llm_index_enabled():
task = PaperlessTask.objects.create(
type=PaperlessTask.TaskType.SCHEDULED_TASK
if scheduled
else PaperlessTask.TaskType.AUTO
if auto
else PaperlessTask.TaskType.MANUAL_TASK,
task_id=uuid.uuid4(),
task_name=PaperlessTask.TaskName.LLMINDEX_UPDATE,
status=states.STARTED,
date_created=timezone.now(),
date_started=timezone.now(),
)
from paperless_ai.indexing import update_llm_index
try:
result = update_llm_index(
progress_bar_disable=progress_bar_disable,
rebuild=rebuild,
)
task.status = states.SUCCESS
task.result = result
except Exception as e:
logger.error("LLM index error: " + str(e))
task.status = states.FAILURE
task.result = str(e)
task.date_done = timezone.now()
task.save(update_fields=["status", "result", "date_done"])
@shared_task
def update_document_in_llm_index(document):
llm_index_add_or_update_document(document)
@shared_task
def remove_document_from_llm_index(document):
llm_index_remove_document(document)

View File

@@ -1,5 +1,6 @@
import json
from pathlib import Path
from unittest.mock import patch
from django.contrib.auth.models import User
from rest_framework import status
@@ -64,6 +65,13 @@ class TestApiAppConfig(DirectoriesMixin, APITestCase):
"barcode_max_pages": None,
"barcode_enable_tag": None,
"barcode_tag_mapping": None,
"ai_enabled": False,
"llm_embedding_backend": None,
"llm_embedding_model": None,
"llm_backend": None,
"llm_model": None,
"llm_api_key": None,
"llm_url": None,
},
)
@@ -189,3 +197,76 @@ class TestApiAppConfig(DirectoriesMixin, APITestCase):
)
self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
self.assertEqual(ApplicationConfiguration.objects.count(), 1)
def test_update_llm_api_key(self):
"""
GIVEN:
- Existing config with llm_api_key specified
WHEN:
- API to update llm_api_key is called with all *s
- API to update llm_api_key is called with empty string
THEN:
- llm_api_key is unchanged
- llm_api_key is set to None
"""
config = ApplicationConfiguration.objects.first()
config.llm_api_key = "1234567890"
config.save()
# Test with all *
response = self.client.patch(
f"{self.ENDPOINT}1/",
json.dumps(
{
"llm_api_key": "*" * 32,
},
),
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
config.refresh_from_db()
self.assertEqual(config.llm_api_key, "1234567890")
# Test with empty string
response = self.client.patch(
f"{self.ENDPOINT}1/",
json.dumps(
{
"llm_api_key": "",
},
),
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
config.refresh_from_db()
self.assertEqual(config.llm_api_key, None)
def test_enable_ai_index_triggers_update(self):
"""
GIVEN:
- Existing config with AI disabled
WHEN:
- Config is updated to enable AI with llm_embedding_backend
THEN:
- LLM index is triggered to update
"""
config = ApplicationConfiguration.objects.first()
config.ai_enabled = False
config.llm_embedding_backend = None
config.save()
with (
patch("documents.tasks.llmindex_index.delay") as mock_update,
patch("paperless_ai.indexing.vector_store_file_exists") as mock_exists,
):
mock_exists.return_value = False
self.client.patch(
f"{self.ENDPOINT}1/",
json.dumps(
{
"ai_enabled": True,
"llm_embedding_backend": "openai",
},
),
content_type="application/json",
)
mock_update.assert_called_once()

View File

@@ -310,3 +310,69 @@ class TestSystemStatus(APITestCase):
"ERROR",
)
self.assertIsNotNone(response.data["tasks"]["sanity_check_error"])
def test_system_status_ai_disabled(self):
"""
GIVEN:
- The AI feature is disabled
WHEN:
- The user requests the system status
THEN:
- The response contains the correct AI status
"""
with override_settings(AI_ENABLED=False):
self.client.force_login(self.user)
response = self.client.get(self.ENDPOINT)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["tasks"]["llmindex_status"], "DISABLED")
self.assertIsNone(response.data["tasks"]["llmindex_error"])
def test_system_status_ai_enabled(self):
"""
GIVEN:
- The AI index feature is enabled, but no tasks are found
- The AI index feature is enabled and a task is found
WHEN:
- The user requests the system status
THEN:
- The response contains the correct AI status
"""
with override_settings(AI_ENABLED=True, LLM_EMBEDDING_BACKEND="openai"):
self.client.force_login(self.user)
# No tasks found
response = self.client.get(self.ENDPOINT)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["tasks"]["llmindex_status"], "WARNING")
PaperlessTask.objects.create(
type=PaperlessTask.TaskType.SCHEDULED_TASK,
status=states.SUCCESS,
task_name=PaperlessTask.TaskName.LLMINDEX_UPDATE,
)
response = self.client.get(self.ENDPOINT)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["tasks"]["llmindex_status"], "OK")
self.assertIsNone(response.data["tasks"]["llmindex_error"])
def test_system_status_ai_error(self):
"""
GIVEN:
- The AI index feature is enabled and a task is found with an error
WHEN:
- The user requests the system status
THEN:
- The response contains the correct AI status
"""
with override_settings(AI_ENABLED=True, LLM_EMBEDDING_BACKEND="openai"):
PaperlessTask.objects.create(
type=PaperlessTask.TaskType.SCHEDULED_TASK,
status=states.FAILURE,
task_name=PaperlessTask.TaskName.LLMINDEX_UPDATE,
result="AI index update failed",
)
self.client.force_login(self.user)
response = self.client.get(self.ENDPOINT)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["tasks"]["llmindex_status"], "ERROR")
self.assertIsNotNone(response.data["tasks"]["llmindex_error"])

View File

@@ -49,6 +49,7 @@ class TestApiUiSettings(DirectoriesMixin, APITestCase):
"backend_setting": "default",
},
"email_enabled": False,
"ai_enabled": False,
},
)

View File

@@ -188,7 +188,7 @@ class TestFileHandling(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
@override_settings(
FILENAME_FORMAT="{correspondent}/{correspondent}",
EMPTY_TRASH_DIR=tempfile.mkdtemp(),
EMPTY_TRASH_DIR=Path(tempfile.mkdtemp()),
)
def test_document_delete_trash_dir(self):
document = Document()

View File

@@ -3,14 +3,17 @@ from datetime import timedelta
from pathlib import Path
from unittest import mock
from celery import states
from django.conf import settings
from django.test import TestCase
from django.test import override_settings
from django.utils import timezone
from documents import tasks
from documents.models import Correspondent
from documents.models import Document
from documents.models import DocumentType
from documents.models import PaperlessTask
from documents.models import Tag
from documents.sanity_checker import SanityCheckFailedException
from documents.sanity_checker import SanityCheckMessages
@@ -270,3 +273,103 @@ class TestUpdateContent(DirectoriesMixin, TestCase):
tasks.update_document_content_maybe_archive_file(doc.pk)
self.assertNotEqual(Document.objects.get(pk=doc.pk).content, "test")
class TestAIIndex(DirectoriesMixin, TestCase):
@override_settings(
AI_ENABLED=True,
LLM_EMBEDDING_BACKEND="huggingface",
)
def test_ai_index_success(self):
"""
GIVEN:
- Document exists, AI is enabled, llm index backend is set
WHEN:
- llmindex_index task is called
THEN:
- update_llm_index is called, and the task is marked as success
"""
Document.objects.create(
title="test",
content="my document",
checksum="wow",
)
# lazy-loaded so mock the actual function
with mock.patch("paperless_ai.indexing.update_llm_index") as update_llm_index:
update_llm_index.return_value = "LLM index updated successfully."
tasks.llmindex_index()
update_llm_index.assert_called_once()
task = PaperlessTask.objects.get(
task_name=PaperlessTask.TaskName.LLMINDEX_UPDATE,
)
self.assertEqual(task.status, states.SUCCESS)
self.assertEqual(task.result, "LLM index updated successfully.")
@override_settings(
AI_ENABLED=True,
LLM_EMBEDDING_BACKEND="huggingface",
)
def test_ai_index_failure(self):
"""
GIVEN:
- Document exists, AI is enabled, llm index backend is set
WHEN:
- llmindex_index task is called
THEN:
- update_llm_index raises an exception, and the task is marked as failure
"""
Document.objects.create(
title="test",
content="my document",
checksum="wow",
)
# lazy-loaded so mock the actual function
with mock.patch("paperless_ai.indexing.update_llm_index") as update_llm_index:
update_llm_index.side_effect = Exception("LLM index update failed.")
tasks.llmindex_index()
update_llm_index.assert_called_once()
task = PaperlessTask.objects.get(
task_name=PaperlessTask.TaskName.LLMINDEX_UPDATE,
)
self.assertEqual(task.status, states.FAILURE)
self.assertIn("LLM index update failed.", task.result)
def test_update_document_in_llm_index(self):
"""
GIVEN:
- Nothing
WHEN:
- update_document_in_llm_index task is called
THEN:
- llm_index_add_or_update_document is called
"""
doc = Document.objects.create(
title="test",
content="my document",
checksum="wow",
)
with mock.patch(
"documents.tasks.llm_index_add_or_update_document",
) as llm_index_add_or_update_document:
tasks.update_document_in_llm_index(doc)
llm_index_add_or_update_document.assert_called_once_with(doc)
def test_remove_document_from_llm_index(self):
"""
GIVEN:
- Nothing
WHEN:
- remove_document_from_llm_index task is called
THEN:
- llm_index_remove_document is called
"""
doc = Document.objects.create(
title="test",
content="my document",
checksum="wow",
)
with mock.patch(
"documents.tasks.llm_index_remove_document",
) as llm_index_remove_document:
tasks.remove_document_from_llm_index(doc)
llm_index_remove_document.assert_called_once_with(doc)

View File

@@ -1,6 +1,8 @@
import tempfile
from datetime import timedelta
from pathlib import Path
from unittest.mock import MagicMock
from unittest.mock import patch
from django.conf import settings
from django.contrib.auth.models import Permission
@@ -10,8 +12,15 @@ from django.test import override_settings
from django.utils import timezone
from rest_framework import status
from documents.caching import get_llm_suggestion_cache
from documents.caching import set_llm_suggestions_cache
from documents.models import Correspondent
from documents.models import Document
from documents.models import DocumentType
from documents.models import ShareLink
from documents.models import StoragePath
from documents.models import Tag
from documents.signals.handlers import update_llm_suggestions_cache
from documents.tests.utils import DirectoriesMixin
from paperless.models import ApplicationConfiguration
@@ -154,3 +163,104 @@ class TestViews(DirectoriesMixin, TestCase):
response.render()
self.assertEqual(response.request["PATH_INFO"], "/accounts/login/")
self.assertContains(response, b"Share link has expired")
class TestAISuggestions(DirectoriesMixin, TestCase):
def setUp(self):
self.user = User.objects.create_superuser(username="testuser")
self.document = Document.objects.create(
title="Test Document",
filename="test.pdf",
mime_type="application/pdf",
)
self.tag1 = Tag.objects.create(name="tag1")
self.correspondent1 = Correspondent.objects.create(name="correspondent1")
self.document_type1 = DocumentType.objects.create(name="type1")
self.path1 = StoragePath.objects.create(name="path1")
super().setUp()
@patch("documents.views.get_llm_suggestion_cache")
@patch("documents.views.refresh_suggestions_cache")
@override_settings(
AI_ENABLED=True,
LLM_BACKEND="mock_backend",
)
def test_suggestions_with_cached_llm(self, mock_refresh_cache, mock_get_cache):
mock_get_cache.return_value = MagicMock(suggestions={"tags": ["tag1", "tag2"]})
self.client.force_login(user=self.user)
response = self.client.get(f"/api/documents/{self.document.pk}/suggestions/")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json(), {"tags": ["tag1", "tag2"]})
mock_refresh_cache.assert_called_once_with(self.document.pk)
@patch("documents.views.get_ai_document_classification")
@override_settings(
AI_ENABLED=True,
LLM_BACKEND="mock_backend",
)
def test_suggestions_with_ai_enabled(
self,
mock_get_ai_classification,
):
mock_get_ai_classification.return_value = {
"title": "AI Title",
"tags": ["tag1", "tag2"],
"correspondents": ["correspondent1"],
"document_types": ["type1"],
"storage_paths": ["path1"],
"dates": ["2023-01-01"],
}
self.client.force_login(user=self.user)
response = self.client.get(f"/api/documents/{self.document.pk}/suggestions/")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
response.json(),
{
"title": "AI Title",
"tags": [self.tag1.pk],
"suggested_tags": ["tag2"],
"correspondents": [self.correspondent1.pk],
"suggested_correspondents": [],
"document_types": [self.document_type1.pk],
"suggested_document_types": [],
"storage_paths": [self.path1.pk],
"suggested_storage_paths": [],
"dates": ["2023-01-01"],
},
)
def test_invalidate_suggestions_cache(self):
self.client.force_login(user=self.user)
suggestions = {
"title": "AI Title",
"tags": ["tag1", "tag2"],
"correspondents": ["correspondent1"],
"document_types": ["type1"],
"storage_paths": ["path1"],
"dates": ["2023-01-01"],
}
set_llm_suggestions_cache(
self.document.pk,
suggestions,
backend="mock_backend",
)
self.assertEqual(
get_llm_suggestion_cache(
self.document.pk,
backend="mock_backend",
).suggestions,
suggestions,
)
# post_save signal triggered
update_llm_suggestions_cache(
sender=None,
instance=self.document,
)
self.assertIsNone(
get_llm_suggestion_cache(
self.document.pk,
backend="mock_backend",
),
)

View File

@@ -1,4 +1,5 @@
import itertools
import json
import logging
import os
import platform
@@ -16,6 +17,7 @@ import httpx
import pathvalidate
from celery import states
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import Group
from django.contrib.auth.models import User
from django.db import connections
@@ -38,6 +40,7 @@ from django.http import HttpResponseBadRequest
from django.http import HttpResponseForbidden
from django.http import HttpResponseRedirect
from django.http import HttpResponseServerError
from django.http import StreamingHttpResponse
from django.shortcuts import get_object_or_404
from django.utils import timezone
from django.utils.decorators import method_decorator
@@ -45,6 +48,7 @@ from django.utils.timezone import make_aware
from django.utils.translation import get_language
from django.views import View
from django.views.decorators.cache import cache_control
from django.views.decorators.csrf import ensure_csrf_cookie
from django.views.decorators.http import condition
from django.views.decorators.http import last_modified
from django.views.generic import TemplateView
@@ -80,10 +84,12 @@ from documents import index
from documents.bulk_download import ArchiveOnlyStrategy
from documents.bulk_download import OriginalAndArchiveStrategy
from documents.bulk_download import OriginalsOnlyStrategy
from documents.caching import get_llm_suggestion_cache
from documents.caching import get_metadata_cache
from documents.caching import get_suggestion_cache
from documents.caching import refresh_metadata_cache
from documents.caching import refresh_suggestions_cache
from documents.caching import set_llm_suggestions_cache
from documents.caching import set_metadata_cache
from documents.caching import set_suggestions_cache
from documents.classifier import load_classifier
@@ -171,11 +177,20 @@ from documents.templating.filepath import validate_filepath_template_and_render
from documents.utils import get_boolean
from paperless import version
from paperless.celery import app as celery_app
from paperless.config import AIConfig
from paperless.config import GeneralConfig
from paperless.db import GnuPG
from paperless.serialisers import GroupSerializer
from paperless.serialisers import UserSerializer
from paperless.views import StandardPagination
from paperless_ai.ai_classifier import get_ai_document_classification
from paperless_ai.chat import stream_chat_with_documents
from paperless_ai.indexing import update_llm_index
from paperless_ai.matching import extract_unmatched_names
from paperless_ai.matching import match_correspondents_by_name
from paperless_ai.matching import match_document_types_by_name
from paperless_ai.matching import match_storage_paths_by_name
from paperless_ai.matching import match_tags_by_name
from paperless_mail.models import MailAccount
from paperless_mail.models import MailRule
from paperless_mail.oauth import PaperlessMailOAuth2Manager
@@ -763,37 +778,103 @@ class DocumentViewSet(
):
return HttpResponseForbidden("Insufficient permissions")
document_suggestions = get_suggestion_cache(doc.pk)
ai_config = AIConfig()
if document_suggestions is not None:
refresh_suggestions_cache(doc.pk)
return Response(document_suggestions.suggestions)
classifier = load_classifier()
dates = []
if settings.NUMBER_OF_SUGGESTED_DATES > 0:
gen = parse_date_generator(doc.filename, doc.content)
dates = sorted(
{i for i in itertools.islice(gen, settings.NUMBER_OF_SUGGESTED_DATES)},
if ai_config.ai_enabled:
cached_llm_suggestions = get_llm_suggestion_cache(
doc.pk,
backend=ai_config.llm_backend,
)
resp_data = {
"correspondents": [
c.id for c in match_correspondents(doc, classifier, request.user)
],
"tags": [t.id for t in match_tags(doc, classifier, request.user)],
"document_types": [
dt.id for dt in match_document_types(doc, classifier, request.user)
],
"storage_paths": [
dt.id for dt in match_storage_paths(doc, classifier, request.user)
],
"dates": [date.strftime("%Y-%m-%d") for date in dates if date is not None],
}
if cached_llm_suggestions:
refresh_suggestions_cache(doc.pk)
return Response(cached_llm_suggestions.suggestions)
# Cache the suggestions and the classifier hash for later
set_suggestions_cache(doc.pk, resp_data, classifier)
llm_suggestions = get_ai_document_classification(doc, request.user)
matched_tags = match_tags_by_name(
llm_suggestions.get("tags", []),
request.user,
)
matched_correspondents = match_correspondents_by_name(
llm_suggestions.get("correspondents", []),
request.user,
)
matched_types = match_document_types_by_name(
llm_suggestions.get("document_types", []),
request.user,
)
matched_paths = match_storage_paths_by_name(
llm_suggestions.get("storage_paths", []),
request.user,
)
resp_data = {
"title": llm_suggestions.get("title"),
"tags": [t.id for t in matched_tags],
"suggested_tags": extract_unmatched_names(
llm_suggestions.get("tags", []),
matched_tags,
),
"correspondents": [c.id for c in matched_correspondents],
"suggested_correspondents": extract_unmatched_names(
llm_suggestions.get("correspondents", []),
matched_correspondents,
),
"document_types": [d.id for d in matched_types],
"suggested_document_types": extract_unmatched_names(
llm_suggestions.get("document_types", []),
matched_types,
),
"storage_paths": [s.id for s in matched_paths],
"suggested_storage_paths": extract_unmatched_names(
llm_suggestions.get("storage_paths", []),
matched_paths,
),
"dates": llm_suggestions.get("dates", []),
}
set_llm_suggestions_cache(doc.pk, resp_data, backend=ai_config.llm_backend)
else:
document_suggestions = get_suggestion_cache(doc.pk)
if document_suggestions is not None:
refresh_suggestions_cache(doc.pk)
return Response(document_suggestions.suggestions)
classifier = load_classifier()
dates = []
if settings.NUMBER_OF_SUGGESTED_DATES > 0:
gen = parse_date_generator(doc.filename, doc.content)
dates = sorted(
{
i
for i in itertools.islice(
gen,
settings.NUMBER_OF_SUGGESTED_DATES,
)
},
)
resp_data = {
"correspondents": [
c.id for c in match_correspondents(doc, classifier, request.user)
],
"tags": [t.id for t in match_tags(doc, classifier, request.user)],
"document_types": [
dt.id for dt in match_document_types(doc, classifier, request.user)
],
"storage_paths": [
dt.id for dt in match_storage_paths(doc, classifier, request.user)
],
"dates": [
date.strftime("%Y-%m-%d") for date in dates if date is not None
],
}
# Cache the suggestions and the classifier hash for later
set_suggestions_cache(doc.pk, resp_data, classifier)
return Response(resp_data)
@@ -1093,6 +1174,52 @@ class DocumentViewSet(
)
@method_decorator(
[
ensure_csrf_cookie,
login_required,
cache_control(no_cache=True),
],
name="dispatch",
)
class ChatStreamingView(View):
def post(self, request):
request.compress_exempt = True
ai_config = AIConfig()
if not ai_config.ai_enabled:
return HttpResponseBadRequest("AI is required for this feature")
try:
data = json.loads(request.body)
question = data["q"]
doc_id = data.get("document_id", None)
except (KeyError, json.JSONDecodeError):
return HttpResponseBadRequest("Invalid request")
if doc_id:
try:
document = Document.objects.get(id=doc_id)
except Document.DoesNotExist:
return HttpResponseBadRequest("Document not found")
if not has_perms_owner_aware(request.user, "view_document", document):
return HttpResponseForbidden("Insufficient permissions")
documents = [document]
else:
documents = get_objects_for_user_owner_aware(
request.user,
"view_document",
Document,
)
response = StreamingHttpResponse(
stream_chat_with_documents(query_str=question, documents=documents),
content_type="text/event-stream",
)
return response
@extend_schema_view(
list=extend_schema(
parameters=[
@@ -2208,6 +2335,10 @@ class UiSettingsView(GenericAPIView):
ui_settings["email_enabled"] = settings.EMAIL_ENABLED
ai_config = AIConfig()
ui_settings["ai_enabled"] = ai_config.ai_enabled
user_resp = {
"id": user.id,
"username": user.username,
@@ -2335,6 +2466,10 @@ class TasksViewSet(ReadOnlyModelViewSet):
sanity_check,
{"scheduled": False, "raise_on_error": False},
),
PaperlessTask.TaskName.LLMINDEX_UPDATE: (
update_llm_index,
{"scheduled": False, "rebuild": False},
),
}
def get_queryset(self):
@@ -2840,6 +2975,31 @@ class SystemStatusView(PassUserMixin):
last_sanity_check.date_done if last_sanity_check else None
)
ai_config = AIConfig()
if not ai_config.llm_index_enabled():
llmindex_status = "DISABLED"
llmindex_error = None
llmindex_last_modified = None
else:
last_llmindex_update = (
PaperlessTask.objects.filter(
task_name=PaperlessTask.TaskName.LLMINDEX_UPDATE,
)
.order_by("-date_done")
.first()
)
llmindex_status = "OK"
llmindex_error = None
if last_llmindex_update is None:
llmindex_status = "WARNING"
llmindex_error = "No LLM index update tasks found"
elif last_llmindex_update and last_llmindex_update.status == states.FAILURE:
llmindex_status = "ERROR"
llmindex_error = last_llmindex_update.result
llmindex_last_modified = (
last_llmindex_update.date_done if last_llmindex_update else None
)
return Response(
{
"pngx_version": current_version,
@@ -2877,6 +3037,9 @@ class SystemStatusView(PassUserMixin):
"sanity_check_status": sanity_check_status,
"sanity_check_last_run": sanity_check_last_run,
"sanity_check_error": sanity_check_error,
"llmindex_status": llmindex_status,
"llmindex_last_modified": llmindex_last_modified,
"llmindex_error": llmindex_error,
},
},
)

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Afrikaans\n"
"Language: af_ZA\n"
@@ -1618,143 +1618,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Engels (VS)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arabies"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr ""
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Belorussies"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr ""
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Katalaans"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Tsjeggies"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Deens"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Duits"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr ""
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Engels (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Spaans"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Fins"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Frans"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr ""
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italiaans"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr ""
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luxemburgs"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr ""
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Nederlands"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Pools"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugees (Brasilië)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugees"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Roemeens"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Russies"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr ""
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Sloweens"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Serwies"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Sweeds"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turks"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr ""
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Vereenvoudigde Sjinees"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Arabic\n"
"Language: ar_SA\n"
@@ -1619,143 +1619,143 @@ msgstr ""
msgid "paperless application settings"
msgstr "إعدادات التطبيق paperless"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "الإنجليزية (الولايات المتحدة)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "العربية"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "اللغة الأفريقانية"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "البيلاروسية"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "البلغارية"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "اللغة الكتالونية"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "التشيكية"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "الدانماركية"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "الألمانية"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "اليونانية"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "الإنجليزية (المملكة المتحدة)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "الإسبانية"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "الفنلندية"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "الفرنسية"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "المجرية"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "الإيطالية"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "اليابانية"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "اللوكسمبرجية"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "النرويجية"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "الهولندية"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "البولندية"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "البرتغالية (البرازيل)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "البرتغالية"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "الرومانية"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "الروسية"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "السلوفاكية"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "السلوفانية"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "الصربية"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "السويدية"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "التركية"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "الأوكرانية"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "الصينية المبسطة"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Belarusian\n"
"Language: be_BY\n"
@@ -1618,143 +1618,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Англійская (ЗША)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr ""
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr ""
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Беларуская"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr ""
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr ""
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Чэшская"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Дацкая"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Нямецкая"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr ""
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Англійская (Вялікабрытанія)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Іспанская"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr ""
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Французская"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr ""
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Італьянская"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr ""
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Люксембургская"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr ""
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Нідэрландская"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Польская"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Партугальская (Бразілія)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Партугальская"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Румынская"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Руская"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr ""
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Славенская"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Сербская"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Шведская"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Турэцкая"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr ""
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Кітайская спрошчаная"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Bulgarian\n"
"Language: bg_BG\n"
@@ -1619,143 +1619,143 @@ msgstr ""
msgid "paperless application settings"
msgstr "настройки на софтуера"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Английски (САЩ)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Арабски"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Африканс"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Беларуски"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Български"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Каталунски"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Чешки"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Датски"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Немски"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Гръцки"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Английски (Великобритания)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Испански"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Финландски"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Френски"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Унгарски"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Италиански"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Японски"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Корейски"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Люксембургски"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Норвежки"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Холандски"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Полски"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Португалски (Бразилия)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Португалски"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Румънски"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Руски"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Словашки"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Словенски"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Сръбски"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Шведски"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Турски"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Украински"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Китайски опростен"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "Китайски традиционен"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-18 12:14\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Catalan\n"
"Language: ca_ES\n"
@@ -1619,143 +1619,143 @@ msgstr "Defineix el mapatge de l'etiqueta del codi de barres"
msgid "paperless application settings"
msgstr "configuració de l'aplicació paperless"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Anglès (US)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Àrab"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Africà"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Bielorús"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Búlgar"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Català"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Txec"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Danès"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Alemany"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Grec"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Anglès (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Espanyol"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr "Persa"
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Finès"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Francès"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Hongarès"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italià"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Japonès"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Coreà"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luxemburguès"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Noruec"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Holandès"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Polonès"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portuguès (Brasil)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portuguès"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Romanès"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Rus"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Eslovac"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Eslovè"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Serbi"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Suec"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turc"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ucranià"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Xinès Simplificat"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "Xinès tradicional"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 12:14\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Czech\n"
"Language: cs_CZ\n"
@@ -1619,143 +1619,143 @@ msgstr "Nastaví mapování čárových kódů na štítky"
msgid "paperless application settings"
msgstr "nastavení aplikace paperless"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Angličtina (US)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arabština"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Afrikánština"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Běloruština"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Bulharština"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Katalánština"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Čeština"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Dánština"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Němčina"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Řečtina"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Angličtina (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Španělština"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr "Perština"
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Finština"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Francouzština"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Maďarština"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italština"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Japonština"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Korejština"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Lucemburština"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norština"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Holandština"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Polština"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugalština (Brazílie)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugalština"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Rumunština"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Ruština"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Slovenština"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Slovinština"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Srbština"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Švédština"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turečtina"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ukrajinština"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Čínština (zjednodušená)"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "Čínština (tradiční)"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Danish\n"
"Language: da_DK\n"
@@ -1619,143 +1619,143 @@ msgstr ""
msgid "paperless application settings"
msgstr "paperless-applikationsindstillinger"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Engelsk (USA)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr ""
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Afrikaans"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Hviderussisk"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Bulgarsk"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Katalansk"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Tjekkisk"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Dansk"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Tysk"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Græsk"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Engelsk (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Spansk"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Finsk"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Fransk"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Ungarsk"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italiensk"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Japansk"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Koreansk"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luxemburgsk"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norsk"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Hollandsk"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Polsk"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugisisk (Brasilien)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugisisk"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Romansk"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Russisk"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Slovakisk"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Slovensk"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Serbisk"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Svensk"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Tyrkisk"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ukrainsk"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Kinesisk, forenklet"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "Kinesisk, traditionelt"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: German\n"
"Language: de_DE\n"
@@ -1619,143 +1619,143 @@ msgstr "Legt die Tag-Barcode-Zuweisung fest"
msgid "paperless application settings"
msgstr "Paperless-ngx-Anwendungseinstellungen"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Englisch (US)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arabisch"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Afrikanisch"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Belarussisch"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Bulgarisch"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Katalanisch"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Tschechisch"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Dänisch"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Deutsch"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Griechisch"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Englisch (UK)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Spanisch"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr "Persisch"
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Finnisch"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Französisch"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Ungarisch"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italienisch"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Japanisch"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Koreanisch"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luxemburgisch"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norwegisch"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Niederländisch"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Polnisch"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugiesisch (Brasilien)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugiesisch"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Rumänisch"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Russisch"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Slowakisch"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Slowenisch"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Serbisch"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Schwedisch"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Türkisch"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ukrainisch"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Chinesisch (vereinfacht)"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "Chinesisch (traditionell)"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Greek\n"
"Language: el_GR\n"
@@ -1619,143 +1619,143 @@ msgstr ""
msgid "paperless application settings"
msgstr "ρυθμίσεις εφαρμογής paperless"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Αγγλικά (ΗΠΑ)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Αραβικά"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Αφρικανικά"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Λευκορωσικά"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Βουλγαρικά"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Καταλανικά"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Τσέχικα"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Δανέζικα"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Γερμανικά"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Ελληνικά"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Αγγλικά (Ηνωμένο Βασίλειο)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Ισπανικά"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Φινλανδικά"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Γαλλικά"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Ουγγρικά"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Ιταλικά"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Ιαπωνικά"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Κορεάτικα"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Λουξεμβουργικά"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Νορβηγικά"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Ολλανδικά"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Πολωνικά"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Πορτογαλικά (Βραζιλίας)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Πορτογαλικά"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Ρουμάνικα"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Ρωσικά"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Σλοβακικά"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Σλοβενικά"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Σερβικά"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Σουηδικά"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Τούρκικα"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ουκρανικά"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Κινέζικα Απλοποιημένα"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "Κινεζικά Παραδοσιακά"

View File

@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2022-02-17 04:17\n"
"Last-Translator: \n"
"Language-Team: English\n"
@@ -1645,143 +1645,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr ""
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr ""
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr ""
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr ""
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr ""
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr ""
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr ""
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr ""
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr ""
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr ""
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr ""
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr ""
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr ""
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr ""
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr ""
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr ""
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr ""
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr ""
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr ""
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr ""
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr ""
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr ""
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr ""
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr ""
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr ""
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr ""
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr ""
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr ""
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr ""
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr ""
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr ""
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr ""
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Spanish\n"
"Language: es_ES\n"
@@ -1619,143 +1619,143 @@ msgstr "Establece el mapeo de códigos de barras de etiquetas"
msgid "paperless application settings"
msgstr "Ajustes de la aplicación paperless"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Inglés (US)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Árabe"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Africano"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Bielorruso"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Búlgaro"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Catalán"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Checo"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Danés"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Alemán"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Griego"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Inglés (Gran Bretaña)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Español"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Finlandés"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Francés"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Húngaro"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italiano"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Japonés"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Coreano"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luxemburgués"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Noruego"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Alemán"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Polaco"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugués (Brasil)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugués"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Rumano"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Ruso"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Eslovaco"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Esloveno"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Serbio"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Sueco"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turco"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ucraniano"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Chino simplificado"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "Chino tradicional"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Estonian\n"
"Language: et_EE\n"
@@ -1618,143 +1618,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr ""
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr ""
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr ""
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr ""
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr ""
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr ""
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr ""
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr ""
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr ""
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr ""
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr ""
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr ""
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr ""
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr ""
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr ""
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr ""
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr ""
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr ""
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr ""
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr ""
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr ""
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr ""
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr ""
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr ""
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr ""
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr ""
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr ""
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr ""
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr ""
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr ""
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr ""
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr ""
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Persian\n"
"Language: fa_IR\n"
@@ -1618,143 +1618,143 @@ msgstr "نقشه بارکد برچسب را تنظیم می کند"
msgid "paperless application settings"
msgstr "تنظیمات برنامه بدون کاغذ"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "انگلیسی (ایالات متحده)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "عربی"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "افریکان"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "وابسته به بلروس"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "وابسته به بلغاری"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "کاتالان"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "وابسته به چک"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "وابسته به دانمارکی"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "آلمانی"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "یونانی"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "انگلیسی (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "اسپانیایی"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "فنلاندی"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "فرانسوی"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "مجارستانی"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "ایتالیایی"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "وابسته به ژاپنی"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "کره ای"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "وابسته به لوکس"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "نروژی"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "هلندی"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "صیقل دادن"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "پرتغالی (برزیل)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "وابسته به پرتغالی"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "وابسته به رومانی"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "روسی"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "لگن"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "وابسته به اسلوونی"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "صرب"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "سوئدی"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "ترکی"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "وابسته به اوکراینی"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "چینی ساده شد"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "چینی سنتی"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Finnish\n"
"Language: fi_FI\n"
@@ -1619,143 +1619,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Englanti (US)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arabialainen"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr ""
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "valkovenäjä"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr ""
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Katalaani"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Tšekki"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Tanska"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Saksa"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Kreikka"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Englanti (US)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Espanja"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Suomi"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Ranska"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr ""
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italia"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr ""
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luxemburg"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norja"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Hollanti"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "puola"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "portugali (Brasilia)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "portugali"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "romania"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "venäjä"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Slovakia"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Slovenia"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Serbia"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "ruotsi"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turkki"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ukraina"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Kiina (yksinkertaistettu)"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: French\n"
"Language: fr_FR\n"
@@ -1618,143 +1618,143 @@ msgstr ""
msgid "paperless application settings"
msgstr "paramètres de l'application paperless"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Anglais (US)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arabe"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Afrikaans"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Biélorusse"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Bulgare"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Catalan"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Tchèque"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Danois"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Allemand"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Grec"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Anglais (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Espagnol"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Finnois"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Français"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Hongrois"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italien"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Japonais"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Coréen"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luxembourgeois"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norvégien"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Néerlandais"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Polonais"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugais (Brésil)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugais"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Roumain"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Russe"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Solvaque"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Slovène"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Serbe"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Suédois"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turc"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ukrainien"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Chinois simplifié"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "Chinois traditionnel"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Hebrew\n"
"Language: he_IL\n"
@@ -1620,143 +1620,143 @@ msgstr "מגדיר את מיפוי הברקוד"
msgid "paperless application settings"
msgstr "הגדרות יישום paperless"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "אנגלית (ארה״ב)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "ערבית"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "אפריקאנס"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "בלרוסית"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "בולגרית"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "קטלאנית"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "צ'כית"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "דנית"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "גרמנית"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "יוונית"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "אנגלית (בריטניה)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "ספרדית"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "פינית"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "צרפתית"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "הונגרית"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "איטלקית"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "יפנית"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "קוריאנית"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "לוקסמבורגית"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "נורווגית"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "הולנדית"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "פולנית"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "פורטוגלית ברזילאית"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "פורטוגלית"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "רומנית"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "רוסית"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "סלובקית"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "סלובנית"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "סרבית"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "שוודית"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "טורקית"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "אוקראינית"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "סינית מפושטת"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "סינית מסורתית"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Croatian\n"
"Language: hr_HR\n"
@@ -1618,143 +1618,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Engleski (US)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arapski"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr ""
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Bjeloruski"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr ""
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr ""
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Češki"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Danski"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Njemački"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr ""
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Engleski (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Španjolski"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr ""
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Francuski"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr ""
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Talijanski"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr ""
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luksemburški"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr ""
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Nizozemski"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Poljski"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugalski (Brazil)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugalski"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Rumunjski"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Ruski"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr ""
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Slovenski"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Srpski"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Švedski"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turski"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr ""
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Pojednostavljeni kineski"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Hungarian\n"
"Language: hu_HU\n"
@@ -1618,143 +1618,143 @@ msgstr "Beállítja a vonalkódok címkékhez rendelését"
msgid "paperless application settings"
msgstr "paperless alkalmazás beállítások"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Angol (US)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arab"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Afrikai"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Fehérorosz"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Bolgár"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Katalán"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Cseh"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Dán"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Német"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Görög"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Angol (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Spanyol"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Finn"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Francia"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Magyar"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Olasz"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "japán"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "koreai"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luxemburgi"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norvég"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Holland"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Lengyel"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugál (Brazília)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugál"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Román"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Orosz"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Szlovák"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Szlovén"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Szerb"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Svéd"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Török"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ukrán"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Kínai egyszerűsített"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "tradicionális kínai"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Indonesian\n"
"Language: id_ID\n"
@@ -1619,143 +1619,143 @@ msgstr ""
msgid "paperless application settings"
msgstr "pengaturan aplikasi paperless"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Inggris (AS)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arab"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Bahasa Afrika"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Belarusia"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Bahasa Bulgaria"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr ""
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Bahasa Ceko"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr ""
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Jerman"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Yunani"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Inggris (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Spanyol"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr ""
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Prancis"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Hungaria"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italia"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Bahasa Jepang"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Bahasa Korea"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luksemburg"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norwegia"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Belanda"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Polandia"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugis (Brasil)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugis"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Rumania"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Rusia"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Slovakia"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Slovenia"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Serbia"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Swedia"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turki"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ukraina"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Mandarin Sederhana"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Italian\n"
"Language: it_IT\n"
@@ -1619,143 +1619,143 @@ msgstr ""
msgid "paperless application settings"
msgstr "impostazioni dell'applicazione paperless"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Inglese (US)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arabo"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Africano"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Bielorusso"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Bulgaro"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Catalano"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Ceco"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Danese"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Tedesco"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Greco"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Inglese (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Spagnolo"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Finlandese"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Francese"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Ungherese"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italiano"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Giapponese"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Coreano"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Lussemburghese"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norvegese"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Olandese"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Polacco"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portoghese (Brasile)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portoghese"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Rumeno"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Russo"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Slovacco"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Sloveno"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Serbo"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Svedese"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turco"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ucraino"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Cinese semplificato"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Japanese\n"
"Language: ja_JP\n"
@@ -1619,143 +1619,143 @@ msgstr ""
msgid "paperless application settings"
msgstr "Paperless アプリケーションの設定"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "英語 (米国)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "アラビア語"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "アフリカーンス語"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "ベラルーシ語"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "ブルガリア語"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "カタロニア語"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "チェコ語"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "デンマーク語"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "ドイツ語"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "ギリシャ語"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "英語 (英国)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "スペイン語"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "フィンランド語"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "フランス語"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "ハンガリー語"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "イタリア語"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "日本語"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "韓国語"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "ルクセンブルク語"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "ノルウェー語"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "オランダ語"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "ポーランド語"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "ポルトガル語 (ブラジル)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "ポルトガル語"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "ルーマニア語"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "ロシア語"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "スロバキア語"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "スロベニア語"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "セルビア語"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "スウェーデン語"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "トルコ語"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "ウクライナ語"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "中国語 (簡体字)"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "中国語 (繁体)"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Korean\n"
"Language: ko_KR\n"
@@ -1619,143 +1619,143 @@ msgstr ""
msgid "paperless application settings"
msgstr "페이퍼리스 애플리케이션 설정"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "영어 (미국)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "아랍어"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "아프리칸스어"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "벨라루스어"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "불가리어"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "카탈로니아어"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "체코어"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "덴마크어"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "독일어"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "그리스어"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "영어 (영국)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "스페인어"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "핀란드어"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "프랑스어"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "헝가리어"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "이탈리아어"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "일본어"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "한국어"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "룩셈부르크어"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "노르웨이어"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "네덜란드어"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "폴란드어"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "포르투갈어 (브라질)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "포르투갈어"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "루마니아어"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "러시아어"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "슬로바키아어"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "슬로베니아어"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "세르비아어"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "스웨덴어"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "튀르키예어"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "우크라이나어"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "중국어 간체"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "중국어 번체"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Luxembourgish\n"
"Language: lb_LU\n"
@@ -1618,143 +1618,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Englesch (USA)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr ""
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr ""
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Belarusesch"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr ""
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr ""
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Tschechesch"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Dänesch"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Däitsch"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr ""
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Englesch (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Spuenesch"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr ""
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Franséisch"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr ""
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italienesch"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr ""
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Lëtzebuergesch"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr ""
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Hollännesch"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Polnesch"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugisesch (Brasilien)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugisesch"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Rumänesch"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Russesch"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr ""
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Slowenesch"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Serbesch"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Schwedesch"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Tierkesch"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr ""
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Chinesesch (Vereinfacht)"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Lithuanian\n"
"Language: lt_LT\n"
@@ -1618,143 +1618,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr ""
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr ""
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr ""
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr ""
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr ""
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr ""
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr ""
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr ""
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr ""
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr ""
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr ""
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr ""
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr ""
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr ""
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr ""
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr ""
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr ""
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr ""
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr ""
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr ""
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr ""
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr ""
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr ""
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr ""
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr ""
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr ""
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr ""
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr ""
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr ""
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr ""
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr ""
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr ""
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Latvian\n"
"Language: lv_LV\n"
@@ -1618,143 +1618,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Angļu (ASV)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arābu"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Āfrikāņu"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Baltkrievu"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Bulgāru"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Kataloniešu"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Čehu"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Dāņu"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Vācu"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Grieķu"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Angļu (ASV)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Spāņu"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Somu"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Franču"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Ungāru"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Itāļu"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Japāņu"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luksemburgiešu"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norvēģu"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Holandiešu"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Poļu"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugāļu (Brazīlija)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugāļu"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Rumāņu"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Krievu"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Slovāku"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Slovēņu"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Sērbu"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Zviedru"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turku"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ukraiņu"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Ķīniešu (vienkāršota)"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Malay\n"
"Language: ms_MY\n"
@@ -1618,143 +1618,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr ""
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr ""
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr ""
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr ""
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr ""
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr ""
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr ""
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr ""
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr ""
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr ""
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr ""
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr ""
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr ""
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr ""
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr ""
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr ""
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr ""
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr ""
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr ""
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr ""
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr ""
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr ""
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr ""
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr ""
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr ""
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr ""
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr ""
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr ""
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr ""
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr ""
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr ""
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr ""
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-19 12:14\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Dutch\n"
"Language: nl_NL\n"
@@ -1619,143 +1619,143 @@ msgstr ""
msgid "paperless application settings"
msgstr "paperless applicatie instellingen"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Engels (US)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arabisch"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Afrikaans"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Wit-Russisch"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Bulgaars"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Catalaans"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Tsjechisch"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Deens"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Duits"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Grieks"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Engels (Brits)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Spaans"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Fins"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Frans"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Hongaars"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italiaans"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Japans"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luxemburgs"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Noors"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Nederlands"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Pools"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugees (Brazilië)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugees"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Roemeens"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Russisch"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Slowaaks"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Sloveens"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Servisch"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Zweeds"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turks"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Oekraïens"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Chinees (vereenvoudigd)"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Norwegian\n"
"Language: no_NO\n"
@@ -1618,143 +1618,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Engelsk (US)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arabisk"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Afrikansk"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Hviterussisk"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr ""
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Katalansk"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Tsjekkisk"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Dansk"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Tysk"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Gresk"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Engelsk (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Spansk"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Finsk"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Fransk"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr ""
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italiensk"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr ""
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luxembourgsk"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norsk"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Nederlandsk"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Polsk"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugisisk (Brasil)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugisisk"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Rumensk"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Russisk"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Slovakisk"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Slovenian"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Serbisk"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Svensk"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Tyrkisk"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ukrainsk"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Kinesisk forenklet"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-18 00:36\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Polish\n"
"Language: pl_PL\n"
@@ -1619,143 +1619,143 @@ msgstr "Ustawia mapowanie kodu kreskowego tagu"
msgid "paperless application settings"
msgstr "paperless ustawienia aplikacji"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Angielski (USA)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "arabski"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Afrykanerski"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Białoruski"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Bułgarski"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Kataloński"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Czeski"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Duński"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Niemiecki"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Grecki"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Angielski (Wielka Brytania)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Hiszpański"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr "perski"
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Fiński"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Francuski"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Węgierski"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Włoski"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Japoński"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Koreański"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luksemburski"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norweski"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Holenderski"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Polski"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugalski (Brazylia)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugalski"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Rumuński"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Rosyjski"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Słowacki"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Słoweński"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Serbski"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Szwedzki"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turecki"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ukraiński"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Chiński uproszczony"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "chiński tradycyjny"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Portuguese, Brazilian\n"
"Language: pt_BR\n"
@@ -1620,143 +1620,143 @@ msgstr "Define o mapeamento de códigos de barras da tag"
msgid "paperless application settings"
msgstr "configurações do aplicativo paperless"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Inglês (EUA)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Árabe"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Africanês"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Bielorrusso"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Búlgaro"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Catalão"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Tcheco"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Dinamarquês"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Alemão"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Grego"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Inglês (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Espanhol"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Finlandês"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Francês"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Húngaro"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italiano"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Japonês"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Coreano"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luxemburguês"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norueguês"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Holandês"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Polonês"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Português (Brasil)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Português"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Romeno"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Russo"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Eslovaco"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Esloveno"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Sérvio"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Sueco"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turco"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ucraniano"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Chinês Simplificado"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "Chinês Tradicional"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Portuguese\n"
"Language: pt_PT\n"
@@ -1619,143 +1619,143 @@ msgstr ""
msgid "paperless application settings"
msgstr "configurações do paperless"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Inglês (EUA)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Árabe"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Africano"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Bielorrusso"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Búlgaro"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Catalão"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Checo"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Dinamarquês"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Deutsch"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Grego"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Inglês (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Espanhol"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Finlandês"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Français"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Húngaro"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italiano"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Japonês"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luxemburguês"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norueguês"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Nederlandse"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Polaco"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Português (Brasil)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Português"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Romeno"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Russo"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Eslovaco"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Esloveno"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Sérvio"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Sueco"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turco"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ucraniano"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Chinês Simplificado"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Romanian\n"
"Language: ro_RO\n"
@@ -1618,143 +1618,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Engleză (Americană)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr ""
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr ""
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr ""
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr ""
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr ""
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Cehă"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Daneză"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Germană"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr ""
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Engleză (Britanică)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Spaniolă"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr ""
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Franceză"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr ""
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italiană"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr ""
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luxemburgheză"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr ""
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Olandeză"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Poloneză"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugheză (Brazilia)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugheză"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Română"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Rusă"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr ""
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr ""
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr ""
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Suedeză"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr ""
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr ""
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr ""
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Russian\n"
"Language: ru_RU\n"
@@ -1619,143 +1619,143 @@ msgstr ""
msgid "paperless application settings"
msgstr "настройки приложения paperless"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Английский (США)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Арабский"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Африкаанс"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Белорусский"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Болгарский"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Каталонский"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Чешский"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Датский"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Немецкий"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Греческий"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Английский (Великобритании)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Испанский"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Финский"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Французский"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Венгерский"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Итальянский"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Японский"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Корейский"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Люксембургский"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Норвежский"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Датский"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Польский"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Португальский (Бразилия)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Португальский"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Румынский"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Русский"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Словацкий"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Словенский"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Сербский"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Шведский"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Турецкий"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Украинский"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Китайский упрощенный"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "Китайский (традиционный)"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 12:14\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Slovak\n"
"Language: sk_SK\n"
@@ -1619,143 +1619,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Angličtina (US)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arabčina"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr ""
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Bieloruština"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr ""
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Catalan"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Čeština"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Dánčina"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Nemčina"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr ""
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Angličtina (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Španielčina"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Finnish"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Francúzština"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr ""
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Taliančina"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr ""
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luxemburčina"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr ""
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Holandčina"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Polština"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugalčina (Brazília)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugalčina"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Rumunčina"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Ruština"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Slovenčina"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Slovinčina"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Srbčina"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Švédčina"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turečtina"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr ""
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Čínština (zjednodušená)"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 12:14\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Slovenian\n"
"Language: sl_SI\n"
@@ -1619,143 +1619,143 @@ msgstr "Nastavi preslikavo črtne kode oznake"
msgid "paperless application settings"
msgstr "aplikacijske nastavitve paperless"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Angleščina (ZDA)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arabščina"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Afrikanščina"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Beloruščina"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Bolgarščina"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Katalonščina"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Češčina"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Danščina"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Nemščina"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Grščina"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Angleščina (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Španščina"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr "Perzijščina"
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Finščina"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Francoščina"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Madžarščina"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italijanščina"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "japonščina"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Korejščina"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luksemburški"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norveščina"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Nizozemščina"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Poljščina"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugalščina (Brazilija)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugalščina"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Romunščina"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Ruščina"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Slovaščina"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Slovenščina"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Srbščina"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Švedščina"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turščina"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ukrajinščina"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Poenostavljena kitajščina"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "Tradicionalna kitajščina"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Serbian (Latin)\n"
"Language: sr_CS\n"
@@ -1619,143 +1619,143 @@ msgstr "Postavlja mapiranje barkoda oznake"
msgid "paperless application settings"
msgstr "podešavanje paperless aplikacije"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Engleski (US)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arapski"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Afrički"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Beloruski"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Bugarski"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Katalonski"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Češki"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Danski"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Nemački"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Grčki"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Engleski (UK)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Španski"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr "Persijski"
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Finski"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Francuski"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Mađarski"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italijanski"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Japanski"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Korejski"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luksemburški"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norveški"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Holandski"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Poljski"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugalski (Brazil)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugalski"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Rumunski"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Ruski"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Slovački"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Slovenački"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Srpski"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Švedski"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turski"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ukrajinski"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Kineski pojednostavljen"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "Tradicionalni kineski"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Swedish\n"
"Language: sv_SE\n"
@@ -1619,143 +1619,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Engelska (USA)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arabiska"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Afrikaans"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Belarusiska"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Bulgariska"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Kataloniska"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Tjeckiska"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Danska"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Tyska"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Grekiska"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Engelska (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Spanska"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Finska"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Franska"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr ""
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Italienska"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Japanska"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Koreanska"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Luxemburgiska"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norska"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Holländska"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Polska"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portugisiska (Brasilien)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portugisiska"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Rumänska"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Ryska"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Slovakiska"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Slovenska"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Serbiska"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Svenska"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Turkiska"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ukrainiska"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Kinesiska (förenklad)"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "Kinesiska traditionell"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Thai\n"
"Language: th_TH\n"
@@ -1618,143 +1618,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "ภาษาอังกฤษ (สหรัฐฯ)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "ภาษาอาหรับ"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "ภาษาอาฟรีกานส์"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "ภาษาเบลารุส"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr ""
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "ภาษาคาตาลัน"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "ภาษาเช็ก"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "ภาษาเดนมาร์ก"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "ภาษาเยอรมัน"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "ภาษากรีก"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "ภาษาอังกฤษ (สหราชอาณาจักร)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "ภาษาสเปน"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "ภาษาฟินแลนด์"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "ภาษาฝรั่งเศส"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr ""
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "ภาษาอิตาลี"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr ""
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "ภาษาลักเซมเบิร์ก"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "ภาษานอร์เวย์"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "ภาษาดัตช์"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "ภาษาโปแลนด์"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "ภาษาโปรตุเกส (บราซิล)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "ภาษาโปรตุเกส"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "ภาษาโรมาเนีย"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "ภาษารัสเซีย"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "ภาษาสโลวาเกีย"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "ภาษาสโลเวเนีย"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "ภาษาเซอร์เบีย"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "ภาษาสวีเดน"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "ภาษาตุรกี"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "ภาษายูเครน"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "ภาษาจีน (ตัวย่อ)"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Turkish\n"
"Language: tr_TR\n"
@@ -1618,143 +1618,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "İngilizce (Birleşik Devletler)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Arapça"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Afrika dili"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Belarusça"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Bulgarca"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Katalanca"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Çekçe"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Danca"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Almanca"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Yunanca"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "İngilizce (GB)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "İspanyolca"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Fince"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Fransızca"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr ""
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "İtalyanca"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr ""
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Lüksemburgca"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norveçce"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Hollandaca"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Polonyaca"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Portekizce (Brezilya)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Portekizce"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Romence"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Rusça"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Slovakça"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Slovakça"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Sırpça"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "İsveççe"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Türkçe"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Ukraynaca"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Basitleştirilmiş Çince"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-18 00:36\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Ukrainian\n"
"Language: uk_UA\n"
@@ -1619,143 +1619,143 @@ msgstr ""
msgid "paperless application settings"
msgstr "налаштування програми документообігу"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "Англійська (США)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "Арабська"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Африкаанс"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "Білоруська"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "Болгарська"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Каталонська"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "Чеська"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "Данська"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "Німецька"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Грецька"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "Англійська (Велика Британія)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "Іспанська"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "Фінська"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "Французька"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "Угорська"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "Італійська"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "Японська"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "Корейська"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "Люксембурзька"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Норвезька"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "Нідерландська"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "Польська"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "Португальська (Бразилія)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "Португальська"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "Румунська"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "Російська"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "Словацька"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "Словенська"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "Сербська"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "Шведська"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "Турецька"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "Українська"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "Китайська спрощена"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Vietnamese\n"
"Language: vi_VN\n"
@@ -1618,143 +1618,143 @@ msgstr ""
msgid "paperless application settings"
msgstr ""
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr ""
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr ""
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr ""
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr ""
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr ""
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr ""
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr ""
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr ""
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr ""
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr ""
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr ""
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr ""
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr ""
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr ""
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr ""
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr ""
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr ""
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr ""
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr ""
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr ""
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr ""
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr ""
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr ""
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr ""
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr ""
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr ""
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr ""
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr ""
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr ""
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr ""
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr ""
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr ""
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr ""
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 05:49\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Chinese Simplified\n"
"Language: zh_CN\n"
@@ -1619,143 +1619,143 @@ msgstr ""
msgid "paperless application settings"
msgstr "无纸应用设置"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "英语(美国)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "阿拉伯语"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "Afrikaans 荷兰语"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "白俄罗斯语"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "保加利亚语"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "Catalan 加泰罗尼亚语"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "捷克语"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "丹麦语"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "德语"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "Greek 希腊语"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "英语(英国)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "西班牙语"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr ""
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "已完成"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "法语"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "匈牙利语"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "意大利语"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "日语"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "韩语"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "卢森堡语"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "Norwegian 挪威语"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "荷兰语"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "波兰语"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "葡萄牙语 (巴西)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "葡萄牙语"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "罗马尼亚语"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "俄语"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "斯洛伐克语"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "斯洛语尼亚语"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "塞尔维亚语"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "瑞典语"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "土耳其语"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "乌克兰语"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "简体中文"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "繁体中文"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-17 05:45+0000\n"
"PO-Revision-Date: 2025-06-17 12:14\n"
"POT-Creation-Date: 2025-06-19 18:51+0000\n"
"PO-Revision-Date: 2025-06-19 18:52\n"
"Last-Translator: \n"
"Language-Team: Chinese Traditional\n"
"Language: zh_TW\n"
@@ -1619,143 +1619,143 @@ msgstr "設定標籤條碼對應"
msgid "paperless application settings"
msgstr "Paperless 應用程式設定"
#: paperless/settings.py:754
#: paperless/settings.py:755
msgid "English (US)"
msgstr "英文(美國)"
#: paperless/settings.py:755
#: paperless/settings.py:756
msgid "Arabic"
msgstr "阿拉伯文"
#: paperless/settings.py:756
#: paperless/settings.py:757
msgid "Afrikaans"
msgstr "南非荷蘭文"
#: paperless/settings.py:757
#: paperless/settings.py:758
msgid "Belarusian"
msgstr "白俄羅斯文"
#: paperless/settings.py:758
#: paperless/settings.py:759
msgid "Bulgarian"
msgstr "保加利亞文"
#: paperless/settings.py:759
#: paperless/settings.py:760
msgid "Catalan"
msgstr "加泰羅尼亞文"
#: paperless/settings.py:760
#: paperless/settings.py:761
msgid "Czech"
msgstr "捷克文"
#: paperless/settings.py:761
#: paperless/settings.py:762
msgid "Danish"
msgstr "丹麥文"
#: paperless/settings.py:762
#: paperless/settings.py:763
msgid "German"
msgstr "德文"
#: paperless/settings.py:763
#: paperless/settings.py:764
msgid "Greek"
msgstr "希臘文"
#: paperless/settings.py:764
#: paperless/settings.py:765
msgid "English (GB)"
msgstr "英文(英國)"
#: paperless/settings.py:765
#: paperless/settings.py:766
msgid "Spanish"
msgstr "西班牙文"
#: paperless/settings.py:766
#: paperless/settings.py:767
msgid "Persian"
msgstr "波斯文"
#: paperless/settings.py:767
#: paperless/settings.py:768
msgid "Finnish"
msgstr "芬蘭文"
#: paperless/settings.py:768
#: paperless/settings.py:769
msgid "French"
msgstr "法文"
#: paperless/settings.py:769
#: paperless/settings.py:770
msgid "Hungarian"
msgstr "匈牙利文"
#: paperless/settings.py:770
#: paperless/settings.py:771
msgid "Italian"
msgstr "義大利文"
#: paperless/settings.py:771
#: paperless/settings.py:772
msgid "Japanese"
msgstr "日文"
#: paperless/settings.py:772
#: paperless/settings.py:773
msgid "Korean"
msgstr "韓文"
#: paperless/settings.py:773
#: paperless/settings.py:774
msgid "Luxembourgish"
msgstr "盧森堡文"
#: paperless/settings.py:774
#: paperless/settings.py:775
msgid "Norwegian"
msgstr "挪威文"
#: paperless/settings.py:775
#: paperless/settings.py:776
msgid "Dutch"
msgstr "荷蘭文"
#: paperless/settings.py:776
#: paperless/settings.py:777
msgid "Polish"
msgstr "波蘭文"
#: paperless/settings.py:777
#: paperless/settings.py:778
msgid "Portuguese (Brazil)"
msgstr "葡萄牙文(巴西)"
#: paperless/settings.py:778
#: paperless/settings.py:779
msgid "Portuguese"
msgstr "葡萄牙文"
#: paperless/settings.py:779
#: paperless/settings.py:780
msgid "Romanian"
msgstr "羅馬尼亞文"
#: paperless/settings.py:780
#: paperless/settings.py:781
msgid "Russian"
msgstr "俄文"
#: paperless/settings.py:781
#: paperless/settings.py:782
msgid "Slovak"
msgstr "斯洛伐克文"
#: paperless/settings.py:782
#: paperless/settings.py:783
msgid "Slovenian"
msgstr "斯洛維尼亞文"
#: paperless/settings.py:783
#: paperless/settings.py:784
msgid "Serbian"
msgstr "塞爾維亞文"
#: paperless/settings.py:784
#: paperless/settings.py:785
msgid "Swedish"
msgstr "瑞典文"
#: paperless/settings.py:785
#: paperless/settings.py:786
msgid "Turkish"
msgstr "土耳其文"
#: paperless/settings.py:786
#: paperless/settings.py:787
msgid "Ukrainian"
msgstr "烏克蘭文"
#: paperless/settings.py:787
#: paperless/settings.py:788
msgid "Chinese Simplified"
msgstr "簡體中文"
#: paperless/settings.py:788
#: paperless/settings.py:789
msgid "Chinese Traditional"
msgstr "繁體中文"

View File

@@ -169,3 +169,36 @@ class GeneralConfig(BaseConfig):
self.app_title = app_config.app_title or None
self.app_logo = app_config.app_logo.url if app_config.app_logo else None
@dataclasses.dataclass
class AIConfig(BaseConfig):
"""
AI related settings that require global scope
"""
ai_enabled: bool = dataclasses.field(init=False)
llm_embedding_backend: str = dataclasses.field(init=False)
llm_embedding_model: str = dataclasses.field(init=False)
llm_backend: str = dataclasses.field(init=False)
llm_model: str = dataclasses.field(init=False)
llm_api_key: str = dataclasses.field(init=False)
llm_url: str = dataclasses.field(init=False)
def __post_init__(self) -> None:
app_config = self._get_config_instance()
self.ai_enabled = app_config.ai_enabled or settings.AI_ENABLED
self.llm_embedding_backend = (
app_config.llm_embedding_backend or settings.LLM_EMBEDDING_BACKEND
)
self.llm_embedding_model = (
app_config.llm_embedding_model or settings.LLM_EMBEDDING_MODEL
)
self.llm_backend = app_config.llm_backend or settings.LLM_BACKEND
self.llm_model = app_config.llm_model or settings.LLM_MODEL
self.llm_api_key = app_config.llm_api_key or settings.LLM_API_KEY
self.llm_url = app_config.llm_url or settings.LLM_URL
def llm_index_enabled(self) -> bool:
return self.ai_enabled and self.llm_embedding_backend

Some files were not shown because too many files have changed in this diff Show More