Merge branch 'main' into redesign

This commit is contained in:
Anthony Stirling 2024-05-09 19:49:06 +01:00 committed by GitHub
commit 29ec42bc35
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
42 changed files with 425 additions and 248 deletions

View file

@ -5,7 +5,7 @@ FROM alpine:20240329
COPY scripts /scripts COPY scripts /scripts
COPY pipeline /pipeline COPY pipeline /pipeline
COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/ COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto/ #COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto/
COPY build/libs/*.jar app.jar COPY build/libs/*.jar app.jar
ARG VERSION_TAG ARG VERSION_TAG

View file

@ -51,8 +51,16 @@ For Fedora-based systems use this command:
sudo dnf install -y git automake autoconf libtool leptonica-devel pkg-config zlib-devel make gcc-c++ java-17-openjdk python3 python3-pip sudo dnf install -y git automake autoconf libtool leptonica-devel pkg-config zlib-devel make gcc-c++ java-17-openjdk python3 python3-pip
``` ```
For non-root users with Nix Package Manager, use the following command:
```bash
nix-channel --update
nix-env -iA nixpkgs.jdk17 nixpkgs.git nixpkgs.python38 nixpkgs.gnumake nixpkgs.libgcc nixpkgs.automake nixpkgs.autoconf nixpkgs.libtool nixpkgs.pkg-config nixpkgs.zlib nixpkgs.leptonica
```
### Step 2: Clone and Build jbig2enc (Only required for certain OCR functionality) ### Step 2: Clone and Build jbig2enc (Only required for certain OCR functionality)
For Debian and Fedora, you can build it from source using the following commands:
```bash ```bash
mkdir ~/.git mkdir ~/.git
cd ~/.git &&\ cd ~/.git &&\
@ -64,6 +72,11 @@ make &&\
sudo make install sudo make install
``` ```
For Nix, you will face `Leptonica not detected`. Bypass this by installing it directly using the following command:
```bash
nix-env -iA nixpkgs.jbig2enc
```
### Step 3: Install Additional Software ### Step 3: Install Additional Software
Next we need to install LibreOffice for conversions, ocrmypdf for OCR, and opencv for pattern recognition functionality. Next we need to install LibreOffice for conversions, ocrmypdf for OCR, and opencv for pattern recognition functionality.
@ -105,6 +118,13 @@ sudo dnf install -y libreoffice-writer libreoffice-calc libreoffice-impress unpa
pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint
``` ```
For Nix:
```bash
nix-env -iA nixpkgs.unpaper nixpkgs.libreoffice nixpkgs.ocrmypdf nixpkgs.poppler_utils
pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint
```
### Step 4: Clone and Build Stirling-PDF ### Step 4: Clone and Build Stirling-PDF
```bash ```bash
@ -115,13 +135,12 @@ chmod +x ./gradlew &&\
./gradlew build ./gradlew build
``` ```
### Step 5: Move jar to desired location ### Step 5: Move jar to desired location
After the build process, a `.jar` file will be generated in the `build/libs` directory. After the build process, a `.jar` file will be generated in the `build/libs` directory.
You can move this file to a desired location, for example, `/opt/Stirling-PDF/`. You can move this file to a desired location, for example, `/opt/Stirling-PDF/`.
You must also move the Script folder within the Stirling-PDF repo that you have downloaded to this directory. You must also move the Script folder within the Stirling-PDF repo that you have downloaded to this directory.
This folder is required for the python scripts using OpenCV This folder is required for the python scripts using OpenCV.
```bash ```bash
sudo mkdir /opt/Stirling-PDF &&\ sudo mkdir /opt/Stirling-PDF &&\
@ -129,19 +148,25 @@ sudo mv ./build/libs/Stirling-PDF-*.jar /opt/Stirling-PDF/ &&\
sudo mv scripts /opt/Stirling-PDF/ &&\ sudo mv scripts /opt/Stirling-PDF/ &&\
echo "Scripts installed." echo "Scripts installed."
``` ```
For non-root users, you can just keep the jar in the main directory of Stirling-PDF using the following command:
```bash
mv ./build/libs/Stirling-PDF-*.jar ./Stirling-PDF-*.jar
```
### Step 6: Other files ### Step 6: Other files
#### OCR #### OCR
If you plan to use the OCR (Optical Character Recognition) functionality, you might need to install language packs for Tesseract if running non-english scanning. If you plan to use the OCR (Optical Character Recognition) functionality, you might need to install language packs for Tesseract if running non-english scanning.
##### Installing Language Packs ##### Installing Language Packs
Easiest is to use the langpacks provided by your repositories. Skip the other steps Easiest is to use the langpacks provided by your repositories. Skip the other steps.
Manual: Manual:
1. Download the desired language pack(s) by selecting the `.traineddata` file(s) for the language(s) you need. 1. Download the desired language pack(s) by selecting the `.traineddata` file(s) for the language(s) you need.
2. Place the `.traineddata` files in the Tesseract tessdata directory: `/usr/share/tessdata` 2. Place the `.traineddata` files in the Tesseract tessdata directory: `/usr/share/tessdata`
3. 3. Please view [OCRmyPDF install guide](https://ocrmypdf.readthedocs.io/en/latest/installation.html) for more info.
Please view [OCRmyPDF install guide](https://ocrmypdf.readthedocs.io/en/latest/installation.html) for more info.
**IMPORTANT:** DO NOT REMOVE EXISTING `eng.traineddata`, IT'S REQUIRED. **IMPORTANT:** DO NOT REMOVE EXISTING `eng.traineddata`, IT'S REQUIRED.
Debian based systems, install languages with this command: Debian based systems, install languages with this command:
@ -171,14 +196,38 @@ dnf search -C tesseract-langpack-
rpm -qa | grep tesseract-langpack | sed 's/tesseract-langpack-//g' rpm -qa | grep tesseract-langpack | sed 's/tesseract-langpack-//g'
``` ```
Nix:
```bash
nix-env -iA nixpkgs.tesseract
```
**Note:** Nix Package Manager pre-installs almost all the language packs when tesseract is installed.
### Step 7: Run Stirling-PDF ### Step 7: Run Stirling-PDF
Those who have pushed to the root directory, run the following commands:
```bash ```bash
./gradlew bootRun ./gradlew bootRun
or or
java -jar /opt/Stirling-PDF/Stirling-PDF-*.jar java -jar /opt/Stirling-PDF/Stirling-PDF-*.jar
``` ```
Since libreoffice, soffice, and conversion tools have their dbus_tmp_dir set as `dbus_tmp_dir="/run/user/$(id -u)/libreoffice-dbus"`, you might get the following error when using their endpoints:
```
[Thread-7] INFO s.s.SPDF.utils.ProcessExecutor - mkdir: cannot create directory /run/user/1501: Permission denied
```
To resolve this, before starting the Stirling-PDF, you have to set the environment variable to a directory you have write access to by using the following commands:
```bash
mkdir temp
export DBUS_SESSION_BUS_ADDRESS="unix:path=./temp"
./gradlew bootRun
or
java -jar ./Stirling-PDF-*.jar
```
### Step 8: Adding a Desktop icon ### Step 8: Adding a Desktop icon
This will add a modified Appstarter to your Appmenu. This will add a modified Appstarter to your Appmenu.
@ -202,7 +251,19 @@ EOF
Note: Currently the app will run in the background until manually closed. Note: Currently the app will run in the background until manually closed.
### Optional: Run Stirling-PDF as a service ### Optional: Changing the host and port of the application:
To override the default configuration, you can add the following to `/.git/Stirling-PDF/configs/custom_settings.yml` file:
```bash
server:
host: 0.0.0.0
port: 3000
```
**Note:** This file is created after the first application launch. To have it before that, you can create the directory and add the file yourself.
### Optional: Run Stirling-PDF as a service (requires root).
First create a .env file, where you can store environment variables: First create a .env file, where you can store environment variables:
``` ```
@ -239,6 +300,7 @@ WantedBy=multi-user.target
``` ```
Notify systemd that it has to rebuild its internal service database (you have to run this command every time you make a change in the service file): Notify systemd that it has to rebuild its internal service database (you have to run this command every time you make a change in the service file):
``` ```
sudo systemctl daemon-reload sudo systemctl daemon-reload
``` ```

View file

@ -166,7 +166,7 @@ Stirling PDF currently supports 27!
| English (English) (en_GB) | ![100%](https://geps.dev/progress/100) | | English (English) (en_GB) | ![100%](https://geps.dev/progress/100) |
| English (US) (en_US) | ![100%](https://geps.dev/progress/100) | | English (US) (en_US) | ![100%](https://geps.dev/progress/100) |
| Arabic (العربية) (ar_AR) | ![42%](https://geps.dev/progress/42) | | Arabic (العربية) (ar_AR) | ![42%](https://geps.dev/progress/42) |
| German (Deutsch) (de_DE) | ![100%](https://geps.dev/progress/100) | | German (Deutsch) (de_DE) | ![99%](https://geps.dev/progress/99) |
| French (Français) (fr_FR) | ![91%](https://geps.dev/progress/91) | | French (Français) (fr_FR) | ![91%](https://geps.dev/progress/91) |
| Spanish (Español) (es_ES) | ![99%](https://geps.dev/progress/99) | | Spanish (Español) (es_ES) | ![99%](https://geps.dev/progress/99) |
| Simplified Chinese (简体中文) (zh_CN) | ![98%](https://geps.dev/progress/98) | | Simplified Chinese (简体中文) (zh_CN) | ![98%](https://geps.dev/progress/98) |
@ -178,16 +178,16 @@ Stirling PDF currently supports 27!
| Romanian (Română) (ro_RO) | ![41%](https://geps.dev/progress/41) | | Romanian (Română) (ro_RO) | ![41%](https://geps.dev/progress/41) |
| Korean (한국어) (ko_KR) | ![91%](https://geps.dev/progress/91) | | Korean (한국어) (ko_KR) | ![91%](https://geps.dev/progress/91) |
| Portuguese Brazilian (Português) (pt_BR) | ![64%](https://geps.dev/progress/64) | | Portuguese Brazilian (Português) (pt_BR) | ![64%](https://geps.dev/progress/64) |
| Russian (Русский) (ru_RU) | ![91%](https://geps.dev/progress/91) | | Russian (Русский) (ru_RU) | ![90%](https://geps.dev/progress/90) |
| Basque (Euskara) (eu_ES) | ![66%](https://geps.dev/progress/66) | | Basque (Euskara) (eu_ES) | ![66%](https://geps.dev/progress/66) |
| Japanese (日本語) (ja_JP) | ![91%](https://geps.dev/progress/91) | | Japanese (日本語) (ja_JP) | ![91%](https://geps.dev/progress/91) |
| Dutch (Nederlands) (nl_NL) | ![88%](https://geps.dev/progress/88) | | Dutch (Nederlands) (nl_NL) | ![88%](https://geps.dev/progress/88) |
| Greek (Ελληνικά) (el_GR) | ![88%](https://geps.dev/progress/88) | | Greek (Ελληνικά) (el_GR) | ![89%](https://geps.dev/progress/89) |
| Turkish (Türkçe) (tr_TR) | ![99%](https://geps.dev/progress/99) | | Turkish (Türkçe) (tr_TR) | ![99%](https://geps.dev/progress/99) |
| Indonesia (Bahasa Indonesia) (id_ID) | ![82%](https://geps.dev/progress/82) | | Indonesia (Bahasa Indonesia) (id_ID) | ![82%](https://geps.dev/progress/82) |
| Hindi (हिंदी) (hi_IN) | ![82%](https://geps.dev/progress/82) | | Hindi (हिंदी) (hi_IN) | ![82%](https://geps.dev/progress/82) |
| Hungarian (Magyar) (hu_HU) | ![81%](https://geps.dev/progress/81) | | Hungarian (Magyar) (hu_HU) | ![81%](https://geps.dev/progress/81) |
| Bulgarian (Български) (bg_BG) | ![75%](https://geps.dev/progress/75) | | Bulgarian (Български) (bg_BG) | ![98%](https://geps.dev/progress/98) |
| Sebian Latin alphabet (Srpski) (sr_LATN_RS) | ![84%](https://geps.dev/progress/84) | | Sebian Latin alphabet (Srpski) (sr_LATN_RS) | ![84%](https://geps.dev/progress/84) |
| Ukrainian (Українська) (uk_UA) | ![90%](https://geps.dev/progress/90) | | Ukrainian (Українська) (uk_UA) | ![90%](https://geps.dev/progress/90) |
@ -271,7 +271,7 @@ For those wanting to use Stirling-PDFs backend API to link with their own custom
### Prerequisites: ### Prerequisites:
- User must have the folder ./configs volumed within docker so that it is retained during updates. - User must have the folder ./configs volumed within docker so that it is retained during updates.
- Docker uses must download the security jar version by setting ``DOCKER_ENABLE_SECURITY`` to ``true`` in environment variables. - Docker users must download the security jar version by setting ``DOCKER_ENABLE_SECURITY`` to ``true`` in environment variables.
- Then either enable login via the settings.yml file or via setting ``SECURITY_ENABLE_LOGIN`` to ``true`` - Then either enable login via the settings.yml file or via setting ``SECURITY_ENABLE_LOGIN`` to ``true``
- Now the initial user will be generated with username ``admin`` and password ``stirling``. On login you will be forced to change the password to a new one. You can also use the environment variables ``SECURITY_INITIALLOGIN_USERNAME`` and ``SECURITY_INITIALLOGIN_PASSWORD`` to set your own straight away (Recommended to remove them after user creation). - Now the initial user will be generated with username ``admin`` and password ``stirling``. On login you will be forced to change the password to a new one. You can also use the environment variables ``SECURITY_INITIALLOGIN_USERNAME`` and ``SECURITY_INITIALLOGIN_PASSWORD`` to set your own straight away (Recommended to remove them after user creation).

View file

@ -12,7 +12,7 @@ plugins {
import com.github.jk1.license.render.* import com.github.jk1.license.render.*
group = 'stirling.software' group = 'stirling.software'
version = '0.23.1' version = '0.23.2'
sourceCompatibility = '17' sourceCompatibility = '17'
repositories { repositories {

View file

@ -1,5 +1,5 @@
apiVersion: v2 apiVersion: v2
appVersion: 0.23.1 appVersion: 0.23.2
description: locally hosted web application that allows you to perform various operations description: locally hosted web application that allows you to perform various operations
on PDF files on PDF files
home: https://github.com/Stirling-Tools/Stirling-PDF home: https://github.com/Stirling-Tools/Stirling-PDF

View file

@ -13,8 +13,6 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
@ -76,6 +74,7 @@ public class ConfigInitializer
Files.createFile(customSettingsPath); Files.createFile(customSettingsPath);
} }
} }
private static Map<String, String> extractEntries(List<String> lines) { private static Map<String, String> extractEntries(List<String> lines) {
Map<String, String> entries = new HashMap<>(); Map<String, String> entries = new HashMap<>();
StringBuilder currentEntry = new StringBuilder(); StringBuilder currentEntry = new StringBuilder();
@ -121,8 +120,10 @@ public class ConfigInitializer
return entries; return entries;
} }
private static List<String> mergeConfigs(
private static List<String> mergeConfigs(List<String> templateLines, Map<String, String> templateEntries, Map<String, String> userEntries) { List<String> templateLines,
Map<String, String> templateEntries,
Map<String, String> userEntries) {
List<String> mergedLines = new ArrayList<>(); List<String> mergedLines = new ArrayList<>();
Set<String> handledKeys = new HashSet<>(); Set<String> handledKeys = new HashSet<>();
@ -141,7 +142,8 @@ public class ConfigInitializer
blockIndent = indentLevel; blockIndent = indentLevel;
} }
if (userEntries.containsKey(currentBlockKey) && !handledKeys.contains(currentBlockKey)) { if (userEntries.containsKey(currentBlockKey)
&& !handledKeys.contains(currentBlockKey)) {
mergedLines.add(userEntries.get(currentBlockKey)); mergedLines.add(userEntries.get(currentBlockKey));
handledKeys.add(currentBlockKey); handledKeys.add(currentBlockKey);
} else if (!handledKeys.contains(currentBlockKey)) { } else if (!handledKeys.contains(currentBlockKey)) {
@ -152,8 +154,6 @@ public class ConfigInitializer
return mergedLines; return mergedLines;
} }
private static List<String> cleanInvalidYamlEntries(List<String> lines) { private static List<String> cleanInvalidYamlEntries(List<String> lines) {
List<String> cleanedLines = new ArrayList<>(); List<String> cleanedLines = new ArrayList<>();
for (int i = 0; i < lines.size(); i++) { for (int i = 0; i < lines.size(); i++) {

View file

@ -85,6 +85,7 @@ public class InitialSecuritySetup {
// Write back to the file // Write back to the file
Files.write(path, lines); Files.write(path, lines);
} }
private boolean isValidUUID(String uuid) { private boolean isValidUUID(String uuid) {
if (uuid == null) { if (uuid == null) {
return false; return false;
@ -96,5 +97,4 @@ public class InitialSecuritySetup {
return false; return false;
} }
} }
} }

View file

@ -1,5 +1,6 @@
package stirling.software.SPDF.config.security; package stirling.software.SPDF.config.security;
import io.github.pixee.security.Newlines;
import java.io.IOException; import java.io.IOException;
import java.time.Duration; import java.time.Duration;
import java.util.Map; import java.util.Map;
@ -125,12 +126,12 @@ public class UserBasedRateLimitingFilter extends OncePerRequestFilter {
ConsumptionProbe probe = userBucket.tryConsumeAndReturnRemaining(1); ConsumptionProbe probe = userBucket.tryConsumeAndReturnRemaining(1);
if (probe.isConsumed()) { if (probe.isConsumed()) {
response.setHeader("X-Rate-Limit-Remaining", Long.toString(probe.getRemainingTokens())); response.setHeader("X-Rate-Limit-Remaining", Newlines.stripAll(Long.toString(probe.getRemainingTokens())));
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
} else { } else {
long waitForRefill = probe.getNanosToWaitForRefill() / 1_000_000_000; long waitForRefill = probe.getNanosToWaitForRefill() / 1_000_000_000;
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value()); response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
response.setHeader("X-Rate-Limit-Retry-After-Seconds", String.valueOf(waitForRefill)); response.setHeader("X-Rate-Limit-Retry-After-Seconds", Newlines.stripAll(String.valueOf(waitForRefill)));
response.getWriter().write("Rate limit exceeded for POST requests."); response.getWriter().write("Rate limit exceeded for POST requests.");
} }
} }

View file

@ -0,0 +1,84 @@
package stirling.software.SPDF.controller.api.misc;
import java.awt.image.BufferedImage;
import java.io.IOException;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.image.JPEGFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.PdfMetadata;
import stirling.software.SPDF.model.api.misc.FlattenRequest;
import stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@RequestMapping("/api/v1/misc")
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class FlattenController {
@PostMapping(consumes = "multipart/form-data", value = "/flatten")
@Operation(
summary = "Flatten PDF form fields or full page",
description =
"Flattening just PDF form fields or converting each page to images to make text unselectable. Input: PDF, Output: PDF. Type: SISO")
public ResponseEntity<byte[]> flatten(@ModelAttribute FlattenRequest request) throws Exception {
MultipartFile file = request.getFileInput();
PDDocument document = Loader.loadPDF(file.getBytes());
PdfMetadata metadata = PdfUtils.extractMetadataFromPdf(document);
Boolean flattenOnlyForms = request.getFlattenOnlyForms();
if (Boolean.TRUE.equals(flattenOnlyForms)) {
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
if (acroForm != null) {
acroForm.flatten();
}
return WebResponseUtils.pdfDocToWebResponse(
document, Filenames.toSimpleFileName(file.getOriginalFilename()));
} else {
// flatten whole page aka convert each page to image and readd it (making text
// unselectable)
PDFRenderer pdfRenderer = new PDFRenderer(document);
PDDocument newDocument = new PDDocument();
int numPages = document.getNumberOfPages();
for (int i = 0; i < numPages; i++) {
try {
BufferedImage image = pdfRenderer.renderImageWithDPI(i, 300, ImageType.RGB);
PDPage page = new PDPage();
page.setMediaBox(document.getPage(i).getMediaBox());
newDocument.addPage(page);
try (PDPageContentStream contentStream =
new PDPageContentStream(newDocument, page)) {
PDImageXObject pdImage = JPEGFactory.createFromImage(newDocument, image);
float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight();
contentStream.drawImage(pdImage, 0, 0, pageWidth, pageHeight);
}
} catch (IOException e) {
e.printStackTrace();
}
}
PdfUtils.setMetadataToPdf(newDocument, metadata);
return WebResponseUtils.pdfDocToWebResponse(
newDocument, Filenames.toSimpleFileName(file.getOriginalFilename()));
}
}
}

View file

@ -0,0 +1,17 @@
package stirling.software.SPDF.model.api.misc;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import stirling.software.SPDF.model.api.PDFFile;
@Data
@EqualsAndHashCode(callSuper = true)
public class FlattenRequest extends PDFFile {
@Schema(
description =
"True to flatten only the forms, false to flatten full PDF (Convert page to image)")
private Boolean flattenOnlyForms;
}

View file

@ -58,10 +58,10 @@ public class ProcessExecutor {
long timeoutMinutes = long timeoutMinutes =
switch (key) { switch (key) {
case LIBRE_OFFICE -> 30; case LIBRE_OFFICE -> 30;
case PDFTOHTML -> 5; case PDFTOHTML -> 20;
case OCR_MY_PDF -> 30; case OCR_MY_PDF -> 30;
case PYTHON_OPENCV -> 30; case PYTHON_OPENCV -> 30;
case GHOSTSCRIPT -> 5; case GHOSTSCRIPT -> 30;
case WEASYPRINT -> 30; case WEASYPRINT -> 30;
case INSTALL_APP -> 60; case INSTALL_APP -> 60;
case CALIBRE -> 30; case CALIBRE -> 30;

View file

@ -24,8 +24,8 @@ spring.devtools.livereload.enabled=true
spring.thymeleaf.encoding=UTF-8 spring.thymeleaf.encoding=UTF-8
server.connection-timeout=${SYSTEM_CONNECTIONTIMEOUTMINUTES:5m} server.connection-timeout=${SYSTEM_CONNECTIONTIMEOUTMINUTES:20m}
spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:300000} spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:1200000}
spring.resources.static-locations=file:customFiles/static/ spring.resources.static-locations=file:customFiles/static/
#spring.thymeleaf.prefix=file:/customFiles/templates/,classpath:/templates/ #spring.thymeleaf.prefix=file:/customFiles/templates/,classpath:/templates/

View file

@ -698,6 +698,7 @@ repair.submit=الإصلاح
#flatten #flatten
flatten.title=تسطيح flatten.title=تسطيح
flatten.header=تسوية ملفات PDF flatten.header=تسوية ملفات PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=تسطيح flatten.submit=تسطيح

View file

@ -11,17 +11,17 @@ imgPrompt=Изберете изображение(я)
genericSubmit=Подайте genericSubmit=Подайте
processTimeWarning=Предупреждение: Този процес може да отнеме до минута в зависимост от размера на файла processTimeWarning=Предупреждение: Този процес може да отнеме до минута в зависимост от размера на файла
pageOrderPrompt=Персонализиран ред на страниците (Въведете разделен със запетаи списък с номера на страници или функции като 2n+1): pageOrderPrompt=Персонализиран ред на страниците (Въведете разделен със запетаи списък с номера на страници или функции като 2n+1):
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) : pageSelectionPrompt=Персонализиран избор на страница (Въведете списък с номера на страници 1,5,6, разделени със запетая, или функции като 2n+1) :
goToPage=Давай goToPage=Давай
true=Вярно true=Вярно
false=Невярно false=Невярно
unknown=Непознат unknown=Непознат
save=Съхранете save=Съхранете
saveToBrowser=Save to Browser saveToBrowser=Съхраняване в браузъра
close=Затворете close=Затворете
filesSelected=избрани файлове filesSelected=избрани файлове
noFavourites=Няма добавени любими noFavourites=Няма добавени любими
downloadComplete=Download Complete downloadComplete=Свалянето завършено
bored=Отекчени сте да чакате? bored=Отекчени сте да чакате?
alphabet=Азбука alphabet=Азбука
downloadPdf=Изтеглете PDF downloadPdf=Изтеглете PDF
@ -45,57 +45,58 @@ red=Червено
green=Зелено green=Зелено
blue=Синьо blue=Синьо
custom=Персонализиране... custom=Персонализиране...
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems! WorkInProgess=Работата е в ход, може да не работи или да има грешки, моля, докладвайте за проблеми!
poweredBy=Powered by poweredBy=Задвижван чрез
yes=Yes yes=Да
no=No no=Не
changedCredsMessage=Идентификационните данни са променени! changedCredsMessage=Идентификационните данни са променени!
notAuthenticatedMessage=Потребителят не е автентикиран. notAuthenticatedMessage=Потребителят не е автентикиран.
userNotFoundMessage=Потребителят не е намерен userNotFoundMessage=Потребителят не е намерен
incorrectPasswordMessage=Текущата парола е неправилна. incorrectPasswordMessage=Текущата парола е неправилна.
usernameExistsMessage=Новият потребител вече съществува. usernameExistsMessage=Новият потребител вече съществува.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers. invalidUsernameMessage=Невалидно потребителско име, потребителското име трябва да съдържа само букви и цифри.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Не може да се изтрие вписания в момента потребител.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=Потребителското име не съществува и не може да бъде изтрито.
downgradeCurrentUserMessage=Не може да се понижи ролята на текущия потребител downgradeCurrentUserMessage=Не може да се понижи ролята на текущия потребител
downgradeCurrentUserLongMessage=Не може да се понижи ролята на текущия потребител. Следователно текущият потребител няма да бъде показан. downgradeCurrentUserLongMessage=Не може да се понижи ролята на текущия потребител. Следователно текущият потребител няма да бъде показан.
error=Error error=Грешка
oops=Oops! oops=Опаа!
help=Help help=Помощ
goHomepage=Go to Homepage goHomepage=Отидете на началната страница
joinDiscord=Join our Discord server joinDiscord=Присъединете се към нашия Discord сървър
seeDockerHub=See Docker Hub seeDockerHub=Погледнете Docker Hub
visitGithub=Visit Github Repository visitGithub=Посетете Github Repository
donate=Donate donate=Направете дарение
color=Color color=Цвят
sponsor=Sponsor sponsor=Спонсор
info=Info info=Info
############### ###############
# Pipeline # # Pipeline #
############### ###############
pipeline.header=Pipeline Menu (Beta) pipeline.header=Pipeline Меню (Бета)
pipeline.uploadButton=Upload Custom pipeline.uploadButton=Качване на персонализиран
pipeline.configureButton=Configure pipeline.configureButton=Настройка
pipeline.defaultOption=Custom pipeline.defaultOption=Персонализиран
pipeline.submitButton=Submit pipeline.submitButton=Подайте
pipeline.help=Pipeline Help pipeline.help=Pipeline Помощ
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Помощ за сканиране на папки
###################### ######################
# Pipeline Options # # Pipeline Options #
###################### ######################
pipelineOptions.header=Pipeline Configuration pipelineOptions.header=Pipeline Конфигурация
pipelineOptions.pipelineNameLabel=Pipeline Name pipelineOptions.pipelineNameLabel=Pipeline име
pipelineOptions.saveSettings=Save Operation Settings pipelineOptions.saveSettings=Запазете настройките за работа
pipelineOptions.pipelineNamePrompt=Enter pipeline name here pipelineOptions.pipelineNamePrompt=Въведете името на pipeline тук
pipelineOptions.selectOperation=Select Operation pipelineOptions.selectOperation=Избор на операция
pipelineOptions.addOperationButton=Add operation pipelineOptions.addOperationButton=Добавяне на операция
pipelineOptions.pipelineHeader=Pipeline: pipelineOptions.pipelineHeader=Pipeline:
pipelineOptions.saveButton=Download pipelineOptions.saveButton=Изтегли
pipelineOptions.validateButton=Validate pipelineOptions.validateButton=Валидирай
@ -119,7 +120,7 @@ navbar.sections.edit=View & Edit
############# #############
settings.title=Настройки settings.title=Настройки
settings.update=Налична актуализация settings.update=Налична актуализация
settings.updateAvailable={0} is the current installed version. A new version ({1}) is available. settings.updateAvailable={0} е текущата инсталирана версия. Налична е нова версия ({1}).
settings.appVersion=Версия на приложението: settings.appVersion=Версия на приложението:
settings.downloadOption.title=Изберете опция за изтегляне (за изтегляния на един файл без да е архивиран): settings.downloadOption.title=Изберете опция за изтегляне (за изтегляния на един файл без да е архивиран):
settings.downloadOption.1=Отваряне в същия прозорец settings.downloadOption.1=Отваряне в същия прозорец
@ -128,13 +129,13 @@ settings.downloadOption.3=Изтегли файл
settings.zipThreshold=Архивирайте файловете, когато броят на изтеглените файлове надвишава settings.zipThreshold=Архивирайте файловете, когато броят на изтеглените файлове надвишава
settings.signOut=Изход settings.signOut=Изход
settings.accountSettings=Настройки на акаунта settings.accountSettings=Настройки на акаунта
settings.bored.help=Enables easter egg game settings.bored.help=Активира игра с великденски яйца
settings.cacheInputs.name=Save form inputs settings.cacheInputs.name=Запазете въведените формуляри
settings.cacheInputs.help=Enable to store previously used inputs for future runs settings.cacheInputs.help=Активирайте за съхраняване на предишни използвани въведени данни за бъдещи изпълнения
changeCreds.title=Промяна на идентификационните данни changeCreds.title=Промяна на идентификационните данни
changeCreds.header=Актуализирайте данните за акаунта си changeCreds.header=Актуализирайте данните за акаунта си
changeCreds.changePassword=You are using default login credentials. Please enter a new password changeCreds.changePassword=Използвате идентификационни данни за вход по подразбиране. Моля, въведете нова парола
changeCreds.newUsername=Ново потребителско име changeCreds.newUsername=Ново потребителско име
changeCreds.oldPassword=Текуща парола changeCreds.oldPassword=Текуща парола
changeCreds.newPassword=Нова парола changeCreds.newPassword=Нова парола
@ -160,8 +161,8 @@ account.syncTitle=Синхронизиране на настройките на
account.settingsCompare=Сравняване на настройките: account.settingsCompare=Сравняване на настройките:
account.property=Свойство account.property=Свойство
account.webBrowserSettings=Уеб-браузър настройки account.webBrowserSettings=Уеб-браузър настройки
account.syncToBrowser=Синхронизиране на акаунт -> Бразър account.syncToBrowser=Синхронизиране на акаунт -> Браузър
account.syncToAccount=Синхронизиране на акаунт <- Бразър account.syncToAccount=Синхронизиране на акаунт <- Браузър
adminUserSettings.title=Настройки за потребителски контрол adminUserSettings.title=Настройки за потребителски контрол
@ -169,15 +170,15 @@ adminUserSettings.header=Настройки за администраторск
adminUserSettings.admin=Администратор adminUserSettings.admin=Администратор
adminUserSettings.user=Потребител adminUserSettings.user=Потребител
adminUserSettings.addUser=Добавяне на нов потребител adminUserSettings.addUser=Добавяне на нов потребител
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Потребителското име трябва да съдържа само букви и цифри, без интервали или специални знаци.
adminUserSettings.roles=Роли adminUserSettings.roles=Роли
adminUserSettings.role=Роля adminUserSettings.role=Роля
adminUserSettings.actions=Действия adminUserSettings.actions=Действия
adminUserSettings.apiUser=Ограничен API потребител adminUserSettings.apiUser=Ограничен API потребител
adminUserSettings.extraApiUser=Additional Limited API User adminUserSettings.extraApiUser=Допълнителен ограничен API потребител
adminUserSettings.webOnlyUser=Само за уеб-потребител adminUserSettings.webOnlyUser=Само за уеб-потребител
adminUserSettings.demoUser=Demo User (No custom settings) adminUserSettings.demoUser=Демо потребител (без персонализирани настройки)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Вътрешен API потребител
adminUserSettings.forceChange=Принудете потребителя да промени потребителското име/парола при влизане adminUserSettings.forceChange=Принудете потребителя да промени потребителското име/парола при влизане
adminUserSettings.submit=Съхранете потребителя adminUserSettings.submit=Съхранете потребителя
adminUserSettings.changeUserRole=Промяна на ролята на потребителя adminUserSettings.changeUserRole=Промяна на ролята на потребителя
@ -186,12 +187,12 @@ adminUserSettings.changeUserRole=Промяна на ролята на потр
# HOME-PAGE # # HOME-PAGE #
############# #############
home.desc=Вашето локално хоствано обслужване на едно място за всички ваши PDF нужди. home.desc=Вашето локално хоствано обслужване на едно място за всички ваши PDF нужди.
home.searchBar=Search for features... home.searchBar=Търсене на функции...
home.viewPdf.title=View PDF home.viewPdf.title=Преглед на PDF
home.viewPdf.desc=View, annotate, add text or images home.viewPdf.desc=Преглеждайте, коментирайте, добавяйте текст или изображения
viewPdf.tags=view,read,annotate,text,image viewPdf.tags=преглед,четене,анотиране,текст,изображение
home.multiTool.title=PDF Мулти инструмент home.multiTool.title=PDF Мулти инструмент
home.multiTool.desc=Обединяване, завъртане, пренареждане и премахване на страници home.multiTool.desc=Обединяване, завъртане, пренареждане и премахване на страници
@ -262,7 +263,7 @@ home.fileToPDF.desc=Преобразуване почти всеки файл к
fileToPDF.tags=трансформация,формат,документ,изображение,слайд,текст,преобразуване,офис,документи,word,excel,powerpoint fileToPDF.tags=трансформация,формат,документ,изображение,слайд,текст,преобразуване,офис,документи,word,excel,powerpoint
home.ocr.title=OCR / Почистващи сканирания home.ocr.title=OCR / Почистващи сканирания
home.ocr.desc=Cleanup сканира и открива текст от изображения към PDF и го добавя отново като текст. home.ocr.desc=Почистване, сканира и открива текст от изображения към PDF и го добавя отново като текст.
ocr.tags=разпознаване,текст,изображение,сканиране,четене,идентифициране,откриване,редактиране ocr.tags=разпознаване,текст,изображение,сканиране,четене,идентифициране,откриване,редактиране
@ -315,9 +316,9 @@ home.removeBlanks.title=Премахване на празни страници
home.removeBlanks.desc=Открива и премахва празни страници от документ home.removeBlanks.desc=Открива и премахва празни страници от документ
removeBlanks.tags=почистване,рационализиране,без съдържание,организиране removeBlanks.tags=почистване,рационализиране,без съдържание,организиране
home.removeAnnotations.title=Remove Annotations home.removeAnnotations.title=Премахване на анотации
home.removeAnnotations.desc=Removes all comments/annotations from a PDF home.removeAnnotations.desc=Премахва всички коментари/анотации от PDF
removeAnnotations.tags=comments,highlight,notes,markup,remove removeAnnotations.tags=коментари, маркиране, бележки, маркиране, премахване
home.compare.title=Сравнете home.compare.title=Сравнете
home.compare.desc=Сравнява и показва разликите между 2 PDF документа home.compare.desc=Сравнява и показва разликите между 2 PDF документа
@ -359,7 +360,7 @@ home.autoSplitPDF.title=Автоматично разделяне на стра
home.autoSplitPDF.desc=Автоматично разделяне на сканиран PDF файл с QR код за разделяне на физически сканирани страници home.autoSplitPDF.desc=Автоматично разделяне на сканиран PDF файл с QR код за разделяне на физически сканирани страници
autoSplitPDF.tags=QR-базиран,отделен,сканиране-сегмент,организиране autoSplitPDF.tags=QR-базиран,отделен,сканиране-сегмент,организиране
home.sanitizePdf.title=Дезинфекцирай home.sanitizePdf.title=Дезинфенкцирам
home.sanitizePdf.desc=Премахване на скриптове и други елементи от PDF файлове home.sanitizePdf.desc=Премахване на скриптове и други елементи от PDF файлове
sanitizePdf.tags=чисти,сигурни,безопасни,премахване-заплахи sanitizePdf.tags=чисти,сигурни,безопасни,премахване-заплахи
@ -401,35 +402,35 @@ home.autoRedact.desc=Автоматично редактира (зачерняв
autoRedact.tags=Редактиране,Скриване,затъмняване,черен,маркер,скрит autoRedact.tags=Редактиране,Скриване,затъмняване,черен,маркер,скрит
home.tableExtraxt.title=PDF to CSV home.tableExtraxt.title=PDF to CSV
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV home.tableExtraxt.desc=Извлича таблици от PDF, като ги конвертира в CSV
tableExtraxt.tags=CSV,Table Extraction,extract,convert tableExtraxt.tags=CSV,извличане на таблица,извличане,конвертиране
home.autoSizeSplitPDF.title=Auto Split by Size/Count home.autoSizeSplitPDF.title=Автоматично разделяне по размер/брой
home.autoSizeSplitPDF.desc=Split a single PDF into multiple documents based on size, page count, or document count home.autoSizeSplitPDF.desc=Разделете един PDF на множество документи въз основа на размер, брой страници или брой документи
autoSizeSplitPDF.tags=pdf,split,document,organization autoSizeSplitPDF.tags=pdf,разделяне,документ,организация
home.overlay-pdfs.title=Overlay PDFs home.overlay-pdfs.title=Наслагване PDF-и
home.overlay-pdfs.desc=Overlays PDFs on-top of another PDF home.overlay-pdfs.desc=Наслагва PDF файлове върху друг PDF
overlay-pdfs.tags=Overlay overlay-pdfs.tags=Наслагване
home.split-by-sections.title=Split PDF by Sections home.split-by-sections.title=Разделяне на PDF по секции
home.split-by-sections.desc=Divide each page of a PDF into smaller horizontal and vertical sections home.split-by-sections.desc=Разделете всяка страница от PDF на по-малки хоризонтални и вертикални секции
split-by-sections.tags=Section Split, Divide, Customize split-by-sections.tags=Разделяне на секция,Разделяне,Персонализиране
home.AddStampRequest.title=Add Stamp to PDF home.AddStampRequest.title=Добавяне на печат към PDF
home.AddStampRequest.desc=Add text or add image stamps at set locations home.AddStampRequest.desc=Добавете текст или добавете печати с изображения на определени места
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize AddStampRequest.tags=Печат,добавяне на изображение,централно изображение,воден знак,PDF,вграждане,персонализиране
home.PDFToBook.title=PDF to Book home.PDFToBook.title=PDF към книга
home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre home.PDFToBook.desc=Преобразува PDF във формати на книги/комикси с помощта на calibre
PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle PDFToBook.tags=Книга,комикс,calibre,конвертиране,манга,Amazon,Kindle
home.BookToPDF.title=Book to PDF home.BookToPDF.title=Книга към PDF
home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre home.BookToPDF.desc=Преобразува формати на книги/комикси в PDF с помощта на calibre
BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle BookToPDF.tags=Книга,комикс,calibre,конвертиране,манга,Amazon,Kindle
########################### ###########################
@ -476,9 +477,9 @@ pdfToSinglePage.submit=Преобразуване към единична стр
#pageExtracter #pageExtracter
pageExtracter.title=Extract Pages pageExtracter.title=Извличане на страници
pageExtracter.header=Extract Pages pageExtracter.header=Извличане на страници
pageExtracter.submit=Extract pageExtracter.submit=Извличане
pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1) pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
@ -508,40 +509,40 @@ URLToPDF.credit=Използва WeasyPrint
#html-to-pdf #html-to-pdf
HTMLToPDF.title=HTML към PDF HTMLToPDF.title=HTML към PDF
HTMLToPDF.header=HTML към PDF HTMLToPDF.header=HTML към PDF
HTMLToPDF.help=Приема HTML файлове и ZIP файлове, съдържащи html/css/изображения и т.н HTMLToPDF.help=Приемане на HTML файлове и ZIP файлове, съдържащи html/css/изображения и т.н.
HTMLToPDF.submit=Преобразуване HTMLToPDF.submit=Преобразуване
HTMLToPDF.credit=Използва WeasyPrint HTMLToPDF.credit=Използва WeasyPrint
HTMLToPDF.zoom=Zoom level for displaying the website. HTMLToPDF.zoom=Ниво на мащабиране за показване на уебсайта.
HTMLToPDF.pageWidth=Width of the page in centimeters. (Blank to default) HTMLToPDF.pageWidth=Ширина на страницата в сантиметри. (Празно по подразбиране)
HTMLToPDF.pageHeight=Height of the page in centimeters. (Blank to default) HTMLToPDF.pageHeight=Височина на страницата в сантиметри. (Празно по подразбиране)
HTMLToPDF.marginTop=Top margin of the page in millimeters. (Blank to default) HTMLToPDF.marginTop=Горно поле на страницата в милиметри. (Празно по подразбиране)
HTMLToPDF.marginBottom=Bottom margin of the page in millimeters. (Blank to default) HTMLToPDF.marginBottom=Долно поле на страницата в милиметри. (Празно по подразбиране)
HTMLToPDF.marginLeft=Left margin of the page in millimeters. (Blank to default) HTMLToPDF.marginLeft=Ляво поле на страницата в милиметри. (Празно по подразбиране)
HTMLToPDF.marginRight=Right margin of the page in millimeters. (Blank to default) HTMLToPDF.marginRight=Дясно поле на страницата в милиметри. (Празно по подразбиране)
HTMLToPDF.printBackground=Render the background of websites. HTMLToPDF.printBackground=Изобразете фона на уебсайтове.
HTMLToPDF.defaultHeader=Enable Default Header (Name and page number) HTMLToPDF.defaultHeader=Активиране на горния колонтитул по подразбиране (име и номер на страница)
HTMLToPDF.cssMediaType=Change the CSS media type of the page. HTMLToPDF.cssMediaType=Променете CSS медийния тип на страницата.
HTMLToPDF.none=None HTMLToPDF.none=Няма
HTMLToPDF.print=Print HTMLToPDF.print=Печат
HTMLToPDF.screen=Screen HTMLToPDF.screen=Екран
#AddStampRequest #AddStampRequest
AddStampRequest.header=Stamp PDF AddStampRequest.header=Поставяне на печат на PDF
AddStampRequest.title=Stamp PDF AddStampRequest.title=Поставяне на печат на PDF
AddStampRequest.stampType=Stamp Type AddStampRequest.stampType=Тип печат
AddStampRequest.stampText=Stamp Text AddStampRequest.stampText=Поставяне на текст
AddStampRequest.stampImage=Stamp Image AddStampRequest.stampImage=Изображение с печат
AddStampRequest.alphabet=Alphabet AddStampRequest.alphabet=Азбука
AddStampRequest.fontSize=Font/Image Size AddStampRequest.fontSize=Размер на шрифта/изображението
AddStampRequest.rotation=Rotation AddStampRequest.rotation=Ротация
AddStampRequest.opacity=Opacity AddStampRequest.opacity=Непрозрачност
AddStampRequest.position=Position AddStampRequest.position=Позиция
AddStampRequest.overrideX=Override X Coordinate AddStampRequest.overrideX=Замяна на X координата
AddStampRequest.overrideY=Override Y Coordinate AddStampRequest.overrideY=Замяна на Y координата
AddStampRequest.customMargin=Custom Margin AddStampRequest.customMargin=Персонализиран марж
AddStampRequest.customColor=Custom Text Color AddStampRequest.customColor=Персонализиран цвят на текста
AddStampRequest.submit=Submit AddStampRequest.submit=Изпращане
#sanitizePDF #sanitizePDF
@ -630,11 +631,11 @@ scalePages.submit=Подайте
certSign.title=Подписване на сертификат certSign.title=Подписване на сертификат
certSign.header=Подпишете PDF с вашия сертификат (В процес на работа) certSign.header=Подпишете PDF с вашия сертификат (В процес на работа)
certSign.selectPDF=Изберете PDF файл за подписване: certSign.selectPDF=Изберете PDF файл за подписване:
certSign.jksNote=Note: If your certificate type is not listed below, please convert it to a Java Keystore (.jks) file using the keytool command line tool. Then, choose the .jks file option below. certSign.jksNote=Забележка: Ако вашият тип сертификат не е в списъка по-долу, моля, конвертирайте го във файл на Java Keystore (.jks) с помощта на инструмента за команден ред keytool. След това изберете опцията за .jks файл по-долу.
certSign.selectKey=Изберете вашия файл с личен ключ (формат PKCS#8, може да бъде .pem или .der): certSign.selectKey=Изберете вашия файл с личен ключ (формат PKCS#8, може да бъде .pem или .der):
certSign.selectCert=Изберете вашия файл със сертификат (формат X.509, може да бъде .pem или .der): certSign.selectCert=Изберете вашия файл със сертификат (формат X.509, може да бъде .pem или .der):
certSign.selectP12=Изберете вашия PKCS#12 Keystore файл (.p12 или .pfx) (По избор, ако е предоставен, трябва да съдържа вашия личен ключ и сертификат): certSign.selectP12=Изберете вашия PKCS#12 Keystore файл (.p12 или .pfx) (По избор, ако е предоставен, трябва да съдържа вашия личен ключ и сертификат):
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore): certSign.selectJKS=Изберете Вашия Java Keystore Файл (.jks или .keystore):
certSign.certType=Тип сертификат certSign.certType=Тип сертификат
certSign.password=Въведете вашата парола за Keystore за ключове или частен ключ (ако има): certSign.password=Въведете вашата парола за Keystore за ключове или частен ключ (ако има):
certSign.showSig=Показване на подпис certSign.showSig=Показване на подпис
@ -655,9 +656,9 @@ removeBlanks.submit=Премахване на празни места
#removeAnnotations #removeAnnotations
removeAnnotations.title=Remove Annotations removeAnnotations.title=Премахване на анотации
removeAnnotations.header=Remove Annotations removeAnnotations.header=Премахване на анотации
removeAnnotations.submit=Remove removeAnnotations.submit=Премахване
#compare #compare
@ -668,17 +669,17 @@ compare.document.2=Документ 2
compare.submit=Сравнявай compare.submit=Сравнявай
#BookToPDF #BookToPDF
BookToPDF.title=Books and Comics to PDF BookToPDF.title=Книги и комикси в PDF
BookToPDF.header=Book to PDF BookToPDF.header=Книга в PDF
BookToPDF.credit=Uses Calibre BookToPDF.credit=Използва Calibre
BookToPDF.submit=Convert BookToPDF.submit=Конвертиране
#PDFToBook #PDFToBook
PDFToBook.title=PDF to Book PDFToBook.title=PDF към книга
PDFToBook.header=PDF to Book PDFToBook.header=PDF към книга
PDFToBook.selectText.1=Format PDFToBook.selectText.1=Формат
PDFToBook.credit=Uses Calibre PDFToBook.credit=Използва Calibre
PDFToBook.submit=Convert PDFToBook.submit=Конвертиране
#sign #sign
sign.title=Подпишете sign.title=Подпишете
@ -699,6 +700,7 @@ repair.submit=Поправи
#flatten #flatten
flatten.title=Изравнете flatten.title=Изравнете
flatten.header=Изравнете PDF-и flatten.header=Изравнете PDF-и
flatten.flattenOnlyForms=Изравнете само форми
flatten.submit=Изравнете flatten.submit=Изравнете
@ -759,7 +761,7 @@ compress.selectText.1=Ръчен режим - От 1 до 4
compress.selectText.2=Ниво на оптимизация: compress.selectText.2=Ниво на оптимизация:
compress.selectText.3=4 (Ужасно за текстови изображения) compress.selectText.3=4 (Ужасно за текстови изображения)
compress.selectText.4=Автоматичен режим - Автоматично настройва качеството, за да получи PDF точен размер compress.selectText.4=Автоматичен режим - Автоматично настройва качеството, за да получи PDF точен размер
compress.selectText.5=Очакван PDF размер (напр. 25MB, 10.8MB, 25KB) compress.selectText.5=Очакван PDF размер (напр. 25МБ, 10.8МБ, 25КБ)
compress.submit=Компресиране compress.submit=Компресиране
@ -783,17 +785,17 @@ merge.submit=Обединяване
pdfOrganiser.title=Организатор на страници pdfOrganiser.title=Организатор на страници
pdfOrganiser.header=Организатор на PDF страници pdfOrganiser.header=Организатор на PDF страници
pdfOrganiser.submit=Пренареждане на страниците pdfOrganiser.submit=Пренареждане на страниците
pdfOrganiser.mode=Mode pdfOrganiser.mode=Режим
pdfOrganiser.mode.1=Custom Page Order pdfOrganiser.mode.1=Персонализиран ред на страниците
pdfOrganiser.mode.2=Reverse Order pdfOrganiser.mode.2=Обърнат ред
pdfOrganiser.mode.3=Duplex Sort pdfOrganiser.mode.3=Двустранно сортиране
pdfOrganiser.mode.4=Booklet Sort pdfOrganiser.mode.4=Сортиране на брошури
pdfOrganiser.mode.5=Side Stitch Booklet Sort pdfOrganiser.mode.5=Сортиране на брошури със страничен шев
pdfOrganiser.mode.6=Odd-Even Split pdfOrganiser.mode.6=Четно-нечетно разделяне
pdfOrganiser.mode.7=Remove First pdfOrganiser.mode.7=Премахни първо
pdfOrganiser.mode.8=Remove Last pdfOrganiser.mode.8=Премахване на последния
pdfOrganiser.mode.9=Remove First and Last pdfOrganiser.mode.9=Премахване на първия и последния
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1) pdfOrganiser.placeholder=(напр. 1,3,2 или 4-8,2,10-12 или 2n-1)
#multiTool #multiTool
@ -801,9 +803,10 @@ multiTool.title=PDF Мулти инструмент
multiTool.header=PDF Мулти инструмент multiTool.header=PDF Мулти инструмент
multiTool.uploadPrompts=File Name multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=View PDF viewPdf.title=Преглед на PDF
viewPdf.header=View PDF viewPdf.header=Преглед на PDF
#pageRemover #pageRemover
pageRemover.title=Премахване на страници pageRemover.title=Премахване на страници
@ -951,8 +954,8 @@ pdfToPDFA.title=PDF към PDF/A
pdfToPDFA.header=PDF към PDF/A pdfToPDFA.header=PDF към PDF/A
pdfToPDFA.credit=Тази услуга използва OCRmyPDF за PDF/A преобразуване. pdfToPDFA.credit=Тази услуга използва OCRmyPDF за PDF/A преобразуване.
pdfToPDFA.submit=Преобразуване pdfToPDFA.submit=Преобразуване
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=В момента не работи за няколко входа наведнъж
pdfToPDFA.outputFormat=Output format pdfToPDFA.outputFormat=Изходен формат
#PDFToWord #PDFToWord
@ -995,75 +998,75 @@ PDFToXML.submit=Преобразуване
#PDFToCSV #PDFToCSV
PDFToCSV.title=PDF ??? CSV PDFToCSV.title=PDF ??? CSV
PDFToCSV.header=PDF ??? CSV PDFToCSV.header=PDF ??? CSV
PDFToCSV.prompt=Choose page to extract table PDFToCSV.prompt=Изберете страница за извличане на таблица
PDFToCSV.submit=???????? PDFToCSV.submit=????
#split-by-size-or-count #split-by-size-or-count
split-by-size-or-count.title=Split PDF by Size or Count split-by-size-or-count.title=Разделяне на PDF по размер или брой
split-by-size-or-count.header=Split PDF by Size or Count split-by-size-or-count.header=Разделяне на PDF по размер или брой
split-by-size-or-count.type.label=Select Split Type split-by-size-or-count.type.label=Изберете тип разделяне
split-by-size-or-count.type.size=By Size split-by-size-or-count.type.size=По размер
split-by-size-or-count.type.pageCount=By Page Count split-by-size-or-count.type.pageCount=По брой страници
split-by-size-or-count.type.docCount=By Document Count split-by-size-or-count.type.docCount=По брой документи
split-by-size-or-count.value.label=Enter Value split-by-size-or-count.value.label=Въведете стойност
split-by-size-or-count.value.placeholder=Enter size (e.g., 2MB or 3KB) or count (e.g., 5) split-by-size-or-count.value.placeholder=Въведете размер (напр. 2МБ или 3КБ) или брой (напр. 5)
split-by-size-or-count.submit=Submit split-by-size-or-count.submit=Изпращане
#overlay-pdfs #overlay-pdfs
overlay-pdfs.header=Overlay PDF Files overlay-pdfs.header=Наслагване на PDF файлове
overlay-pdfs.baseFile.label=Select Base PDF File overlay-pdfs.baseFile.label=Изберете Основен PDF файл
overlay-pdfs.overlayFiles.label=Select Overlay PDF Files overlay-pdfs.overlayFiles.label=Изберете наслагване на PDF файлове
overlay-pdfs.mode.label=Select Overlay Mode overlay-pdfs.mode.label=Изберете режим на наслагване
overlay-pdfs.mode.sequential=Sequential Overlay overlay-pdfs.mode.sequential=Последователно наслагване
overlay-pdfs.mode.interleaved=Interleaved Overlay overlay-pdfs.mode.interleaved=Преплетено наслагване
overlay-pdfs.mode.fixedRepeat=Fixed Repeat Overlay overlay-pdfs.mode.fixedRepeat=Фиксирано наслагване при повторение
overlay-pdfs.counts.label=Overlay Counts (for Fixed Repeat Mode) overlay-pdfs.counts.label=Брой наслагвания (за режим на фиксирано повторение)
overlay-pdfs.counts.placeholder=Enter comma-separated counts (e.g., 2,3,1) overlay-pdfs.counts.placeholder=Въведете броя, разделени със запетая (напр. 2,3,1)
overlay-pdfs.position.label=Select Overlay Position overlay-pdfs.position.label=Изберете позиция на наслагване
overlay-pdfs.position.foreground=Foreground overlay-pdfs.position.foreground=Преден план
overlay-pdfs.position.background=Background overlay-pdfs.position.background=Фон
overlay-pdfs.submit=Submit overlay-pdfs.submit=Изпращане
#split-by-sections #split-by-sections
split-by-sections.title=Split PDF by Sections split-by-sections.title=Разделяне на PDF по секции
split-by-sections.header=Split PDF into Sections split-by-sections.header=Разделяне на PDF на секции
split-by-sections.horizontal.label=Horizontal Divisions split-by-sections.horizontal.label=Хоризонтални разделения
split-by-sections.vertical.label=Vertical Divisions split-by-sections.vertical.label=Вертикални разделения
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions split-by-sections.horizontal.placeholder=Въведете брой хоризонтални деления
split-by-sections.vertical.placeholder=Enter number of vertical divisions split-by-sections.vertical.placeholder=Въведете брой вертикални деления
split-by-sections.submit=Split PDF split-by-sections.submit=Разделяне на PDF
split-by-sections.merge=Merge Into One PDF split-by-sections.merge=Сливане в един PDF
#printFile #printFile
printFile.title=Print File printFile.title=Печат на файл
printFile.header=Print File to Printer printFile.header=Печат на файл на принтер
printFile.selectText.1=Select File to Print printFile.selectText.1=Изберете файл за печат
printFile.selectText.2=Enter Printer Name printFile.selectText.2=Въведете име на принтер
printFile.submit=Print printFile.submit=Печат
#licenses #licenses
licenses.nav=Licenses licenses.nav=Лицензи
licenses.title=3rd Party Licenses licenses.title=Лицензи на трети страни
licenses.header=3rd Party Licenses licenses.header=Лицензи на трети страни
licenses.module=Module licenses.module=Модул
licenses.version=Version licenses.version=Версия
licenses.license=License licenses.license=Лиценз
# error # error
error.sorry=Sorry for the issue! error.sorry=Извинете за проблема!
error.needHelp=Need help / Found an issue? error.needHelp=Нуждаете се от помощ / Открихте проблем?
error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord: error.contactTip=Ако все още имате проблеми, не се колебайте да се свържете с нас за помощ. Можете да изпратите запитване на нашата страница в GitHub или да се свържете с нас чрез Discord:
error.404.head=404 - Page Not Found | Oops, we tripped in the code! error.404.head=404 - Страницата не е намерена | Опа! Спънахме се в кода!
error.404.1=We can't seem to find the page you're looking for. error.404.1=Изглежда не можем да намерим страницата, която търсите.
error.404.2=Something went wrong error.404.2=Нещо се обърка
error.github=Submit a ticket on GitHub error.github=Изпратете запитване в GitHub
error.showStack=Show Stack Trace error.showStack=Покажи проследяване на стека
error.copyStack=Copy Stack Trace error.copyStack=Копиране на проследяване на стека
error.githubSubmit=GitHub - Submit a ticket error.githubSubmit=GitHub - Изпратете запитване
error.discordSubmit=Discord - Submit Support post error.discordSubmit=Discord - Изпратете запитване за поддръжка

View file

@ -699,6 +699,7 @@ repair.submit=Reparar
#flatten #flatten
flatten.title=Aplanar flatten.title=Aplanar
flatten.header=Aplana els PDF flatten.header=Aplana els PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Aplanar flatten.submit=Aplanar

View file

@ -699,6 +699,7 @@ repair.submit=Reparieren
#flatten #flatten
flatten.title=Abflachen flatten.title=Abflachen
flatten.header=PDFs reduzieren flatten.header=PDFs reduzieren
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Abflachen flatten.submit=Abflachen

View file

@ -699,6 +699,7 @@ repair.submit=Επιδιόρθωση
#flatten #flatten
flatten.title=Flatten flatten.title=Flatten
flatten.header=Flatten PDFs flatten.header=Flatten PDFs
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Flatten flatten.submit=Flatten

View file

@ -698,7 +698,8 @@ repair.submit=Repair
#flatten #flatten
flatten.title=Flatten flatten.title=Flatten
flatten.header=Flatten PDFs flatten.header=Flatten PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Flatten flatten.submit=Flatten

View file

@ -698,6 +698,7 @@ repair.submit=Repair
#flatten #flatten
flatten.title=Flatten flatten.title=Flatten
flatten.header=Flatten PDFs flatten.header=Flatten PDFs
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Flatten flatten.submit=Flatten

View file

@ -702,6 +702,7 @@ repair.submit=Reparar
#flatten #flatten
flatten.title=Aplanar flatten.title=Aplanar
flatten.header=Acoplar archivos PDF flatten.header=Acoplar archivos PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Aplanar flatten.submit=Aplanar

View file

@ -699,6 +699,7 @@ repair.submit=Konpondu
#flatten #flatten
flatten.title=Lautu flatten.title=Lautu
flatten.header=Akoplatu PDF fitxategiak flatten.header=Akoplatu PDF fitxategiak
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Lautu flatten.submit=Lautu

View file

@ -698,6 +698,7 @@ repair.submit=Réparer
#flatten #flatten
flatten.title=Rendre inerte flatten.title=Rendre inerte
flatten.header=Rendre inerte flatten.header=Rendre inerte
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Rendre inerte flatten.submit=Rendre inerte

View file

@ -699,6 +699,7 @@ repair.submit=मरम्मत
#flatten #flatten
flatten.title=समतल करें flatten.title=समतल करें
flatten.header=पीडीएफ़ समतल करें flatten.header=पीडीएफ़ समतल करें
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=समतल करें flatten.submit=समतल करें

View file

@ -699,6 +699,7 @@ repair.submit=Javítás
#flatten #flatten
flatten.title=Kiegyenlítés flatten.title=Kiegyenlítés
flatten.header=PDF-ek kiegyenlítése flatten.header=PDF-ek kiegyenlítése
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Kiegyenlítés flatten.submit=Kiegyenlítés

View file

@ -699,6 +699,7 @@ repair.submit=Perbaiki
#flatten #flatten
flatten.title=Ratakan flatten.title=Ratakan
flatten.header=Ratakan PDF flatten.header=Ratakan PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Ratakan flatten.submit=Ratakan

View file

@ -119,7 +119,7 @@ navbar.sections.edit=View & Edit
############# #############
settings.title=Impostazioni settings.title=Impostazioni
settings.update=Aggiornamento disponibile settings.update=Aggiornamento disponibile
settings.updateAvailable={0} is the current installed version. A new version ({1}) is available. settings.updateAvailable={0} è la versione attualmente installata. Una nuova versione ({1}) è disponibile.
settings.appVersion=Versione App: settings.appVersion=Versione App:
settings.downloadOption.title=Scegli opzione di download (Per file singoli non compressi): settings.downloadOption.title=Scegli opzione di download (Per file singoli non compressi):
settings.downloadOption.1=Apri in questa finestra settings.downloadOption.1=Apri in questa finestra
@ -697,8 +697,9 @@ repair.submit=Ripara
#flatten #flatten
flatten.title=Appiattisci flatten.title=Appiattire
flatten.header=Appiattisci PDF flatten.header=Appiattisci PDF
flatten.flattenOnlyForms=Appiattisci solo i moduli
flatten.submit=Appiattisci flatten.submit=Appiattisci

View file

@ -699,6 +699,7 @@ repair.submit=修復
#flatten #flatten
flatten.title=平坦化 flatten.title=平坦化
flatten.header=PDFを平坦化する flatten.header=PDFを平坦化する
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=平坦化 flatten.submit=平坦化

View file

@ -700,6 +700,7 @@ repair.submit=복구
#flatten #flatten
flatten.title=평탄화 flatten.title=평탄화
flatten.header=PDF 문서의 레이어 평탄화 flatten.header=PDF 문서의 레이어 평탄화
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=평탄화 flatten.submit=평탄화

View file

@ -699,6 +699,7 @@ repair.submit=Repareren
#flatten #flatten
flatten.title=Afvlakken flatten.title=Afvlakken
flatten.header=PDF's afvlakken flatten.header=PDF's afvlakken
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Afvlakken flatten.submit=Afvlakken

View file

@ -699,6 +699,7 @@ repair.submit=Napraw
#flatten #flatten
flatten.title=Spłaszcz flatten.title=Spłaszcz
flatten.header=Spłaszcz dokument(y) PDF flatten.header=Spłaszcz dokument(y) PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Spłaszcz flatten.submit=Spłaszcz

View file

@ -699,6 +699,7 @@ repair.submit=Reparar
#flatten #flatten
flatten.title=Achatar flatten.title=Achatar
flatten.header=Achatar PDFs flatten.header=Achatar PDFs
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Achatar flatten.submit=Achatar

View file

@ -699,6 +699,7 @@ repair.submit=Reparar
#flatten #flatten
flatten.title=Achatar flatten.title=Achatar
flatten.header=Achatar PDFs flatten.header=Achatar PDFs
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Achatar flatten.submit=Achatar

View file

@ -699,6 +699,7 @@ repair.submit=Repară
#flatten #flatten
flatten.title=Nivelare flatten.title=Nivelare
flatten.header=Nivelează documente PDF flatten.header=Nivelează documente PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Nivelează flatten.submit=Nivelează

View file

@ -700,6 +700,7 @@ repair.submit=Ремонт
#flatten #flatten
flatten.title=Сглаживание flatten.title=Сглаживание
flatten.header=Сглаживание PDF ов flatten.header=Сглаживание PDF ов
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Сгладить flatten.submit=Сгладить

View file

@ -699,6 +699,7 @@ repair.submit=Popravi
#flatten #flatten
flatten.title=Ravnanje flatten.title=Ravnanje
flatten.header=Ravnanje PDF fajlova flatten.header=Ravnanje PDF fajlova
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Ravnanje flatten.submit=Ravnanje

View file

@ -699,6 +699,7 @@ repair.submit=Reparera
#flatten #flatten
flatten.title=Platta till flatten.title=Platta till
flatten.header=Placera PDF-filer flatten.header=Placera PDF-filer
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Platta till flatten.submit=Platta till

View file

@ -699,6 +699,7 @@ repair.submit=Onar
#flatten #flatten
flatten.title=Düzleştir flatten.title=Düzleştir
flatten.header=PDF'leri Düzleştir flatten.header=PDF'leri Düzleştir
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Düzleştir flatten.submit=Düzleştir

View file

@ -694,6 +694,7 @@ repair.submit=Ремонтувати
#flatten #flatten
flatten.title=Згладжування flatten.title=Згладжування
flatten.header=Згладжування PDF flatten.header=Згладжування PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Згладити flatten.submit=Згладити

View file

@ -699,6 +699,7 @@ repair.submit=修复
#flatten #flatten
flatten.title=展平 flatten.title=展平
flatten.header=展平 PDF flatten.header=展平 PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=展平 flatten.submit=展平

View file

@ -699,6 +699,7 @@ repair.submit=修復
#flatten #flatten
flatten.title=平坦化 flatten.title=平坦化
flatten.header=PDF 平坦化 flatten.header=PDF 平坦化
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=平坦化 flatten.submit=平坦化

View file

@ -71,6 +71,7 @@
<script src="js/darkmode.js"></script> <script src="js/darkmode.js"></script>
</th:block> </th:block>
<th:block th:fragment="game"> <th:block th:fragment="game">
<dialog id="game-container-wrapper" class="game-container-wrapper" data-bs-modal> <dialog id="game-container-wrapper" class="game-container-wrapper" data-bs-modal>
<script th:inline="javascript"> <script th:inline="javascript">

View file

@ -11,41 +11,23 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6" id="bg-card"> <div class="col-md-6" id="bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon other">layers_clear</span> <span class="material-symbols-rounded tool-header-icon other">layers_clear</span>
<span class="tool-header-text" th:text="#{flatten.header}"></span> <span class="tool-header-text" th:text="#{flatten.header}"></span>
</div> </div>
<form id="pdfForm" class="mb-3"> <form method="post" enctype="multipart/form-data" th:action="@{api/v1/misc/flatten}" id="pdfForm" class="mb-3">
<div class="custom-file"> <div class="custom-file">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf', remoteCall='false')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf', remoteCall='false')}"></div>
</div> </div>
<div class="form-check ms-3">
<input type="checkbox" id="flattenOnlyForms" name="flattenOnlyForms">
<label for="flattenOnlyForms" th:text="#{flatten.flattenOnlyForms}" ></label>
</div>
</div>
<br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{flatten.submit}"></button> <button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{flatten.submit}"></button>
<script src="js/local-pdf-input-download.js"></script>
<script>
document.getElementById('pdfForm').addEventListener('submit', async (e) => {
e.preventDefault();
const { PDFDocument } = PDFLib;
const processFile = async (file) => {
const origFileUrl = URL.createObjectURL(file);
const formPdfBytes = await fetch(origFileUrl).then(res => res.arrayBuffer());
const pdfDoc = await PDFDocument.load(formPdfBytes, { ignoreEncryption: true });
const form = pdfDoc.getForm();
form.flatten();
const pdfBytes = await pdfDoc.save();
const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
const fileName = (file.name ? file.name.replace('.pdf', '') : 'pdf') + '_flattened.pdf';
return { processedData: pdfBlob, fileName };
};
await downloadFilesWithCallback(processFile);
});
</script>
</form> </form>
</div> </div>
</div> </div>