Compare commits
113 Commits
add-elemen
...
v0.19.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50ee829e5f | ||
|
|
1924dfb4f1 | ||
|
|
873a4ecb7e | ||
|
|
32da14acbf | ||
|
|
139c793b5e | ||
|
|
e717d83f75 | ||
|
|
ef12c2f892 | ||
|
|
362a7ff434 | ||
|
|
624e015315 | ||
|
|
d76752d7f6 | ||
|
|
7260e578e3 | ||
|
|
2544b762ba | ||
|
|
164d1abdbb | ||
|
|
863b48b5a9 | ||
|
|
b5e0e147ac | ||
|
|
2fe454ea47 | ||
|
|
c8458ffe50 | ||
|
|
572f9f728f | ||
|
|
6c963e1b6c | ||
|
|
770b61bb7a | ||
|
|
db64b3f71d | ||
|
|
5fad085db5 | ||
|
|
7ed8a69326 | ||
|
|
5d1786cda0 | ||
|
|
550f8b0eea | ||
|
|
b5d5b6e3e2 | ||
|
|
97b6f0eeb4 | ||
|
|
bd7e2fea0b | ||
|
|
eee7e4d707 | ||
|
|
43410de851 | ||
|
|
37c92ee9aa | ||
|
|
351cf25f86 | ||
|
|
10cb02020c | ||
|
|
5e40f00bae | ||
|
|
cebc0daf2b | ||
|
|
04f3f735fc | ||
|
|
f7ef8c32aa | ||
|
|
49f2071a93 | ||
|
|
ecb62e0c94 | ||
|
|
846ebe6dda | ||
|
|
56afd35c82 | ||
|
|
eadd513b02 | ||
|
|
97f581ad6d | ||
|
|
d96a3db60a | ||
|
|
0592bac5bf | ||
|
|
4b0df4ffd5 | ||
|
|
a244d563f2 | ||
|
|
f433e8032f | ||
|
|
23b85dc47c | ||
|
|
6a9ef7d538 | ||
|
|
c75efede79 | ||
|
|
a0212bbfb7 | ||
|
|
87efa175cb | ||
|
|
ad7150d616 | ||
|
|
6fe268adcb | ||
|
|
0c2b05eabf | ||
|
|
38ebc28108 | ||
|
|
0a08831aac | ||
|
|
2a744473f9 | ||
|
|
56ce53a966 | ||
|
|
6baf1f94c1 | ||
|
|
8a57165547 | ||
|
|
de9e9a0f84 | ||
|
|
73a55c0666 | ||
|
|
4ac5262be2 | ||
|
|
dfee149da0 | ||
|
|
fbe0a8ddcc | ||
|
|
56a1867270 | ||
|
|
c23a5ad5fb | ||
|
|
31fbeaae1d | ||
|
|
e0d79990c8 | ||
|
|
468808167c | ||
|
|
5af5794dfe | ||
|
|
1d470691a5 | ||
|
|
f32832f70d | ||
|
|
cd0464092a | ||
|
|
c67eaf2b4d | ||
|
|
b1f80bc9f6 | ||
|
|
f3742ebeb6 | ||
|
|
adc7b9606b | ||
|
|
aa34257080 | ||
|
|
0f126eaf81 | ||
|
|
7389543af6 | ||
|
|
9795c68220 | ||
|
|
7ffa447cbc | ||
|
|
d755fd1861 | ||
|
|
e273294360 | ||
|
|
827ed62761 | ||
|
|
ee96d2a0e3 | ||
|
|
044a779a7c | ||
|
|
03a8f45128 | ||
|
|
b5423f3434 | ||
|
|
88c993367f | ||
|
|
04acdb3b02 | ||
|
|
cd3cc15888 | ||
|
|
76e6a23674 | ||
|
|
4fbfd0bae4 | ||
|
|
b74819cf6c | ||
|
|
a5ad9e13fe | ||
|
|
328e873344 | ||
|
|
39045df785 | ||
|
|
d83bd1ae94 | ||
|
|
143b770882 | ||
|
|
d91c600925 | ||
|
|
cbac784c57 | ||
|
|
f535387ac4 | ||
|
|
739dcc1327 | ||
|
|
3864e130cc | ||
|
|
5b0145fa47 | ||
|
|
7dfeb4bb0f | ||
|
|
eda91cc556 | ||
|
|
c853465d1d | ||
|
|
6ca9001fe6 |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1,3 +1,5 @@
|
||||
* text=auto eol=lf
|
||||
|
||||
# Ignore all JavaScript files in a directory
|
||||
src/main/resources/static/pdfjs/* linguist-vendored
|
||||
src/main/resources/static/pdfjs/** linguist-vendored
|
||||
|
||||
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
@@ -9,3 +9,7 @@ updates:
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/" # Location of Dockerfile
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
48
.github/workflows/licenses-update.yml
vendored
Normal file
48
.github/workflows/licenses-update.yml
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
name: License Report Workflow
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'build.gradle'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
generate-license-report:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'adopt'
|
||||
|
||||
- name: Run Gradle Command
|
||||
run: ./gradlew clean generateLicenseReport
|
||||
|
||||
- name: Move and Rename License File
|
||||
run: |
|
||||
mv build/reports/dependency-license/index.json src/main/resources/static/3rdPartyLicenses.json
|
||||
|
||||
- name: Check for Changes
|
||||
id: git-check
|
||||
run: |
|
||||
git add src/main/resources/static/3rdPartyLicenses.json
|
||||
git diff --staged --exit-code || echo "changes=true" >> $GITHUB_ENV
|
||||
|
||||
- name: Commit and Push Changes
|
||||
if: env.changes == 'true'
|
||||
run: |
|
||||
git config --global user.name 'Stirling-PDF-Bot'
|
||||
git config --global user.email 'Stirling-PDF-Bot@stirlingtools.com'
|
||||
git commit -m "Update 3rd Party Licenses"
|
||||
git push
|
||||
|
||||
3
.github/workflows/push-docker.yml
vendored
3
.github/workflows/push-docker.yml
vendored
@@ -6,6 +6,9 @@ on:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
jobs:
|
||||
push:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
4
.github/workflows/releaseArtifacts.yml
vendored
4
.github/workflows/releaseArtifacts.yml
vendored
@@ -3,7 +3,9 @@ name: Release Artifacts
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
jobs:
|
||||
push:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
56
.github/workflows/test.yml
vendored
Normal file
56
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
name: Docker Compose Tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/**'
|
||||
- '**.gradle'
|
||||
- '!src/main/java/resources/messages*'
|
||||
- 'exampleYmlFiles/**'
|
||||
- 'Dockerfile'
|
||||
- 'Dockerfile**'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Java 17
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'adopt'
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: Run Docker Compose Tests
|
||||
run: |
|
||||
chmod +x ./gradlew
|
||||
|
||||
- name: Get version number
|
||||
id: versionNumber
|
||||
run: echo "::set-output name=versionNumber::$(./gradlew printVersion --quiet | tail -1)"
|
||||
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildx-${{ steps.versionNumber.outputs.versionNumber }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-
|
||||
|
||||
- name: Install Docker Compose
|
||||
run: |
|
||||
sudo curl -L "https://github.com/docker/compose/releases/download/v2.6.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
||||
sudo chmod +x /usr/local/bin/docker-compose
|
||||
|
||||
|
||||
- name: Run Docker Compose Tests
|
||||
run: |
|
||||
chmod +x ./test.sh
|
||||
./test.sh
|
||||
@@ -6,7 +6,8 @@ FROM ubuntu:latest AS base
|
||||
# JDK for app
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
openjdk-17-jre
|
||||
openjdk-17-jre && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Doc conversion
|
||||
RUN apt-get update && \
|
||||
@@ -18,7 +19,8 @@ RUN apt-get update && \
|
||||
libreoffice-impress \
|
||||
python3-uno \
|
||||
curl \
|
||||
unoconv
|
||||
unoconv && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
# OCR MY PDF (unpaper for descew and other advanced featues)
|
||||
@@ -30,21 +32,12 @@ apt-get update && \
|
||||
python3-pip \
|
||||
ocrmypdf \
|
||||
unpaper && \
|
||||
pip install --upgrade pip && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
mv /usr/share/tesseract-ocr /usr/share/tesseract-ocr-original && \
|
||||
pip install --no-cache-dir --upgrade pip && \
|
||||
pip install --no-cache-dir --upgrade ocrmypdf && \
|
||||
pip install --no-cache-dir --upgrade pillow==10.0.1 reportlab==3.6.13 wheel==0.38.1 setuptools==65.5.1 pyjwt==2.4.0 cryptography==39.0.1
|
||||
|
||||
|
||||
#CV and HTML
|
||||
RUN pip install --no-cache-dir opencv-python-headless WeasyPrint
|
||||
|
||||
|
||||
# cleanup and etc
|
||||
RUN rm -rf /var/lib/apt/lists/* && \
|
||||
mkdir /usr/share/tesseract-ocr-original && \
|
||||
cp -r /usr/share/tesseract-ocr/* /usr/share/tesseract-ocr-original && \
|
||||
rm -rf /usr/share/tesseract-ocr
|
||||
|
||||
|
||||
|
||||
|
||||
41
FolderScanning.md
Normal file
41
FolderScanning.md
Normal file
@@ -0,0 +1,41 @@
|
||||
## User Guide for Local Directory Scanning and File Processing
|
||||
|
||||
### Whilst Pipelines are in alpha...
|
||||
You must enable this alpha functionality by setting
|
||||
```
|
||||
system:
|
||||
enableAlphaFunctionality: true
|
||||
```
|
||||
To true like in the above for your `/config/settings.yml` file, after restarting Stirling-PDF you should see both UI and folder scanning enabled.
|
||||
|
||||
### Setting Up Watched Folders:
|
||||
- Create a folder where you want your files to be monitored. This is your 'watched folder'.
|
||||
- The default directory for this is `./pipeline/watchedFolders/`
|
||||
- Place any directories you want to be scanned into this folder, this folder should contain multiple folders each for their own tasks and pipelines.
|
||||
|
||||
### Configuring Processing with JSON Files:
|
||||
- In each directory you want processed (e.g `./pipeline/watchedFolders/officePrinter`), include a JSON configuration file.
|
||||
- This JSON file should specify how you want the files in the directory to be handled (e.g., what operations to perform on them) which can be made, configured and downloaded from Stirling-PDF Pipeline interface.r
|
||||
|
||||
### Automatic Scanning and Processing:
|
||||
- The system automatically checks the watched folder every minute for new directories and files to process.
|
||||
- When a directory with a valid JSON configuration file is found, it begins processing the files inside as per the configuration.
|
||||
|
||||
### Processing Steps:
|
||||
- Files in each directory are processed according to the instructions in the JSON file.
|
||||
- This might involve file conversions, data filtering, renaming files, etc. If the output of a step is a zip, this zip will be automatically unzipped as it passes to next process.
|
||||
|
||||
### Results and Output:
|
||||
- After processing, the results are saved in a specified output location. This could be a different folder or location as defined in the JSON file or the default location `./pipeline/finishedFolders/`.
|
||||
- Each processed file is named and organized according to the rules set in the JSON configuration.
|
||||
|
||||
### Completion and Cleanup:
|
||||
- Once processing is complete, the original files in the watched folder's directory are removed.
|
||||
- You can find the processed files in the designated output location.
|
||||
|
||||
### Error Handling:
|
||||
- If there's an error during processing, the system will not delete the original files, allowing you to check and retry if necessary.
|
||||
|
||||
### User Interaction:
|
||||
- As a user, your main tasks are to set up the watched folders, place directories with files for processing, and create the corresponding JSON configuration files.
|
||||
- The system handles the rest, including scanning, processing, and outputting results.
|
||||
@@ -1,4 +1,4 @@
|
||||
<p align="center"><img src="https://raw.githubusercontent.com/Frooodle/Stirling-PDF/main/docs/stirling.png" width="80" ><br><h1 align="center">Stirling-PDF</h1>
|
||||
<p align="center"><img src="https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/main/docs/stirling.png" width="80" ><br><h1 align="center">Stirling-PDF</h1>
|
||||
</p>
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ Fork Stirling-PDF and make a new branch out of Main
|
||||
|
||||
Then add reference to the language in the navbar by adding a new language entry to the dropdown
|
||||
|
||||
https://github.com/Frooodle/Stirling-PDF/blob/main/src/main/resources/templates/fragments/languages.html
|
||||
https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/templates/fragments/languages.html
|
||||
and add a flag svg file to
|
||||
https://github.com/Frooodle/Stirling-PDF/tree/main/src/main/resources/static/images/flags
|
||||
https://github.com/Stirling-Tools/Stirling-PDF/tree/main/src/main/resources/static/images/flags
|
||||
Any SVG flags are fine, i got most of mine from [here](https://flagicons.lipis.dev/)
|
||||
If your language isnt represented by a flag just find whichever closely matches it, such as for Arabic i chose Saudi Arabia
|
||||
|
||||
@@ -25,7 +25,7 @@ The data-language-code is the code used to reference the file in the next step.
|
||||
|
||||
Start by copying the existing english property file
|
||||
|
||||
[https://github.com/Frooodle/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties](https://github.com/Frooodle/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties)
|
||||
[https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties)
|
||||
|
||||
Copy and rename it to messages_{your data-language-code here}.properties, in the polish example you would set the name to messages_pl_PL.properties
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint
|
||||
|
||||
```bash
|
||||
cd ~/.git &&\
|
||||
git clone https://github.com/Frooodle/Stirling-PDF.git &&\
|
||||
git clone https://github.com/Stirling-Tools/Stirling-PDF.git &&\
|
||||
cd Stirling-PDF &&\
|
||||
chmod +x ./gradlew &&\
|
||||
./gradlew build
|
||||
|
||||
42
PipelineFeature.md
Normal file
42
PipelineFeature.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Pipeline Configuration and Usage Tutorial
|
||||
|
||||
## Whilst Pipelines are in alpha...
|
||||
You must enable this alpha functionality by setting
|
||||
```
|
||||
system:
|
||||
enableAlphaFunctionality: true
|
||||
```
|
||||
To true like in the above for your `/config/settings.yml` file, after restarting Stirling-PDF you should see both UI and folder scanning enabled.
|
||||
|
||||
|
||||
## Steps to Configure and Use Your Pipeline
|
||||
|
||||
1. **Access Configuration**
|
||||
- Upon entering the screen, click on the **Configure** button.
|
||||
|
||||
2. **Enter Pipeline Name**
|
||||
- Provide a name for your pipeline in the designated field.
|
||||
|
||||
3. **Select Operations**
|
||||
- Choose the operations for your pipeline (e.g., **Split Pages**), then click **Add Operation**.
|
||||
|
||||
4. **Configure Operation Settings**
|
||||
- Input the necessary settings for each added operation. Settings are highlighted in yellow if customization is needed.
|
||||
|
||||
5. **Add More Operations**
|
||||
- You can add and adjust the order of multiple operations. Ensure each operation's settings are customized.
|
||||
|
||||
6. **Save Settings**
|
||||
- Click **Save Operation Settings** after customizing settings for each operation.
|
||||
|
||||
7. **Validate Pipeline**
|
||||
- Use the **Validation** button to check your pipeline. A green indicator signifies correct setup; a pop-out error indicates issues.
|
||||
|
||||
8. **Download Pipeline Configuration**
|
||||
- To use the configuration for folder scanning (or save it for future use and reupload it), you can also download a JSON file in this menu. You can also pre-load this for future use by placing it in ``/pipeline/defaultWebUIConfigs/``. It will then appear in the dropdown menu for all users to use.
|
||||
|
||||
9. **Submit Files for Processing**
|
||||
- If your pipeline is correctly set up close the configure menu, input the files and hit **Submit**.
|
||||
|
||||
10. **Note on Web UI Limitations**
|
||||
- The current web UI version does not support operations that require multiple different types of inputs, such as adding a separate image to a PDF.
|
||||
40
README.md
40
README.md
@@ -1,14 +1,14 @@
|
||||
<p align="center"><img src="https://raw.githubusercontent.com/Frooodle/Stirling-PDF/main/docs/stirling.png" width="80" ><br><h1 align="center">Stirling-PDF</h1>
|
||||
<p align="center"><img src="https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/main/docs/stirling.png" width="80" ><br><h1 align="center">Stirling-PDF</h1>
|
||||
</p>
|
||||
|
||||
[](https://hub.docker.com/r/frooodle/s-pdf)
|
||||
[](https://discord.gg/Cn8pWhQRxZ)
|
||||
[](https://github.com/Frooodle/Stirling-PDF/)
|
||||
[](https://github.com/Frooodle/stirling-pdf)
|
||||
[](https://github.com/Stirling-Tools/Stirling-PDF/)
|
||||
[](https://github.com/Stirling-Tools/stirling-pdf)
|
||||
[](https://www.paypal.com/paypalme/froodleplex)
|
||||
[](https://github.com/sponsors/Frooodle)
|
||||
|
||||
[](https://cloud.digitalocean.com/apps/new?repo=https://github.com/Frooodle/Stirling-PDF/tree/digitalOcean&refcode=c3210994b1af)
|
||||
[](https://cloud.digitalocean.com/apps/new?repo=https://github.com/Stirling-Tools/Stirling-PDF/tree/digitalOcean&refcode=c3210994b1af)
|
||||
|
||||
This is a powerful locally hosted web based PDF manipulation tool using docker that allows you to perform various operations on PDF files, such as splitting merging, converting, reorganizing, adding images, rotating, compressing, and more. This locally hosted web application started as a 100% ChatGPT-made application and has evolved to include a wide range of features to handle all your PDF needs.
|
||||
|
||||
@@ -22,10 +22,10 @@ Please feel free to submit feature requests or report bugs either through GitHub
|
||||
|
||||
## Features
|
||||
- Dark mode support.
|
||||
- Custom download options (see [here](https://github.com/Frooodle/Stirling-PDF/blob/main/images/settings.png) for example)
|
||||
- Custom download options (see [here](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/images/settings.png) for example)
|
||||
- Parallel file processing and downloads
|
||||
- API for integration with external scripts
|
||||
- Optional Login and Authentication support (see [here](https://github.com/Frooodle/Stirling-PDF/tree/main#login-authentication) for documentation)
|
||||
- Optional Login and Authentication support (see [here](https://github.com/Stirling-Tools/Stirling-PDF/tree/main#login-authentication) for documentation)
|
||||
|
||||
|
||||
## **PDF Features**
|
||||
@@ -80,29 +80,29 @@ Please feel free to submit feature requests or report bugs either through GitHub
|
||||
- Get all information on a PDF to view or export as JSON.
|
||||
|
||||
|
||||
For a overview of the tasks and the technology each uses please view [Endpoint-groups.md](https://github.com/Frooodle/Stirling-PDF/blob/main/Endpoint-groups.md)
|
||||
For a overview of the tasks and the technology each uses please view [Endpoint-groups.md](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Endpoint-groups.md)
|
||||
Hosted instance/demo of the app can be seen [here](https://pdf.adminforge.de/) hosted by the team at adminforge.de
|
||||
|
||||
## Technologies used
|
||||
- Spring Boot + Thymeleaf
|
||||
- PDFBox
|
||||
- [PDFBox](https://github.com/apache/pdfbox/tree/trunk)
|
||||
- [LibreOffice](https://www.libreoffice.org/discover/libreoffice/) for advanced conversions
|
||||
- [OcrMyPdf](https://github.com/ocrmypdf/OCRmyPDF)
|
||||
- HTML, CSS, JavaScript
|
||||
- Docker
|
||||
- PDF.js
|
||||
- PDF-LIB.js
|
||||
- [PDF.js](https://github.com/mozilla/pdf.js)
|
||||
- [PDF-LIB.js](https://github.com/Hopding/pdf-lib)
|
||||
|
||||
## How to use
|
||||
|
||||
### Locally
|
||||
Please view https://github.com/Frooodle/Stirling-PDF/blob/main/LocalRunGuide.md
|
||||
Please view https://github.com/Stirling-Tools/Stirling-PDF/blob/main/LocalRunGuide.md
|
||||
|
||||
### Docker / Podman
|
||||
https://hub.docker.com/r/frooodle/s-pdf
|
||||
|
||||
Stirling PDF has 3 different versions, a Full version, Lite, and ultra-Lite. Depending on the types of features you use you may want a smaller image to save on space.
|
||||
To see what the different versions offer please look at our [version mapping](https://github.com/Frooodle/Stirling-PDF/blob/main/Version-groups.md)
|
||||
To see what the different versions offer please look at our [version mapping](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Version-groups.md)
|
||||
For people that don't mind about space optimization just use the latest tag.
|
||||

|
||||

|
||||
@@ -144,17 +144,18 @@ services:
|
||||
Note: Podman is CLI-compatible with Docker, so simply replace "docker" with "podman".
|
||||
|
||||
## Enable OCR/Compression feature
|
||||
Please view https://github.com/Frooodle/Stirling-PDF/blob/main/HowToUseOCR.md
|
||||
Please view https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToUseOCR.md
|
||||
|
||||
## Want to add your own language?
|
||||
Stirling PDF currently supports 21!
|
||||
Stirling PDF currently supports 26!
|
||||
- English (English) (en_GB)
|
||||
- English (US) (en_US)
|
||||
- Arabic (العربية) (ar_AR)
|
||||
- German (Deutsch) (de_DE)
|
||||
- French (Français) (fr_FR)
|
||||
- Spanish (Español) (es_ES)
|
||||
- Chinese (简体中文) (zh_CN)
|
||||
- Simplified Chinese (简体中文) (zh_CN)
|
||||
- Traditional Chinese (繁體中文) (zh_TW)
|
||||
- Catalan (Català) (ca_CA)
|
||||
- Italian (Italiano) (it_IT)
|
||||
- Swedish (Svenska) (sv_SE)
|
||||
@@ -170,9 +171,12 @@ Stirling PDF currently supports 21!
|
||||
- Turkish (Türkçe) (tr_TR)
|
||||
- Indonesia (Bahasa Indonesia) (id_ID)
|
||||
- Hindi (हिंदी) (hi_IN)
|
||||
- Hungarian (Magyar) (hu_HU)
|
||||
- Bulgarian (Български) (bg_BG)
|
||||
- Sebian Latin alphabet (Srpski) (sr-Latn-RS)
|
||||
|
||||
If you want to add your own language to Stirling-PDF please refer
|
||||
https://github.com/Frooodle/Stirling-PDF/blob/main/HowToAddNewLanguage.md
|
||||
https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md
|
||||
|
||||
And please create a PR to merge it back in so others can use it!
|
||||
|
||||
@@ -224,7 +228,7 @@ metrics:
|
||||
enabled: true # 'true' to enable Info APIs endpoints (view http://localhost:8080/swagger-ui/index.html#/API to learn more), 'false' to disable
|
||||
```
|
||||
### Extra notes
|
||||
- Endpoints. Currently, the endpoints ENDPOINTS_TO_REMOVE and GROUPS_TO_REMOVE can include comma separate lists of endpoints and groups to disable as example ENDPOINTS_TO_REMOVE=img-to-pdf,remove-pages would disable both image-to-pdf and remove pages, GROUPS_TO_REMOVE=LibreOffice Would disable all things that use LibreOffice. You can see a list of all endpoints and groups [here](https://github.com/Frooodle/Stirling-PDF/blob/main/Endpoint-groups.md)
|
||||
- Endpoints. Currently, the endpoints ENDPOINTS_TO_REMOVE and GROUPS_TO_REMOVE can include comma separate lists of endpoints and groups to disable as example ENDPOINTS_TO_REMOVE=img-to-pdf,remove-pages would disable both image-to-pdf and remove pages, GROUPS_TO_REMOVE=LibreOffice Would disable all things that use LibreOffice. You can see a list of all endpoints and groups [here](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Endpoint-groups.md)
|
||||
- customStaticFilePath. Customise static files such as the app logo by placing files in the /customFiles/static/ directory. An example of customising app logo is placing a /customFiles/static/favicon.svg to override current SVG. This can be used to change any images/icons/css/fonts/js etc in Stirling-PDF
|
||||
|
||||
### Environment only parameters
|
||||
@@ -234,7 +238,7 @@ metrics:
|
||||
|
||||
## API
|
||||
For those wanting to use Stirling-PDFs backend API to link with their own custom scripting to edit PDFs you can view all existing API documentation
|
||||
[here](https://app.swaggerhub.com/apis-docs/Frooodle/Stirling-PDF/) or navigate to /swagger-ui/index.html of your stirling-pdf instance for your versions documentation (Or by following the API button in your settings of Stirling-PDF)
|
||||
[here](https://app.swaggerhub.com/apis-docs/Stirling-Tools/Stirling-PDF/) or navigate to /swagger-ui/index.html of your stirling-pdf instance for your versions documentation (Or by following the API button in your settings of Stirling-PDF)
|
||||
|
||||
|
||||
## Login authentication
|
||||
|
||||
29
build.gradle
29
build.gradle
@@ -1,21 +1,30 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'org.springframework.boot' version '3.1.2'
|
||||
id 'org.springframework.boot' version '3.2.1'
|
||||
id 'io.spring.dependency-management' version '1.1.3'
|
||||
id 'org.springdoc.openapi-gradle-plugin' version '1.8.0'
|
||||
id "io.swagger.swaggerhub" version "1.3.2"
|
||||
id 'edu.sc.seis.launch4j' version '3.0.5'
|
||||
id 'com.diffplug.spotless' version '6.23.3'
|
||||
id 'com.github.jk1.dependency-license-report' version '2.5'
|
||||
}
|
||||
|
||||
import com.github.jk1.license.render.*
|
||||
|
||||
group = 'stirling.software'
|
||||
version = '0.18.1'
|
||||
version = '0.19.1'
|
||||
sourceCompatibility = '17'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
|
||||
|
||||
licenseReport {
|
||||
renderers = [new JsonReportRenderer()]
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
@@ -80,17 +89,19 @@ dependencies {
|
||||
//security updates
|
||||
implementation 'ch.qos.logback:logback-classic:1.4.14'
|
||||
implementation 'ch.qos.logback:logback-core:1.4.14'
|
||||
implementation 'org.springframework:spring-webmvc:6.0.15'
|
||||
implementation 'org.springframework:spring-webmvc:6.1.2'
|
||||
|
||||
implementation 'org.yaml:snakeyaml:2.1'
|
||||
implementation 'org.yaml:snakeyaml:2.2'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web:3.2.1'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.2.1'
|
||||
|
||||
if (System.getenv('DOCKER_ENABLE_SECURITY') != 'false') {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-security:3.2.1'
|
||||
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.RELEASE'
|
||||
implementation "org.springframework.boot:spring-boot-starter-data-jpa"
|
||||
implementation "com.h2database:h2"
|
||||
implementation "org.springframework.boot:spring-boot-starter-data-jpa:3.2.1"
|
||||
|
||||
//2.2.x requires rebuild of DB file.. need migration path
|
||||
implementation "com.h2database:h2:2.1.214"
|
||||
}
|
||||
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test:3.2.1'
|
||||
@@ -122,15 +133,15 @@ dependencies {
|
||||
//general PDF
|
||||
|
||||
// https://mvnrepository.com/artifact/com.opencsv/opencsv
|
||||
implementation ('com.opencsv:opencsv:5.7.1') {
|
||||
implementation ('com.opencsv:opencsv:5.9') {
|
||||
exclude group: 'commons-logging', module: 'commons-logging'
|
||||
}
|
||||
|
||||
implementation ('org.apache.pdfbox:pdfbox:2.0.29'){
|
||||
implementation ('org.apache.pdfbox:pdfbox:2.0.30'){
|
||||
exclude group: 'commons-logging', module: 'commons-logging'
|
||||
}
|
||||
|
||||
implementation ('org.apache.pdfbox:xmpbox:2.0.29'){
|
||||
implementation ('org.apache.pdfbox:xmpbox:2.0.30'){
|
||||
exclude group: 'commons-logging', module: 'commons-logging'
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
apiVersion: v2
|
||||
appVersion: 0.14.2
|
||||
description: locally hosted web application that allows you to perform various operations on PDF files
|
||||
home: https://github.com/Frooodle/Stirling-PDF
|
||||
home: https://github.com/Stirling-Tools/Stirling-PDF
|
||||
keywords:
|
||||
- stirling-pdf
|
||||
- helm
|
||||
- charts repo
|
||||
maintainers:
|
||||
- name: Frooodle
|
||||
url: https://github.com/Frooodle/Stirling-PDF
|
||||
- name: Stirling-Tools
|
||||
url: https://github.com/Stirling-Tools/Stirling-PDF
|
||||
name: stirling-pdf-chart
|
||||
sources:
|
||||
- https://github.com/Frooodle/Stirling-PDF
|
||||
- https://github.com/Stirling-Tools/Stirling-PDF
|
||||
version: 1.0.0
|
||||
|
||||
31
exampleYmlFiles/docker-compose-latest-lite-security.yml
Normal file
31
exampleYmlFiles/docker-compose-latest-lite-security.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
version: '3.3'
|
||||
services:
|
||||
stirling-pdf:
|
||||
container_name: Stirling-PDF-Lite-Security
|
||||
image: frooodle/s-pdf:latest-lite
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 2G
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP' && curl -fL http://localhost:8080/ | grep -q 'Please sign in'"]
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 16
|
||||
ports:
|
||||
- 8080:8080
|
||||
volumes:
|
||||
- /stirling/latest/data:/usr/share/tesseract-ocr/5/tessdata:rw
|
||||
- /stirling/latest/config:/configs:rw
|
||||
- /stirling/latest/logs:/logs:rw
|
||||
environment:
|
||||
DOCKER_ENABLE_SECURITY: "true"
|
||||
SECURITY_ENABLELOGIN: "true"
|
||||
SYSTEM_DEFAULTLOCALE: en_US
|
||||
UI_APPNAME: Stirling-PDF-Lite
|
||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF-Lite Latest with Security
|
||||
UI_APPNAMENAVBAR: Stirling-PDF-Lite Latest
|
||||
SYSTEM_MAXFILESIZE: "100"
|
||||
METRICS_ENABLED: "true"
|
||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
||||
restart: on-failure:5
|
||||
30
exampleYmlFiles/docker-compose-latest-lite.yml
Normal file
30
exampleYmlFiles/docker-compose-latest-lite.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
version: '3.3'
|
||||
services:
|
||||
stirling-pdf:
|
||||
container_name: Stirling-PDF-Lite
|
||||
image: frooodle/s-pdf:latest-lite
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 2G
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP' && curl -fL http://localhost:8080/ | grep -qv 'Please sign in'"]
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 16
|
||||
ports:
|
||||
- 8080:8080
|
||||
volumes:
|
||||
- /stirling/latest/config:/configs:rw
|
||||
- /stirling/latest/logs:/logs:rw
|
||||
environment:
|
||||
DOCKER_ENABLE_SECURITY: "false"
|
||||
SECURITY_ENABLELOGIN: "false"
|
||||
SYSTEM_DEFAULTLOCALE: en_US
|
||||
UI_APPNAME: Stirling-PDF-Lite
|
||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF-Lite Latest
|
||||
UI_APPNAMENAVBAR: Stirling-PDF-Lite Latest
|
||||
SYSTEM_MAXFILESIZE: "100"
|
||||
METRICS_ENABLED: "true"
|
||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
||||
restart: on-failure:5
|
||||
31
exampleYmlFiles/docker-compose-latest-security.yml
Normal file
31
exampleYmlFiles/docker-compose-latest-security.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
version: '3.3'
|
||||
services:
|
||||
stirling-pdf:
|
||||
container_name: Stirling-PDF-Security
|
||||
image: frooodle/s-pdf:latest
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 4G
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP' && curl -fL http://localhost:8080/ | grep -q 'Please sign in'"]
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 16
|
||||
ports:
|
||||
- 8080:8080
|
||||
volumes:
|
||||
- /stirling/latest/data:/usr/share/tesseract-ocr/5/tessdata:rw
|
||||
- /stirling/latest/config:/configs:rw
|
||||
- /stirling/latest/logs:/logs:rw
|
||||
environment:
|
||||
DOCKER_ENABLE_SECURITY: "true"
|
||||
SECURITY_ENABLELOGIN: "true"
|
||||
SYSTEM_DEFAULTLOCALE: en_US
|
||||
UI_APPNAME: Stirling-PDF
|
||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest with Security
|
||||
UI_APPNAMENAVBAR: Stirling-PDF Latest
|
||||
SYSTEM_MAXFILESIZE: "100"
|
||||
METRICS_ENABLED: "true"
|
||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
||||
restart: on-failure:5
|
||||
@@ -0,0 +1,31 @@
|
||||
version: '3.3'
|
||||
services:
|
||||
stirling-pdf:
|
||||
container_name: Stirling-PDF-Ultra-Lite-Security
|
||||
image: frooodle/s-pdf:latest-ultra-lite
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1G
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP' && curl -fL http://localhost:8080/ | grep -q 'Please sign in'"]
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 16
|
||||
ports:
|
||||
- 8080:8080
|
||||
volumes:
|
||||
- /stirling/latest/data:/usr/share/tesseract-ocr/5/tessdata:rw
|
||||
- /stirling/latest/config:/configs:rw
|
||||
- /stirling/latest/logs:/logs:rw
|
||||
environment:
|
||||
DOCKER_ENABLE_SECURITY: "true"
|
||||
SECURITY_ENABLELOGIN: "true"
|
||||
SYSTEM_DEFAULTLOCALE: en_US
|
||||
UI_APPNAME: Stirling-PDF-Lite
|
||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF-Lite Latest with Security
|
||||
UI_APPNAMENAVBAR: Stirling-PDF-Lite Latest
|
||||
SYSTEM_MAXFILESIZE: "100"
|
||||
METRICS_ENABLED: "true"
|
||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
||||
restart: on-failure:5
|
||||
30
exampleYmlFiles/docker-compose-latest-ultra-lite.yml
Normal file
30
exampleYmlFiles/docker-compose-latest-ultra-lite.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
version: '3.3'
|
||||
services:
|
||||
stirling-pdf:
|
||||
container_name: Stirling-PDF-Ultra-Lite
|
||||
image: frooodle/s-pdf:latest-ultra-lite
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1G
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP' && curl -fL http://localhost:8080/ | grep -qv 'Please sign in'"]
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 16
|
||||
ports:
|
||||
- 8080:8080
|
||||
volumes:
|
||||
- /stirling/latest/config:/configs:rw
|
||||
- /stirling/latest/logs:/logs:rw
|
||||
environment:
|
||||
DOCKER_ENABLE_SECURITY: "false"
|
||||
SECURITY_ENABLELOGIN: "false"
|
||||
SYSTEM_DEFAULTLOCALE: en_US
|
||||
UI_APPNAME: Stirling-PDF-Ultra-lite
|
||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF-Ultra-lite Latest
|
||||
UI_APPNAMENAVBAR: Stirling-PDF-Ultra-lite Latest
|
||||
SYSTEM_MAXFILESIZE: "100"
|
||||
METRICS_ENABLED: "true"
|
||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
||||
restart: on-failure:5
|
||||
31
exampleYmlFiles/docker-compose-latest.yml
Normal file
31
exampleYmlFiles/docker-compose-latest.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
version: '3.3'
|
||||
services:
|
||||
stirling-pdf:
|
||||
container_name: Stirling-PDF
|
||||
image: frooodle/s-pdf:latest
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 4G
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP' && curl -fL http://localhost:8080/ | grep -qv 'Please sign in'"]
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 16
|
||||
ports:
|
||||
- 8080:8080
|
||||
volumes:
|
||||
- /stirling/latest/data:/usr/share/tesseract-ocr/5/tessdata:rw
|
||||
- /stirling/latest/config:/configs:rw
|
||||
- /stirling/latest/logs:/logs:rw
|
||||
environment:
|
||||
DOCKER_ENABLE_SECURITY: "false"
|
||||
SECURITY_ENABLELOGIN: "false"
|
||||
SYSTEM_DEFAULTLOCALE: en_US
|
||||
UI_APPNAME: Stirling-PDF
|
||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest
|
||||
UI_APPNAMENAVBAR: Stirling-PDF Latest
|
||||
SYSTEM_MAXFILESIZE: "100"
|
||||
METRICS_ENABLED: "true"
|
||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
||||
restart: on-failure:5
|
||||
@@ -2,13 +2,13 @@ echo "Running Stirling PDF with DOCKER_ENABLE_SECURITY=${DOCKER_ENABLE_SECURITY}
|
||||
# Check for DOCKER_ENABLE_SECURITY and download the appropriate JAR if required
|
||||
if [ "$DOCKER_ENABLE_SECURITY" = "true" ] && [ "$VERSION_TAG" != "alpha" ]; then
|
||||
if [ ! -f app-security.jar ]; then
|
||||
echo "Trying to download from: https://github.com/Frooodle/Stirling-PDF/releases/download/v$VERSION_TAG/Stirling-PDF-with-login.jar"
|
||||
curl -L -o app-security.jar https://github.com/Frooodle/Stirling-PDF/releases/download/v$VERSION_TAG/Stirling-PDF-with-login.jar
|
||||
echo "Trying to download from: https://github.com/Stirling-Tools/Stirling-PDF/releases/download/v$VERSION_TAG/Stirling-PDF-with-login.jar"
|
||||
curl -L -o app-security.jar https://github.com/Stirling-Tools/Stirling-PDF/releases/download/v$VERSION_TAG/Stirling-PDF-with-login.jar
|
||||
|
||||
# If the first download attempt failed, try with the 'v' prefix
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Trying to download from: https://github.com/Frooodle/Stirling-PDF/releases/download/$VERSION_TAG/Stirling-PDF-with-login.jar"
|
||||
curl -L -o app-security.jar https://github.com/Frooodle/Stirling-PDF/releases/download/$VERSION_TAG/Stirling-PDF-with-login.jar
|
||||
echo "Trying to download from: https://github.com/Stirling-Tools/Stirling-PDF/releases/download/$VERSION_TAG/Stirling-PDF-with-login.jar"
|
||||
curl -L -o app-security.jar https://github.com/Stirling-Tools/Stirling-PDF/releases/download/$VERSION_TAG/Stirling-PDF-with-login.jar
|
||||
fi
|
||||
|
||||
if [ $? -eq 0 ]; then # checks if curl was successful
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.pdfbox.examples.signature;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
||||
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
|
||||
import org.bouncycastle.cms.CMSException;
|
||||
import org.bouncycastle.cms.CMSTypedData;
|
||||
|
||||
/**
|
||||
* Wraps a InputStream into a CMSProcessable object for bouncy castle. It's a memory saving
|
||||
* alternative to the {@link org.bouncycastle.cms.CMSProcessableByteArray CMSProcessableByteArray}
|
||||
* class.
|
||||
*
|
||||
* @author Thomas Chojecki
|
||||
*/
|
||||
class CMSProcessableInputStream implements CMSTypedData {
|
||||
private final InputStream in;
|
||||
private final ASN1ObjectIdentifier contentType;
|
||||
|
||||
CMSProcessableInputStream(InputStream is) {
|
||||
this(new ASN1ObjectIdentifier(CMSObjectIdentifiers.data.getId()), is);
|
||||
}
|
||||
|
||||
CMSProcessableInputStream(ASN1ObjectIdentifier type, InputStream is) {
|
||||
contentType = type;
|
||||
in = is;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getContent() {
|
||||
return in;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(OutputStream out) throws IOException, CMSException {
|
||||
// read the content only one time
|
||||
in.transferTo(out);
|
||||
in.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASN1ObjectIdentifier getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2015 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.pdfbox.examples.signature;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface;
|
||||
import org.bouncycastle.cert.jcajce.JcaCertStore;
|
||||
import org.bouncycastle.cms.CMSException;
|
||||
import org.bouncycastle.cms.CMSSignedData;
|
||||
import org.bouncycastle.cms.CMSSignedDataGenerator;
|
||||
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
|
||||
import org.bouncycastle.operator.ContentSigner;
|
||||
import org.bouncycastle.operator.OperatorCreationException;
|
||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
||||
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
|
||||
|
||||
public abstract class CreateSignatureBase implements SignatureInterface {
|
||||
private PrivateKey privateKey;
|
||||
private Certificate[] certificateChain;
|
||||
private String tsaUrl;
|
||||
private boolean externalSigning;
|
||||
|
||||
/**
|
||||
* Initialize the signature creator with a keystore (pkcs12) and pin that should be used for the
|
||||
* signature.
|
||||
*
|
||||
* @param keystore is a pkcs12 keystore.
|
||||
* @param pin is the pin for the keystore / private key
|
||||
* @throws KeyStoreException if the keystore has not been initialized (loaded)
|
||||
* @throws NoSuchAlgorithmException if the algorithm for recovering the key cannot be found
|
||||
* @throws UnrecoverableKeyException if the given password is wrong
|
||||
* @throws CertificateException if the certificate is not valid as signing time
|
||||
* @throws IOException if no certificate could be found
|
||||
*/
|
||||
public CreateSignatureBase(KeyStore keystore, char[] pin)
|
||||
throws KeyStoreException,
|
||||
UnrecoverableKeyException,
|
||||
NoSuchAlgorithmException,
|
||||
IOException,
|
||||
CertificateException {
|
||||
// grabs the first alias from the keystore and get the private key. An
|
||||
// alternative method or constructor could be used for setting a specific
|
||||
// alias that should be used.
|
||||
Enumeration<String> aliases = keystore.aliases();
|
||||
String alias;
|
||||
Certificate cert = null;
|
||||
while (cert == null && aliases.hasMoreElements()) {
|
||||
alias = aliases.nextElement();
|
||||
setPrivateKey((PrivateKey) keystore.getKey(alias, pin));
|
||||
Certificate[] certChain = keystore.getCertificateChain(alias);
|
||||
if (certChain != null) {
|
||||
setCertificateChain(certChain);
|
||||
cert = certChain[0];
|
||||
if (cert instanceof X509Certificate) {
|
||||
// avoid expired certificate
|
||||
((X509Certificate) cert).checkValidity();
|
||||
|
||||
//// SigUtils.checkCertificateUsage((X509Certificate) cert);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cert == null) {
|
||||
throw new IOException("Could not find certificate");
|
||||
}
|
||||
}
|
||||
|
||||
public final void setPrivateKey(PrivateKey privateKey) {
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
public final void setCertificateChain(final Certificate[] certificateChain) {
|
||||
this.certificateChain = certificateChain;
|
||||
}
|
||||
|
||||
public Certificate[] getCertificateChain() {
|
||||
return certificateChain;
|
||||
}
|
||||
|
||||
public void setTsaUrl(String tsaUrl) {
|
||||
this.tsaUrl = tsaUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* SignatureInterface sample implementation.
|
||||
*
|
||||
* <p>This method will be called from inside of the pdfbox and create the PKCS #7 signature. The
|
||||
* given InputStream contains the bytes that are given by the byte range.
|
||||
*
|
||||
* <p>This method is for internal use only.
|
||||
*
|
||||
* <p>Use your favorite cryptographic library to implement PKCS #7 signature creation. If you
|
||||
* want to create the hash and the signature separately (e.g. to transfer only the hash to an
|
||||
* external application), read <a href="https://stackoverflow.com/questions/41767351">this
|
||||
* answer</a> or <a href="https://stackoverflow.com/questions/56867465">this answer</a>.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public byte[] sign(InputStream content) throws IOException {
|
||||
// cannot be done private (interface)
|
||||
try {
|
||||
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
|
||||
X509Certificate cert = (X509Certificate) certificateChain[0];
|
||||
ContentSigner sha1Signer =
|
||||
new JcaContentSignerBuilder("SHA256WithRSA").build(privateKey);
|
||||
gen.addSignerInfoGenerator(
|
||||
new JcaSignerInfoGeneratorBuilder(
|
||||
new JcaDigestCalculatorProviderBuilder().build())
|
||||
.build(sha1Signer, cert));
|
||||
gen.addCertificates(new JcaCertStore(Arrays.asList(certificateChain)));
|
||||
CMSProcessableInputStream msg = new CMSProcessableInputStream(content);
|
||||
CMSSignedData signedData = gen.generate(msg, false);
|
||||
if (tsaUrl != null && !tsaUrl.isEmpty()) {
|
||||
ValidationTimeStamp validation = new ValidationTimeStamp(tsaUrl);
|
||||
signedData = validation.addSignedTimeStamp(signedData);
|
||||
}
|
||||
return signedData.getEncoded();
|
||||
} catch (GeneralSecurityException
|
||||
| CMSException
|
||||
| OperatorCreationException
|
||||
| URISyntaxException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if external signing scenario should be used. If {@code false}, SignatureInterface would
|
||||
* be used for signing.
|
||||
*
|
||||
* <p>Default: {@code false}
|
||||
*
|
||||
* @param externalSigning {@code true} if external signing should be performed
|
||||
*/
|
||||
public void setExternalSigning(boolean externalSigning) {
|
||||
this.externalSigning = externalSigning;
|
||||
}
|
||||
|
||||
public boolean isExternalSigning() {
|
||||
return externalSigning;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.pdfbox.examples.signature;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.DigestInputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Base64;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
||||
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
|
||||
import org.bouncycastle.operator.DigestAlgorithmIdentifierFinder;
|
||||
import org.bouncycastle.tsp.TSPException;
|
||||
import org.bouncycastle.tsp.TimeStampRequest;
|
||||
import org.bouncycastle.tsp.TimeStampRequestGenerator;
|
||||
import org.bouncycastle.tsp.TimeStampResponse;
|
||||
import org.bouncycastle.tsp.TimeStampToken;
|
||||
|
||||
/**
|
||||
* Time Stamping Authority (TSA) Client [RFC 3161].
|
||||
*
|
||||
* @author Vakhtang Koroghlishvili
|
||||
* @author John Hewson
|
||||
*/
|
||||
public class TSAClient {
|
||||
private static final Logger LOG = LogManager.getLogger(TSAClient.class);
|
||||
|
||||
private static final DigestAlgorithmIdentifierFinder ALGORITHM_OID_FINDER =
|
||||
new DefaultDigestAlgorithmIdentifierFinder();
|
||||
|
||||
private final URL url;
|
||||
private final String username;
|
||||
private final String password;
|
||||
private final MessageDigest digest;
|
||||
|
||||
// SecureRandom.getInstanceStrong() would be better, but sometimes blocks on Linux
|
||||
private static final Random RANDOM = new SecureRandom();
|
||||
|
||||
/**
|
||||
* @param url the URL of the TSA service
|
||||
* @param username user name of TSA
|
||||
* @param password password of TSA
|
||||
* @param digest the message digest to use
|
||||
*/
|
||||
public TSAClient(URL url, String username, String password, MessageDigest digest) {
|
||||
this.url = url;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.digest = digest;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param content
|
||||
* @return the time stamp token
|
||||
* @throws IOException if there was an error with the connection or data from the TSA server, or
|
||||
* if the time stamp response could not be validated
|
||||
*/
|
||||
public TimeStampToken getTimeStampToken(InputStream content) throws IOException {
|
||||
digest.reset();
|
||||
DigestInputStream dis = new DigestInputStream(content, digest);
|
||||
while (dis.read() != -1) {
|
||||
// do nothing
|
||||
}
|
||||
byte[] hash = digest.digest();
|
||||
|
||||
// 32-bit cryptographic nonce
|
||||
int nonce = RANDOM.nextInt();
|
||||
|
||||
// generate TSA request
|
||||
TimeStampRequestGenerator tsaGenerator = new TimeStampRequestGenerator();
|
||||
tsaGenerator.setCertReq(true);
|
||||
ASN1ObjectIdentifier oid = ALGORITHM_OID_FINDER.find(digest.getAlgorithm()).getAlgorithm();
|
||||
TimeStampRequest request = tsaGenerator.generate(oid, hash, BigInteger.valueOf(nonce));
|
||||
|
||||
// get TSA response
|
||||
byte[] tsaResponse = getTSAResponse(request.getEncoded());
|
||||
|
||||
TimeStampResponse response;
|
||||
try {
|
||||
response = new TimeStampResponse(tsaResponse);
|
||||
response.validate(request);
|
||||
} catch (TSPException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
TimeStampToken timeStampToken = response.getTimeStampToken();
|
||||
if (timeStampToken == null) {
|
||||
// https://www.ietf.org/rfc/rfc3161.html#section-2.4.2
|
||||
throw new IOException(
|
||||
"Response from "
|
||||
+ url
|
||||
+ " does not have a time stamp token, status: "
|
||||
+ response.getStatus()
|
||||
+ " ("
|
||||
+ response.getStatusString()
|
||||
+ ")");
|
||||
}
|
||||
|
||||
return timeStampToken;
|
||||
}
|
||||
|
||||
// gets response data for the given encoded TimeStampRequest data
|
||||
// throws IOException if a connection to the TSA cannot be established
|
||||
private byte[] getTSAResponse(byte[] request) throws IOException {
|
||||
LOG.debug("Opening connection to TSA server");
|
||||
|
||||
// todo: support proxy servers
|
||||
URLConnection connection = url.openConnection();
|
||||
connection.setDoOutput(true);
|
||||
connection.setDoInput(true);
|
||||
connection.setRequestProperty("Content-Type", "application/timestamp-query");
|
||||
|
||||
LOG.debug("Established connection to TSA server");
|
||||
|
||||
if (username != null && password != null && !username.isEmpty() && !password.isEmpty()) {
|
||||
String contentEncoding = connection.getContentEncoding();
|
||||
if (contentEncoding == null) {
|
||||
contentEncoding = StandardCharsets.UTF_8.name();
|
||||
}
|
||||
connection.setRequestProperty(
|
||||
"Authorization",
|
||||
"Basic "
|
||||
+ new String(
|
||||
Base64.getEncoder()
|
||||
.encode(
|
||||
(username + ":" + password)
|
||||
.getBytes(contentEncoding))));
|
||||
}
|
||||
|
||||
// read response
|
||||
try (OutputStream output = connection.getOutputStream()) {
|
||||
output.write(request);
|
||||
} catch (IOException ex) {
|
||||
LOG.error("Exception when writing to {}", this.url, ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
LOG.debug("Waiting for response from TSA server");
|
||||
|
||||
byte[] response;
|
||||
try (InputStream input = connection.getInputStream()) {
|
||||
response = input.readAllBytes();
|
||||
} catch (IOException ex) {
|
||||
LOG.error("Exception when reading from {}", this.url, ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
LOG.debug("Received response from TSA server");
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.pdfbox.examples.signature;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1EncodableVector;
|
||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
||||
import org.bouncycastle.asn1.ASN1Primitive;
|
||||
import org.bouncycastle.asn1.DERSet;
|
||||
import org.bouncycastle.asn1.cms.Attribute;
|
||||
import org.bouncycastle.asn1.cms.AttributeTable;
|
||||
import org.bouncycastle.asn1.cms.Attributes;
|
||||
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
|
||||
import org.bouncycastle.cms.CMSSignedData;
|
||||
import org.bouncycastle.cms.SignerInformation;
|
||||
import org.bouncycastle.cms.SignerInformationStore;
|
||||
import org.bouncycastle.tsp.TimeStampToken;
|
||||
|
||||
/**
|
||||
* This class wraps the TSAClient and the work that has to be done with it. Like Adding Signed
|
||||
* TimeStamps to a signature, or creating a CMS timestamp attribute (with a signed timestamp)
|
||||
*
|
||||
* @author Others
|
||||
* @author Alexis Suter
|
||||
*/
|
||||
public class ValidationTimeStamp {
|
||||
private TSAClient tsaClient;
|
||||
|
||||
/**
|
||||
* @param tsaUrl The url where TS-Request will be done.
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws MalformedURLException
|
||||
* @throws java.net.URISyntaxException
|
||||
*/
|
||||
public ValidationTimeStamp(String tsaUrl)
|
||||
throws NoSuchAlgorithmException, MalformedURLException, URISyntaxException {
|
||||
if (tsaUrl != null) {
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
this.tsaClient = new TSAClient(new URI(tsaUrl).toURL(), null, null, digest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a signed timestamp token by the given input stream.
|
||||
*
|
||||
* @param content InputStream of the content to sign
|
||||
* @return the byte[] of the timestamp token
|
||||
* @throws IOException
|
||||
*/
|
||||
public byte[] getTimeStampToken(InputStream content) throws IOException {
|
||||
TimeStampToken timeStampToken = tsaClient.getTimeStampToken(content);
|
||||
return timeStampToken.getEncoded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend cms signed data with TimeStamp first or to all signers
|
||||
*
|
||||
* @param signedData Generated CMS signed data
|
||||
* @return CMSSignedData Extended CMS signed data
|
||||
* @throws IOException
|
||||
*/
|
||||
public CMSSignedData addSignedTimeStamp(CMSSignedData signedData) throws IOException {
|
||||
SignerInformationStore signerStore = signedData.getSignerInfos();
|
||||
List<SignerInformation> newSigners = new ArrayList<>();
|
||||
|
||||
for (SignerInformation signer : signerStore.getSigners()) {
|
||||
// This adds a timestamp to every signer (into his unsigned attributes) in the
|
||||
// signature.
|
||||
newSigners.add(signTimeStamp(signer));
|
||||
}
|
||||
|
||||
// Because new SignerInformation is created, new SignerInfoStore has to be created
|
||||
// and also be replaced in signedData. Which creates a new signedData object.
|
||||
return CMSSignedData.replaceSigners(signedData, new SignerInformationStore(newSigners));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend CMS Signer Information with the TimeStampToken into the unsigned Attributes.
|
||||
*
|
||||
* @param signer information about signer
|
||||
* @return information about SignerInformation
|
||||
* @throws IOException
|
||||
*/
|
||||
private SignerInformation signTimeStamp(SignerInformation signer) throws IOException {
|
||||
AttributeTable unsignedAttributes = signer.getUnsignedAttributes();
|
||||
|
||||
ASN1EncodableVector vector = new ASN1EncodableVector();
|
||||
if (unsignedAttributes != null) {
|
||||
vector = unsignedAttributes.toASN1EncodableVector();
|
||||
}
|
||||
|
||||
TimeStampToken timeStampToken =
|
||||
tsaClient.getTimeStampToken(new ByteArrayInputStream(signer.getSignature()));
|
||||
byte[] token = timeStampToken.getEncoded();
|
||||
ASN1ObjectIdentifier oid = PKCSObjectIdentifiers.id_aa_signatureTimeStampToken;
|
||||
ASN1Encodable signatureTimeStamp =
|
||||
new Attribute(oid, new DERSet(ASN1Primitive.fromByteArray(token)));
|
||||
|
||||
vector.add(signatureTimeStamp);
|
||||
Attributes signedAttributes = new Attributes(vector);
|
||||
|
||||
// There is no other way changing the unsigned attributes of the signer information.
|
||||
// result is never null, new SignerInformation always returned,
|
||||
// see source code of replaceUnsignedAttributes
|
||||
return SignerInformation.replaceUnsignedAttributes(
|
||||
signer, new AttributeTable(signedAttributes));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.pdfbox.examples.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
|
||||
/**
|
||||
* Delegate class to close the connection when the class gets closed.
|
||||
*
|
||||
* @author Tilman Hausherr
|
||||
*/
|
||||
public class ConnectedInputStream extends InputStream {
|
||||
HttpURLConnection con;
|
||||
InputStream is;
|
||||
|
||||
public ConnectedInputStream(HttpURLConnection con, InputStream is) {
|
||||
this.con = con;
|
||||
this.is = is;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return is.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return is.read(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
return is.read(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long n) throws IOException {
|
||||
return is.skip(n);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
return is.available();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void mark(int readlimit) {
|
||||
is.mark(readlimit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void reset() throws IOException {
|
||||
is.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markSupported() {
|
||||
return is.markSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
is.close();
|
||||
con.disconnect();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -57,4 +60,22 @@ public class AppConfig {
|
||||
if (appName == null) appName = System.getenv("rateLimit");
|
||||
return (appName != null) ? Boolean.valueOf(appName) : false;
|
||||
}
|
||||
|
||||
@Bean(name = "RunningInDocker")
|
||||
public boolean runningInDocker() {
|
||||
return Files.exists(Paths.get("/.dockerenv"));
|
||||
}
|
||||
|
||||
@Bean(name = "bookFormatsInstalled")
|
||||
public boolean bookFormatsInstalled() {
|
||||
return applicationProperties.getSystem().getCustomApplications().isInstallBookFormats();
|
||||
}
|
||||
|
||||
@Bean(name = "htmlFormatsInstalled")
|
||||
public boolean htmlFormatsInstalled() {
|
||||
return applicationProperties
|
||||
.getSystem()
|
||||
.getCustomApplications()
|
||||
.isInstallAdvancedHtmlToPDF();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,11 +9,14 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import stirling.software.SPDF.model.ApplicationProperties;
|
||||
|
||||
@Service
|
||||
@DependsOn({"bookFormatsInstalled"})
|
||||
public class EndpointConfiguration {
|
||||
private static final Logger logger = LoggerFactory.getLogger(EndpointConfiguration.class);
|
||||
private Map<String, Boolean> endpointStatuses = new ConcurrentHashMap<>();
|
||||
@@ -21,9 +24,14 @@ public class EndpointConfiguration {
|
||||
|
||||
private final ApplicationProperties applicationProperties;
|
||||
|
||||
private boolean bookFormatsInstalled;
|
||||
|
||||
@Autowired
|
||||
public EndpointConfiguration(ApplicationProperties applicationProperties) {
|
||||
public EndpointConfiguration(
|
||||
ApplicationProperties applicationProperties,
|
||||
@Qualifier("bookFormatsInstalled") boolean bookFormatsInstalled) {
|
||||
this.applicationProperties = applicationProperties;
|
||||
this.bookFormatsInstalled = bookFormatsInstalled;
|
||||
init();
|
||||
processEnvironmentConfigs();
|
||||
}
|
||||
@@ -145,6 +153,12 @@ public class EndpointConfiguration {
|
||||
addEndpointToGroup("CLI", "ocr-pdf");
|
||||
addEndpointToGroup("CLI", "html-to-pdf");
|
||||
addEndpointToGroup("CLI", "url-to-pdf");
|
||||
addEndpointToGroup("CLI", "book-to-pdf");
|
||||
addEndpointToGroup("CLI", "pdf-to-book");
|
||||
|
||||
// Calibre
|
||||
addEndpointToGroup("Calibre", "book-to-pdf");
|
||||
addEndpointToGroup("Calibre", "pdf-to-book");
|
||||
|
||||
// python
|
||||
addEndpointToGroup("Python", "extract-image-scans");
|
||||
@@ -215,7 +229,9 @@ public class EndpointConfiguration {
|
||||
private void processEnvironmentConfigs() {
|
||||
List<String> endpointsToRemove = applicationProperties.getEndpoints().getToRemove();
|
||||
List<String> groupsToRemove = applicationProperties.getEndpoints().getGroupsToRemove();
|
||||
|
||||
if (!bookFormatsInstalled) {
|
||||
groupsToRemove.add("Calibre");
|
||||
}
|
||||
if (endpointsToRemove != null) {
|
||||
for (String endpoint : endpointsToRemove) {
|
||||
disableEndpoint(endpoint.trim());
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import stirling.software.SPDF.model.ApplicationProperties;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||
|
||||
@Component
|
||||
public class PostStartupProcesses {
|
||||
|
||||
@Autowired ApplicationProperties applicationProperties;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("RunningInDocker")
|
||||
private boolean runningInDocker;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("bookFormatsInstalled")
|
||||
private boolean bookFormatsInstalled;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("htmlFormatsInstalled")
|
||||
private boolean htmlFormatsInstalled;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PostStartupProcesses.class);
|
||||
|
||||
@PostConstruct
|
||||
public void runInstallCommandBasedOnEnvironment() throws IOException, InterruptedException {
|
||||
List<List<String>> commands = new ArrayList<>();
|
||||
// Checking for DOCKER_INSTALL_BOOK_FORMATS environment variable
|
||||
if (bookFormatsInstalled) {
|
||||
List<String> tmpList = new ArrayList<>();
|
||||
// Set up the timezone configuration commands
|
||||
tmpList.addAll(
|
||||
Arrays.asList(
|
||||
"sh",
|
||||
"-c",
|
||||
"echo 'tzdata tzdata/Areas select Europe' | debconf-set-selections; "
|
||||
+ "echo 'tzdata tzdata/Zones/Europe select Berlin' | debconf-set-selections"));
|
||||
commands.add(tmpList);
|
||||
|
||||
// Install calibre with DEBIAN_FRONTEND set to noninteractive
|
||||
tmpList = new ArrayList<>();
|
||||
tmpList.addAll(
|
||||
Arrays.asList(
|
||||
"sh",
|
||||
"-c",
|
||||
"DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends calibre"));
|
||||
commands.add(tmpList);
|
||||
}
|
||||
|
||||
// Checking for DOCKER_INSTALL_HTML_FORMATS environment variable
|
||||
if (htmlFormatsInstalled) {
|
||||
List<String> tmpList = new ArrayList<>();
|
||||
// Add -y flag for automatic yes to prompts and --no-install-recommends to reduce size
|
||||
tmpList.addAll(
|
||||
Arrays.asList(
|
||||
"apt-get", "install", "wkhtmltopdf", "-y", "--no-install-recommends"));
|
||||
commands.add(tmpList);
|
||||
}
|
||||
|
||||
if (!commands.isEmpty()) {
|
||||
// Run the command
|
||||
if (runningInDocker) {
|
||||
List<String> tmpList = new ArrayList<>();
|
||||
tmpList.addAll(Arrays.asList("apt-get", "update"));
|
||||
commands.add(0, tmpList);
|
||||
|
||||
for (List<String> list : commands) {
|
||||
ProcessExecutorResult returnCode =
|
||||
ProcessExecutor.getInstance(ProcessExecutor.Processes.INSTALL_APP, true)
|
||||
.runCommandWithOutputHandling(list);
|
||||
logger.info("RC for app installs {}", returnCode.getRc());
|
||||
}
|
||||
} else {
|
||||
|
||||
logger.info(
|
||||
"Not running inside Docker so skipping automated install process with command.");
|
||||
}
|
||||
|
||||
} else {
|
||||
if (runningInDocker) {
|
||||
logger.info("No custom apps to install.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,7 +102,9 @@ public class SecurityConfiguration {
|
||||
|| trimmedUri.startsWith("/images/")
|
||||
|| trimmedUri.startsWith("/public/")
|
||||
|| trimmedUri.startsWith("/css/")
|
||||
|| trimmedUri.startsWith("/js/");
|
||||
|| trimmedUri.startsWith("/js/")
|
||||
|| trimmedUri.startsWith(
|
||||
"/api/v1/info/status");
|
||||
})
|
||||
.permitAll()
|
||||
.anyRequest()
|
||||
@@ -113,6 +115,7 @@ public class SecurityConfiguration {
|
||||
http.csrf(csrf -> csrf.disable())
|
||||
.authorizeHttpRequests(authz -> authz.anyRequest().permitAll());
|
||||
}
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
|
||||
contextPath + "/css/",
|
||||
contextPath + "/js/",
|
||||
contextPath + "/pdfjs/",
|
||||
contextPath + "/api/v1/info/status",
|
||||
contextPath + "/site.webmanifest"
|
||||
};
|
||||
|
||||
|
||||
@@ -120,6 +120,9 @@ public class SplitPdfBySectionsController {
|
||||
float translateX = -subPageWidth * i;
|
||||
float translateY = height - subPageHeight * (verticalDivisions - j);
|
||||
|
||||
// Code for google Docs pdfs..
|
||||
// float translateY = -subPageHeight * (verticalDivisions - 1 - j);
|
||||
|
||||
contentStream.saveGraphicsState();
|
||||
contentStream.addRect(0, 0, subPageWidth, subPageHeight);
|
||||
contentStream.clip();
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package stirling.software.SPDF.controller.api.converters;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
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.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import stirling.software.SPDF.model.api.GeneralFile;
|
||||
import stirling.software.SPDF.utils.FileToPdf;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Convert", description = "Convert APIs")
|
||||
@RequestMapping("/api/v1/convert")
|
||||
public class ConvertBookToPDFController {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("bookFormatsInstalled")
|
||||
private boolean bookFormatsInstalled;
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/book/pdf")
|
||||
@Operation(
|
||||
summary =
|
||||
"Convert a BOOK/comic (*.epub | *.mobi | *.azw3 | *.fb2 | *.txt | *.docx) to PDF",
|
||||
description =
|
||||
"(Requires bookFormatsInstalled flag and Calibre installed) This endpoint takes an BOOK/comic (*.epub | *.mobi | *.azw3 | *.fb2 | *.txt | *.docx) input and converts it to PDF format.")
|
||||
public ResponseEntity<byte[]> HtmlToPdf(@ModelAttribute GeneralFile request) throws Exception {
|
||||
MultipartFile fileInput = request.getFileInput();
|
||||
|
||||
if (!bookFormatsInstalled) {
|
||||
throw new IllegalArgumentException(
|
||||
"bookFormatsInstalled flag is False, this functionality is not avaiable");
|
||||
}
|
||||
|
||||
if (fileInput == null) {
|
||||
throw new IllegalArgumentException("Please provide a file for conversion.");
|
||||
}
|
||||
|
||||
String originalFilename = fileInput.getOriginalFilename();
|
||||
|
||||
if (originalFilename != null) {
|
||||
String originalFilenameLower = originalFilename.toLowerCase();
|
||||
if (!originalFilenameLower.endsWith(".epub")
|
||||
&& !originalFilenameLower.endsWith(".mobi")
|
||||
&& !originalFilenameLower.endsWith(".azw3")
|
||||
&& !originalFilenameLower.endsWith(".fb2")
|
||||
&& !originalFilenameLower.endsWith(".txt")
|
||||
&& !originalFilenameLower.endsWith(".docx")) {
|
||||
throw new IllegalArgumentException(
|
||||
"File must be in .epub, .mobi, .azw3, .fb2, .txt, or .docx format.");
|
||||
}
|
||||
}
|
||||
byte[] pdfBytes = FileToPdf.convertBookTypeToPdf(fileInput.getBytes(), originalFilename);
|
||||
|
||||
String outputFilename =
|
||||
originalFilename.replaceFirst("[.][^.]+$", "")
|
||||
+ ".pdf"; // Remove file extension and append .pdf
|
||||
|
||||
return WebResponseUtils.bytesToWebResponse(pdfBytes, outputFilename);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package stirling.software.SPDF.controller.api.converters;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@@ -19,6 +21,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
@RequestMapping("/api/v1/convert")
|
||||
public class ConvertHtmlToPDF {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("htmlFormatsInstalled")
|
||||
private boolean htmlFormatsInstalled;
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/html/pdf")
|
||||
@Operation(
|
||||
summary = "Convert an HTML or ZIP (containing HTML and CSS) to PDF",
|
||||
@@ -37,7 +43,9 @@ public class ConvertHtmlToPDF {
|
||||
|| (!originalFilename.endsWith(".html") && !originalFilename.endsWith(".zip"))) {
|
||||
throw new IllegalArgumentException("File must be either .html or .zip format.");
|
||||
}
|
||||
byte[] pdfBytes = FileToPdf.convertHtmlToPdf(fileInput.getBytes(), originalFilename);
|
||||
byte[] pdfBytes =
|
||||
FileToPdf.convertHtmlToPdf(
|
||||
fileInput.getBytes(), originalFilename, htmlFormatsInstalled);
|
||||
|
||||
String outputFilename =
|
||||
originalFilename.replaceFirst("[.][^.]+$", "")
|
||||
|
||||
@@ -3,6 +3,8 @@ package stirling.software.SPDF.controller.api.converters;
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.parser.Parser;
|
||||
import org.commonmark.renderer.html.HtmlRenderer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@@ -22,6 +24,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
@RequestMapping("/api/v1/convert")
|
||||
public class ConvertMarkdownToPdf {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("htmlFormatsInstalled")
|
||||
private boolean htmlFormatsInstalled;
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/markdown/pdf")
|
||||
@Operation(
|
||||
summary = "Convert a Markdown file to PDF",
|
||||
@@ -46,7 +52,9 @@ public class ConvertMarkdownToPdf {
|
||||
HtmlRenderer renderer = HtmlRenderer.builder().build();
|
||||
String htmlContent = renderer.render(document);
|
||||
|
||||
byte[] pdfBytes = FileToPdf.convertHtmlToPdf(htmlContent.getBytes(), "converted.html");
|
||||
byte[] pdfBytes =
|
||||
FileToPdf.convertHtmlToPdf(
|
||||
htmlContent.getBytes(), "converted.html", htmlFormatsInstalled);
|
||||
|
||||
String outputFilename =
|
||||
originalFilename.replaceFirst("[.][^.]+$", "")
|
||||
|
||||
@@ -79,7 +79,7 @@ public class ConvertOfficeController {
|
||||
@Operation(
|
||||
summary = "Convert a file to a PDF using LibreOffice",
|
||||
description =
|
||||
"This endpoint converts a given file to a PDF using LibreOffice API Input:Any Output:PDF Type:SISO")
|
||||
"This endpoint converts a given file to a PDF using LibreOffice API Input:ANY Output:PDF Type:SISO")
|
||||
public ResponseEntity<byte[]> processFileToPDF(@ModelAttribute GeneralFile request)
|
||||
throws Exception {
|
||||
MultipartFile inputFile = request.getFileInput();
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package stirling.software.SPDF.controller.api.converters;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
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.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import stirling.software.SPDF.model.api.converters.PdfToBookRequest;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Convert", description = "Convert APIs")
|
||||
@RequestMapping("/api/v1/convert")
|
||||
public class ConvertPDFToBookController {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("bookFormatsInstalled")
|
||||
private boolean bookFormatsInstalled;
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf/book")
|
||||
@Operation(
|
||||
summary =
|
||||
"Convert a PDF to a Book/comic (*.epub | *.mobi | *.azw3 | *.fb2 | *.txt | *.docx .. (others to include by chatgpt) to PDF",
|
||||
description =
|
||||
"(Requires bookFormatsInstalled flag and Calibre installed) This endpoint Convert a PDF to a Book/comic (*.epub | *.mobi | *.azw3 | *.fb2 | *.txt | *.docx .. (others to include by chatgpt) to PDF")
|
||||
public ResponseEntity<byte[]> HtmlToPdf(@ModelAttribute PdfToBookRequest request)
|
||||
throws Exception {
|
||||
MultipartFile fileInput = request.getFileInput();
|
||||
|
||||
if (!bookFormatsInstalled) {
|
||||
throw new IllegalArgumentException(
|
||||
"bookFormatsInstalled flag is False, this functionality is not avaiable");
|
||||
}
|
||||
|
||||
if (fileInput == null) {
|
||||
throw new IllegalArgumentException("Please provide a file for conversion.");
|
||||
}
|
||||
|
||||
// Validate the output format
|
||||
String outputFormat = request.getOutputFormat().toLowerCase();
|
||||
List<String> allowedFormats =
|
||||
Arrays.asList(
|
||||
"epub", "mobi", "azw3", "docx", "rtf", "txt", "html", "lit", "fb2", "pdb",
|
||||
"lrf");
|
||||
if (!allowedFormats.contains(outputFormat)) {
|
||||
throw new IllegalArgumentException("Invalid output format: " + outputFormat);
|
||||
}
|
||||
|
||||
byte[] outputFileBytes;
|
||||
List<String> command = new ArrayList<>();
|
||||
Path tempOutputFile =
|
||||
Files.createTempFile(
|
||||
"output_",
|
||||
"." + outputFormat); // Use the output format for the file extension
|
||||
Path tempInputFile = null;
|
||||
|
||||
try {
|
||||
// Create temp input file from the provided PDF
|
||||
tempInputFile = Files.createTempFile("input_", ".pdf"); // Assuming input is always PDF
|
||||
Files.write(tempInputFile, fileInput.getBytes());
|
||||
|
||||
command.add("ebook-convert");
|
||||
command.add(tempInputFile.toString());
|
||||
command.add(tempOutputFile.toString());
|
||||
|
||||
ProcessExecutorResult returnCode =
|
||||
ProcessExecutor.getInstance(ProcessExecutor.Processes.CALIBRE)
|
||||
.runCommandWithOutputHandling(command);
|
||||
|
||||
outputFileBytes = Files.readAllBytes(tempOutputFile);
|
||||
} finally {
|
||||
// Clean up temporary files
|
||||
if (tempInputFile != null) {
|
||||
Files.deleteIfExists(tempInputFile);
|
||||
}
|
||||
Files.deleteIfExists(tempOutputFile);
|
||||
}
|
||||
|
||||
String outputFilename =
|
||||
fileInput.getOriginalFilename().replaceFirst("[.][^.]+$", "")
|
||||
+ "."
|
||||
+ outputFormat; // Remove file extension and append .pdf
|
||||
|
||||
return WebResponseUtils.bytesToWebResponse(outputFileBytes, outputFilename);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@@ -26,6 +28,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
@RequestMapping("/api/v1/convert")
|
||||
public class ConvertWebsiteToPDF {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("htmlFormatsInstalled")
|
||||
private boolean htmlFormatsInstalled;
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/url/pdf")
|
||||
@Operation(
|
||||
summary = "Convert a URL to a PDF",
|
||||
@@ -47,7 +53,11 @@ public class ConvertWebsiteToPDF {
|
||||
|
||||
// Prepare the OCRmyPDF command
|
||||
List<String> command = new ArrayList<>();
|
||||
command.add("weasyprint");
|
||||
if (!htmlFormatsInstalled) {
|
||||
command.add("weasyprint");
|
||||
} else {
|
||||
command.add("wkhtmltopdf");
|
||||
}
|
||||
command.add(URL);
|
||||
command.add(tempOutputFile.toString());
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
|
||||
public class AutoSplitPdfController {
|
||||
|
||||
private static final String QR_CONTENT = "https://github.com/Frooodle/Stirling-PDF";
|
||||
private static final String QR_CONTENT = "https://github.com/Stirling-Tools/Stirling-PDF";
|
||||
|
||||
@PostMapping(value = "/auto-split-pdf", consumes = "multipart/form-data")
|
||||
@Operation(
|
||||
|
||||
@@ -2,7 +2,9 @@ package stirling.software.SPDF.controller.api.pipeline;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
@@ -84,9 +86,26 @@ public class PipelineController {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ZipOutputStream zipOut = new ZipOutputStream(baos);
|
||||
|
||||
// A map to keep track of filenames and their counts
|
||||
Map<String, Integer> filenameCount = new HashMap<>();
|
||||
|
||||
// Loop through each file and add it to the zip
|
||||
for (Resource file : outputFiles) {
|
||||
ZipEntry zipEntry = new ZipEntry(file.getFilename());
|
||||
String originalFilename = file.getFilename();
|
||||
String filename = originalFilename;
|
||||
|
||||
// Check if the filename already exists, and modify it if necessary
|
||||
if (filenameCount.containsKey(originalFilename)) {
|
||||
int count = filenameCount.get(originalFilename);
|
||||
String baseName = originalFilename.replaceAll("\\.[^.]*$", "");
|
||||
String extension = originalFilename.replaceAll("^.*\\.", "");
|
||||
filename = baseName + "(" + count + ")." + extension;
|
||||
filenameCount.put(originalFilename, count + 1);
|
||||
} else {
|
||||
filenameCount.put(originalFilename, 1);
|
||||
}
|
||||
|
||||
ZipEntry zipEntry = new ZipEntry(filename);
|
||||
zipOut.putNextEntry(zipEntry);
|
||||
|
||||
// Read the file into a byte array
|
||||
|
||||
@@ -5,6 +5,8 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
@@ -132,8 +134,6 @@ public class PipelineProcessor {
|
||||
+ operation);
|
||||
hasErrors = true;
|
||||
}
|
||||
|
||||
outputFiles = newOutputFiles;
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -185,10 +185,12 @@ public class PipelineProcessor {
|
||||
}
|
||||
}
|
||||
logPrintStream.close();
|
||||
outputFiles = newOutputFiles;
|
||||
}
|
||||
if (hasErrors) {
|
||||
logger.error("Errors occurred during processing. Log: {}", logStream.toString());
|
||||
}
|
||||
|
||||
return outputFiles;
|
||||
}
|
||||
|
||||
@@ -196,6 +198,7 @@ public class PipelineProcessor {
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
|
||||
// Set up headers, including API key
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
String apiKey = getApiKeyForUser();
|
||||
headers.add("X-API-Key", apiKey);
|
||||
@@ -216,11 +219,12 @@ public class PipelineProcessor {
|
||||
throws IOException {
|
||||
// Define filename
|
||||
String newFilename;
|
||||
if ("auto-rename".equals(operation)) {
|
||||
if (operation.contains("auto-rename")) {
|
||||
// If the operation is "auto-rename", generate a new filename.
|
||||
// This is a simple example of generating a filename using current timestamp.
|
||||
// Modify as per your needs.
|
||||
newFilename = "file_" + System.currentTimeMillis();
|
||||
|
||||
newFilename = extractFilename(response);
|
||||
} else {
|
||||
// Otherwise, keep the original filename.
|
||||
newFilename = fileName;
|
||||
@@ -244,6 +248,28 @@ public class PipelineProcessor {
|
||||
return newOutputFiles;
|
||||
}
|
||||
|
||||
public String extractFilename(ResponseEntity<byte[]> response) {
|
||||
String filename = "default-filename.ext"; // Default filename if not found
|
||||
|
||||
HttpHeaders headers = response.getHeaders();
|
||||
String contentDisposition = headers.getFirst(HttpHeaders.CONTENT_DISPOSITION);
|
||||
|
||||
if (contentDisposition != null && !contentDisposition.isEmpty()) {
|
||||
String[] parts = contentDisposition.split(";");
|
||||
for (String part : parts) {
|
||||
if (part.trim().startsWith("filename")) {
|
||||
// Extracts filename and removes quotes if present
|
||||
filename = part.split("=")[1].trim().replace("\"", "");
|
||||
filename = URLDecoder.decode(filename, StandardCharsets.UTF_8);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
List<Resource> generateInputFiles(File[] files) throws Exception {
|
||||
if (files == null || files.length == 0) {
|
||||
logger.info("No files");
|
||||
|
||||
@@ -4,44 +4,34 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.security.KeyFactory;
|
||||
import java.io.OutputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.Security;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.pdfbox.examples.signature.CreateSignatureBase;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||
import org.apache.pdfbox.pdmodel.PDResources;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.apache.pdfbox.pdmodel.font.PDType1Font;
|
||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
|
||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
|
||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
|
||||
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.ExternalSigningSupport;
|
||||
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
|
||||
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;
|
||||
import org.bouncycastle.cert.jcajce.JcaCertStore;
|
||||
import org.bouncycastle.cms.CMSProcessableByteArray;
|
||||
import org.bouncycastle.cms.CMSSignedData;
|
||||
import org.bouncycastle.cms.CMSSignedDataGenerator;
|
||||
import org.bouncycastle.cms.CMSTypedData;
|
||||
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
|
||||
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.operator.ContentSigner;
|
||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
||||
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
|
||||
import org.bouncycastle.util.io.pem.PemReader;
|
||||
import org.bouncycastle.openssl.PEMDecryptorProvider;
|
||||
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
|
||||
import org.bouncycastle.openssl.PEMKeyPair;
|
||||
import org.bouncycastle.openssl.PEMParser;
|
||||
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
|
||||
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
|
||||
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
|
||||
import org.bouncycastle.operator.InputDecryptorProvider;
|
||||
import org.bouncycastle.operator.OperatorCreationException;
|
||||
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
|
||||
import org.bouncycastle.pkcs.PKCSException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -68,6 +58,17 @@ public class CertSignController {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
class CreateSignature extends CreateSignatureBase {
|
||||
public CreateSignature(KeyStore keystore, char[] pin)
|
||||
throws KeyStoreException,
|
||||
UnrecoverableKeyException,
|
||||
NoSuchAlgorithmException,
|
||||
IOException,
|
||||
CertificateException {
|
||||
super(keystore, pin);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/cert-sign")
|
||||
@Operation(
|
||||
summary = "Sign PDF with a Digital Certificate",
|
||||
@@ -80,6 +81,7 @@ public class CertSignController {
|
||||
MultipartFile privateKeyFile = request.getPrivateKeyFile();
|
||||
MultipartFile certFile = request.getCertFile();
|
||||
MultipartFile p12File = request.getP12File();
|
||||
MultipartFile jksfile = request.getJksFile();
|
||||
String password = request.getPassword();
|
||||
Boolean showSignature = request.isShowSignature();
|
||||
String reason = request.getReason();
|
||||
@@ -87,203 +89,94 @@ public class CertSignController {
|
||||
String name = request.getName();
|
||||
Integer pageNumber = request.getPageNumber();
|
||||
|
||||
PrivateKey privateKey = null;
|
||||
X509Certificate cert = null;
|
||||
|
||||
if (certType != null) {
|
||||
logger.info("Cert type provided: {}", certType);
|
||||
switch (certType) {
|
||||
case "PKCS12":
|
||||
if (p12File != null) {
|
||||
KeyStore ks = KeyStore.getInstance("PKCS12");
|
||||
ks.load(
|
||||
new ByteArrayInputStream(p12File.getBytes()),
|
||||
password.toCharArray());
|
||||
String alias = ks.aliases().nextElement();
|
||||
if (!ks.isKeyEntry(alias)) {
|
||||
throw new IllegalArgumentException(
|
||||
"The provided PKCS12 file does not contain a private key.");
|
||||
}
|
||||
privateKey = (PrivateKey) ks.getKey(alias, password.toCharArray());
|
||||
cert = (X509Certificate) ks.getCertificate(alias);
|
||||
}
|
||||
break;
|
||||
case "PEM":
|
||||
if (privateKeyFile != null && certFile != null) {
|
||||
// Load private key
|
||||
KeyFactory keyFactory =
|
||||
KeyFactory.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME);
|
||||
if (isPEM(privateKeyFile.getBytes())) {
|
||||
privateKey =
|
||||
keyFactory.generatePrivate(
|
||||
new PKCS8EncodedKeySpec(
|
||||
parsePEM(privateKeyFile.getBytes())));
|
||||
} else {
|
||||
privateKey =
|
||||
keyFactory.generatePrivate(
|
||||
new PKCS8EncodedKeySpec(privateKeyFile.getBytes()));
|
||||
}
|
||||
|
||||
// Load certificate
|
||||
CertificateFactory certFactory =
|
||||
CertificateFactory.getInstance(
|
||||
"X.509", BouncyCastleProvider.PROVIDER_NAME);
|
||||
if (isPEM(certFile.getBytes())) {
|
||||
cert =
|
||||
(X509Certificate)
|
||||
certFactory.generateCertificate(
|
||||
new ByteArrayInputStream(
|
||||
parsePEM(certFile.getBytes())));
|
||||
} else {
|
||||
cert =
|
||||
(X509Certificate)
|
||||
certFactory.generateCertificate(
|
||||
new ByteArrayInputStream(certFile.getBytes()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (certType == null) {
|
||||
throw new IllegalArgumentException("Cert type must be provided");
|
||||
}
|
||||
PDSignature signature = new PDSignature();
|
||||
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); // default filter
|
||||
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_SHA1);
|
||||
signature.setName(name);
|
||||
signature.setLocation(location);
|
||||
signature.setReason(reason);
|
||||
signature.setSignDate(Calendar.getInstance());
|
||||
|
||||
// Load the PDF
|
||||
try (PDDocument document = PDDocument.load(pdf.getBytes())) {
|
||||
logger.info("Successfully loaded the provided PDF");
|
||||
SignatureOptions signatureOptions = new SignatureOptions();
|
||||
KeyStore ks = null;
|
||||
|
||||
// If you want to show the signature
|
||||
switch (certType) {
|
||||
case "PEM":
|
||||
ks = KeyStore.getInstance("JKS");
|
||||
ks.load(null);
|
||||
PrivateKey privateKey = getPrivateKeyFromPEM(privateKeyFile.getBytes(), password);
|
||||
Certificate cert = (Certificate) getCertificateFromPEM(certFile.getBytes());
|
||||
ks.setKeyEntry(
|
||||
"alias", privateKey, password.toCharArray(), new Certificate[] {cert});
|
||||
break;
|
||||
case "PKCS12":
|
||||
ks = KeyStore.getInstance("PKCS12");
|
||||
ks.load(p12File.getInputStream(), password.toCharArray());
|
||||
break;
|
||||
case "JKS":
|
||||
ks = KeyStore.getInstance("JKS");
|
||||
ks.load(jksfile.getInputStream(), password.toCharArray());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid cert type: " + certType);
|
||||
}
|
||||
|
||||
// ATTEMPT 2
|
||||
if (showSignature != null && showSignature) {
|
||||
PDPage page = document.getPage(pageNumber - 1);
|
||||
// TODO: page number
|
||||
|
||||
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
|
||||
if (acroForm == null) {
|
||||
acroForm = new PDAcroForm(document);
|
||||
document.getDocumentCatalog().setAcroForm(acroForm);
|
||||
}
|
||||
CreateSignature createSignature = new CreateSignature(ks, password.toCharArray());
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
sign(pdf.getBytes(), baos, createSignature, name, location, reason);
|
||||
return WebResponseUtils.boasToWebResponse(
|
||||
baos, pdf.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_signed.pdf");
|
||||
}
|
||||
|
||||
// Create a new signature field and widget
|
||||
private static void sign(
|
||||
byte[] input,
|
||||
OutputStream output,
|
||||
CreateSignature instance,
|
||||
String name,
|
||||
String location,
|
||||
String reason) {
|
||||
try (PDDocument doc = PDDocument.load(input)) {
|
||||
PDSignature signature = new PDSignature();
|
||||
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
|
||||
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
|
||||
signature.setName(name);
|
||||
signature.setLocation(location);
|
||||
signature.setReason(reason);
|
||||
signature.setSignDate(Calendar.getInstance());
|
||||
|
||||
PDSignatureField signatureField = new PDSignatureField(acroForm);
|
||||
PDAnnotationWidget widget = signatureField.getWidgets().get(0);
|
||||
PDRectangle rect =
|
||||
new PDRectangle(100, 100, 200, 50); // Define the rectangle size here
|
||||
widget.setRectangle(rect);
|
||||
page.getAnnotations().add(widget);
|
||||
|
||||
// Set the appearance for the signature field
|
||||
PDAppearanceDictionary appearanceDict = new PDAppearanceDictionary();
|
||||
PDAppearanceStream appearanceStream = new PDAppearanceStream(document);
|
||||
appearanceStream.setResources(new PDResources());
|
||||
appearanceStream.setBBox(rect);
|
||||
appearanceDict.setNormalAppearance(appearanceStream);
|
||||
widget.setAppearance(appearanceDict);
|
||||
|
||||
try (PDPageContentStream contentStream =
|
||||
new PDPageContentStream(document, appearanceStream)) {
|
||||
contentStream.beginText();
|
||||
contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12);
|
||||
contentStream.newLineAtOffset(110, 130);
|
||||
contentStream.showText(
|
||||
"Digitally signed by: " + (name != null ? name : "Unknown"));
|
||||
contentStream.newLineAtOffset(0, -15);
|
||||
contentStream.showText(
|
||||
"Date: "
|
||||
+ new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z")
|
||||
.format(new Date()));
|
||||
contentStream.newLineAtOffset(0, -15);
|
||||
if (reason != null && !reason.isEmpty()) {
|
||||
contentStream.showText("Reason: " + reason);
|
||||
contentStream.newLineAtOffset(0, -15);
|
||||
}
|
||||
if (location != null && !location.isEmpty()) {
|
||||
contentStream.showText("Location: " + location);
|
||||
contentStream.newLineAtOffset(0, -15);
|
||||
}
|
||||
contentStream.endText();
|
||||
}
|
||||
|
||||
// Add the widget annotation to the page
|
||||
page.getAnnotations().add(widget);
|
||||
|
||||
// Add the signature field to the acroform
|
||||
acroForm.getFields().add(signatureField);
|
||||
|
||||
// Handle multiple signatures by ensuring a unique field name
|
||||
String baseFieldName = "Signature";
|
||||
String signatureFieldName = baseFieldName;
|
||||
int suffix = 1;
|
||||
while (acroForm.getField(signatureFieldName) != null) {
|
||||
suffix++;
|
||||
signatureFieldName = baseFieldName + suffix;
|
||||
}
|
||||
signatureField.setPartialName(signatureFieldName);
|
||||
}
|
||||
|
||||
document.addSignature(signature, signatureOptions);
|
||||
logger.info("Signature added to the PDF document");
|
||||
// External signing
|
||||
ExternalSigningSupport externalSigning =
|
||||
document.saveIncrementalForExternalSigning(new ByteArrayOutputStream());
|
||||
|
||||
byte[] content = IOUtils.toByteArray(externalSigning.getContent());
|
||||
|
||||
// Using BouncyCastle to sign
|
||||
CMSTypedData cmsData = new CMSProcessableByteArray(content);
|
||||
|
||||
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
|
||||
ContentSigner signer =
|
||||
new JcaContentSignerBuilder("SHA256withRSA")
|
||||
.setProvider(BouncyCastleProvider.PROVIDER_NAME)
|
||||
.build(privateKey);
|
||||
|
||||
gen.addSignerInfoGenerator(
|
||||
new JcaSignerInfoGeneratorBuilder(
|
||||
new JcaDigestCalculatorProviderBuilder()
|
||||
.setProvider(BouncyCastleProvider.PROVIDER_NAME)
|
||||
.build())
|
||||
.build(signer, cert));
|
||||
|
||||
gen.addCertificates(new JcaCertStore(Collections.singletonList(cert)));
|
||||
CMSSignedData signedData = gen.generate(cmsData, false);
|
||||
|
||||
byte[] cmsSignature = signedData.getEncoded();
|
||||
logger.info("About to sign content using BouncyCastle");
|
||||
externalSigning.setSignature(cmsSignature);
|
||||
logger.info("Signature set successfully");
|
||||
|
||||
// After setting the signature, return the resultant PDF
|
||||
try (ByteArrayOutputStream signedPdfOutput = new ByteArrayOutputStream()) {
|
||||
document.save(signedPdfOutput);
|
||||
return WebResponseUtils.boasToWebResponse(
|
||||
signedPdfOutput,
|
||||
pdf.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_signed.pdf");
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
doc.addSignature(signature, instance);
|
||||
doc.saveIncremental(output);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private byte[] parsePEM(byte[] content) throws IOException {
|
||||
PemReader pemReader =
|
||||
new PemReader(new InputStreamReader(new ByteArrayInputStream(content)));
|
||||
return pemReader.readPemObject().getContent();
|
||||
private PrivateKey getPrivateKeyFromPEM(byte[] pemBytes, String password)
|
||||
throws IOException, OperatorCreationException, PKCSException {
|
||||
try (PEMParser pemParser =
|
||||
new PEMParser(new InputStreamReader(new ByteArrayInputStream(pemBytes)))) {
|
||||
Object pemObject = pemParser.readObject();
|
||||
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
|
||||
PrivateKeyInfo pkInfo;
|
||||
if (pemObject instanceof PKCS8EncryptedPrivateKeyInfo) {
|
||||
InputDecryptorProvider decProv =
|
||||
new JceOpenSSLPKCS8DecryptorProviderBuilder().build(password.toCharArray());
|
||||
pkInfo = ((PKCS8EncryptedPrivateKeyInfo) pemObject).decryptPrivateKeyInfo(decProv);
|
||||
} else if (pemObject instanceof PEMEncryptedKeyPair) {
|
||||
PEMDecryptorProvider decProv =
|
||||
new JcePEMDecryptorProviderBuilder().build(password.toCharArray());
|
||||
pkInfo =
|
||||
((PEMEncryptedKeyPair) pemObject)
|
||||
.decryptKeyPair(decProv)
|
||||
.getPrivateKeyInfo();
|
||||
} else {
|
||||
pkInfo = ((PEMKeyPair) pemObject).getPrivateKeyInfo();
|
||||
}
|
||||
return converter.getPrivateKey(pkInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPEM(byte[] content) {
|
||||
String contentStr = new String(content);
|
||||
return contentStr.contains("-----BEGIN") && contentStr.contains("-----END");
|
||||
private Certificate getCertificateFromPEM(byte[] pemBytes)
|
||||
throws IOException, CertificateException {
|
||||
try (ByteArrayInputStream bis = new ByteArrayInputStream(pemBytes)) {
|
||||
return CertificateFactory.getInstance("X.509").generateCertificate(bis);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package stirling.software.SPDF.controller.web;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -12,6 +13,22 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@Tag(name = "Convert", description = "Convert APIs")
|
||||
public class ConverterWebController {
|
||||
|
||||
@ConditionalOnExpression("#{bookFormatsInstalled}")
|
||||
@GetMapping("/book-to-pdf")
|
||||
@Hidden
|
||||
public String convertBookToPdfForm(Model model) {
|
||||
model.addAttribute("currentPage", "book-to-pdf");
|
||||
return "convert/book-to-pdf";
|
||||
}
|
||||
|
||||
@ConditionalOnExpression("#{bookFormatsInstalled}")
|
||||
@GetMapping("/pdf-to-book")
|
||||
@Hidden
|
||||
public String convertPdfToBookForm(Model model) {
|
||||
model.addAttribute("currentPage", "pdf-to-book");
|
||||
return "convert/pdf-to-book";
|
||||
}
|
||||
|
||||
@GetMapping("/img-to-pdf")
|
||||
@Hidden
|
||||
public String convertImgToPdfForm(Model model) {
|
||||
|
||||
@@ -59,6 +59,14 @@ public class GeneralWebController {
|
||||
.readValue(config, new TypeReference<Map<String, Object>>() {});
|
||||
|
||||
String name = (String) jsonContent.get("name");
|
||||
if (name == null || name.length() < 1) {
|
||||
String filename =
|
||||
jsonFiles
|
||||
.get(pipelineConfigs.indexOf(config))
|
||||
.getFileName()
|
||||
.toString();
|
||||
name = filename.substring(0, filename.lastIndexOf('.'));
|
||||
}
|
||||
Map<String, String> configWithName = new HashMap<>();
|
||||
configWithName.put("json", config);
|
||||
configWithName.put("name", name);
|
||||
|
||||
@@ -1,15 +1,27 @@
|
||||
package stirling.software.SPDF.controller.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
|
||||
import stirling.software.SPDF.model.ApplicationProperties;
|
||||
import stirling.software.SPDF.model.Dependency;
|
||||
|
||||
@Controller
|
||||
public class HomeWebController {
|
||||
@@ -21,6 +33,24 @@ public class HomeWebController {
|
||||
return "about";
|
||||
}
|
||||
|
||||
@GetMapping("/licenses")
|
||||
@Hidden
|
||||
public String licensesForm(Model model) {
|
||||
model.addAttribute("currentPage", "licenses");
|
||||
Resource resource = new ClassPathResource("static/3rdPartyLicenses.json");
|
||||
try {
|
||||
InputStream is = resource.getInputStream();
|
||||
String json = new String(is.readAllBytes(), StandardCharsets.UTF_8);
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
Map<String, List<Dependency>> data =
|
||||
mapper.readValue(json, new TypeReference<Map<String, List<Dependency>>>() {});
|
||||
model.addAttribute("dependencies", data.get("dependencies"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "licenses";
|
||||
}
|
||||
|
||||
@GetMapping("/")
|
||||
public String home(Model model) {
|
||||
model.addAttribute("currentPage", "home");
|
||||
|
||||
@@ -210,6 +210,7 @@ public class ApplicationProperties {
|
||||
private String rootURIPath;
|
||||
private String customStaticFilePath;
|
||||
private Integer maxFileSize;
|
||||
private CustomApplications customApplications;
|
||||
|
||||
private Boolean enableAlphaFunctionality;
|
||||
|
||||
@@ -261,6 +262,14 @@ public class ApplicationProperties {
|
||||
this.maxFileSize = maxFileSize;
|
||||
}
|
||||
|
||||
public CustomApplications getCustomApplications() {
|
||||
return customApplications != null ? customApplications : new CustomApplications();
|
||||
}
|
||||
|
||||
public void setCustomApplications(CustomApplications customApplications) {
|
||||
this.customApplications = customApplications;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "System [defaultLocale="
|
||||
@@ -273,10 +282,42 @@ public class ApplicationProperties {
|
||||
+ customStaticFilePath
|
||||
+ ", maxFileSize="
|
||||
+ maxFileSize
|
||||
+ ", customApplications="
|
||||
+ customApplications
|
||||
+ ", enableAlphaFunctionality="
|
||||
+ enableAlphaFunctionality
|
||||
+ "]";
|
||||
}
|
||||
|
||||
public static class CustomApplications {
|
||||
private boolean installBookFormats;
|
||||
private boolean installAdvancedHtmlToPDF;
|
||||
|
||||
public boolean isInstallBookFormats() {
|
||||
return installBookFormats;
|
||||
}
|
||||
|
||||
public void setInstallBookFormats(boolean installBookFormats) {
|
||||
this.installBookFormats = installBookFormats;
|
||||
}
|
||||
|
||||
public boolean isInstallAdvancedHtmlToPDF() {
|
||||
return installAdvancedHtmlToPDF;
|
||||
}
|
||||
|
||||
public void setInstallAdvancedHtmlToPDF(boolean installAdvancedHtmlToPDF) {
|
||||
this.installAdvancedHtmlToPDF = installAdvancedHtmlToPDF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CustomApplications [installBookFormats="
|
||||
+ installBookFormats
|
||||
+ ", installAdvancedHtmlToPDF="
|
||||
+ installAdvancedHtmlToPDF
|
||||
+ "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Ui {
|
||||
|
||||
12
src/main/java/stirling/software/SPDF/model/Dependency.java
Normal file
12
src/main/java/stirling/software/SPDF/model/Dependency.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package stirling.software.SPDF.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class Dependency {
|
||||
private String moduleName;
|
||||
private String moduleUrl;
|
||||
private String moduleVersion;
|
||||
private String moduleLicense;
|
||||
private String moduleLicenseUrl;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package stirling.software.SPDF.model.api.converters;
|
||||
|
||||
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 PdfToBookRequest extends PDFFile {
|
||||
|
||||
@Schema(
|
||||
description = "The output Ebook format",
|
||||
allowableValues = {
|
||||
"epub", "mobi", "azw3", "docx", "rtf", "txt", "html", "lit", "fb2", "pdb", "lrf"
|
||||
})
|
||||
private String outputFormat;
|
||||
}
|
||||
@@ -14,7 +14,7 @@ public class SignPDFWithCertRequest extends PDFFile {
|
||||
|
||||
@Schema(
|
||||
description = "The type of the digital certificate",
|
||||
allowableValues = {"PKCS12", "PEM"})
|
||||
allowableValues = {"PEM", "PKCS12", "JKS"})
|
||||
private String certType;
|
||||
|
||||
@Schema(
|
||||
@@ -28,6 +28,9 @@ public class SignPDFWithCertRequest extends PDFFile {
|
||||
@Schema(description = "The PKCS12 keystore file (required for PKCS12 type certificates)")
|
||||
private MultipartFile p12File;
|
||||
|
||||
@Schema(description = "The JKS keystore file (Java Key Store)")
|
||||
private MultipartFile jksFile;
|
||||
|
||||
@Schema(description = "The password for the keystore or the private key")
|
||||
private String password;
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@ import java.util.zip.ZipInputStream;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||
|
||||
public class FileToPdf {
|
||||
public static byte[] convertHtmlToPdf(byte[] fileBytes, String fileName)
|
||||
|
||||
public static byte[] convertHtmlToPdf(
|
||||
byte[] fileBytes, String fileName, boolean htmlFormatsInstalled)
|
||||
throws IOException, InterruptedException {
|
||||
|
||||
Path tempOutputFile = Files.createTempFile("output_", ".pdf");
|
||||
@@ -29,11 +31,22 @@ public class FileToPdf {
|
||||
}
|
||||
|
||||
List<String> command = new ArrayList<>();
|
||||
command.add("weasyprint");
|
||||
if (!htmlFormatsInstalled) {
|
||||
command.add("weasyprint");
|
||||
} else {
|
||||
command.add("wkhtmltopdf");
|
||||
command.add("--enable-local-file-access");
|
||||
}
|
||||
|
||||
command.add(tempInputFile.toString());
|
||||
command.add(tempOutputFile.toString());
|
||||
ProcessExecutorResult returnCode;
|
||||
if (fileName.endsWith(".zip")) {
|
||||
|
||||
if (htmlFormatsInstalled) {
|
||||
// command.add(1, "--allow");
|
||||
// command.add(2, tempInputFile.getParent().toString());
|
||||
}
|
||||
returnCode =
|
||||
ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
|
||||
.runCommandWithOutputHandling(
|
||||
@@ -97,4 +110,38 @@ public class FileToPdf {
|
||||
return htmlFiles.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] convertBookTypeToPdf(byte[] bytes, String originalFilename)
|
||||
throws IOException, InterruptedException {
|
||||
if (originalFilename == null || originalFilename.lastIndexOf('.') == -1) {
|
||||
throw new IllegalArgumentException("Invalid original filename.");
|
||||
}
|
||||
|
||||
String fileExtension = originalFilename.substring(originalFilename.lastIndexOf('.'));
|
||||
List<String> command = new ArrayList<>();
|
||||
Path tempOutputFile = Files.createTempFile("output_", ".pdf");
|
||||
Path tempInputFile = null;
|
||||
|
||||
try {
|
||||
// Create temp file with appropriate extension
|
||||
tempInputFile = Files.createTempFile("input_", fileExtension);
|
||||
Files.write(tempInputFile, bytes);
|
||||
|
||||
command.add("ebook-convert");
|
||||
command.add(tempInputFile.toString());
|
||||
command.add(tempOutputFile.toString());
|
||||
|
||||
ProcessExecutorResult returnCode =
|
||||
ProcessExecutor.getInstance(ProcessExecutor.Processes.CALIBRE)
|
||||
.runCommandWithOutputHandling(command);
|
||||
|
||||
return Files.readAllBytes(tempOutputFile);
|
||||
} finally {
|
||||
// Clean up temporary files
|
||||
if (tempInputFile != null) {
|
||||
Files.deleteIfExists(tempInputFile);
|
||||
}
|
||||
Files.deleteIfExists(tempOutputFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,26 +4,39 @@ import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ProcessExecutor {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ProcessExecutor.class);
|
||||
|
||||
public enum Processes {
|
||||
LIBRE_OFFICE,
|
||||
OCR_MY_PDF,
|
||||
PYTHON_OPENCV,
|
||||
GHOSTSCRIPT,
|
||||
WEASYPRINT
|
||||
WEASYPRINT,
|
||||
INSTALL_APP,
|
||||
CALIBRE
|
||||
}
|
||||
|
||||
private static final Map<Processes, ProcessExecutor> instances = new ConcurrentHashMap<>();
|
||||
|
||||
public static ProcessExecutor getInstance(Processes processType) {
|
||||
return getInstance(processType, true);
|
||||
}
|
||||
|
||||
public static ProcessExecutor getInstance(Processes processType, boolean liveUpdates) {
|
||||
return instances.computeIfAbsent(
|
||||
processType,
|
||||
key -> {
|
||||
@@ -34,15 +47,32 @@ public class ProcessExecutor {
|
||||
case PYTHON_OPENCV -> 8;
|
||||
case GHOSTSCRIPT -> 16;
|
||||
case WEASYPRINT -> 16;
|
||||
case INSTALL_APP -> 1;
|
||||
case CALIBRE -> 1;
|
||||
};
|
||||
return new ProcessExecutor(semaphoreLimit);
|
||||
|
||||
long timeoutMinutes =
|
||||
switch (key) {
|
||||
case LIBRE_OFFICE -> 30;
|
||||
case OCR_MY_PDF -> 30;
|
||||
case PYTHON_OPENCV -> 30;
|
||||
case GHOSTSCRIPT -> 5;
|
||||
case WEASYPRINT -> 30;
|
||||
case INSTALL_APP -> 60;
|
||||
case CALIBRE -> 30;
|
||||
};
|
||||
return new ProcessExecutor(semaphoreLimit, liveUpdates, timeoutMinutes);
|
||||
});
|
||||
}
|
||||
|
||||
private final Semaphore semaphore;
|
||||
private final boolean liveUpdates;
|
||||
private long timeoutDuration;
|
||||
|
||||
private ProcessExecutor(int semaphoreLimit) {
|
||||
private ProcessExecutor(int semaphoreLimit, boolean liveUpdates, long timeout) {
|
||||
this.semaphore = new Semaphore(semaphoreLimit);
|
||||
this.liveUpdates = liveUpdates;
|
||||
this.timeoutDuration = timeout;
|
||||
}
|
||||
|
||||
public ProcessExecutorResult runCommandWithOutputHandling(List<String> command)
|
||||
@@ -52,12 +82,12 @@ public class ProcessExecutor {
|
||||
|
||||
public ProcessExecutorResult runCommandWithOutputHandling(
|
||||
List<String> command, File workingDirectory) throws IOException, InterruptedException {
|
||||
int exitCode = 1;
|
||||
String messages = "";
|
||||
int exitCode = 1;
|
||||
semaphore.acquire();
|
||||
try {
|
||||
|
||||
System.out.print("Running command: " + String.join(" ", command));
|
||||
logger.info("Running command: " + String.join(" ", command));
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
||||
|
||||
// Use the working directory if it's set
|
||||
@@ -81,7 +111,11 @@ public class ProcessExecutor {
|
||||
String line;
|
||||
while ((line = errorReader.readLine()) != null) {
|
||||
errorLines.add(line);
|
||||
if (liveUpdates) logger.info(line);
|
||||
}
|
||||
} catch (InterruptedIOException e) {
|
||||
logger.warn(
|
||||
"Error reader thread was interrupted due to timeout.");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -98,7 +132,11 @@ public class ProcessExecutor {
|
||||
String line;
|
||||
while ((line = outputReader.readLine()) != null) {
|
||||
outputLines.add(line);
|
||||
if (liveUpdates) logger.info(line);
|
||||
}
|
||||
} catch (InterruptedIOException e) {
|
||||
logger.warn(
|
||||
"Error reader thread was interrupted due to timeout.");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -108,29 +146,42 @@ public class ProcessExecutor {
|
||||
outputReaderThread.start();
|
||||
|
||||
// Wait for the conversion process to complete
|
||||
exitCode = process.waitFor();
|
||||
boolean finished = process.waitFor(timeoutDuration, TimeUnit.MINUTES);
|
||||
|
||||
if (!finished) {
|
||||
// Terminate the process
|
||||
process.destroy();
|
||||
// Interrupt the reader threads
|
||||
errorReaderThread.interrupt();
|
||||
outputReaderThread.interrupt();
|
||||
throw new IOException("Process timeout exceeded.");
|
||||
}
|
||||
exitCode = process.exitValue();
|
||||
// Wait for the reader threads to finish
|
||||
errorReaderThread.join();
|
||||
outputReaderThread.join();
|
||||
|
||||
if (outputLines.size() > 0) {
|
||||
String outputMessage = String.join("\n", outputLines);
|
||||
messages += outputMessage;
|
||||
System.out.println("Command output:\n" + outputMessage);
|
||||
}
|
||||
|
||||
if (errorLines.size() > 0) {
|
||||
String errorMessage = String.join("\n", errorLines);
|
||||
messages += errorMessage;
|
||||
System.out.println("Command error output:\n" + errorMessage);
|
||||
if (exitCode != 0) {
|
||||
throw new IOException(
|
||||
"Command process failed with exit code "
|
||||
+ exitCode
|
||||
+ ". Error message: "
|
||||
+ errorMessage);
|
||||
if (!liveUpdates) {
|
||||
if (outputLines.size() > 0) {
|
||||
String outputMessage = String.join("\n", outputLines);
|
||||
messages += outputMessage;
|
||||
logger.info("Command output:\n" + outputMessage);
|
||||
}
|
||||
|
||||
if (errorLines.size() > 0) {
|
||||
String errorMessage = String.join("\n", errorLines);
|
||||
messages += errorMessage;
|
||||
logger.warn("Command error output:\n" + errorMessage);
|
||||
if (exitCode != 0) {
|
||||
throw new IOException(
|
||||
"Command process failed with exit code "
|
||||
+ exitCode
|
||||
+ ". Error message: "
|
||||
+ errorMessage);
|
||||
}
|
||||
}
|
||||
} else if (exitCode != 0) {
|
||||
throw new IOException("Command process failed with exit code " + exitCode);
|
||||
}
|
||||
} finally {
|
||||
semaphore.release();
|
||||
|
||||
@@ -9,6 +9,7 @@ public class RequestUriUtils {
|
||||
|| requestURI.startsWith("/images/")
|
||||
|| requestURI.startsWith("/public/")
|
||||
|| requestURI.startsWith("/pdfjs/")
|
||||
|| requestURI.endsWith(".svg");
|
||||
|| requestURI.endsWith(".svg")
|
||||
|| requestURI.startsWith("/api/v1/info/status");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
fileToPDF.fileTypesList=Microsoft Word: (DOC, DOCX, DOT, DOTX) <br> \
|
||||
fileToPDF.fileTypesList=Microsoft Word: (DOC, DOCX, DOT, DOTX) <br> \
|
||||
Microsoft Excel: (CSV, XLS, XLSX, XLT, XLTX, SLK, DIF) <br> \
|
||||
Microsoft PowerPoint: (PPT, PPTX) <br> \
|
||||
OpenDocument Formats: (ODT, OTT, ODS, OTS, ODP, OTP, ODG, OTG) <br> \
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Credentials changed!
|
||||
notAuthenticatedMessage=User not authenticated.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=Submit
|
||||
certSign.title=توقيع الشهادة
|
||||
certSign.header=قم بتوقيع ملف 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.selectKey=حدد ملف المفتاح الخاص (تنسيق PKCS # 8 ، يمكن أن يكون .pem أو .der):
|
||||
certSign.selectCert=حدد ملف الشهادة الخاص بك (تنسيق X.509 ، يمكن أن يكون .pem أو .der):
|
||||
certSign.selectP12=حدد ملف تخزين المفاتيح PKCS # 12 (.p12 أو .pfx) (اختياري ، إذا تم توفيره ، يجب أن يحتوي على مفتاحك الخاص وشهادتك):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=نوع الشهادة
|
||||
certSign.password=أدخل ملف تخزين المفاتيح أو كلمة المرور الخاصة (إن وجدت):
|
||||
certSign.showSig=إظهار التوقيع
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Червено
|
||||
green=Зелено
|
||||
blue=Синьо
|
||||
custom=Персонализиране...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Идентификационните данни са променени!
|
||||
notAuthenticatedMessage=Потребителят не е автентикиран.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=Текущата парола е неправилна.
|
||||
usernameExistsMessage=Новият потребител вече съществува.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=Подайте
|
||||
certSign.title=Подписване на сертификат
|
||||
certSign.header=Подпишете 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.selectKey=Изберете вашия файл с личен ключ (формат PKCS#8, може да бъде .pem или .der):
|
||||
certSign.selectCert=Изберете вашия файл със сертификат (формат X.509, може да бъде .pem или .der):
|
||||
certSign.selectP12=Изберете вашия PKCS#12 Keystore файл (.p12 или .pfx) (По избор, ако е предоставен, трябва да съдържа вашия личен ключ и сертификат):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Тип сертификат
|
||||
certSign.password=Въведете вашата парола за Keystore за ключове или частен ключ (ако има):
|
||||
certSign.showSig=Показване на подпис
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Vermell
|
||||
green=Verd
|
||||
blue=Blau
|
||||
custom=Personalitzat...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Credentials changed!
|
||||
notAuthenticatedMessage=User not authenticated.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=Submit
|
||||
certSign.title=Significació del certificat
|
||||
certSign.header=Firmar un PDF amb el vostre certificat (Treball en curs)
|
||||
certSign.selectPDF=Seleccioneu un fitxer PDF per signar:
|
||||
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.selectKey=Seleccioneu el vostre fitxer de clau privada (format PKCS#8, podria ser .pem o .der):
|
||||
certSign.selectCert=Seleccioneu el vostre fitxer de certificat (format X.509, podria ser .pem o .der):
|
||||
certSign.selectP12=Seleccioneu el vostre fitxer de magatzem de claus PKCS#12 (.p12 o .pfx) (Opcional, si es proporciona, hauria de contenir la vostra clau privada i certificat):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Tipus de certificat
|
||||
certSign.password=Introduïu el vostre magatzem de claus o contrasenya de clau privada (si n'hi ha):
|
||||
certSign.showSig=Mostra la signatura
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Rot
|
||||
green=Grün
|
||||
blue=Blau
|
||||
custom=benutzerdefiniert...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Anmeldedaten geändert!
|
||||
notAuthenticatedMessage=Benutzer nicht authentifiziert.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=Das Passwort ist falsch.
|
||||
usernameExistsMessage=Neuer Benutzername existiert bereits.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=Abschicken
|
||||
certSign.title=Zertifikatsignierung
|
||||
certSign.header=Signieren Sie ein PDF mit Ihrem Zertifikat (in Arbeit)
|
||||
certSign.selectPDF=Wählen Sie eine PDF-Datei zum Signieren aus:
|
||||
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.selectKey=Wählen Sie Ihre private Schlüsseldatei aus (PKCS#8-Format, könnte .pem oder .der sein):
|
||||
certSign.selectCert=Wählen Sie Ihre Zertifikatsdatei aus (X.509-Format, könnte .pem oder .der sein):
|
||||
certSign.selectP12=Wählen Sie Ihre PKCS#12-Keystore-Datei (.p12 oder .pfx) aus (optional, falls angegeben, sollte sie Ihren privaten Schlüssel und Ihr Zertifikat enthalten):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Zertifikattyp
|
||||
certSign.password=Geben Sie Ihr Keystore- oder Private-Key-Passwort ein (falls vorhanden):
|
||||
certSign.showSig=Signatur anzeigen
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=\u039A\u03CC\u03BA\u03BA\u03B9\u03BD\u03BF
|
||||
green=\u03A0\u03C1\u03AC\u03C3\u03B9\u03BD\u03BF
|
||||
blue=\u039C\u03C0\u03BB\u03AD
|
||||
custom=\u03A0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03B3\u03AE...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=\u03A4\u03B1 \u03B4\u03B9\u03B1\u03C0\u03B9\u03C3\u03C4\u03B5\u03C5\u03C4\u03AE\u03C1\u03B9\u03B1 \u03AD\u03C7\u03BF\u03C5\u03BD \u03B1\u03BB\u03BB\u03AC\u03BE\u03B5\u03B9!
|
||||
notAuthenticatedMessage=\u039F \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7\u03C2 \u03B4\u03B5\u03BD \u03AD\u03C7\u03B5\u03B9 \u03B1\u03C5\u03B8\u03B5\u03BD\u03C4\u03B9\u03BA\u03BF\u03C0\u03BF\u03B9\u03B7\u03B8\u03B5\u03AF.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=\u039F \u03C4\u03C1\u03AD\u03C7\u03C9\u03BD \u03BA\u03C
|
||||
usernameExistsMessage=\u03A4\u03BF \u03BD\u03AD\u03BF \u03CC\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 \u03C5\u03C0\u03AC\u03C1\u03C7\u03B5\u03B9 \u03AE\u03B4\u03B7.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=\u03A5\u03C0\u03BF\u03B2\u03BF\u03BB\u03AE
|
||||
certSign.title=\u03A5\u03C0\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE \u03A0\u03B9\u03C3\u03C4\u03BF\u03C0\u03BF\u03B9\u03B7\u03C4\u03B9\u03BA\u03BF\u03CD
|
||||
certSign.header=\u03A5\u03C0\u03BF\u03B3\u03C1\u03AC\u03C8\u03C4\u03B5 \u03AD\u03BD\u03B1 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF PDF \u03BC\u03B5 \u03C4\u03BF \u03C0\u03B9\u03C3\u03C4\u03BF\u03C0\u03BF\u03B9\u03B7\u03C4\u03B9\u03BA\u03CC \u03C3\u03B1\u03C2 (\u0395\u03C1\u03B3\u03B1\u03C3\u03AF\u03B1 \u03C3\u03B5 \u03B5\u03BE\u03AD\u03BB\u03B9\u03BE\u03B7)
|
||||
certSign.selectPDF=\u0395\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5 PDF \u03B3\u03B9\u03B1 \u03C5\u03C0\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE:
|
||||
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.selectKey=\u0395\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 \u03C4\u03BF \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF \u03C4\u03BF\u03C5 \u03B9\u03B4\u03B9\u03C9\u03C4\u03B9\u03BA\u03BF\u03CD \u03BA\u03BB\u03B5\u03B9\u03B4\u03B9\u03BF\u03CD \u03C3\u03B1\u03C2 (\u03BC\u03BF\u03C1\u03C6\u03AE PKCS#8, \u03BC\u03C0\u03BF\u03C1\u03B5\u03AF \u03BD\u03B1 \u03B5\u03AF\u03BD\u03B1\u03B9 .pem \u03AE .der):
|
||||
certSign.selectCert=\u0395\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 \u03C4\u03BF \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF \u03C0\u03B9\u03C3\u03C4\u03BF\u03C0\u03BF\u03B9\u03B7\u03C4\u03B9\u03BA\u03BF\u03CD \u03C3\u03B1\u03C2 (\u03BC\u03BF\u03C1\u03C6\u03AE X.509, \u03BC\u03C0\u03BF\u03C1\u03B5\u03AF \u03BD\u03B1 \u03B5\u03AF\u03BD\u03B1\u03B9 .pem \u03AE .der):
|
||||
certSign.selectP12=\u0395\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 \u03C4\u03BF \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF PKCS#12 Keystore (.p12 \u03AE .pfx) (\u03A0\u03C1\u03BF\u03B1\u03B9\u03C1\u03B5\u03C4\u03B9\u03BA\u03CC, \u03B5\u03AC\u03BD \u03C0\u03B1\u03C1\u03AD\u03C7\u03B5\u03C4\u03B1\u03B9, \u03B8\u03B1 \u03C0\u03C1\u03AD\u03C0\u03B5\u03B9 \u03BD\u03B1 \u03C0\u03B5\u03C1\u03B9\u03AD\u03C7\u03B5\u03B9 \u03C4\u03BF \u03B9\u03B4\u03B9\u03C9\u03C4\u03B9\u03BA\u03CC \u03BA\u03BB\u03B5\u03B9\u03B4\u03AF \u03BA\u03B1\u03B9 \u03C4\u03BF \u03C0\u03B9\u03C3\u03C4\u03BF\u03C0\u03BF\u03B9\u03B7\u03C4\u03B9\u03BA\u03CC \u03C3\u03B1\u03C2):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=\u03A4\u03CD\u03C0\u03BF\u03C2 \u03A0\u03B9\u03C3\u03C4\u03BF\u03C0\u03BF\u03B9\u03B7\u03C4\u03B9\u03BA\u03BF\u03CD
|
||||
certSign.password=\u0395\u03B9\u03C3\u03B1\u03B3\u03AC\u03B3\u03B5\u03C4\u03B5 \u03C4\u03BF\u03BD \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC \u03C4\u03BF\u03C5 Keystore \u03AE \u03C4\u03BF\u03C5 \u0399\u03B4\u03B9\u03C9\u03C4\u03B9\u03BA\u03BF\u03CD \u039A\u03BB\u03B5\u03B9\u03B4\u03B9\u03BF\u03CD (\u03B5\u03AC\u03BD \u03C5\u03C0\u03AC\u03C1\u03C7\u03B5\u03B9):
|
||||
certSign.showSig=\u0395\u03BC\u03C6\u03AC\u03BD\u03B9\u03C3\u03B7 \u03A5\u03C0\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE\u03C2
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr = left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Credentials changed!
|
||||
notAuthenticatedMessage=User not authenticated.
|
||||
@@ -50,6 +52,30 @@ incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.selectOperation=Select Operation
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +548,11 @@ scalePages.submit=Submit
|
||||
certSign.title=Certificate Signing
|
||||
certSign.header=Sign a PDF with your certificate (Work in progress)
|
||||
certSign.selectPDF=Select a PDF File for Signing:
|
||||
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.selectKey=Select Your Private Key File (PKCS#8 format, could be .pem or .der):
|
||||
certSign.selectCert=Select Your Certificate File (X.509 format, could be .pem or .der):
|
||||
certSign.selectP12=Select Your PKCS#12 Keystore File (.p12 or .pfx) (Optional, If provided, it should contain your private key and certificate):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Certificate Type
|
||||
certSign.password=Enter Your Keystore or Private Key Password (If Any):
|
||||
certSign.showSig=Show Signature
|
||||
@@ -894,3 +922,14 @@ split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Credentials changed!
|
||||
notAuthenticatedMessage=User not authenticated.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=Submit
|
||||
certSign.title=Certificate Signing
|
||||
certSign.header=Sign a PDF with your certificate (Work in progress)
|
||||
certSign.selectPDF=Select a PDF File for Signing:
|
||||
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.selectKey=Select Your Private Key File (PKCS#8 format, could be .pem or .der):
|
||||
certSign.selectCert=Select Your Certificate File (X.509 format, could be .pem or .der):
|
||||
certSign.selectP12=Select Your PKCS#12 Keystore File (.p12 or .pfx) (Optional, If provided, it should contain your private key and certificate):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Certificate Type
|
||||
certSign.password=Enter Your Keystore or Private Key Password (If Any):
|
||||
certSign.showSig=Show Signature
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Rojo
|
||||
green=Verde
|
||||
blue=Azul
|
||||
custom=Personalizado...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Se cambiaron las credenciales!
|
||||
notAuthenticatedMessage=Usuario no autentificado.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=La contraseña actual no es correcta.
|
||||
usernameExistsMessage=El nuevo nombre de usuario está en uso.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=Entregar
|
||||
certSign.title=Firma con certificado
|
||||
certSign.header=Firmar un PDF con su certificado (en desarrollo)
|
||||
certSign.selectPDF=Seleccione un archivo PDF para firmar:
|
||||
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.selectKey=Seleccione su archivo de clave privada (formato PKCS#8, podría ser .pem o .der):
|
||||
certSign.selectCert=Seleccione su archivo de certificado (formato X.509, podría ser .pem o .der):
|
||||
certSign.selectP12=Seleccione su archivo de almacén de claves PKCS#12 (.p12 o .pfx) (Opcional, si se proporciona, debe contener su clave privada y certificado):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Tipo de certificado
|
||||
certSign.password=Introduzca su almacén de claves o contraseña de clave privada (si corresponde):
|
||||
certSign.showSig=Mostrar firma
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Divisiones Verticales
|
||||
split-by-sections.horizontal.placeholder=Introduzca el número de divisiones horizontales
|
||||
split-by-sections.vertical.placeholder=Introduzca el número de divisiones verticales
|
||||
split-by-sections.submit=Dividir PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Gorria
|
||||
green=Berdea
|
||||
blue=Urdina
|
||||
custom=Pertsonalizatu...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Credentials changed!
|
||||
notAuthenticatedMessage=User not authenticated.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=Entregatu
|
||||
certSign.title=Ziurtagiriaren sinadura
|
||||
certSign.header=Sinatu PDF bat haren ziurtagiriarekin (lanean)
|
||||
certSign.selectPDF=Hautatu PDF fitxategi bat sinatzeko:
|
||||
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.selectKey=Hautatu gako pribatuko fitxategia (PKCS#8 formatua, .pem edo .der izan liteke):
|
||||
certSign.selectCert=Hautatu ziurtagiridun fitxategia (X.509 formatua, .pem edo .der izan liteke):
|
||||
certSign.selectP12=Hautatu gakoak gordetzeko fitxategia PKCS#12 (.p12 o .pfx) (Aukerakoa, ematen bada, gako pribatua eta ziurtagiria izan beharko ditu):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Ziurtagiri-mota
|
||||
certSign.password=Sartu zure gakoen biltegia edo gako pribatuko pasahitza (hala badagokio):
|
||||
certSign.showSig=Erakutsi sinadura
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Rouge
|
||||
green=Vert
|
||||
blue=Bleu
|
||||
custom=Personnalisé\u2026
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Les identifiants ont été mis à jour\u00a0!
|
||||
notAuthenticatedMessage=Utilisateur non authentifié.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=Le mot de passe actuel est incorrect.
|
||||
usernameExistsMessage=Le nouveau nom d\u2019utilisateur existe déjà.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=Ajuster
|
||||
certSign.title=Signer avec un certificat
|
||||
certSign.header=Signer avec un certificat (Travail en cours)
|
||||
certSign.selectPDF=PDF à signer
|
||||
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.selectKey=Fichier de clé privée (format PKCS#8, peut être .pem ou .der)
|
||||
certSign.selectCert=Fichier de certificat (format X.509, peut être .pem ou .der)
|
||||
certSign.selectP12=Fichier keystore de clés PKCS#12 (.p12 ou .pfx) (facultatif, s\u2019il n\u2019est fourni, il doit contenir votre clé privée et votre certificat)
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Type de certificat
|
||||
certSign.password=Mot de passe keystore ou clé privée le cas échéant
|
||||
certSign.showSig=Afficher la signature
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Divisions verticales
|
||||
split-by-sections.horizontal.placeholder=Saisir le nombre de divisions horizontales
|
||||
split-by-sections.vertical.placeholder=Entrer le nombre de divisions verticales
|
||||
split-by-sections.submit=Diviser le PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=लाल
|
||||
green=हरा
|
||||
blue=नीला
|
||||
custom=कस्टम...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=क्रेडेंशियल्स बदल दी गईं!
|
||||
notAuthenticatedMessage=उपयोगकर्ता प्रमाणित नहीं है।
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=वर्तमान पासवर्ड गलत
|
||||
usernameExistsMessage=नया उपयोगकर्ता नाम पहले से मौजूद है।
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=प्रस्तुत करें
|
||||
certSign.title=प्रमाणपत्र साइनिंग
|
||||
certSign.header=अपने प्रमाणपत्र के साथ एक पीडीएफ़ पर हस्ताक्षर करें (काम जारी है)
|
||||
certSign.selectPDF=साइन करने के लिए एक पीडीएफ़ फ़ाइल का चयन करें:
|
||||
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.selectKey=अपनी निजी कुंजी फ़ाइल का चयन करें (PKCS#8 प्रारूप, .pem या .der हो सकता है):
|
||||
certSign.selectCert=अपनी प्रमाणपत्र फ़ाइल का चयन करें (X.509 प्रारूप, .pem या .der हो सकता है):
|
||||
certSign.selectP12=अपनी PKCS#12 कीस्टोर फ़ाइल का चयन करें (.p12 या .pfx) (वैकल्पिक, यदि प्रदान की गई हो, तो इसमें आपकी निजी कुंजी और प्रमाणपत्र होना चाहिए):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=प्रमाणपत्र प्रकार
|
||||
certSign.password=अपनी कीस्टोर या निजी कुंजी पासवर्ड दर्ज करें (यदि कोई हो):
|
||||
certSign.showSig=हस्ताक्षर दिखाएं
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=लंबवत विभाजन
|
||||
split-by-sections.horizontal.placeholder=क्षैतिज विभाजन की संख्या दर्ज करें
|
||||
split-by-sections.vertical.placeholder=लंबवत विभाजन की संख्या दर्ज करें
|
||||
split-by-sections.submit=PDF को विभाजित करें
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Piros
|
||||
green=Zöld
|
||||
blue=Kék
|
||||
custom=Egyedi...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=A hitelek megváltoztak!
|
||||
notAuthenticatedMessage=Felhasználó nincs hitelesítve.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=A jelenlegi jelszó helytelen.
|
||||
usernameExistsMessage=Az új felhasználónév már létezik.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=Küldés
|
||||
certSign.title=Tanúsítvánnyal történő aláírás
|
||||
certSign.header=Aláírás PDF tanúsítvánnyal (fejlesztés alatt)
|
||||
certSign.selectPDF=Válasszon PDF fájlt az aláíráshoz:
|
||||
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.selectKey=Válassza ki a saját kulcsfájlját (PKCS#8 formátum, lehet .pem vagy .der kiterjesztésű):
|
||||
certSign.selectCert=Válassza ki a tanúsítványfájlját (X.509 formátum, lehet .pem vagy .der kiterjesztésű):
|
||||
certSign.selectP12=Válassza ki a PKCS#12 kulcstár fájlját (.p12 vagy .pfx) (Opcionális, ha rendelkezésre áll, tartalmaznia kell a privát kulcsot és a tanúsítványt.):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Tanúsítvány típusa
|
||||
certSign.password=Adja meg a kulcstár vagy a privát kulcs jelszavát (ha van):
|
||||
certSign.showSig=Aláírás megjelenítése
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Vízszintes szakaszok
|
||||
split-by-sections.horizontal.placeholder=Adja meg a vízszintes szakaszok számát
|
||||
split-by-sections.vertical.placeholder=Adja meg a függőleges szakaszok számát
|
||||
split-by-sections.submit=Felosztás
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl=right to left)
|
||||
@@ -42,6 +42,8 @@ red=Merah
|
||||
green=Hijau
|
||||
blue=Biru
|
||||
custom=Kustom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Kredensial berubah!!
|
||||
notAuthenticatedMessage=Pengguna tidak ter-autentikasi.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=Kata sandi saat ini salah.
|
||||
usernameExistsMessage=Nama pengguna baru sudah ada.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=Kirim
|
||||
certSign.title=Penandatanganan Sertifikat
|
||||
certSign.header=Menandatangani PDF dengan sertifikat Anda (Sedang dalam proses)
|
||||
certSign.selectPDF=Pilih Berkas PDF untuk Penandatanganan:
|
||||
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.selectKey=Pilih Berkas Kunci Pribadi Anda (format PKCS # 8, bisa .pem atau .der):
|
||||
certSign.selectCert=Pilih Berkas Sertifikat Anda (format X.509, bisa .pem atau .der):
|
||||
certSign.selectP12=Pilih Berkas Keystore PKCS #12 Anda (.p12 atau .pfx) (Opsional, Jika disediakan, berkas tersebut harus berisi kunci pribadi dan sertifikat Anda):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Jenis Sertifikat
|
||||
certSign.password=Masukkan Kata Sandi Kunci atau Kunci Pribadi Anda (Jika Ada):
|
||||
certSign.showSig=Tampilkan Tanda Tangan
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Pembagian Vertikal
|
||||
split-by-sections.horizontal.placeholder=Input angka untuk pembagian horizontal
|
||||
split-by-sections.vertical.placeholder=Input angka untuk pembagian vertikal
|
||||
split-by-sections.submit=Pisahkan PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Rosso
|
||||
green=Verde
|
||||
blue=Blu
|
||||
custom=Personalizzato
|
||||
WorkInProgess=Lavori in corso, potrebbe non funzionare o essere difettoso, segnalare eventuali problemi!
|
||||
poweredBy=Alimentato da
|
||||
|
||||
changedCredsMessage=Credenziali cambiate!
|
||||
notAuthenticatedMessage=Utente non autenticato.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=La password attuale non è corretta.
|
||||
usernameExistsMessage=Il nuovo nome utente esiste già.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Caricamento personalizzato
|
||||
pipeline.configureButton=Configura
|
||||
pipeline.defaultOption=Personalizzato
|
||||
pipeline.submitButton=Invia
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Configurazione Pipeline
|
||||
pipelineOptions.pipelineNameLabel=Nome della Pipeline
|
||||
pipelineOptions.saveSettings=Salva Impostazioni
|
||||
pipelineOptions.pipelineNamePrompt=Inserisci qui il nome della pipeline
|
||||
pipelineOptions.addOperationButton=Aggiungi operazione
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Convalidare
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=Invia
|
||||
certSign.title=Firma del certificato
|
||||
certSign.header=Firma un PDF con il tuo certificato (Lavoro in corso)
|
||||
certSign.selectPDF=Seleziona un file PDF per la firma:
|
||||
certSign.jksNote=Nota: se il tipo di certificato non è elencato di seguito, convertilo in un file Java Keystore (.jks) utilizzando lo strumento da riga di comando keytool. Quindi, scegli l'opzione del file .jks di seguito.
|
||||
certSign.selectKey=Seleziona il file della tua chiave privata (formato PKCS#8, potrebbe essere .pem o .der):
|
||||
certSign.selectCert=Seleziona il tuo file di certificato (formato X.509, potrebbe essere .pem o .der):
|
||||
certSign.selectP12=Selezionare il file keystore PKCS#12 (.p12 o .pfx) (facoltativo, se fornito, dovrebbe contenere la chiave privata e il certificato):
|
||||
certSign.selectJKS=Seleziona il tuo file Java Keystore (.jks o .keystore):
|
||||
certSign.certType=Tipo di certificato
|
||||
certSign.password=Inserisci la tua password dell'archivio chiavi o della chiave privata (se presente):
|
||||
certSign.showSig=Mostra firma
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Divisioni verticali
|
||||
split-by-sections.horizontal.placeholder=Inserire il numero di divisioni orizzontali
|
||||
split-by-sections.vertical.placeholder=Inserire il numero di divisioni verticali
|
||||
split-by-sections.submit=Dividi PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenze
|
||||
licenses.title=Licenze di terze parti
|
||||
licenses.header=Licenze di terze parti
|
||||
licenses.module=Modulo
|
||||
licenses.version=Versione
|
||||
licenses.license=Licenza
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=赤
|
||||
green=緑
|
||||
blue=青
|
||||
custom=カスタム...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=資格情報が変更されました!
|
||||
notAuthenticatedMessage=ユーザーが認証されていません。
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=現在のパスワードが正しくありません。
|
||||
usernameExistsMessage=新しいユーザー名はすでに存在します。
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=送信
|
||||
certSign.title=証明書による署名
|
||||
certSign.header=証明書を使用して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.selectKey=秘密キーファイルを選択 (PKCS#8形式、.pemまたは.der) :
|
||||
certSign.selectCert=証明書ファイルを選択 (X.509形式、.pemまたは.der) :
|
||||
certSign.selectP12=PKCS#12キーストアファイルを選択 (.p12または.pfx) (オプション。指定する場合は秘密キーと証明書が含まれている必要があります。):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=証明書の種類
|
||||
certSign.password=キーストアまたは秘密キーのパスワードを入力 (ある場合) :
|
||||
certSign.showSig=署名を表示
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=계정 정보 변경 성공!
|
||||
notAuthenticatedMessage=User not authenticated.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=현재 비밀번호가 틀립니다.
|
||||
usernameExistsMessage=새 사용자명이 이미 존재합니다.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=제출
|
||||
certSign.title=인증서로 서명
|
||||
certSign.header=인증서로 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.selectKey=개인 키 파일을 선택합니다 (PKCS#8 형식, .pem 또는 .der):
|
||||
certSign.selectCert=인증서 파일을 선택합니다 (X.509 형식, .pem 또는 .der):
|
||||
certSign.selectP12=PKCS#12 키 저장소 파일을 선택합니다 (.p12 or .pfx) (선택 사항, 선택할 경우, 개인 키와 인증서를 포함하고 있어야 합니다):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=인증서 유형
|
||||
certSign.password=키 저장소 또는 개인 키 비밀번호를 입력합니다 (있는 경우):
|
||||
certSign.showSig=서명 보기
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Credentials changed!
|
||||
notAuthenticatedMessage=User not authenticated.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=Indienen
|
||||
certSign.title=Certificaat ondertekening
|
||||
certSign.header=Onderteken een PDF met je certificaat (in ontwikkeling)
|
||||
certSign.selectPDF=Selecteer een PDF-bestand voor ondertekening:
|
||||
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.selectKey=Selecteer je privésleutelbestand (PKCS#8 formaat, kan .pem of .der zijn):
|
||||
certSign.selectCert=Selecteer je certificaatbestand (X.509 formaat, kan .pem of .der zijn):
|
||||
certSign.selectP12=Selecteer je PKCS#12 Sleutelopslagbestand (.p12 of .pfx) (Optioneel, indien verstrekt, moet het je privésleutel en certificaat bevatten):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Certificaattype
|
||||
certSign.password=Voer je sleutelopslag of privésleutel wachtwoord in (indien van toepassing):
|
||||
certSign.showSig=Toon handtekening
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Credentials changed!
|
||||
notAuthenticatedMessage=User not authenticated.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=Wykonaj
|
||||
certSign.title=Podpisywanie certyfikatem
|
||||
certSign.header=Podpisz dokument PDF certyfikatem prywatnym (moduł w budowie)
|
||||
certSign.selectPDF=Wybierz dokument PDF do podpisania:
|
||||
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.selectKey=Wybierz plik klucza prywatnego (format PKCS#8, może to być .pem lub .der):
|
||||
certSign.selectCert=Wybierz plik certyfikatu (format X.509, może to być .pem lub .der):
|
||||
certSign.selectP12=Wybierz plik magazynu kluczy PKCS#12 (.p12 lub .pfx) (opcjonalnie, jeśli jest podany, powinien zawierać klucz prywatny i certyfikat):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Typ certyfikatu
|
||||
certSign.password=Wprowadź hasło do magazynu kluczy lub klucza prywatnego (jeśli istnieje):
|
||||
certSign.showSig=Wyświetl podpis
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Credentials changed!
|
||||
notAuthenticatedMessage=User not authenticated.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -119,6 +144,7 @@ adminUserSettings.role=Role
|
||||
adminUserSettings.actions=Actions
|
||||
adminUserSettings.apiUser=Limited API User
|
||||
adminUserSettings.webOnlyUser=Web Only User
|
||||
adminUserSettings.demoUser=Demo User (No custom settings)
|
||||
adminUserSettings.forceChange=Force user to change username/password on login
|
||||
adminUserSettings.submit=Save User
|
||||
|
||||
@@ -255,6 +281,10 @@ home.removeBlanks.title=Remover Páginas em Branco
|
||||
home.removeBlanks.desc=Detectar e remover páginas em branco de um documento
|
||||
removeBlanks.tags=limpeza,otimização,sem-conteúdo,organizar
|
||||
|
||||
home.removeAnnotations.title=Remove Annotations
|
||||
home.removeAnnotations.desc=Removes all comments/annotations from a PDF
|
||||
removeAnnotations.tags=comments,highlight,notes,markup,remove
|
||||
|
||||
home.compare.title=Comparar
|
||||
home.compare.desc=Comparar e mostrar as diferenças entre 2 documentos PDF
|
||||
compare.tags=diferenciar,contraste,mudanças,análise
|
||||
@@ -336,6 +366,24 @@ home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JavaScript
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
tableExtraxt.tags=CSV,Table Extraction,extract,convert
|
||||
|
||||
|
||||
home.autoSizeSplitPDF.title=Auto Split by Size/Count
|
||||
home.autoSizeSplitPDF.desc=Split a single PDF into multiple documents based on size, page count, or document count
|
||||
autoSizeSplitPDF.tags=pdf,split,document,organization
|
||||
|
||||
|
||||
home.overlay-pdfs.title=Overlay PDFs
|
||||
home.overlay-pdfs.desc=Overlays PDFs on-top of another PDF
|
||||
overlay-pdfs.tags=Overlay
|
||||
|
||||
home.split-by-sections.title=Split PDF by Sections
|
||||
home.split-by-sections.desc=Divide each page of a PDF into smaller horizontal and vertical sections
|
||||
split-by-sections.tags=Section Split, Divide, Customize
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
@@ -499,9 +547,11 @@ scalePages.submit=Enviar
|
||||
certSign.title=Assinatura com Certificado
|
||||
certSign.header=Assine um PDF com o seu certificado (Em desenvolvimento)
|
||||
certSign.selectPDF=Selecione um arquivo PDF para assinatura:
|
||||
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.selectKey=Selecione o seu arquivo de chave privada (formato PKCS#8, pode ser .pem ou .der):
|
||||
certSign.selectCert=Selecione o seu arquivo de certificado (formato X.509, pode ser .pem ou .der):
|
||||
certSign.selectP12=Selecione o seu arquivo de armazenamento de chave PKCS#12 (.p12 ou .pfx) (opcional, se fornecido, deve conter a sua chave privada e certificado):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Tipo de Certificado
|
||||
certSign.password=Digite a senha do seu armazenamento de chave ou chave privada (se aplicável):
|
||||
certSign.showSig=Mostrar Assinatura
|
||||
@@ -521,6 +571,12 @@ removeBlanks.whitePercentDesc=Porcentagem da página que deve ser branca para se
|
||||
removeBlanks.submit=Remover Páginas em Branco
|
||||
|
||||
|
||||
#removeAnnotations
|
||||
removeAnnotations.title=Remove Annotations
|
||||
removeAnnotations.header=Remove Annotations
|
||||
removeAnnotations.submit=Remove
|
||||
|
||||
|
||||
#compare
|
||||
compare.title=Comparar
|
||||
compare.header=Comparar PDFs
|
||||
@@ -827,4 +883,52 @@ PDFToXML.submit=Converter
|
||||
#PDFToCSV
|
||||
PDFToCSV.title=PDF para CSV
|
||||
PDFToCSV.header=PDF para CSV
|
||||
PDFToCSV.submit=Eztenna<EFBFBD>
|
||||
PDFToCSV.prompt=Choose page to extract table
|
||||
PDFToCSV.submit=Eztenna
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.header=Split PDF by Size or Count
|
||||
split-by-size-or-count.type.label=Select Split Type
|
||||
split-by-size-or-count.type.size=By Size
|
||||
split-by-size-or-count.type.pageCount=By Page Count
|
||||
split-by-size-or-count.type.docCount=By Document Count
|
||||
split-by-size-or-count.value.label=Enter Value
|
||||
split-by-size-or-count.value.placeholder=Enter size (e.g., 2MB or 3KB) or count (e.g., 5)
|
||||
split-by-size-or-count.submit=Submit
|
||||
|
||||
|
||||
#overlay-pdfs
|
||||
overlay-pdfs.header=Overlay PDF Files
|
||||
overlay-pdfs.baseFile.label=Select Base PDF File
|
||||
overlay-pdfs.overlayFiles.label=Select Overlay PDF Files
|
||||
overlay-pdfs.mode.label=Select Overlay Mode
|
||||
overlay-pdfs.mode.sequential=Sequential Overlay
|
||||
overlay-pdfs.mode.interleaved=Interleaved Overlay
|
||||
overlay-pdfs.mode.fixedRepeat=Fixed Repeat Overlay
|
||||
overlay-pdfs.counts.label=Overlay Counts (for Fixed Repeat Mode)
|
||||
overlay-pdfs.counts.placeholder=Enter comma-separated counts (e.g., 2,3,1)
|
||||
overlay-pdfs.position.label=Select Overlay Position
|
||||
overlay-pdfs.position.foreground=Foreground
|
||||
overlay-pdfs.position.background=Background
|
||||
overlay-pdfs.submit=Submit
|
||||
|
||||
|
||||
#split-by-sections
|
||||
split-by-sections.title=Split PDF by Sections
|
||||
split-by-sections.header=Split PDF into Sections
|
||||
split-by-sections.horizontal.label=Horizontal Divisions
|
||||
split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Credentials changed!
|
||||
notAuthenticatedMessage=User not authenticated.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -119,6 +144,7 @@ adminUserSettings.role=Role
|
||||
adminUserSettings.actions=Actions
|
||||
adminUserSettings.apiUser=Limited API User
|
||||
adminUserSettings.webOnlyUser=Web Only User
|
||||
adminUserSettings.demoUser=Demo User (No custom settings)
|
||||
adminUserSettings.forceChange=Force user to change username/password on login
|
||||
adminUserSettings.submit=Save User
|
||||
|
||||
@@ -255,6 +281,10 @@ home.removeBlanks.title=Elimină pagini goale
|
||||
home.removeBlanks.desc=Detectează și elimină paginile goale dintr-un document.
|
||||
removeBlanks.tags=cleanup,streamline,non-content,organize
|
||||
|
||||
home.removeAnnotations.title=Remove Annotations
|
||||
home.removeAnnotations.desc=Removes all comments/annotations from a PDF
|
||||
removeAnnotations.tags=comments,highlight,notes,markup,remove
|
||||
|
||||
home.compare.title=Compară
|
||||
home.compare.desc=Compară și arată diferențele dintre 2 documente PDF.
|
||||
compare.tags=differentiate,contrast,changes,analysis
|
||||
@@ -336,6 +366,24 @@ home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
tableExtraxt.tags=CSV,Table Extraction,extract,convert
|
||||
|
||||
|
||||
home.autoSizeSplitPDF.title=Auto Split by Size/Count
|
||||
home.autoSizeSplitPDF.desc=Split a single PDF into multiple documents based on size, page count, or document count
|
||||
autoSizeSplitPDF.tags=pdf,split,document,organization
|
||||
|
||||
|
||||
home.overlay-pdfs.title=Overlay PDFs
|
||||
home.overlay-pdfs.desc=Overlays PDFs on-top of another PDF
|
||||
overlay-pdfs.tags=Overlay
|
||||
|
||||
home.split-by-sections.title=Split PDF by Sections
|
||||
home.split-by-sections.desc=Divide each page of a PDF into smaller horizontal and vertical sections
|
||||
split-by-sections.tags=Section Split, Divide, Customize
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
@@ -499,9 +547,11 @@ scalePages.submit=Submit
|
||||
certSign.title=Semnare certificat
|
||||
certSign.header=Semnează un fișier PDF cu certificatul tău (În curs de desfășurare)
|
||||
certSign.selectPDF=Selectează un fișier PDF pentru semnare:
|
||||
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.selectKey=Selectează fișierul cheie privată (format PKCS#8, poate fi .pem sau .der):
|
||||
certSign.selectCert=Selectează fișierul de certificat (format X.509, poate fi .pem sau .der):
|
||||
certSign.selectP12=Selectează fișierul de stocare cheie PKCS#12 (.p12 sau .pfx) (Opțional, dacă este furnizat, ar trebui să conțină cheia privată și certificatul tău):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Tipul certificatului
|
||||
certSign.password=Introdu parola pentru stocarea cheie sau cheia privată (dacă există):
|
||||
certSign.showSig=Afișează semnătura
|
||||
@@ -521,6 +571,12 @@ removeBlanks.whitePercentDesc=Procentul paginii care trebuie să fie alb pentru
|
||||
removeBlanks.submit=Elimină pagini goale
|
||||
|
||||
|
||||
#removeAnnotations
|
||||
removeAnnotations.title=Remove Annotations
|
||||
removeAnnotations.header=Remove Annotations
|
||||
removeAnnotations.submit=Remove
|
||||
|
||||
|
||||
#compare
|
||||
compare.title=Compară
|
||||
compare.header=Compară PDF-uri
|
||||
@@ -825,6 +881,54 @@ PDFToXML.credit=Acest serviciu utilizează LibreOffice pentru conversia fișieru
|
||||
PDFToXML.submit=Convert
|
||||
|
||||
#PDFToCSV
|
||||
PDFToCSV.title=PDF în CSV
|
||||
PDFToCSV.header=PDF în CSV
|
||||
PDFToCSV.title=PDF <EFBFBD>n CSV
|
||||
PDFToCSV.header=PDF <EFBFBD>n CSV
|
||||
PDFToCSV.prompt=Choose page to extract table
|
||||
PDFToCSV.submit=Extrage
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.header=Split PDF by Size or Count
|
||||
split-by-size-or-count.type.label=Select Split Type
|
||||
split-by-size-or-count.type.size=By Size
|
||||
split-by-size-or-count.type.pageCount=By Page Count
|
||||
split-by-size-or-count.type.docCount=By Document Count
|
||||
split-by-size-or-count.value.label=Enter Value
|
||||
split-by-size-or-count.value.placeholder=Enter size (e.g., 2MB or 3KB) or count (e.g., 5)
|
||||
split-by-size-or-count.submit=Submit
|
||||
|
||||
|
||||
#overlay-pdfs
|
||||
overlay-pdfs.header=Overlay PDF Files
|
||||
overlay-pdfs.baseFile.label=Select Base PDF File
|
||||
overlay-pdfs.overlayFiles.label=Select Overlay PDF Files
|
||||
overlay-pdfs.mode.label=Select Overlay Mode
|
||||
overlay-pdfs.mode.sequential=Sequential Overlay
|
||||
overlay-pdfs.mode.interleaved=Interleaved Overlay
|
||||
overlay-pdfs.mode.fixedRepeat=Fixed Repeat Overlay
|
||||
overlay-pdfs.counts.label=Overlay Counts (for Fixed Repeat Mode)
|
||||
overlay-pdfs.counts.placeholder=Enter comma-separated counts (e.g., 2,3,1)
|
||||
overlay-pdfs.position.label=Select Overlay Position
|
||||
overlay-pdfs.position.foreground=Foreground
|
||||
overlay-pdfs.position.background=Background
|
||||
overlay-pdfs.submit=Submit
|
||||
|
||||
|
||||
#split-by-sections
|
||||
split-by-sections.title=Split PDF by Sections
|
||||
split-by-sections.header=Split PDF into Sections
|
||||
split-by-sections.horizontal.label=Horizontal Divisions
|
||||
split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Credentials changed!
|
||||
notAuthenticatedMessage=User not authenticated.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=Отправить
|
||||
certSign.title=Подписание сертификата
|
||||
certSign.header=Подпишите 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.selectKey=Выберите файл закрытого ключа (формат PKCS#8, может быть .pem или .der):
|
||||
certSign.selectCert=Выберите файл сертификата (формат X.509, может быть .pem или .der):
|
||||
certSign.selectP12=Выберите файл хранилища ключей PKCS#12 (.p12 или .pfx) (необязательно, если он предоставлен, он должен содержать ваш закрытый ключ и сертификат):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Тип сертификата
|
||||
certSign.password=Введите пароль от хранилища ключей или личного ключа (если есть):
|
||||
certSign.showSig=Показать подпись
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
934
src/main/resources/messages_sr-Latn-RS.properties
Normal file
934
src/main/resources/messages_sr-Latn-RS.properties
Normal file
@@ -0,0 +1,934 @@
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
language.direction=ltr
|
||||
|
||||
pdfPrompt=Odaberi PDF(ove)
|
||||
multiPdfPrompt=Odaberi PDF-ove (2+)
|
||||
multiPdfDropPrompt=Odaberi (prevuci i pusti ) sve PDF-ove koji su vam potrebni
|
||||
imgPrompt=Odaberi sliku (slike)
|
||||
genericSubmit=Prihvatiti
|
||||
processTimeWarning=Warning:Upozorenje: Ovaj proces može trajati i do minut, u zavisnosti od veličine dokumenta
|
||||
pageOrderPrompt=Prilagođeni redosled stranica (unesi listu brojeva stranica ili funkcija, kao što su 2n+1, razdvojene zarezima) :
|
||||
goToPage=Idi
|
||||
true=Tačno
|
||||
false=Netačno
|
||||
unknown=Nepoznato
|
||||
save=Sačuvaj
|
||||
close=Zatvori
|
||||
filesSelected=odabrani fajlovi
|
||||
noFavourites=Nema dodatih favorita
|
||||
bored=Da li ti je dosadno dok čekaš?
|
||||
alphabet=Alfabet
|
||||
downloadPdf=Skini PDF
|
||||
text=Tekst
|
||||
font=Font
|
||||
selectFillter=-- Izaberi --
|
||||
pageNum=Broj Strane
|
||||
sizes.small=Malo
|
||||
sizes.medium=Srednje
|
||||
sizes.large=Veliko
|
||||
sizes.x-large=X-Veliko
|
||||
error.pdfPassword=PDF dokument je šifrovan i lozinka nije data ili je netačna
|
||||
delete=Obriši
|
||||
username=Korisničko ime
|
||||
password=Šifra
|
||||
welcome=Dobrodošli
|
||||
property=Svojstvo
|
||||
black=Crno
|
||||
white=Belo
|
||||
red=Crveno
|
||||
green=Zeleno
|
||||
blue=Plavo
|
||||
custom=Prilagođeno...
|
||||
WorkInProgess=Radovi u toku, možda neće raditi ili će biti grešaka, molimo prijavite sve probleme !
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Podaci za prijavu uspešno promenjeni!
|
||||
notAuthenticatedMessage=Korisnik nije autentifikovan.
|
||||
userNotFoundMessage=Korisnik nije pronađen.
|
||||
incorrectPasswordMessage=Trenutna šifra je netačna.
|
||||
usernameExistsMessage=Novi korisnik već postoji
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Meni za Pipeline (Alfa verzija)
|
||||
pipeline.uploadButton=Postavi prilagođeno
|
||||
pipeline.configureButton=Konfiguriši
|
||||
pipeline.defaultOption=Prilagođeno
|
||||
pipeline.submitButton=Pošalji
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Konfiguracija Pipeline-a
|
||||
pipelineOptions.pipelineNameLabel=Ime Pipeline-a
|
||||
pipelineOptions.saveSettings=Sačuvaj podešavanja
|
||||
pipelineOptions.pipelineNamePrompt=Unesite ime pipeline-a ovde
|
||||
pipelineOptions.addOperationButton=Dodaj operaciju
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Preuzmi
|
||||
pipelineOptions.validateButton=Proveri
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
#############
|
||||
navbar.convert=Konvertuj
|
||||
navbar.security=Bezbednost
|
||||
navbar.other=Razno
|
||||
navbar.darkmode=Tamni režim
|
||||
navbar.pageOps=Operacije stranice
|
||||
navbar.settings=Podešavanja
|
||||
|
||||
#############
|
||||
# SETTINGS #
|
||||
#############
|
||||
settings.title=Podešavanja
|
||||
settings.update=Dostupno ažuriranje
|
||||
settings.appVersion=Verzija aplikacije:
|
||||
settings.downloadOption.title=Odaberite opciju preuzimanja (Za preuzimanje pojedinačnih fajlova bez zip formata):
|
||||
settings.downloadOption.1=Otvori u istom prozoru
|
||||
settings.downloadOption.2=Otvori u novom prozoru
|
||||
settings.downloadOption.3=Preuzmi fajl
|
||||
settings.zipThreshold=Zipuj fajlove kada pređe broj preuzetih fajlova
|
||||
settings.signOut=Odjava
|
||||
settings.accountSettings=Podešavanja naloga
|
||||
|
||||
|
||||
|
||||
changeCreds.title=Promeni pristupne podatke
|
||||
changeCreds.header=Ažurirajte detalje svog naloga
|
||||
changeCreds.changeUserAndPassword=Koristite podrazumevane prijavne podatke. Unesite novu lozinku (i korisničko ime ako želite)
|
||||
changeCreds.newUsername=Novo korisničko ime
|
||||
changeCreds.oldPassword=Trenutna lozinka
|
||||
changeCreds.newPassword=Nova lozinka
|
||||
changeCreds.confirmNewPassword=Potvrdite novu lozinku
|
||||
changeCreds.submit=Potvrdi promene
|
||||
|
||||
|
||||
|
||||
account.title=Podešavanja naloga
|
||||
account.accountSettings=Podešavanja naloga
|
||||
account.adminSettings=Admin podešavanja - Pregled i dodavanje korisnika
|
||||
account.userControlSettings=Podešavanja kontrole korisnika
|
||||
account.changeUsername=Pormeni korisničko ime
|
||||
account.changeUsername=Pormeni korisničko ime
|
||||
account.password=Potvrda lozinke
|
||||
account.oldPassword=Stara lozinka
|
||||
account.newPassword=Nova lozinka
|
||||
account.changePassword=Pormeni lozinku
|
||||
account.confirmNewPassword=Potvrdi novu lozinku
|
||||
account.signOut=Odjava
|
||||
account.yourApiKey=Tvoj API ključ
|
||||
account.syncTitle=Sinhronizacija podešavanja pregledača sa nalogom
|
||||
account.settingsCompare=Upoređivanje podešavanja:
|
||||
account.property=Svojstvo
|
||||
account.webBrowserSettings=Podešavanja veb pregledača
|
||||
account.syncToBrowser=Sinhronizacija naloga -> pregledač
|
||||
account.syncToAccount=Sinhronizacija naloga <- pregledač
|
||||
|
||||
|
||||
adminUserSettings.title=Podešavanja kontrole korisnika
|
||||
adminUserSettings.header=Podešavanja kontrole korisnika za administratora
|
||||
adminUserSettings.admin=Administrator
|
||||
adminUserSettings.user=Korisnik
|
||||
adminUserSettings.addUser=Dodaj novog korisnika
|
||||
adminUserSettings.roles=Uloge
|
||||
adminUserSettings.role=Uloga
|
||||
adminUserSettings.actions=Akcije
|
||||
adminUserSettings.apiUser=Korisnik s ograničenim API pristupom
|
||||
adminUserSettings.webOnlyUser=Korisnik samo za web
|
||||
adminUserSettings.demoUser=Demo korisnik (Bez prilagođenih podešavanja)
|
||||
adminUserSettings.forceChange=Prisili korisnika da promeni korisničko ime/lozinku pri prijavi
|
||||
adminUserSettings.submit=Sačuvaj korisnika
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
home.desc=Vaš lokalno hostovan jedinstveni alat za sve vaše potrebe vezane za PDF.
|
||||
home.searchBar=Pretraži funkcije...
|
||||
|
||||
|
||||
home.viewPdf.title=Pregledaj PDF
|
||||
home.viewPdf.desc=Pregledaj, anotiraj, dodaj tekst ili slike
|
||||
viewPdf.tags=pregled,čitanje,anotiranje,tekst,slika
|
||||
|
||||
home.multiTool.title=PDF Multi Alat
|
||||
home.multiTool.desc=Spajanje, rotacija, premeštanje i uklanjanje stranica
|
||||
multiTool.tags=Multi Alat,Multi operacija,Korisnički interfejs,klik i povuci,front end,klijentska strana,interaktivno,pomera
|
||||
|
||||
home.merge.title=Spajanje
|
||||
home.merge.desc=Lako spojite više PDF-ova u jedan.
|
||||
merge.tags=spajanje,Operacije sa stranicama,Backend,server strana
|
||||
|
||||
home.split.title=Razdvajanje
|
||||
home.split.desc=Razdvojite PDF-ove u više dokumenata
|
||||
split.tags=Operacije sa stranicama,podela,Višestruke stranice,sečenje,server strana
|
||||
|
||||
home.rotate.title=Rotacija
|
||||
home.rotate.desc=Lako rotirajte vaše PDF-ove.
|
||||
rotate.tags=server strana
|
||||
|
||||
|
||||
home.imageToPdf.title=Slika u PDF
|
||||
home.imageToPdf.desc=Konvertujte sliku (PNG, JPEG, GIF) u PDF.
|
||||
imageToPdf.tags=konverzija,img,jpg,slika,foto
|
||||
|
||||
home.pdfToImage.title=PDF u Sliku
|
||||
home.pdfToImage.desc=Konvertujte PDF u sliku. (PNG, JPEG, GIF)
|
||||
pdfToImage.tags=konverzija,img,jpg,slika,foto
|
||||
|
||||
home.pdfOrganiser.title=Organizacija
|
||||
home.pdfOrganiser.desc=Uklonite/Premeštajte stranice u bilo kom redosledu
|
||||
pdfOrganiser.tags=duplex,even,odd,sort,move
|
||||
|
||||
|
||||
home.addImage.title=Dodaj sliku
|
||||
home.addImage.desc=Dodaje sliku na određeno mesto u PDF-u
|
||||
addImage.tags=img,jpg,slika,foto
|
||||
|
||||
home.watermark.title=Dodaj vodeni žig
|
||||
home.watermark.desc=Dodajte prilagođeni vodeni žig na vaš PDF dokument.
|
||||
watermark.tags=Tekst,ponavljanje,etiketa,vlastiti,autorsko pravo,zaštita, img,jpg,slika,foto
|
||||
|
||||
home.permissions.title=Promeni dozvole
|
||||
home.permissions.desc=Promenite dozvole vašeg PDF dokumenta
|
||||
permissions.tags=čitanje,pisanje,izmena,štampa
|
||||
|
||||
|
||||
home.removePages.title=Ukloni
|
||||
home.removePages.desc=Obrišite nepotrebne stranice iz vašeg PDF dokumenta.
|
||||
removePages.tags=Ukloni stranice,obriši stranice
|
||||
|
||||
home.addPassword.title=Dodaj lozinku
|
||||
home.addPassword.desc=Enkriptujte vaš PDF dokument lozinkom.
|
||||
addPassword.tags=bezbedno,zaštita
|
||||
|
||||
home.removePassword.title=Ukloni lozinku
|
||||
home.removePassword.desc=Uklonite zaštitu lozinkom sa vašeg PDF dokumenta.
|
||||
removePassword.tags=bezbedno,Dešifruj,zaštita,ukloni lozinku
|
||||
|
||||
home.compressPdfs.title=Kompresuj
|
||||
home.compressPdfs.desc=Kompresujte PDF-ove kako bi smanjili veličinu fajla.
|
||||
compressPdfs.tags=smanji,mali,minijaturni
|
||||
|
||||
|
||||
home.changeMetadata.title=Promena metapodataka
|
||||
home.changeMetadata.desc=Promenite/Uklonite/Dodajte metapodatke u PDF dokumentu
|
||||
changeMetadata.tags=Naslov,autor,datum,kreacije,vreme,izdavač,proizvođač,statistike
|
||||
|
||||
home.fileToPDF.title=Konvertuj fajl u PDF
|
||||
home.fileToPDF.desc=Konvertujte gotovo bilo koji fajl u PDF (DOCX, PNG, XLS, PPT, TXT i više)
|
||||
fileToPDF.tags=transformacija,format,dokument,slika,slajd,tekst,konverzija,office,docs,word,excel,powerpoint
|
||||
|
||||
home.ocr.title=OCR / Čišćenje skenova
|
||||
home.ocr.desc=Čišćenje skenova i detektovanje teksta sa slika unutar PDF-a i ponovno dodavanje kao teksta.
|
||||
ocr.tags=prepoznavanje,tekst,slika,sken,čitanje,identifikacija,detekcija,uređivanje
|
||||
|
||||
|
||||
home.extractImages.title=Izvuci slike
|
||||
home.extractImages.desc=Izvlači sve slike iz PDF-a i čuva ih u zip formatu
|
||||
extractImages.tags=slika,foto,sačuvaj,arhiva,zip,zahvati,uhvati
|
||||
|
||||
home.pdfToPDFA.title=PDF u PDF/A
|
||||
home.pdfToPDFA.desc=Konvertujte PDF u PDF/A za dugoročno čuvanje
|
||||
pdfToPDFA.tags=arhiva,dugoročno,standard,konverzija,čuvanje,čuvanje
|
||||
|
||||
home.PDFToWord.title=PDF u Word
|
||||
home.PDFToWord.desc=Konvertujte PDF u Word formate (DOC, DOCX i ODT)
|
||||
PDFToWord.tags=doc,docx,odt,word,transformacija,format,konverzija,office,microsoft,docfile
|
||||
|
||||
home.PDFToPresentation.title=PDF u Prezentaciju
|
||||
home.PDFToPresentation.desc=Konvertujte PDF u formate za prezentaciju (PPT, PPTX i ODP)
|
||||
PDFToPresentation.tags=slajdovi,prikaz,office,microsoft
|
||||
|
||||
home.PDFToText.title=PDF u RTF (Tekst)
|
||||
home.PDFToText.desc=Konvertujte PDF u tekst ili RTF format
|
||||
PDFToText.tags=richformat,richtextformat,rich text format
|
||||
|
||||
home.PDFToHTML.title=PDF u HTML
|
||||
home.PDFToHTML.desc=Konvertujte PDF u HTML format
|
||||
PDFToHTML.tags=web sadržaj,prijateljski za pretraživače
|
||||
|
||||
|
||||
home.PDFToXML.title=PDF u XML
|
||||
home.PDFToXML.desc=Konvertujte PDF u XML format
|
||||
PDFToXML.tags=izdvajanje-podataka,strukturirani-sadržaj,interop,transformacija,konvertovanje
|
||||
|
||||
home.ScannerImageSplit.title=Detekcija/Razdvajanje skeniranih fotografija
|
||||
home.ScannerImageSplit.desc=Razdvaja više fotografija unutar slike/PDF-a
|
||||
ScannerImageSplit.tags=razdvoji,auto-detekcija,skeniranja,višestruke fotografije,organizacija
|
||||
|
||||
home.sign.title=Potpis
|
||||
home.sign.desc=Dodaje potpis u PDF crtežom, tekstom ili slikom
|
||||
sign.tags=autorizacija,inicijali,crtani-potpis,tekstualni-potpis,slikovni-potpis
|
||||
|
||||
home.flatten.title=Ravnanje
|
||||
home.flatten.desc=Uklanja sve interaktivne elemente i forme iz PDF-a
|
||||
flatten.tags=statično,deaktivirati,neinteraktivno,usmeriti
|
||||
|
||||
home.repair.title=Popravi
|
||||
home.repair.desc=Pokušava popraviti oštećeni/izgubljeni PDF
|
||||
repair.tags=popravi,vrati,korekcija,obnovi
|
||||
|
||||
home.removeBlanks.title=Ukloni prazne stranice
|
||||
home.removeBlanks.desc=Detektuje i uklanja prazne stranice iz dokumenta
|
||||
removeBlanks.tags=čišćenje,usmeriti,ne-sadržaj,organizacija
|
||||
|
||||
home.removeAnnotations.title=Ukloni Anotacije
|
||||
home.removeAnnotations.desc=Uklanja sve komentare/anotacije iz PDF-a
|
||||
removeAnnotations.tags=komentari,isticanje,beleške,oznake,ukloni
|
||||
|
||||
home.compare.title=Uporedi
|
||||
home.compare.desc=Upoređuje i prikazuje razlike između 2 PDF dokumenata
|
||||
compare.tags=razlikovati,kontrast,izmene,analiza
|
||||
|
||||
home.certSign.title=Potpis sa sertifikatom
|
||||
home.certSign.desc=Potpisuje PDF sa sertifikatom/ključem (PEM/P12)
|
||||
certSign.tags=autentifikacija,PEM,P12,zvanično,šifrovanje
|
||||
|
||||
home.pageLayout.title=Višestruki prikaz stranica
|
||||
home.pageLayout.desc=Spaja više stranica PDF dokumenta u jednu stranicu
|
||||
pageLayout.tags=spajanje,kompozit,pojedinačan-prikaz,organizacija
|
||||
|
||||
home.scalePages.title=Podesi veličinu/skalu stranice
|
||||
home.scalePages.desc=Podesi veličinu/skalu stranice i/ili njenog sadržaja.
|
||||
scalePages.tags=izmena,modifikacija,dimenzija,adaptacija
|
||||
|
||||
home.pipeline.title=Pipeline (Napredno)
|
||||
home.pipeline.desc=Pokreće više akcija na PDF-ovima definisanjem skripti u pipelinu
|
||||
pipeline.tags=automatizacija,sekvenciranje,skriptirano,batch-process
|
||||
|
||||
home.add-page-numbers.title=Dodaj brojeve stranica
|
||||
home.add-page-numbers.desc=Dodaje brojeve stranica u dokumentu na određeno mesto
|
||||
add-page-numbers.tags=paginacija,oznaka,organizacija,indeks
|
||||
|
||||
home.auto-rename.title=Automatsko preimenovanje PDF fajla
|
||||
home.auto-rename.desc=Automatski menja ime PDF fajla na osnovu detektovanog zaglavlja
|
||||
auto-rename.tags=auto-detekcija,zaglavlje-bazirano,organizacija,preimenovanje
|
||||
|
||||
home.adjust-contrast.title=Podesi boje/kontrast
|
||||
home.adjust-contrast.desc=Podesi kontrast, zasićenost i osvetljenost PDF-a
|
||||
adjust-contrast.tags=korekcija-boja,podešavanje,modifikacija,unapredi
|
||||
|
||||
home.crop.title=Skraćivanje PDF-a
|
||||
home.crop.desc=Skraćuje PDF radi smanjenja veličine (zadržava tekst!)
|
||||
crop.tags=trimovanje,skupljanje,uređivanje,oblikovanje
|
||||
|
||||
home.autoSplitPDF.title=Automatsko razdvajanje stranica
|
||||
home.autoSplitPDF.desc=Automatski deli skenirane PDF-ove pomoću fizičkog skenera QR koda
|
||||
autoSplitPDF.tags=QR-bazirano,razdvoji,segment-skeniranja,organizacija
|
||||
|
||||
home.sanitizePdf.title=Sanitizacija
|
||||
home.sanitizePdf.desc=Uklanja skripte i druge elemente iz PDF fajlova
|
||||
sanitizePdf.tags=čišćenje,bezbednost,bezbedno,ukloni-pretnje
|
||||
|
||||
home.URLToPDF.title=URL/Website u PDF
|
||||
home.URLToPDF.desc=Konvertuje bilo koji http(s) URL u PDF
|
||||
URLToPDF.tags=uhvati-web,sačuvaj-stranicu,web-u-doc,arhiva
|
||||
|
||||
home.HTMLToPDF.title=HTML u PDF
|
||||
home.HTMLToPDF.desc=Konvertuje bilo koji HTML fajl ili zip u PDF
|
||||
HTMLToPDF.tags=oznake,web-sadržaj,transformacija,konvertovanje
|
||||
|
||||
|
||||
home.MarkdownToPDF.title=Markdown u PDF
|
||||
home.MarkdownToPDF.desc=Konvertuje bilo koji Markdown fajl u PDF
|
||||
MarkdownToPDF.tags=oznake,web-sadržaj,transformacija,konvertovanje
|
||||
|
||||
|
||||
home.getPdfInfo.title=Dohvati SVE informacije o PDF-u
|
||||
home.getPdfInfo.desc=Dobavlja sve moguće informacije o PDF-ovima
|
||||
getPdfInfo.tags=informacije,podaci,statistike
|
||||
|
||||
|
||||
home.extractPage.title=Izdvajanje stranica
|
||||
home.extractPage.desc=Izdvaja odabrane stranice iz PDF-a
|
||||
extractPage.tags=izdvajanje
|
||||
|
||||
|
||||
home.PdfToSinglePage.title=PDF u Jednu Veliku Stranicu
|
||||
home.PdfToSinglePage.desc=Spaja sve stranice PDF-a u jednu veliku stranicu
|
||||
PdfToSinglePage.tags=jedna-stranica
|
||||
|
||||
|
||||
home.showJS.title=Prikaži JavaScript
|
||||
home.showJS.desc=Pretražuje i prikazuje bilo koji JavaScript ubačen u PDF
|
||||
showJS.tags=Cenzura,Sakrij,prekrivanje,crna,marker,skriveno
|
||||
|
||||
home.autoRedact.title=Automatsko Cenzurisanje
|
||||
home.autoRedact.desc=Automatsko cenzurisanje teksta u PDF-u na osnovu unetog teksta
|
||||
showJS.tags=Cenzura,Sakrij,prekrivanje,crna,marker,skriveno
|
||||
|
||||
home.tableExtraxt.title=PDF u CSV
|
||||
home.tableExtraxt.desc=Izdvaja tabele iz PDF-a pretvarajući ih u CSV
|
||||
tableExtraxt.tags=CSV,Izdvajanje tabela,izdvajanje,konvertovanje
|
||||
|
||||
|
||||
home.autoSizeSplitPDF.title=Automatsko Deljenje po Veličini/Broju
|
||||
home.autoSizeSplitPDF.desc=Deljenje jednog PDF-a na više dokumenata na osnovu veličine, broja stranica ili broja dokumenata
|
||||
autoSizeSplitPDF.tags=pdf,delenje,dokumenti,organizacija
|
||||
|
||||
|
||||
home.overlay-pdfs.title=Preklapanje PDF-ova
|
||||
home.overlay-pdfs.desc=Preklapa PDF-ove jedan preko drugog
|
||||
overlay-pdfs.tags=Preklapanje
|
||||
|
||||
home.split-by-sections.title=Deljenje PDF-a po Odeljcima
|
||||
home.split-by-sections.desc=Deljenje svake stranice PDF-a na manje horizontalne i vertikalne odeljke
|
||||
split-by-sections.tags=Deljenje odeljaka,Deljenje,Podešavanje
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
# #
|
||||
###########################
|
||||
#login
|
||||
login.title=Prijavite se
|
||||
login.signin=Prijavite se
|
||||
login.rememberme=Zapamti me
|
||||
login.invalid=Neispravno korisničko ime ili lozinka.
|
||||
login.locked=Vaš nalog je zaključan.
|
||||
login.signinTitle=Molimo vas da se prijavite
|
||||
|
||||
|
||||
#auto-redact
|
||||
autoRedact.title=Auto Cenzura
|
||||
autoRedact.header=Auto Cenzura
|
||||
autoRedact.colorLabel=Boja
|
||||
autoRedact.textsToRedactLabel=Tekst za cenzurisanje (razdvojeni linijama)
|
||||
autoRedact.textsToRedactPlaceholder=npr. \nPoverljivo \nVrhunski Tajno
|
||||
autoRedact.useRegexLabel=Koristi Regex
|
||||
autoRedact.wholeWordSearchLabel=Pretraga celih reči
|
||||
autoRedact.customPaddingLabel=Dodatni prazan prostor
|
||||
autoRedact.convertPDFToImageLabel=Konvertuj PDF u PDF-Image (koristi se za uklanjanje teksta iza okvira)
|
||||
autoRedact.submitButton=Potvrdi
|
||||
|
||||
|
||||
#showJS
|
||||
showJS.title=Prikaži Javascript
|
||||
showJS.header=Prikaži Javascript
|
||||
showJS.downloadJS=Preuzmi Javascript
|
||||
showJS.submit=Prikaži
|
||||
|
||||
|
||||
#pdfToSinglePage
|
||||
pdfToSinglePage.title=PDF u Jednu Stranicu
|
||||
pdfToSinglePage.header=PDF u Jednu Stranicu
|
||||
pdfToSinglePage.submit=Konvertuj u Jednu Stranicu
|
||||
|
||||
|
||||
#pageExtracter
|
||||
pageExtracter.title=Izdvajanje stranica
|
||||
pageExtracter.header=Izdvajanje stranica
|
||||
pageExtracter.submit=Izdvoji
|
||||
|
||||
|
||||
#getPdfInfo
|
||||
getPdfInfo.title=Informacije o PDF-u
|
||||
getPdfInfo.header=Informacije o PDF-u
|
||||
getPdfInfo.submit=Informacije
|
||||
getPdfInfo.downloadJson=Preuzmi JSON
|
||||
|
||||
|
||||
#markdown-to-pdf
|
||||
MarkdownToPDF.title=Markdown u PDF
|
||||
MarkdownToPDF.header=Markdown u PDF
|
||||
MarkdownToPDF.submit=Konvertuj
|
||||
MarkdownToPDF.help=Rad u toku
|
||||
MarkdownToPDF.credit=Koristi WeasyPrint
|
||||
|
||||
|
||||
|
||||
#url-to-pdf
|
||||
URLToPDF.title=URL u PDF
|
||||
URLToPDF.header=URL u PDF
|
||||
URLToPDF.submit=Konvertuj
|
||||
URLToPDF.credit=Koristi WeasyPrint
|
||||
|
||||
|
||||
#html-to-pdf
|
||||
HTMLToPDF.title=HTML u PDF
|
||||
HTMLToPDF.header=HTML u PDF
|
||||
HTMLToPDF.help=Prihvata HTML fajlove i ZIP-ove koji sadrže html/css/slike itd. potrebno
|
||||
HTMLToPDF.submit=Konvertuj
|
||||
HTMLToPDF.credit=Koristi WeasyPrint
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Sanitizacija PDF-a
|
||||
sanitizePDF.header=Sanitizacija PDF fajla
|
||||
sanitizePDF.selectText.1=Ukloni JavaScript akcije
|
||||
sanitizePDF.selectText.2=Ukloni ugrađene fajlove
|
||||
sanitizePDF.selectText.3=Ukloni metapodatke
|
||||
sanitizePDF.selectText.4=Ukloni linkove
|
||||
sanitizePDF.selectText.5=Ukloni fontove
|
||||
sanitizePDF.submit=Sanitizuj PDF
|
||||
|
||||
|
||||
#addPageNumbers
|
||||
addPageNumbers.title=Dodavanje brojeva stranica
|
||||
addPageNumbers.header=Dodavanje brojeva stranica
|
||||
addPageNumbers.selectText.1=Izaberi PDF fajl:
|
||||
addPageNumbers.selectText.2=Veličina margine
|
||||
addPageNumbers.selectText.3=Pozicija
|
||||
addPageNumbers.selectText.4=Početni broj
|
||||
addPageNumbers.selectText.5=Brojane stranice
|
||||
addPageNumbers.selectText.6=Prilagođeni tekst
|
||||
addPageNumbers.customTextDesc=Prilagođeni tekst
|
||||
addPageNumbers.numberPagesDesc=Koje stranice brojati, podrazumevano 'sve', takođe prihvata 1-5 ili 2,5,9 itd.
|
||||
addPageNumbers.customNumberDesc=Podrazumevano je {n}, takođe prihvata 'Stranica {n} od {ukupno}', 'Tekst-{n}', '{ime_fajla}-{n}'
|
||||
addPageNumbers.submit=Dodaj brojeve stranica
|
||||
|
||||
|
||||
#auto-rename
|
||||
auto-rename.title=Automatsko preimenovanje
|
||||
auto-rename.header=Automatsko preimenovanje PDF-a
|
||||
auto-rename.submit=Automatsko preimenovanje
|
||||
|
||||
|
||||
#adjustContrast
|
||||
adjustContrast.title=Podesi Kontrast
|
||||
adjustContrast.header=Podesi Kontrast
|
||||
adjustContrast.contrast=Kontrast:
|
||||
adjustContrast.brightness=Osvetljenje:
|
||||
adjustContrast.saturation=Zasićenje:
|
||||
adjustContrast.download=Preuzmi
|
||||
|
||||
|
||||
#crop
|
||||
crop.title=Iseci
|
||||
crop.header=Iseci Sliku
|
||||
crop.submit=Potvrdi
|
||||
|
||||
|
||||
#autoSplitPDF
|
||||
autoSplitPDF.title=Automatsko Deljenje PDF-a
|
||||
autoSplitPDF.header=Automatsko Deljenje PDF-a
|
||||
autoSplitPDF.description=Štampajte, umetnite, skenirajte, učitajte i dozvolite nam da automatski razdvojimo vaše dokumente. Nije potrebno ručno sortiranje.
|
||||
autoSplitPDF.selectText.1=Odštampajte nekoliko listova razdeljivača ispod (Crno-belo je u redu).
|
||||
autoSplitPDF.selectText.2=Skenirajte sve vaše dokumente odjednom, ubacivanjem lista razdeljivača između njih.
|
||||
autoSplitPDF.selectText.3=Učitajte jedan veliki skenirani PDF fajl i dozvolite Stirling PDF-u da obavi ostalo.
|
||||
autoSplitPDF.selectText.4=Listovi razdeljivača se automatski detektuju i uklanjaju, obezbeđujući uredan konačni dokument.
|
||||
autoSplitPDF.formPrompt=Potvrdite PDF koji sadrži Stirling-PDF listove razdeljivača:
|
||||
autoSplitPDF.duplexMode=Dupleks režim (skeniranje prednje i zadnje strane)
|
||||
autoSplitPDF.dividerDownload1=Preuzmi 'Auto Splitter Divider (minimal).pdf'
|
||||
autoSplitPDF.dividerDownload2=Preuzmi 'Auto Splitter Divider (sa uputstvima).pdf'
|
||||
autoSplitPDF.submit=Potvrdi
|
||||
|
||||
|
||||
#pipeline
|
||||
pipeline.title=Tok rada
|
||||
|
||||
|
||||
#pageLayout
|
||||
pageLayout.title=Višestruki Raspored Stranica
|
||||
pageLayout.header=Višestruki Raspored Stranica
|
||||
pageLayout.pagesPerSheet=Stranica po listu:
|
||||
pageLayout.addBorder=Dodaj ivice
|
||||
pageLayout.submit=Potvrdi
|
||||
|
||||
|
||||
#scalePages
|
||||
scalePages.title=Podesi razmeru stranica
|
||||
scalePages.header=Podesi razmeru stranica
|
||||
scalePages.pageSize=Veličina stranice dokumenta.
|
||||
scalePages.scaleFactor=Nivo zumiranja (rezanje) stranice.
|
||||
scalePages.submit=Potvrdi
|
||||
|
||||
|
||||
#certSign
|
||||
certSign.title=Potpisivanje Sertifikatom
|
||||
certSign.header=Potpiši PDF sa svojim sertifikatom (Rad u toku)
|
||||
certSign.selectPDF=Izaberite PDF fajl za potpisivanje:
|
||||
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.selectKey=Izaberite svoj privatni ključ (PKCS#8 format, može biti .pem ili .der):
|
||||
certSign.selectCert=Izaberite svoj sertifikat (X.509 format, može biti .pem ili .der):
|
||||
certSign.selectP12=Izaberite svoj PKCS#12 keystore fajl (.p12 ili .pfx) (Opciono, ako je dostupan, trebalo bi da sadrži vaš privatni ključ i sertifikat):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Tip sertifikata
|
||||
certSign.password=Unesite lozinku vašeg keystore-a ili privatnog ključa (ako je ima):
|
||||
certSign.showSig=Prikaži potpis
|
||||
certSign.reason=Razlog
|
||||
certSign.location=Lokacija
|
||||
certSign.name=Ime
|
||||
certSign.submit=Potpiši PDF
|
||||
|
||||
|
||||
#removeBlanks
|
||||
removeBlanks.title=Ukloni prazne stranice
|
||||
removeBlanks.header=Ukloni prazne stranice
|
||||
removeBlanks.threshold=Prag beline piksela:
|
||||
removeBlanks.thresholdDesc=Prag za određivanje koliko beli piksel mora biti 'beli'. 0 = Crno, 255 čisto belo.
|
||||
removeBlanks.whitePercent=Procenat bele boje (%):
|
||||
removeBlanks.whitePercentDesc=Procenat stranice koji mora biti 'beli' pikseli da bi se uklonili
|
||||
removeBlanks.submit=Ukloni prazne
|
||||
|
||||
|
||||
#removeAnnotations
|
||||
removeAnnotations.title=Ukloni Anotacije
|
||||
removeAnnotations.header=Ukloni Anotacije
|
||||
removeAnnotations.submit=Ukloni
|
||||
|
||||
|
||||
#compare
|
||||
compare.title=Uporedi
|
||||
compare.header=Uporedi PDF fajlove
|
||||
compare.document.1=Dokument 1
|
||||
compare.document.2=Dokument 2
|
||||
compare.submit=Uporedi
|
||||
|
||||
|
||||
#sign
|
||||
sign.title=Potpiši
|
||||
sign.header=Potpiši PDF fajlove
|
||||
sign.upload=Učitaj sliku
|
||||
sign.draw=Nacrtaj potpis
|
||||
sign.text=Tekstualni unos
|
||||
sign.clear=Obriši
|
||||
sign.add=Dodaj
|
||||
|
||||
|
||||
#repair
|
||||
repair.title=Popravi
|
||||
repair.header=Popravi PDF fajlove
|
||||
repair.submit=Popravi
|
||||
|
||||
|
||||
#flatten
|
||||
flatten.title=Ravnanje
|
||||
flatten.header=Ravnanje PDF fajlova
|
||||
flatten.submit=Ravnanje
|
||||
|
||||
|
||||
#ScannerImageSplit
|
||||
ScannerImageSplit.selectText.1=Ugao praga:
|
||||
ScannerImageSplit.selectText.2=Postavlja minimalni apsolutni ugao potreban za rotiranje slike (podrazumevano: 10).
|
||||
ScannerImageSplit.selectText.3=Tolerancija:
|
||||
ScannerImageSplit.selectText.4=Određuje opseg varijacije boja oko procenjene boje pozadine (podrazumevano: 30).
|
||||
ScannerImageSplit.selectText.5=Minimalna površina:
|
||||
ScannerImageSplit.selectText.6=Postavlja minimalni prag površine za fotografiju (podrazumevano: 10000).
|
||||
ScannerImageSplit.selectText.7=Minimalna površina konture:
|
||||
ScannerImageSplit.selectText.8=Postavlja minimalni prag površine konture za fotografiju
|
||||
ScannerImageSplit.selectText.9=Veličina ivice:
|
||||
ScannerImageSplit.selectText.10=Postavlja veličinu ivice dodate i uklonjene kako bi se sprečile bele ivice u izlazu (podrazumevano: 1).
|
||||
|
||||
|
||||
#OCR
|
||||
ocr.title=OCR / Čišćenje skeniranja
|
||||
ocr.header=Čišćenje skeniranja / OCR (Optičko prepoznavanje znakova)
|
||||
ocr.selectText.1=Odaberite jezike koji će biti detektovani unutar PDF-a (Navedeni su trenutno detektovani):
|
||||
ocr.selectText.2=Proizvedi tekstualni fajl koji sadrži OCR tekst uz OCR-ovani PDF
|
||||
ocr.selectText.3=Ispravite stranice koje su skenirane pod uglom rotirajući ih na svoje mesto
|
||||
ocr.selectText.4=Očistite stranicu tako da je manje verovatno da će OCR pronaći tekst u pozadinskom šumu. (Bez promene izlaza)
|
||||
ocr.selectText.5=Očistite stranicu tako da je manje verovatno da će OCR pronaći tekst u pozadinskom šumu, zadržavajući čišćenje u izlazu.
|
||||
ocr.selectText.6=Ignoriše stranice koje imaju interaktivni tekst, samo OCR-uje stranice koje su slike
|
||||
ocr.selectText.7=Prinudni OCR, OCR-uje svaku stranicu uklanjajući sve originalne tekstualne elemente
|
||||
ocr.selectText.8=Normalno (Prikaže grešku ako PDF sadrži tekst)
|
||||
ocr.selectText.9=Dodatne postavke
|
||||
ocr.selectText.10=Režim OCR-a
|
||||
ocr.selectText.11=Ukloni slike nakon OCR-a (Uklanja SVE slike, korisno samo ako je deo koraka konverzije)
|
||||
ocr.selectText.12=Tip rendiranja (Napredno)
|
||||
ocr.help=Molimo vas da pročitate ovu dokumentaciju o tome kako koristiti ovo za druge jezike i/ili korišćenje van docker-a
|
||||
ocr.credit=Ova usluga koristi OCRmyPDF i Tesseract za OCR.
|
||||
ocr.submit=Obradi PDF sa OCR-om
|
||||
|
||||
|
||||
#extractImages
|
||||
extractImages.title=Izdvajanje slika
|
||||
extractImages.header=Izdvajanje slika
|
||||
extractImages.selectText=Odaberite format slike za konvertovanje izdvojenih slika
|
||||
extractImages.submit=Izdvajanje
|
||||
|
||||
|
||||
#File to PDF
|
||||
fileToPDF.title=Fajl u PDF
|
||||
fileToPDF.header=Konvertuj bilo koji fajl u PDF
|
||||
fileToPDF.credit=Ova usluga koristi LibreOffice i Unoconv za konverziju fajla.
|
||||
fileToPDF.supportedFileTypes=Podržani tipovi fajlova bi trebali uključivati navedeno, ali za punu ažuriranu listu podržanih formata, molimo pogledajte LibreOffice dokumentaciju
|
||||
fileToPDF.submit=Konvertuj u PDF
|
||||
|
||||
|
||||
#compress
|
||||
compress.title=Kompresija
|
||||
compress.header=Kompresuj PDF
|
||||
compress.credit=Ova usluga koristi Ghostscript za kompresiju / optimizaciju PDF-a.
|
||||
compress.selectText.1=Ručni režim - Od 1 do 4
|
||||
compress.selectText.2=Nivo optimizacije:
|
||||
compress.selectText.3=4 (Užasno za tekstualne slike)
|
||||
compress.selectText.4=Automatski režim - Automatski prilagođava kvalitet kako bi PDF bio tačne veličine
|
||||
compress.selectText.5=Očekivana veličina PDF-a (npr. 25MB, 10.8MB, 25KB)
|
||||
compress.submit=Kompresuj
|
||||
|
||||
|
||||
#Add image
|
||||
addImage.title=Dodaj sliku
|
||||
addImage.header=Dodaj sliku u PDF
|
||||
addImage.everyPage=Na svakoj stranici?
|
||||
addImage.upload=Dodaj sliku
|
||||
addImage.submit=Dodaj sliku
|
||||
|
||||
|
||||
#merge
|
||||
merge.title=Spajanje
|
||||
merge.header=Spajanje više PDF fajlova (2+)
|
||||
merge.sortByName=Sortiraj po imenu
|
||||
merge.sortByDate=Sortiraj po datumu
|
||||
merge.submit=Spajanje
|
||||
|
||||
|
||||
#pdfOrganiser
|
||||
pdfOrganiser.title=Organizator stranica
|
||||
pdfOrganiser.header=Organizator stranica u PDF-u
|
||||
pdfOrganiser.submit=Preuredi stranice
|
||||
|
||||
|
||||
#multiTool
|
||||
multiTool.title=PDF Multi Alatka
|
||||
multiTool.header=PDF Multi Alatka
|
||||
|
||||
#view pdf
|
||||
viewPdf.title=Prikaz
|
||||
viewPdf.header=Prikaz PDF-a
|
||||
|
||||
#pageRemover
|
||||
pageRemover.title=Uklanjanje stranica
|
||||
pageRemover.header=Uklanjanje stranica iz PDF-a
|
||||
pageRemover.pagesToDelete=Stranice za brisanje (Unesite listu brojeva stranica odvojenih zarezima) :
|
||||
pageRemover.submit=Obriši stranice
|
||||
|
||||
|
||||
#rotate
|
||||
rotate.title=Rotiranje PDF-a
|
||||
rotate.header=Rotiranje PDF-a
|
||||
rotate.selectAngle=Izaberite ugao rotacije (u višestrukim od 90 stepeni):
|
||||
rotate.submit=Rotiraj
|
||||
|
||||
|
||||
#merge
|
||||
split.title=Razdvajanje PDF-a
|
||||
split.header=Razdvajanje PDF-a
|
||||
split.desc.1=Brojevi koje izaberete predstavljaju brojeve stranica na kojima želite napraviti razdvajanje
|
||||
split.desc.2=Na primer, izbor 1,3,7-8 bi razdvojio dokument od 10 stranica u 6 odvojenih PDF-a sa:
|
||||
split.desc.3=Dokument #1: Stranica 1
|
||||
split.desc.4=Dokument #2: Stranice 2 i 3
|
||||
split.desc.5=Dokument #3: Stranice 4, 5 i 6
|
||||
split.desc.6=Dokument #4: Stranica 7
|
||||
split.desc.7=Dokument #5: Stranica 8
|
||||
split.desc.8=Dokument #6: Stranice 9 i 10
|
||||
split.splitPages=Unesite stranice za razdvajanje:
|
||||
split.submit=Razdvoji
|
||||
|
||||
|
||||
#merge
|
||||
imageToPDF.title=Slika u PDF
|
||||
imageToPDF.header=Slika u PDF
|
||||
imageToPDF.submit=Konvertuj
|
||||
imageToPDF.selectLabel=Opcije prilagođavanja slike
|
||||
imageToPDF.fillPage=Popuni stranicu
|
||||
imageToPDF.fitDocumentToImage=Prilagodi stranicu slici
|
||||
imageToPDF.maintainAspectRatio=Očuvaj proporcije
|
||||
imageToPDF.selectText.2=Automatsko rotiranje PDF-a
|
||||
imageToPDF.selectText.3=Logika za više fajlova (Omogućeno samo ako radite sa više slika)
|
||||
imageToPDF.selectText.4=Spoji u jedan PDF
|
||||
imageToPDF.selectText.5=Konvertuj u odvojene PDF-ove
|
||||
|
||||
|
||||
#pdfToImage
|
||||
pdfToImage.title=PDF u sliku
|
||||
pdfToImage.header=PDF u sliku
|
||||
pdfToImage.selectText=Format slike
|
||||
pdfToImage.singleOrMultiple=Tip rezultata slike po stranici
|
||||
pdfToImage.single=Jedna velika slika koja sadrži sve stranice
|
||||
pdfToImage.multi=Više slika, po jedna slika po stranici
|
||||
pdfToImage.colorType=Tip boje
|
||||
pdfToImage.color=Boja
|
||||
pdfToImage.grey=Nijanse sive
|
||||
pdfToImage.blackwhite=Crno-belo (Može izgubiti podatke!)
|
||||
pdfToImage.submit=Konvertuj
|
||||
|
||||
|
||||
#addPassword
|
||||
addPassword.title=Dodaj šifru
|
||||
addPassword.header=Dodaj šifru (Enkripcija)
|
||||
addPassword.selectText.1=Izaberite PDF za enkripciju
|
||||
addPassword.selectText.2=Korisnička šifra
|
||||
addPassword.selectText.3=Dužina enkripcijskog ključa
|
||||
addPassword.selectText.4=Veće vrednosti su jače, ali manje vrednosti imaju bolju kompatibilnost.
|
||||
addPassword.selectText.5=Postavke dozvola (Preporučuje se korišćenje sa šifrom vlasnika)
|
||||
addPassword.selectText.6=Onemogući sastavljanje dokumenta
|
||||
addPassword.selectText.7=Onemogući ekstrakciju sadržaja
|
||||
addPassword.selectText.8=Onemogući ekstrakciju za pristupačnost
|
||||
addPassword.selectText.9=Onemogući popunjavanje formulara
|
||||
addPassword.selectText.10=Onemogući modifikaciju
|
||||
addPassword.selectText.11=Onemogući modifikaciju anotacija
|
||||
addPassword.selectText.12=Onemogući štampanje
|
||||
addPassword.selectText.13=Onemogući štampanje u različitim formatima
|
||||
addPassword.selectText.14=Šifra vlasnika
|
||||
addPassword.selectText.15=Ograničava šta se može raditi sa dokumentom nakon otvaranja (Nije podržano od svih čitača)
|
||||
addPassword.selectText.16=Ograničava otvaranje samog dokumenta
|
||||
addPassword.submit=Enkriptuj
|
||||
|
||||
|
||||
#watermark
|
||||
watermark.title=Dodaj vodeni žig
|
||||
watermark.header=Dodaj vodeni žig
|
||||
watermark.selectText.1=Izaberite PDF za dodavanje vodenog žiga:
|
||||
watermark.selectText.2=Tekst vodenog žiga:
|
||||
watermark.selectText.3=Veličina fonta:
|
||||
watermark.selectText.4=Rotacija (0-360):
|
||||
watermark.selectText.5=Širina razmaka (Razmak između svakog vodenog žiga horizontalno):
|
||||
watermark.selectText.6=Visina razmaka (Razmak između svakog vodenog žiga vertikalno):
|
||||
watermark.selectText.7=Opačitost (0% - 100%):
|
||||
watermark.selectText.8=Tip vodenog žiga:
|
||||
watermark.selectText.9=Slika vodenog žiga:
|
||||
watermark.submit=Dodaj vodeni žig
|
||||
|
||||
|
||||
#Change permissions
|
||||
permissions.title=Promeni dozvole
|
||||
permissions.header=Promeni dozvole
|
||||
permissions.warning=Upozorenje: Da biste ove dozvole učinili nepromenljivim, preporučuje se postavljanje šifre putem stranice za dodavanje šifre.
|
||||
permissions.selectText.1=Izaberite PDF za promenu dozvola
|
||||
permissions.selectText.2=Postavke dozvola
|
||||
permissions.selectText.3=Onemogući sastavljanje dokumenta
|
||||
permissions.selectText.4=Onemogući ekstrakciju sadržaja
|
||||
permissions.selectText.5=Onemogući ekstrakciju za pristupačnost
|
||||
permissions.selectText.6=Onemogući popunjavanje formulara
|
||||
permissions.selectText.7=Onemogući modifikaciju
|
||||
permissions.selectText.8=Onemogući modifikaciju anotacija
|
||||
permissions.selectText.9=Onemogući štampanje
|
||||
permissions.selectText.10=Onemogući štampanje u različitim formatima
|
||||
permissions.submit=Promeni
|
||||
|
||||
|
||||
#remove password
|
||||
removePassword.title=Ukloni šifru
|
||||
removePassword.header=Ukloni šifru (Dekripcija)
|
||||
removePassword.selectText.1=Izaberite PDF za dekripciju
|
||||
removePassword.selectText.2=Šifra
|
||||
removePassword.submit=Ukloni
|
||||
|
||||
|
||||
#changeMetadata
|
||||
changeMetadata.title=Naslov:
|
||||
changeMetadata.header=Promeni metapodatke
|
||||
changeMetadata.selectText.1=Izmenite promenljive koje želite promeniti
|
||||
changeMetadata.selectText.2=Obriši sve metapodatke
|
||||
changeMetadata.selectText.3=Prikaži prilagođene metapodatke:
|
||||
changeMetadata.author=Autor:
|
||||
changeMetadata.creationDate=Datum kreiranja (gggg/MM/dd HH:mm:ss):
|
||||
changeMetadata.creator=Kreator:
|
||||
changeMetadata.keywords=Ključne reči:
|
||||
changeMetadata.modDate=Datum izmene (gggg/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Proizvođač:
|
||||
changeMetadata.subject=Tema:
|
||||
changeMetadata.title=Naslov:
|
||||
changeMetadata.trapped=Zaglavljeno:
|
||||
changeMetadata.selectText.4=Drugi metapodaci:
|
||||
changeMetadata.selectText.5=Dodaj prilagođeni unos metapodataka
|
||||
changeMetadata.submit=Promeni
|
||||
|
||||
|
||||
#pdfToPDFA
|
||||
pdfToPDFA.title=PDF u PDF/A
|
||||
pdfToPDFA.header=PDF u PDF/A
|
||||
pdfToPDFA.credit=Ova usluga koristi OCRmyPDF za konverziju u PDF/A format
|
||||
pdfToPDFA.submit=Konvertuj
|
||||
|
||||
|
||||
#PDFToWord
|
||||
PDFToWord.title=PDF u Word
|
||||
PDFToWord.header=PDF u Word
|
||||
PDFToWord.selectText.1=Format izlaznog fajla
|
||||
PDFToWord.credit=Ova usluga koristi LibreOffice za konverziju fajlova.
|
||||
PDFToWord.submit=Konvertuj
|
||||
|
||||
|
||||
#PDFToPresentation
|
||||
PDFToPresentation.title=PDF u Prezentaciju
|
||||
PDFToPresentation.header=PDF u Prezentaciju
|
||||
PDFToPresentation.selectText.1=Format izlaznog fajla
|
||||
PDFToPresentation.credit=Ova usluga koristi LibreOffice za konverziju fajlova.
|
||||
PDFToPresentation.submit=Konvertuj
|
||||
|
||||
|
||||
#PDFToText
|
||||
PDFToText.title=PDF u RTF (Tekst)
|
||||
PDFToText.header=PDF u RTF (Tekst)
|
||||
PDFToText.selectText.1=Format izlaznog fajla
|
||||
PDFToText.credit=Ova usluga koristi LibreOffice za konverziju fajlova.
|
||||
PDFToText.submit=Konvertuj
|
||||
|
||||
|
||||
#PDFToHTML
|
||||
PDFToHTML.title=PDF u HTML
|
||||
PDFToHTML.header=PDF u HTML
|
||||
PDFToHTML.credit=Ova usluga koristi LibreOffice za konverziju fajlova.
|
||||
PDFToHTML.submit=Konvertuj
|
||||
|
||||
|
||||
#PDFToXML
|
||||
PDFToXML.title=PDF u XML
|
||||
PDFToXML.header=PDF u XML
|
||||
PDFToXML.credit=Ova usluga koristi LibreOffice za konverziju fajlova.
|
||||
PDFToXML.submit=Konvertuj
|
||||
|
||||
#PDFToCSV
|
||||
PDFToCSV.title=PDF u CSV
|
||||
PDFToCSV.header=PDF u CSV
|
||||
PDFToCSV.prompt=Izaberite stranicu za ekstrakciju tabele
|
||||
PDFToCSV.submit=Izvuci
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.header=Razdvoji PDF po veličini ili broju
|
||||
split-by-size-or-count.type.label=Izaberite tip razdvajanja
|
||||
split-by-size-or-count.type.size=Po veličini
|
||||
split-by-size-or-count.type.pageCount=Po broju stranica
|
||||
split-by-size-or-count.type.docCount=Po broju dokumenata
|
||||
split-by-size-or-count.value.label=Unesite vrednost
|
||||
split-by-size-or-count.value.placeholder=Unesite veličinu (npr. 2MB ili 3KB) ili broj (npr. 5)
|
||||
split-by-size-or-count.submit=Potvrdi
|
||||
|
||||
|
||||
#overlay-pdfs
|
||||
overlay-pdfs.header=Preklapanje PDF fajlova
|
||||
overlay-pdfs.baseFile.label=Izaberite osnovni PDF fajl
|
||||
overlay-pdfs.overlayFiles.label=Izaberite PDF fajlove za preklapanje
|
||||
overlay-pdfs.mode.label=Izaberite režim preklapanja
|
||||
overlay-pdfs.mode.sequential=Sekvencijalno preklapanje
|
||||
overlay-pdfs.mode.interleaved=Interleaved preklapanje
|
||||
overlay-pdfs.mode.fixedRepeat=Fixed Repeat preklapanje
|
||||
overlay-pdfs.counts.label=Broj preklapanja (za režim Fixed Repeat)
|
||||
overlay-pdfs.counts.placeholder=Unesite brojeve odvojene zarezom (npr. 2,3,1)
|
||||
overlay-pdfs.position.label=Izaberite poziciju preklapanja
|
||||
overlay-pdfs.position.foreground=Prethodni plan
|
||||
overlay-pdfs.position.background=Pozadina
|
||||
overlay-pdfs.submit=Potvrdi
|
||||
|
||||
|
||||
#split-by-sections
|
||||
split-by-sections.title=Razdvoji PDF po sekcijama
|
||||
split-by-sections.header=Razdvoji PDF u sekcije
|
||||
split-by-sections.horizontal.label=Horizontalne podele
|
||||
split-by-sections.vertical.label=Vertikalne podele
|
||||
split-by-sections.horizontal.placeholder=Unesite broj horizontalnih podele
|
||||
split-by-sections.vertical.placeholder=Unesite broj vertikalnih podele
|
||||
split-by-sections.submit=Razdvoji PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Credentials changed!
|
||||
notAuthenticatedMessage=User not authenticated.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=Current password is incorrect.
|
||||
usernameExistsMessage=New Username already exists.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=Submit
|
||||
certSign.title=Certifikatsignering
|
||||
certSign.header=Skriv under en PDF med ditt certifikat (Pågående arbete)
|
||||
certSign.selectPDF=Välj en PDF-fil för signering:
|
||||
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.selectKey=Välj din privata nyckelfil (PKCS#8-format, kan vara .pem eller .der):
|
||||
certSign.selectCert=Välj din certifikatfil (X.509-format, kan vara .pem eller .der):
|
||||
certSign.selectP12=Välj din PKCS#12-nyckellagringsfil (.p12 eller .pfx) (Valfritt, om den tillhandahålls bör den innehålla din privata nyckel och certifikat):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Certifikattyp
|
||||
certSign.password=Ange ditt nyckellager eller privata nyckellösenord (om något):
|
||||
certSign.showSig=Visa signatur
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Kırmızı
|
||||
green=Yeşil
|
||||
blue=Mavi
|
||||
custom=Özel
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=Bilgiler değiştirildi!
|
||||
notAuthenticatedMessage=Kullanıcı doğrulanmadı.
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=Mevcut şifre yanlış.
|
||||
usernameExistsMessage=Yeni Kullanıcı Adı zaten var.
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=Gönder
|
||||
certSign.title=Sertifika İmzalama
|
||||
certSign.header=Sertifikanızla bir PDF imzalayın (Devam eden iş)
|
||||
certSign.selectPDF=İmzalamak için bir PDF Dosyası seçin:
|
||||
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.selectKey=Özel Anahtar Dosyanızı Seçin (PKCS#8 formatında, .pem veya .der olabilir):
|
||||
certSign.selectCert=Sertifika Dosyanızı Seçin (X.509 formatında, .pem veya .der olabilir):
|
||||
certSign.selectP12=PKCS#12 Anahtar Deposu Dosyanızı Seçin (.p12 veya .pfx) (İsteğe bağlı, sağlanırsa, özel anahtarınızı ve sertifikanızı içermelidir):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=Sertifika Türü
|
||||
certSign.password=Anahtar Deposu veya Özel Anahtar Şifrenizi Girin (Varsa):
|
||||
certSign.showSig=İmzayı Göster
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=Vertical Divisions
|
||||
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions
|
||||
split-by-sections.vertical.placeholder=Enter number of vertical divisions
|
||||
split-by-sections.submit=Split PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###########
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
@@ -42,6 +42,8 @@ red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=凭证已更改!
|
||||
notAuthenticatedMessage=用户未经过身份验证。
|
||||
@@ -50,6 +52,29 @@ incorrectPasswordMessage=当前密码不正确。
|
||||
usernameExistsMessage=新用户名已存在。
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
@@ -522,9 +547,11 @@ scalePages.submit=提交
|
||||
certSign.title=证书签名
|
||||
certSign.header=使用您的证书签署 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.selectKey=选择您的私钥文件(PKCS#8 格式,可以是 .pem 或 .der):
|
||||
certSign.selectCert=选择您的证书文件(X.509 格式,可以是 .pem 或 .der):
|
||||
certSign.selectP12=选择您的 PKCS#12 密钥库文件(.p12 或 .pfx)(可选,如果提供,它应该包含您的私钥和证书):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=证书类型
|
||||
certSign.password=输入您的密钥库或私钥密码(如果有):
|
||||
certSign.showSig=显示签名
|
||||
@@ -894,3 +921,14 @@ split-by-sections.vertical.label=垂直分割
|
||||
split-by-sections.horizontal.placeholder=输入水平分割数
|
||||
split-by-sections.vertical.placeholder=输入垂直分割数
|
||||
split-by-sections.submit=分割PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
|
||||
934
src/main/resources/messages_zh_TW.properties
Normal file
934
src/main/resources/messages_zh_TW.properties
Normal file
@@ -0,0 +1,934 @@
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
language.direction=ltr
|
||||
|
||||
pdfPrompt=選擇 PDF 檔案
|
||||
multiPdfPrompt=選擇多個 PDF 檔案
|
||||
multiPdfDropPrompt=選擇(或拖放)所有需要的 PDF 檔案
|
||||
imgPrompt=選擇圖片
|
||||
genericSubmit=送出
|
||||
processTimeWarning=警告:此過程可能需要長達一分鐘,具體取決於檔案大小
|
||||
pageOrderPrompt=自訂頁面順序(輸入以逗號分隔的頁碼或函式,如 2n+1):
|
||||
goToPage=前往
|
||||
true=是
|
||||
false=否
|
||||
unknown=未知
|
||||
save=儲存
|
||||
close=關閉
|
||||
filesSelected=已選擇的檔案
|
||||
noFavourites=未新增收藏
|
||||
bored=等待時覺得無聊?
|
||||
alphabet=字母表
|
||||
downloadPdf=下載 PDF
|
||||
text=文字
|
||||
font=字型
|
||||
selectFillter=-- 選擇 --
|
||||
pageNum=頁碼
|
||||
sizes.small=小
|
||||
sizes.medium=中
|
||||
sizes.large=大
|
||||
sizes.x-large=特大
|
||||
error.pdfPassword=PDF 檔案已加密,但未提供密碼或密碼不正確
|
||||
delete=刪除
|
||||
username=使用者名稱
|
||||
password=密碼
|
||||
welcome=歡迎
|
||||
property=屬性
|
||||
black=黑色
|
||||
white=白色
|
||||
red=紅色
|
||||
green=綠色
|
||||
blue=藍色
|
||||
custom=自訂...
|
||||
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
|
||||
poweredBy=Powered by
|
||||
|
||||
changedCredsMessage=憑證已變更!
|
||||
notAuthenticatedMessage=使用者未認證。
|
||||
userNotFoundMessage=找不到使用者。
|
||||
incorrectPasswordMessage=目前密碼不正確。
|
||||
usernameExistsMessage=新使用者名稱已存在。
|
||||
|
||||
|
||||
###############
|
||||
# Pipeline #
|
||||
###############
|
||||
pipeline.header=Pipeline Menu (Alpha)
|
||||
pipeline.uploadButton=Upload Custom
|
||||
pipeline.configureButton=Configure
|
||||
pipeline.defaultOption=Custom
|
||||
pipeline.submitButton=Submit
|
||||
|
||||
######################
|
||||
# Pipeline Options #
|
||||
######################
|
||||
pipelineOptions.header=Pipeline Configuration
|
||||
pipelineOptions.pipelineNameLabel=Pipeline Name
|
||||
pipelineOptions.saveSettings=Save Operation Settings
|
||||
pipelineOptions.pipelineNamePrompt=Enter pipeline name here
|
||||
pipelineOptions.addOperationButton=Add operation
|
||||
pipelineOptions.pipelineHeader=Pipeline:
|
||||
pipelineOptions.saveButton=Download
|
||||
pipelineOptions.validateButton=Validate
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
#############
|
||||
navbar.convert=轉換
|
||||
navbar.security=安全
|
||||
navbar.other=其他
|
||||
navbar.darkmode=暗黑模式
|
||||
navbar.pageOps=頁面操作
|
||||
navbar.settings=設定
|
||||
|
||||
#############
|
||||
# SETTINGS #
|
||||
#############
|
||||
settings.title=設定
|
||||
settings.update=有更新可用
|
||||
settings.appVersion=應用版本:
|
||||
settings.downloadOption.title=選擇下載選項(對於單一檔案非壓縮下載):
|
||||
settings.downloadOption.1=在同一視窗中開啟
|
||||
settings.downloadOption.2=在新視窗中開啟
|
||||
settings.downloadOption.3=下載檔案
|
||||
settings.zipThreshold=當下載的檔案數量超過時,壓縮檔案
|
||||
settings.signOut=登出
|
||||
settings.accountSettings=帳戶設定
|
||||
|
||||
|
||||
|
||||
changeCreds.title=變更憑證
|
||||
changeCreds.header=更新您的帳戶詳細資訊
|
||||
changeCreds.changeUserAndPassword=您正在使用預設的登入憑證。請輸入新的密碼(如果需要,也可以輸入使用者名稱)
|
||||
changeCreds.newUsername=新使用者名稱
|
||||
changeCreds.oldPassword=目前密碼
|
||||
changeCreds.newPassword=新密碼
|
||||
changeCreds.confirmNewPassword=確認新密碼
|
||||
changeCreds.submit=送出變更
|
||||
|
||||
|
||||
|
||||
account.title=帳戶設定
|
||||
account.accountSettings=帳戶設定
|
||||
account.adminSettings=管理設定 - 檢視和新增使用者
|
||||
account.userControlSettings=使用者控制設定
|
||||
account.changeUsername=修改使用者名稱
|
||||
account.changeUsername=修改使用者名稱
|
||||
account.password=確認密碼
|
||||
account.oldPassword=舊密碼
|
||||
account.newPassword=新密碼
|
||||
account.changePassword=修改密碼
|
||||
account.confirmNewPassword=確認新密碼
|
||||
account.signOut=登出
|
||||
account.yourApiKey=您的 API 金鑰
|
||||
account.syncTitle=將瀏覽器設定與帳戶同步
|
||||
account.settingsCompare=設定比較:
|
||||
account.property=屬性
|
||||
account.webBrowserSettings=網頁瀏覽器設定
|
||||
account.syncToBrowser=同步帳戶 -> 瀏覽器
|
||||
account.syncToAccount=同步帳戶 <- 瀏覽器
|
||||
|
||||
|
||||
adminUserSettings.title=使用者控制設定
|
||||
adminUserSettings.header=管理使用者控制設定
|
||||
adminUserSettings.admin=管理員
|
||||
adminUserSettings.user=使用者
|
||||
adminUserSettings.addUser=新增使用者
|
||||
adminUserSettings.roles=角色
|
||||
adminUserSettings.role=角色
|
||||
adminUserSettings.actions=操作
|
||||
adminUserSettings.apiUser=受限制的 API 使用者
|
||||
adminUserSettings.webOnlyUser=僅使用網頁的使用者
|
||||
adminUserSettings.demoUser=示範用途的使用者(無自訂設定)
|
||||
adminUserSettings.forceChange=強制使用者在登入時修改使用者名稱/密碼
|
||||
adminUserSettings.submit=儲存
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
home.desc=您的本地主機一站式 PDF 需求解決方案。
|
||||
home.searchBar=搜尋功能...
|
||||
|
||||
|
||||
home.viewPdf.title=檢視 PDF
|
||||
home.viewPdf.desc=檢視、註釋、新增文字或圖片
|
||||
viewPdf.tags=檢視,閱讀,註釋,文字,圖片
|
||||
|
||||
home.multiTool.title=PDF 多工具
|
||||
home.multiTool.desc=合併、旋轉、重新排列和移除頁面
|
||||
multiTool.tags=多工具,多操作,UI,點選拖動,前端,客戶端,互動,可互動,移動
|
||||
|
||||
home.merge.title=合併
|
||||
home.merge.desc=輕鬆將多個 PDF 合併為一個。
|
||||
merge.tags=合併,頁面操作,後端,伺服器端
|
||||
|
||||
home.split.title=分割
|
||||
home.split.desc=將 PDF 分割為多個文件
|
||||
split.tags=頁面操作,劃分,多頁,剪下,伺服器端
|
||||
|
||||
home.rotate.title=旋轉
|
||||
home.rotate.desc=輕鬆旋轉您的 PDF。
|
||||
rotate.tags=伺服器端
|
||||
|
||||
|
||||
home.imageToPdf.title=圖片轉 PDF
|
||||
home.imageToPdf.desc=將圖片(PNG、JPEG、GIF)轉換為 PDF。
|
||||
imageToPdf.tags=轉換,img,jpg,圖片,照片
|
||||
|
||||
home.pdfToImage.title=PDF 轉圖片
|
||||
home.pdfToImage.desc=將 PDF 轉換為圖片。(PNG、JPEG、GIF)
|
||||
pdfToImage.tags=轉換,img,jpg,圖片,照片
|
||||
|
||||
home.pdfOrganiser.title=整理
|
||||
home.pdfOrganiser.desc=以任何順序移除/重新排列頁面
|
||||
pdfOrganiser.tags=雙面,偶數,奇數,排序,移動
|
||||
|
||||
|
||||
home.addImage.title=新增圖片
|
||||
home.addImage.desc=在 PDF 的指定位置新增圖片
|
||||
addImage.tags=img,jpg,圖片,照片
|
||||
|
||||
home.watermark.title=新增浮水印
|
||||
home.watermark.desc=在您的 PDF 檔案中新增自訂浮水印。
|
||||
watermark.tags=文字,重複,標籤,自有,版權,商標,img,jpg,圖片,照片
|
||||
|
||||
home.permissions.title=修改權限
|
||||
home.permissions.desc=修改您的 PDF 檔案權限
|
||||
permissions.tags=讀取,寫入,編輯,列印
|
||||
|
||||
|
||||
home.removePages.title=移除
|
||||
home.removePages.desc=從您的 PDF 檔案中刪除不需要的頁面。
|
||||
removePages.tags=移除頁面,刪除頁面
|
||||
|
||||
home.addPassword.title=新增密碼
|
||||
home.addPassword.desc=用密碼加密您的 PDF 檔案。
|
||||
addPassword.tags=安全,安全性
|
||||
|
||||
home.removePassword.title=移除密碼
|
||||
home.removePassword.desc=從您的 PDF 檔案中移除密碼保護。
|
||||
removePassword.tags=安全,解密,安全性,取消密碼,刪除密碼
|
||||
|
||||
home.compressPdfs.title=壓縮
|
||||
home.compressPdfs.desc=壓縮 PDF 以減少其檔案大小。
|
||||
compressPdfs.tags=壓縮,小,微小
|
||||
|
||||
|
||||
home.changeMetadata.title=變更中繼資料
|
||||
home.changeMetadata.desc=從 PDF 檔案中變更/移除/新增中繼資料
|
||||
changeMetadata.tags==標題,作者,日期,建立,時間,出版商,製作人,統計
|
||||
|
||||
home.fileToPDF.title=檔案轉 PDF
|
||||
home.fileToPDF.desc=將幾乎所有格式轉換為 PDF(DOCX、PNG、XLS、PPT、TXT 等等)
|
||||
fileToPDF.tags=轉換,格式,文件,圖片,幻燈片,文字,轉換,辦公室,文件,Word,Excel,PowerPoint
|
||||
|
||||
home.ocr.title=OCR / 清理掃描
|
||||
home.ocr.desc=清理掃描並從 PDF 中的影像中偵測文字並重新新增為文字。
|
||||
ocr.tags=識別,文字,影像,掃描,讀取,識別,偵測,可編輯
|
||||
|
||||
|
||||
home.extractImages.title=提取圖片
|
||||
home.extractImages.desc=從 PDF 中提取所有圖片並將它們儲存到壓縮檔中
|
||||
extractImages.tags=圖片,照片,儲存,存檔,壓縮檔,捕獲,抓取
|
||||
|
||||
home.pdfToPDFA.title=PDF 轉 PDF/A
|
||||
home.pdfToPDFA.desc=將 PDF 轉換為長期儲存的 PDF/A
|
||||
pdfToPDFA.tags=存檔,長期,標準,轉換,儲存,儲存
|
||||
|
||||
home.PDFToWord.title=PDF 轉 Word
|
||||
home.PDFToWord.desc=將 PDF 轉換為 Word 格式(DOC、DOCX 和 ODT)
|
||||
PDFToWord.tags=doc,docx,odt,word,轉換,格式,轉換,辦公室,微軟,docfile
|
||||
|
||||
home.PDFToPresentation.title=PDF 轉簡報
|
||||
home.PDFToPresentation.desc=將 PDF 轉換為簡報格式(PPT、PPTX 和 ODP)
|
||||
PDFToPresentation.tags=幻燈片,展示,辦公室,微軟
|
||||
|
||||
home.PDFToText.title=PDF 轉 RTF(文字)
|
||||
home.PDFToText.desc=將 PDF 轉換為文字或 RTF 格式
|
||||
PDFToText.tags=豐富格式,豐富文字格式,豐富文字格式
|
||||
|
||||
home.PDFToHTML.title=PDF 轉 HTML
|
||||
home.PDFToHTML.desc=將 PDF 轉換為 HTML 格式
|
||||
PDFToHTML.tags=網頁內容,瀏覽器友善
|
||||
|
||||
|
||||
home.PDFToXML.title=PDF 轉 XML
|
||||
home.PDFToXML.desc=將 PDF 轉換為 XML 格式
|
||||
PDFToXML.tags=資料提取,結構化內容,互操作,轉換,轉換
|
||||
|
||||
home.ScannerImageSplit.title=偵測/分割掃描照片
|
||||
home.ScannerImageSplit.desc=從照片/PDF 中分割多張照片
|
||||
ScannerImageSplit.tags=分離,自動偵測,掃描,多照片,組織
|
||||
|
||||
home.sign.title=簽章
|
||||
home.sign.desc=透過繪圖、文字或影像新增簽章到 PDF
|
||||
sign.tags=授權,縮寫,繪製簽章,文字,影像簽章
|
||||
|
||||
home.flatten.title=平坦化
|
||||
home.flatten.desc=從 PDF 中移除所有互動元素和表單
|
||||
flatten.tags=靜態,停用,非互動,簡化
|
||||
|
||||
home.repair.title=修復
|
||||
home.repair.desc=嘗試修復損壞/破損的 PDF
|
||||
repair.tags=修復,恢復,修正,恢復
|
||||
|
||||
home.removeBlanks.title=移除空白頁面
|
||||
home.removeBlanks.desc=偵測並從文件中移除空白頁面
|
||||
removeBlanks.tags=清理,簡化,非內容,組織
|
||||
|
||||
home.removeAnnotations.title=移除註釋
|
||||
home.removeAnnotations.desc=從 PDF 中移除所有註釋/註解
|
||||
removeAnnotations.tags=註釋,突出,註解,標記,移除
|
||||
|
||||
home.compare.title=比較
|
||||
home.compare.desc=比較並顯示 2 個 PDF 檔案的差異
|
||||
compare.tags=區分,對比,變化,分析
|
||||
|
||||
home.certSign.title=使用憑證簽章
|
||||
home.certSign.desc=使用憑證/金鑰(PEM/P12)簽章 PDF
|
||||
certSign.tags=驗證,PEM,P12,官方,加密
|
||||
|
||||
home.pageLayout.title=多頁面版面配置
|
||||
home.pageLayout.desc=將 PDF 檔案的多個頁面合併到單一頁面
|
||||
pageLayout.tags=合併,複合,單一檢視,組織
|
||||
|
||||
home.scalePages.title=調整頁面大小/比例
|
||||
home.scalePages.desc=修改頁面及其內容的大小/比例。
|
||||
scalePages.tags=調整大小,修改,尺寸,適應
|
||||
|
||||
home.pipeline.title=管道(進階)
|
||||
home.pipeline.desc=透過定義管道指令碼在 PDF 上執行多個操作
|
||||
pipeline.tags=自動化,序列,指令碼,批次處理
|
||||
|
||||
home.add-page-numbers.title=新增頁碼
|
||||
home.add-page-numbers.desc=在文件的設定位置新增頁碼
|
||||
add-page-numbers.tags=分頁,標籤,組織,索引
|
||||
|
||||
home.auto-rename.title=自動重新命名 PDF 檔案
|
||||
home.auto-rename.desc=根據其偵測到的標頭自動重新命名 PDF 檔案
|
||||
auto-rename.tags=自動偵測,基於標頭,組織,重新標籤
|
||||
|
||||
home.adjust-contrast.title=調整顏色/對比度
|
||||
home.adjust-contrast.desc=調整 PDF 的對比度、飽和度和亮度
|
||||
adjust-contrast.tags=色彩校正,調整,修改,增強
|
||||
|
||||
home.crop.title=裁剪 PDF
|
||||
home.crop.desc=裁剪 PDF 以減少其大小(保持文字!)
|
||||
crop.tags=修剪,縮小,編輯,形狀
|
||||
|
||||
home.autoSplitPDF.title=自動分割頁面
|
||||
home.autoSplitPDF.desc=自動分割掃描的 PDF,使用實體掃描頁面分割器 QR Code
|
||||
autoSplitPDF.tags=基於 QR Code,分離,掃描區段,組織
|
||||
|
||||
home.sanitizePdf.title=清理
|
||||
home.sanitizePdf.desc=從 PDF 檔案中移除指令碼和其他元素
|
||||
sanitizePdf.tags=清理,安全,安全,移除威脅
|
||||
|
||||
home.URLToPDF.title=網址/網站轉 PDF
|
||||
home.URLToPDF.desc=將任何 http(s) 網址轉換為 PDF
|
||||
URLToPDF.tags=網頁捕獲,儲存頁面,網頁轉文件,存檔
|
||||
|
||||
home.HTMLToPDF.title=HTML 轉 PDF
|
||||
home.HTMLToPDF.desc=將任何 HTML 檔案或壓縮檔轉換為 PDF
|
||||
HTMLToPDF.tags=標記,網頁內容,轉換,轉換
|
||||
|
||||
|
||||
home.MarkdownToPDF.title=Markdown 轉 PDF
|
||||
home.MarkdownToPDF.desc=將任何 Markdown 檔案轉換為 PDF
|
||||
MarkdownToPDF.tags=標記,網頁內容,轉換,轉換
|
||||
|
||||
|
||||
home.getPdfInfo.title=取得 PDF 的所有資訊
|
||||
home.getPdfInfo.desc=取得 PDF 的所有可能資訊
|
||||
getPdfInfo.tags=資訊,資料,統計,統計資料
|
||||
|
||||
|
||||
home.extractPage.title=提取多個頁面
|
||||
home.extractPage.desc=從 PDF 中提取選定的頁面
|
||||
extractPage.tags=提取
|
||||
|
||||
|
||||
home.PdfToSinglePage.title=PDF 轉單一大頁面
|
||||
home.PdfToSinglePage.desc=將所有 PDF 頁面合併為一個大的單一頁面
|
||||
PdfToSinglePage.tags=單一頁面
|
||||
|
||||
|
||||
home.showJS.title=顯示 JavaScript
|
||||
home.showJS.desc=搜尋並顯示嵌入 PDF 中的任何 JS(JavaScript)
|
||||
showJS.tags=塗黑,隱藏,塗黑,黑色,標記,隱藏
|
||||
|
||||
home.autoRedact.title=自動塗黑
|
||||
home.autoRedact.desc=根據輸入的文字自動塗黑 PDF 中的文字
|
||||
showJS.tags=塗黑,隱藏,塗黑,黑色,標記,隱藏
|
||||
|
||||
home.tableExtraxt.title=PDF 轉 CSV
|
||||
home.tableExtraxt.desc=從 PDF 中提取表格並將其轉換為 CSV
|
||||
tableExtraxt.tags=CSV,表格提取,提取,轉換
|
||||
|
||||
|
||||
home.autoSizeSplitPDF.title=根據大小/數量自動分割
|
||||
home.autoSizeSplitPDF.desc=根據大小、頁數或文件數將單一 PDF 分割為多個文件
|
||||
autoSizeSplitPDF.tags=pdf,分割,文件,組織
|
||||
|
||||
|
||||
home.overlay-pdfs.title=覆蓋 PDF
|
||||
home.overlay-pdfs.desc=將 PDF 覆蓋在另一個 PDF 上
|
||||
overlay-pdfs.tags=覆蓋
|
||||
|
||||
home.split-by-sections.title=依區段分割 PDF
|
||||
home.split-by-sections.desc=將 PDF 的每一頁分割為較小的水平和垂直區段
|
||||
split-by-sections.tags=區段分割, 劃分, 自訂
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
# #
|
||||
###########################
|
||||
#login
|
||||
login.title=登入
|
||||
login.signin=登入
|
||||
login.rememberme=記住我
|
||||
login.invalid=使用者名稱或密碼無效。
|
||||
login.locked=您的帳戶已被鎖定。
|
||||
login.signinTitle=請登入
|
||||
|
||||
|
||||
#auto-redact
|
||||
autoRedact.title=自動塗黑
|
||||
autoRedact.header=自動塗黑
|
||||
autoRedact.colorLabel=顏色
|
||||
autoRedact.textsToRedactLabel=要塗黑的文字(以行分隔)
|
||||
autoRedact.textsToRedactPlaceholder=例如 \n機密 \n最高機密
|
||||
autoRedact.useRegexLabel=使用正則表達式
|
||||
autoRedact.wholeWordSearchLabel=整個單詞搜尋
|
||||
autoRedact.customPaddingLabel=自訂額外填充
|
||||
autoRedact.convertPDFToImageLabel=將 PDF 轉換為 PDF-影像(用於移除方框後面的文字)
|
||||
autoRedact.submitButton=送出
|
||||
|
||||
|
||||
#showJS
|
||||
showJS.title=顯示 JavaScript
|
||||
showJS.header=顯示 JavaScript
|
||||
showJS.downloadJS=下載 JavaScript
|
||||
showJS.submit=顯示
|
||||
|
||||
|
||||
#pdfToSinglePage
|
||||
pdfToSinglePage.title=PDF 轉為單一頁面
|
||||
pdfToSinglePage.header=PDF 轉為單一頁面
|
||||
pdfToSinglePage.submit=轉換為單一頁面
|
||||
|
||||
|
||||
#pageExtracter
|
||||
pageExtracter.title=提取頁面
|
||||
pageExtracter.header=提取頁面
|
||||
pageExtracter.submit=提取
|
||||
|
||||
|
||||
#getPdfInfo
|
||||
getPdfInfo.title=取得 PDF 資訊
|
||||
getPdfInfo.header=取得 PDF 資訊
|
||||
getPdfInfo.submit=取得資訊
|
||||
getPdfInfo.downloadJson=下載 JSON
|
||||
|
||||
|
||||
#markdown-to-pdf
|
||||
MarkdownToPDF.title=Markdown 轉 PDF
|
||||
MarkdownToPDF.header=Markdown 轉 PDF
|
||||
MarkdownToPDF.submit=轉換
|
||||
MarkdownToPDF.help=正在進行中
|
||||
MarkdownToPDF.credit=使用 WeasyPrint
|
||||
|
||||
|
||||
|
||||
#url-to-pdf
|
||||
URLToPDF.title=URL 轉 PDF
|
||||
URLToPDF.header=URL 轉 PDF
|
||||
URLToPDF.submit=轉換
|
||||
URLToPDF.credit=使用 WeasyPrint
|
||||
|
||||
|
||||
#html-to-pdf
|
||||
HTMLToPDF.title=HTML 轉 PDF
|
||||
HTMLToPDF.header=HTML 轉 PDF
|
||||
HTMLToPDF.help=接受 HTML 文件和包含所需 html/css/images 等的 ZIP
|
||||
HTMLToPDF.submit=轉換
|
||||
HTMLToPDF.credit=使用 WeasyPrint
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=清理 PDF
|
||||
sanitizePDF.header=清理 PDF 檔案
|
||||
sanitizePDF.selectText.1=移除 JavaScript 操作
|
||||
sanitizePDF.selectText.2=移除內嵌文件
|
||||
sanitizePDF.selectText.3=移除中繼資料
|
||||
sanitizePDF.selectText.4=移除連結
|
||||
sanitizePDF.selectText.5=移除字型
|
||||
sanitizePDF.submit=清理 PDF
|
||||
|
||||
|
||||
#addPageNumbers
|
||||
addPageNumbers.title=新增頁碼
|
||||
addPageNumbers.header=新增頁碼
|
||||
addPageNumbers.selectText.1=選擇 PDF 檔案:
|
||||
addPageNumbers.selectText.2=邊距大小
|
||||
addPageNumbers.selectText.3=位置
|
||||
addPageNumbers.selectText.4=起始號碼
|
||||
addPageNumbers.selectText.5=要編號的頁面
|
||||
addPageNumbers.selectText.6=自訂文字
|
||||
addPageNumbers.customTextDesc=自訂文字
|
||||
addPageNumbers.numberPagesDesc=要編號的頁面,預設為 '全部',也可使用 1-5 或 2,5,9 等格式
|
||||
addPageNumbers.customNumberDesc=預設為 {n},也接受 '頁面 {n} 共 {total}','文字-{n}','{filename}-{n}
|
||||
addPageNumbers.submit=新增頁碼
|
||||
|
||||
|
||||
#auto-rename
|
||||
auto-rename.title=自動重新命名
|
||||
auto-rename.header=自動重新命名 PDF
|
||||
auto-rename.submit=自動重新命名
|
||||
|
||||
|
||||
#adjustContrast
|
||||
adjustContrast.title=調整對比度
|
||||
adjustContrast.header=調整對比度
|
||||
adjustContrast.contrast=對比度:
|
||||
adjustContrast.brightness=亮度:
|
||||
adjustContrast.saturation=飽和度:
|
||||
adjustContrast.download=下載
|
||||
|
||||
|
||||
#crop
|
||||
crop.title=裁剪
|
||||
crop.header=裁剪影像
|
||||
crop.submit=送出
|
||||
|
||||
|
||||
#autoSplitPDF
|
||||
autoSplitPDF.title=自動分割 PDF
|
||||
autoSplitPDF.header=自動分割 PDF
|
||||
autoSplitPDF.description=列印,插入,掃描,上傳,讓 Stirling PDF 處理其餘的工作。不需要手動工作排序。
|
||||
autoSplitPDF.selectText.1=從下面列印一些分隔紙張(黑白即可)。
|
||||
autoSplitPDF.selectText.2=透過在它們之間插入分隔紙張一次掃描所有文件。
|
||||
autoSplitPDF.selectText.3=上傳單一大的掃描 PDF 檔案,讓 Stirling PDF 處理其餘的工作。
|
||||
autoSplitPDF.selectText.4=自動偵測並移除分隔頁面,確保最終文件整潔。
|
||||
autoSplitPDF.formPrompt=送出包含 Stirling-PDF 頁面分隔器的 PDF:
|
||||
autoSplitPDF.duplexMode=雙面模式(正反面掃描)
|
||||
autoSplitPDF.dividerDownload1=下載 '自動分割器分隔器(最小化).pdf'
|
||||
autoSplitPDF.dividerDownload2=下載 '自動分割器分隔器(帶說明).pdf'
|
||||
autoSplitPDF.submit=送出
|
||||
|
||||
|
||||
#pipeline
|
||||
pipeline.title=管道
|
||||
|
||||
|
||||
#pageLayout
|
||||
pageLayout.title=多頁面版面配置
|
||||
pageLayout.header=多頁面版面配置
|
||||
pageLayout.pagesPerSheet=每張紙的頁面數:
|
||||
pageLayout.addBorder=新增邊框
|
||||
pageLayout.submit=送出
|
||||
|
||||
|
||||
#scalePages
|
||||
scalePages.title=調整頁面大小/比例
|
||||
scalePages.header=調整頁面大小/比例
|
||||
scalePages.pageSize=文件的頁面大小。
|
||||
scalePages.scaleFactor=頁面的縮放級別(裁剪)。
|
||||
scalePages.submit=送出
|
||||
|
||||
|
||||
#certSign
|
||||
certSign.title=憑證簽章
|
||||
certSign.header=使用您的憑證簽章(進行中)
|
||||
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.selectKey=選擇您的私鑰文件(PKCS#8 格式,可能是 .pem 或 .der):
|
||||
certSign.selectCert=選擇您的憑證文件(X.509 格式,可能是 .pem 或 .der):
|
||||
certSign.selectP12=選擇您的 PKCS#12 金鑰庫文件(.p12 或 .pfx)(可選,如果提供,它應包含您的私鑰和憑證):
|
||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
|
||||
certSign.certType=憑證類型
|
||||
certSign.password=輸入您的金鑰庫或私鑰密碼(如果有):
|
||||
certSign.showSig=顯示簽章
|
||||
certSign.reason=原因
|
||||
certSign.location=位置
|
||||
certSign.name=名稱
|
||||
certSign.submit=簽章 PDF
|
||||
|
||||
|
||||
#removeBlanks
|
||||
removeBlanks.title=移除空白頁面
|
||||
removeBlanks.header=移除空白頁面
|
||||
removeBlanks.threshold=畫素白度閾值:
|
||||
removeBlanks.thresholdDesc=確定一個白色畫素必須多麼白才能被分類為 '白色'。0 = 黑色,255 純白。
|
||||
removeBlanks.whitePercent=白色百分比(%):
|
||||
removeBlanks.whitePercentDesc=頁面必須是 '白色' 畫素的百分比才能被移除
|
||||
removeBlanks.submit=移除空白
|
||||
|
||||
|
||||
#removeAnnotations
|
||||
removeAnnotations.title=移除註釋
|
||||
removeAnnotations.header=移除註釋
|
||||
removeAnnotations.submit=移除
|
||||
|
||||
|
||||
#compare
|
||||
compare.title=比較
|
||||
compare.header=比較 PDF
|
||||
compare.document.1=文件 1
|
||||
compare.document.2=文件 2
|
||||
compare.submit=比較
|
||||
|
||||
|
||||
#sign
|
||||
sign.title=簽章
|
||||
sign.header=簽章 PDF
|
||||
sign.upload=上傳影像
|
||||
sign.draw=繪製簽章
|
||||
sign.text=文字輸入
|
||||
sign.clear=清除
|
||||
sign.add=新增
|
||||
|
||||
|
||||
#repair
|
||||
repair.title=修復
|
||||
repair.header=修復 PDF
|
||||
repair.submit=修復
|
||||
|
||||
|
||||
#flatten
|
||||
flatten.title=平坦化
|
||||
flatten.header=PDF 平坦化
|
||||
flatten.submit=平坦化
|
||||
|
||||
|
||||
#ScannerImageSplit
|
||||
ScannerImageSplit.selectText.1=角度閾值:
|
||||
ScannerImageSplit.selectText.2=設定影像旋轉所需的最小絕對角度(預設:10)。
|
||||
ScannerImageSplit.selectText.3=容忍度:
|
||||
ScannerImageSplit.selectText.4=確定圍繞估計的背景顏色的顏色變化範圍(預設:30)。
|
||||
ScannerImageSplit.selectText.5=最小區域:
|
||||
ScannerImageSplit.selectText.6=設定照片的最小區域閾值(預設:10000)。
|
||||
ScannerImageSplit.selectText.7=最小輪廓區域:
|
||||
ScannerImageSplit.selectText.8=設定照片的最小輪廓區域閾值
|
||||
ScannerImageSplit.selectText.9=邊框大小:
|
||||
ScannerImageSplit.selectText.10=設定新增和移除的邊框大小,以防止輸出中的白色邊框(預設:1)。
|
||||
|
||||
|
||||
#OCR
|
||||
ocr.title=OCR / 掃描清理
|
||||
ocr.header=清理掃描 / OCR(光學字元識別)
|
||||
ocr.selectText.1=選擇要在 PDF 中偵測的語言(列出的是目前可以偵測的語言):
|
||||
ocr.selectText.2=產生包含 OCR 文字的文字文件,並與 OCR 的 PDF 一起
|
||||
ocr.selectText.3=修正掃描的頁面傾斜角度,將它們旋轉回原位
|
||||
ocr.selectText.4=清理頁面,使 OCR 不太可能在背景噪音中找到文字。(無輸出變化)
|
||||
ocr.selectText.5=清理頁面,使 OCR 不太可能在背景噪音中找到文字,保持清理的輸出。
|
||||
ocr.selectText.6=忽略具有互動文字的頁面,只對影像頁面進行 OCR
|
||||
ocr.selectText.7=強制 OCR,將對每一頁進行 OCR,移除所有原始文字元素
|
||||
ocr.selectText.8=正常(如果 PDF 包含文字將出錯)
|
||||
ocr.selectText.9=額外設定
|
||||
ocr.selectText.10=OCR 模式
|
||||
ocr.selectText.11=移除 OCR 後的影像(移除所有影像,只有在轉換步驟中才有用)
|
||||
ocr.selectText.12=渲染類型(進階)
|
||||
ocr.help=請閱讀此文件,了解如何使用其他語言和/或在 Docker 中使用
|
||||
ocr.credit=此服務使用 OCRmyPDF 和 Tesseract 進行 OCR。
|
||||
ocr.submit=使用 OCR 處理 PDF
|
||||
|
||||
|
||||
#extractImages
|
||||
extractImages.title=提取圖片
|
||||
extractImages.header=提取圖片
|
||||
extractImages.selectText=選擇要轉換提取影像的影像格式
|
||||
extractImages.submit=提取
|
||||
|
||||
|
||||
#File to PDF
|
||||
fileToPDF.title=檔案轉 PDF
|
||||
fileToPDF.header=將任何檔案轉換為 PDF
|
||||
fileToPDF.credit=此服務使用 LibreOffice 和 Unoconv 進行檔案轉換。
|
||||
fileToPDF.supportedFileTypes=支援的檔案類型應包括以下內容,但要獲得完整的更新支援格式列表,請參閱 LibreOffice 的文件
|
||||
fileToPDF.submit=轉換為 PDF
|
||||
|
||||
|
||||
#compress
|
||||
compress.title=壓縮
|
||||
compress.header=壓縮 PDF
|
||||
compress.credit=此服務使用 Ghostscript 進行 PDF 壓縮/最佳化。
|
||||
compress.selectText.1=手動模式 - 從 1 到 4
|
||||
compress.selectText.2=最佳化級別:
|
||||
compress.selectText.3=4(對於文字影像非常糟糕)
|
||||
compress.selectText.4=自動模式 - 自動調整品質以使 PDF 達到確定大小
|
||||
compress.selectText.5=預期的 PDF 大小(例如 25MB, 10.8MB, 25KB)
|
||||
compress.submit=壓縮
|
||||
|
||||
|
||||
#Add image
|
||||
addImage.title=新增圖片
|
||||
addImage.header=新增圖片到 PDF
|
||||
addImage.everyPage=每一頁?
|
||||
addImage.upload=新增圖片
|
||||
addImage.submit=新增圖片
|
||||
|
||||
|
||||
#merge
|
||||
merge.title=合併
|
||||
merge.header=合併多個 PDF
|
||||
merge.sortByName=依名稱排序
|
||||
merge.sortByDate=依日期排序
|
||||
merge.submit=合併
|
||||
|
||||
|
||||
#pdfOrganiser
|
||||
pdfOrganiser.title=頁面整理
|
||||
pdfOrganiser.header=PDF 頁面整理
|
||||
pdfOrganiser.submit=重新排列頁面
|
||||
|
||||
|
||||
#multiTool
|
||||
multiTool.title=PDF 多工具
|
||||
multiTool.header=PDF 多工具
|
||||
|
||||
#view pdf
|
||||
viewPdf.title=檢視 PDF
|
||||
viewPdf.header=檢視 PDF
|
||||
|
||||
#pageRemover
|
||||
pageRemover.title=頁面移除
|
||||
pageRemover.header=PDF 頁面移除
|
||||
pageRemover.pagesToDelete=要刪除的頁面(輸入以逗號分隔的頁碼):
|
||||
pageRemover.submit=刪除頁面
|
||||
|
||||
|
||||
#rotate
|
||||
rotate.title=旋轉 PDF
|
||||
rotate.header=旋轉 PDF
|
||||
rotate.selectAngle=選擇旋轉角度(以 90 度的倍數):
|
||||
rotate.submit=旋轉
|
||||
|
||||
|
||||
#merge
|
||||
split.title=分割 PDF
|
||||
split.header=分割 PDF
|
||||
split.desc.1=您選擇的數字是您希望進行分割的頁碼
|
||||
split.desc.2=因此,選擇 1,3,7-8 將會將一個 10 頁的文件分割為 6 個單獨的 PDF,包括:
|
||||
split.desc.3=文件 #1:頁面 1
|
||||
split.desc.4=文件 #2:頁面 2 和 3
|
||||
split.desc.5=文件 #3:頁面 4、5 和 6
|
||||
split.desc.6=文件 #4:頁面 7
|
||||
split.desc.7=文件 #5:頁面 8
|
||||
split.desc.8=文件 #6:頁面 9 和 10
|
||||
split.splitPages=輸入要分割的頁面:
|
||||
split.submit=分割
|
||||
|
||||
|
||||
#merge
|
||||
imageToPDF.title=圖片轉 PDF
|
||||
imageToPDF.header=圖片轉 PDF
|
||||
imageToPDF.submit=轉換
|
||||
imageToPDF.selectLabel=影像適應選項
|
||||
imageToPDF.fillPage=填充頁面
|
||||
imageToPDF.fitDocumentToImage=適應影像到頁面
|
||||
imageToPDF.maintainAspectRatio=保持長寬比
|
||||
imageToPDF.selectText.2=自動旋轉 PDF
|
||||
imageToPDF.selectText.3=多文件邏輯(僅在處理多個影像時啟用)
|
||||
imageToPDF.selectText.4=合併為單一 PDF
|
||||
imageToPDF.selectText.5=轉換為單獨的 PDF
|
||||
|
||||
|
||||
#pdfToImage
|
||||
pdfToImage.title=PDF 轉圖片
|
||||
pdfToImage.header=PDF 轉圖片
|
||||
pdfToImage.selectText=影像格式
|
||||
pdfToImage.singleOrMultiple=頁面到影像的結果類型
|
||||
pdfToImage.single=單一大影像結合所有頁面
|
||||
pdfToImage.multi=多個影像,每頁一個影像
|
||||
pdfToImage.colorType=顏色類型
|
||||
pdfToImage.color=顏色
|
||||
pdfToImage.grey=灰度
|
||||
pdfToImage.blackwhite=黑白(可能會遺失資料!)
|
||||
pdfToImage.submit=轉換
|
||||
|
||||
|
||||
#addPassword
|
||||
addPassword.title=新增密碼
|
||||
addPassword.header=新增密碼(加密)
|
||||
addPassword.selectText.1=選擇要加密的 PDF
|
||||
addPassword.selectText.2=使用者密碼
|
||||
addPassword.selectText.3=加密金鑰長度
|
||||
addPassword.selectText.4=較高的值更強,但較低的值具有更好的相容性。
|
||||
addPassword.selectText.5=要設定的權限(建議與擁有者密碼一起使用)
|
||||
addPassword.selectText.6=防止文件組裝
|
||||
addPassword.selectText.7=防止內容提取
|
||||
addPassword.selectText.8=防止為了無障礙使用而提取資料
|
||||
addPassword.selectText.9=防止填寫表單
|
||||
addPassword.selectText.10=防止修改
|
||||
addPassword.selectText.11=防止註釋修改
|
||||
addPassword.selectText.12=防止列印
|
||||
addPassword.selectText.13=防止列印不同格式
|
||||
addPassword.selectText.14=擁有者密碼
|
||||
addPassword.selectText.15=限制一旦開啟文件可以做什麼(並非所有軟體都支援)
|
||||
addPassword.selectText.16=限制開啟文件本身
|
||||
addPassword.submit=加密
|
||||
|
||||
|
||||
#watermark
|
||||
watermark.title=新增浮水印
|
||||
watermark.header=新增浮水印
|
||||
watermark.selectText.1=選擇要新增浮水印的 PDF:
|
||||
watermark.selectText.2=浮水印文字:
|
||||
watermark.selectText.3=字型大小:
|
||||
watermark.selectText.4=旋轉(0-360):
|
||||
watermark.selectText.5=widthSpacer(每個浮水印之間的水平間距):
|
||||
watermark.selectText.6=heightSpacer(每個浮水印之間的垂直間距):
|
||||
watermark.selectText.7=不透明度(0% - 100%):
|
||||
watermark.selectText.8=浮水印類型:
|
||||
watermark.selectText.9=浮水印影像:
|
||||
watermark.submit=新增浮水印
|
||||
|
||||
|
||||
#Change permissions
|
||||
permissions.title=變更權限
|
||||
permissions.header=變更權限
|
||||
permissions.warning=警告,要使這些權限不可變更,建議透過新增密碼頁面使用密碼設定這些權限
|
||||
permissions.selectText.1=選擇要變更權限的 PDF
|
||||
permissions.selectText.2=要設定的權限
|
||||
permissions.selectText.3=防止文件組裝
|
||||
permissions.selectText.4=防止內容提取
|
||||
permissions.selectText.5=防止為了無障礙使用而提取資料
|
||||
permissions.selectText.6=防止填寫表單
|
||||
permissions.selectText.7=防止修改
|
||||
permissions.selectText.8=防止註釋修改
|
||||
permissions.selectText.9=防止列印
|
||||
permissions.selectText.10=防止列印不同格式
|
||||
permissions.submit=變更
|
||||
|
||||
|
||||
#remove password
|
||||
removePassword.title=移除密碼
|
||||
removePassword.header=移除密碼(解密)
|
||||
removePassword.selectText.1=選擇要解密的 PDF
|
||||
removePassword.selectText.2=密碼
|
||||
removePassword.submit=移除
|
||||
|
||||
|
||||
#changeMetadata
|
||||
changeMetadata.title=標題:
|
||||
changeMetadata.header=變更中繼資料
|
||||
changeMetadata.selectText.1=請編輯您希望變更的變數
|
||||
changeMetadata.selectText.2=刪除所有中繼資料
|
||||
changeMetadata.selectText.3=顯示自訂中繼資料:
|
||||
changeMetadata.author=作者:
|
||||
changeMetadata.creationDate=建立日期(yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.creator=建立者:
|
||||
changeMetadata.keywords=關鍵字:
|
||||
changeMetadata.modDate=修改日期(yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=製作人:
|
||||
changeMetadata.subject=主題:
|
||||
changeMetadata.title=標題:
|
||||
changeMetadata.trapped=陷阱:
|
||||
changeMetadata.selectText.4=其他中繼資料:
|
||||
changeMetadata.selectText.5=新增自訂中繼資料項目
|
||||
changeMetadata.submit=變更
|
||||
|
||||
|
||||
#pdfToPDFA
|
||||
pdfToPDFA.title=PDF 轉 PDF/A
|
||||
pdfToPDFA.header=PDF 轉 PDF/A
|
||||
pdfToPDFA.credit=此服務使用 OCRmyPDF 進行 PDF/A 轉換
|
||||
pdfToPDFA.submit=轉換
|
||||
|
||||
|
||||
#PDFToWord
|
||||
PDFToWord.title=PDF 轉 Word
|
||||
PDFToWord.header=PDF 轉 Word
|
||||
PDFToWord.selectText.1=輸出文件格式
|
||||
PDFToWord.credit=此服務使用 LibreOffice 進行檔案轉換。
|
||||
PDFToWord.submit=轉換
|
||||
|
||||
|
||||
#PDFToPresentation
|
||||
PDFToPresentation.title=PDF 轉簡報
|
||||
PDFToPresentation.header=PDF 轉簡報
|
||||
PDFToPresentation.selectText.1=輸出文件格式
|
||||
PDFToPresentation.credit=此服務使用 LibreOffice 進行檔案轉換。
|
||||
PDFToPresentation.submit=轉換
|
||||
|
||||
|
||||
#PDFToText
|
||||
PDFToText.title=PDF 轉 RTF(文字)
|
||||
PDFToText.header=PDF 轉 RTF(文字)
|
||||
PDFToText.selectText.1=輸出文件格式
|
||||
PDFToText.credit=此服務使用 LibreOffice 進行檔案轉換。
|
||||
PDFToText.submit=轉換
|
||||
|
||||
|
||||
#PDFToHTML
|
||||
PDFToHTML.title=PDF 轉 HTML
|
||||
PDFToHTML.header=PDF 轉 HTML
|
||||
PDFToHTML.credit=此服務使用 LibreOffice 進行檔案轉換。
|
||||
PDFToHTML.submit=轉換
|
||||
|
||||
|
||||
#PDFToXML
|
||||
PDFToXML.title=PDF 轉換為 XML
|
||||
PDFToXML.header=PDF 轉換為 XML
|
||||
PDFToXML.credit=此服務使用 LibreOffice 進行檔案轉換。
|
||||
PDFToXML.submit=轉換
|
||||
|
||||
#PDFToCSV
|
||||
PDFToCSV.title=PDF 轉換為 CSV
|
||||
PDFToCSV.header=PDF 轉換為 CSV
|
||||
PDFToCSV.prompt=選擇要提取表格的頁面
|
||||
PDFToCSV.submit=提取
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.header=依大小或數量分割 PDF
|
||||
split-by-size-or-count.type.label=選擇分割類型
|
||||
split-by-size-or-count.type.size=依大小
|
||||
split-by-size-or-count.type.pageCount=依頁數
|
||||
split-by-size-or-count.type.docCount=依文件數量
|
||||
split-by-size-or-count.value.label=輸入值
|
||||
split-by-size-or-count.value.placeholder=輸入大小(例如:2MB 或 3KB)或數量(例如:5)
|
||||
split-by-size-or-count.submit=送出
|
||||
|
||||
|
||||
#overlay-pdfs
|
||||
overlay-pdfs.header=覆蓋 PDF 檔案
|
||||
overlay-pdfs.baseFile.label=選擇基礎 PDF 檔案
|
||||
overlay-pdfs.overlayFiles.label=選擇覆蓋 PDF 檔案
|
||||
overlay-pdfs.mode.label=選擇覆蓋模式
|
||||
overlay-pdfs.mode.sequential=序列覆蓋
|
||||
overlay-pdfs.mode.interleaved=交錯覆蓋
|
||||
overlay-pdfs.mode.fixedRepeat=固定重複覆蓋
|
||||
overlay-pdfs.counts.label=覆蓋次數(適用於固定重複模式)
|
||||
overlay-pdfs.counts.placeholder=輸入逗號分隔的次數(例如:2,3,1)
|
||||
overlay-pdfs.position.label=選擇覆蓋位置
|
||||
overlay-pdfs.position.foreground=前景
|
||||
overlay-pdfs.position.background=背景
|
||||
overlay-pdfs.submit=送出
|
||||
|
||||
|
||||
#split-by-sections
|
||||
split-by-sections.title=依區段分割 PDF
|
||||
split-by-sections.header=將 PDF 分割成區段
|
||||
split-by-sections.horizontal.label=水平劃分
|
||||
split-by-sections.vertical.label=垂直劃分
|
||||
split-by-sections.horizontal.placeholder=輸入水平劃分的數量
|
||||
split-by-sections.vertical.placeholder=輸入垂直劃分的數量
|
||||
split-by-sections.submit=分割 PDF
|
||||
|
||||
|
||||
#licenses
|
||||
licenses.nav=Licenses
|
||||
licenses.title=3rd Party Licenses
|
||||
licenses.header=3rd Party Licenses
|
||||
licenses.module=Module
|
||||
licenses.version=Version
|
||||
licenses.license=License
|
||||
|
||||
|
||||
@@ -9,9 +9,13 @@ security:
|
||||
loginResetTimeMinutes : 120 # lock account for 2 hours after x attempts
|
||||
|
||||
system:
|
||||
|
||||
defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc)
|
||||
googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow
|
||||
enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes)
|
||||
customApplications:
|
||||
installBookFormats: false # Installs Calibre for book format conversion (For non docker it must be manually downloaded but will need to be true to show in UI)
|
||||
installAdvancedHtmlToPDF: false # DO NOT USE EXTERNALLY, NOT SAFE! Install wkHtmlToPDF (For non docker it must be manually downloaded but will need to be true to show in UI)
|
||||
|
||||
#ui:
|
||||
# appName: exampleAppName # Application's visible name
|
||||
|
||||
846
src/main/resources/static/3rdPartyLicenses.json
Normal file
846
src/main/resources/static/3rdPartyLicenses.json
Normal file
@@ -0,0 +1,846 @@
|
||||
{
|
||||
"dependencies": [
|
||||
{
|
||||
"moduleName": "ch.qos.logback:logback-classic",
|
||||
"moduleUrl": "http://www.qos.ch",
|
||||
"moduleVersion": "1.4.14",
|
||||
"moduleLicense": "GNU Lesser General Public License",
|
||||
"moduleLicenseUrl": "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "ch.qos.logback:logback-core",
|
||||
"moduleUrl": "http://www.qos.ch",
|
||||
"moduleVersion": "1.4.14",
|
||||
"moduleLicense": "GNU Lesser General Public License",
|
||||
"moduleLicenseUrl": "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.fasterxml.jackson.core:jackson-annotations",
|
||||
"moduleUrl": "https://github.com/FasterXML/jackson",
|
||||
"moduleVersion": "2.15.3",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.fasterxml.jackson.core:jackson-core",
|
||||
"moduleUrl": "https://github.com/FasterXML/jackson-core",
|
||||
"moduleVersion": "2.15.3",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.fasterxml.jackson.core:jackson-databind",
|
||||
"moduleUrl": "https://github.com/FasterXML/jackson",
|
||||
"moduleVersion": "2.15.3",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml",
|
||||
"moduleUrl": "https://github.com/FasterXML/jackson-dataformats-text",
|
||||
"moduleVersion": "2.15.3",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.fasterxml.jackson.datatype:jackson-datatype-jdk8",
|
||||
"moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jdk8",
|
||||
"moduleVersion": "2.15.3",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.fasterxml.jackson.datatype:jackson-datatype-jsr310",
|
||||
"moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310",
|
||||
"moduleVersion": "2.15.3",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.fasterxml.jackson.module:jackson-module-parameter-names",
|
||||
"moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names",
|
||||
"moduleVersion": "2.15.3",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.fasterxml.jackson:jackson-bom",
|
||||
"moduleVersion": "2.15.3"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.fasterxml:classmate",
|
||||
"moduleUrl": "https://github.com/FasterXML/java-classmate",
|
||||
"moduleVersion": "1.6.0",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.github.vladimir-bukhtoyarov:bucket4j-core",
|
||||
"moduleUrl": "http://github.com/vladimir-bukhtoyarov/bucket4j/bucket4j-core",
|
||||
"moduleVersion": "7.6.0",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.google.zxing:core",
|
||||
"moduleUrl": "https://github.com/zxing/zxing/core",
|
||||
"moduleVersion": "3.5.2",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.h2database:h2",
|
||||
"moduleUrl": "https://h2database.com",
|
||||
"moduleVersion": "2.1.214",
|
||||
"moduleLicense": "MPL 2.0",
|
||||
"moduleLicenseUrl": "https://www.mozilla.org/en-US/MPL/2.0/"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.opencsv:opencsv",
|
||||
"moduleUrl": "http://opencsv.sf.net",
|
||||
"moduleVersion": "5.9",
|
||||
"moduleLicense": "Apache 2",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.sun.istack:istack-commons-runtime",
|
||||
"moduleUrl": "https://www.eclipse.org",
|
||||
"moduleVersion": "4.1.2",
|
||||
"moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception",
|
||||
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.twelvemonkeys.common:common-image",
|
||||
"moduleVersion": "3.10.1",
|
||||
"moduleLicense": "The BSD License",
|
||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.twelvemonkeys.common:common-io",
|
||||
"moduleVersion": "3.10.1",
|
||||
"moduleLicense": "The BSD License",
|
||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.twelvemonkeys.common:common-lang",
|
||||
"moduleVersion": "3.10.1",
|
||||
"moduleLicense": "The BSD License",
|
||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.twelvemonkeys.imageio:imageio-batik",
|
||||
"moduleVersion": "3.10.1",
|
||||
"moduleLicense": "The BSD License",
|
||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.twelvemonkeys.imageio:imageio-bmp",
|
||||
"moduleVersion": "3.10.1",
|
||||
"moduleLicense": "The BSD License",
|
||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.twelvemonkeys.imageio:imageio-core",
|
||||
"moduleVersion": "3.10.1",
|
||||
"moduleLicense": "The BSD License",
|
||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.twelvemonkeys.imageio:imageio-jpeg",
|
||||
"moduleVersion": "3.10.1",
|
||||
"moduleLicense": "The BSD License",
|
||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.twelvemonkeys.imageio:imageio-metadata",
|
||||
"moduleVersion": "3.10.1",
|
||||
"moduleLicense": "The BSD License",
|
||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.twelvemonkeys.imageio:imageio-tiff",
|
||||
"moduleVersion": "3.10.1",
|
||||
"moduleLicense": "The BSD License",
|
||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.twelvemonkeys.imageio:imageio-webp",
|
||||
"moduleVersion": "3.10.1",
|
||||
"moduleLicense": "The BSD License",
|
||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||
},
|
||||
{
|
||||
"moduleName": "com.zaxxer:HikariCP",
|
||||
"moduleUrl": "https://github.com/brettwooldridge/HikariCP",
|
||||
"moduleVersion": "5.0.1",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "commons-beanutils:commons-beanutils",
|
||||
"moduleUrl": "https://commons.apache.org/proper/commons-beanutils/",
|
||||
"moduleVersion": "1.9.4",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "commons-collections:commons-collections",
|
||||
"moduleUrl": "http://commons.apache.org/collections/",
|
||||
"moduleVersion": "3.2.2",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "commons-io:commons-io",
|
||||
"moduleUrl": "https://commons.apache.org/proper/commons-io/",
|
||||
"moduleVersion": "2.15.1",
|
||||
"moduleLicense": "Apache-2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "commons-logging:commons-logging",
|
||||
"moduleUrl": "http://jakarta.apache.org/commons/logging/",
|
||||
"moduleVersion": "1.0.4",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "/LICENSE.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "io.micrometer:micrometer-commons",
|
||||
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
||||
"moduleVersion": "1.12.1",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "io.micrometer:micrometer-core",
|
||||
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
||||
"moduleVersion": "1.12.1",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "io.micrometer:micrometer-jakarta9",
|
||||
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
||||
"moduleVersion": "1.12.1",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "io.micrometer:micrometer-observation",
|
||||
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
||||
"moduleVersion": "1.12.1",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "io.smallrye:jandex",
|
||||
"moduleVersion": "3.1.2",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "io.swagger.core.v3:swagger-annotations-jakarta",
|
||||
"moduleUrl": "https://github.com/swagger-api/swagger-core/modules/swagger-annotations",
|
||||
"moduleVersion": "2.2.15",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "io.swagger.core.v3:swagger-core-jakarta",
|
||||
"moduleUrl": "https://github.com/swagger-api/swagger-core/modules/swagger-core",
|
||||
"moduleVersion": "2.2.15",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "io.swagger.core.v3:swagger-models-jakarta",
|
||||
"moduleUrl": "https://github.com/swagger-api/swagger-core/modules/swagger-models",
|
||||
"moduleVersion": "2.2.15",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "jakarta.activation:jakarta.activation-api",
|
||||
"moduleUrl": "https://www.eclipse.org",
|
||||
"moduleVersion": "2.1.2",
|
||||
"moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception",
|
||||
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "jakarta.annotation:jakarta.annotation-api",
|
||||
"moduleUrl": "https://www.eclipse.org",
|
||||
"moduleVersion": "2.1.1",
|
||||
"moduleLicense": "GPL2 w/ CPE",
|
||||
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "jakarta.inject:jakarta.inject-api",
|
||||
"moduleUrl": "https://www.eclipse.org",
|
||||
"moduleVersion": "2.0.1",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "jakarta.persistence:jakarta.persistence-api",
|
||||
"moduleUrl": "https://www.eclipse.org",
|
||||
"moduleVersion": "3.1.0",
|
||||
"moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception",
|
||||
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "jakarta.transaction:jakarta.transaction-api",
|
||||
"moduleUrl": "https://projects.eclipse.org/projects/ee4j.jta",
|
||||
"moduleVersion": "2.0.1",
|
||||
"moduleLicense": "GPL2 w/ CPE",
|
||||
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "jakarta.validation:jakarta.validation-api",
|
||||
"moduleUrl": "https://www.eclipse.org",
|
||||
"moduleVersion": "3.0.2",
|
||||
"moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception",
|
||||
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "jakarta.xml.bind:jakarta.xml.bind-api",
|
||||
"moduleUrl": "https://www.eclipse.org",
|
||||
"moduleVersion": "4.0.1",
|
||||
"moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception",
|
||||
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "net.bytebuddy:byte-buddy",
|
||||
"moduleVersion": "1.14.10",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.antlr:antlr4-runtime",
|
||||
"moduleUrl": "https://www.antlr.org/",
|
||||
"moduleVersion": "4.13.0",
|
||||
"moduleLicense": "BSD-3-Clause",
|
||||
"moduleLicenseUrl": "https://www.antlr.org/license.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.apache.commons:commons-collections4",
|
||||
"moduleUrl": "https://commons.apache.org/proper/commons-collections/",
|
||||
"moduleVersion": "4.4",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.apache.commons:commons-lang3",
|
||||
"moduleUrl": "https://commons.apache.org/proper/commons-lang/",
|
||||
"moduleVersion": "3.13.0",
|
||||
"moduleLicense": "Apache-2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.apache.commons:commons-text",
|
||||
"moduleUrl": "https://commons.apache.org/proper/commons-text",
|
||||
"moduleVersion": "1.11.0",
|
||||
"moduleLicense": "Apache-2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.apache.logging.log4j:log4j-api",
|
||||
"moduleVersion": "2.21.1",
|
||||
"moduleLicense": "Apache-2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.apache.logging.log4j:log4j-to-slf4j",
|
||||
"moduleVersion": "2.21.1",
|
||||
"moduleLicense": "Apache-2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.apache.pdfbox:fontbox",
|
||||
"moduleUrl": "http://pdfbox.apache.org/",
|
||||
"moduleVersion": "2.0.29",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.apache.pdfbox:pdfbox",
|
||||
"moduleUrl": "http://pdfbox.apache.org",
|
||||
"moduleVersion": "2.0.29",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.apache.pdfbox:xmpbox",
|
||||
"moduleUrl": "http://pdfbox.apache.org",
|
||||
"moduleVersion": "2.0.29",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.apache.tomcat.embed:tomcat-embed-core",
|
||||
"moduleUrl": "https://tomcat.apache.org/",
|
||||
"moduleVersion": "10.1.17",
|
||||
"moduleLicense": "Eclipse Public License - v 2.0",
|
||||
"moduleLicenseUrl": "https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.apache.tomcat.embed:tomcat-embed-el",
|
||||
"moduleUrl": "https://tomcat.apache.org/",
|
||||
"moduleVersion": "10.1.17",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.apache.tomcat.embed:tomcat-embed-websocket",
|
||||
"moduleUrl": "https://tomcat.apache.org/",
|
||||
"moduleVersion": "10.1.17",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.apache.xmlgraphics:batik-all",
|
||||
"moduleVersion": "1.17",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.apache.xmlgraphics:xmlgraphics-commons",
|
||||
"moduleUrl": "http://xmlgraphics.apache.org/commons/",
|
||||
"moduleVersion": "2.9",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.aspectj:aspectjweaver",
|
||||
"moduleUrl": "https://www.eclipse.org/aspectj/",
|
||||
"moduleVersion": "1.9.21",
|
||||
"moduleLicense": "Eclipse Public License - v 2.0",
|
||||
"moduleLicenseUrl": "https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.attoparser:attoparser",
|
||||
"moduleUrl": "https://www.attoparser.org",
|
||||
"moduleVersion": "2.0.7.RELEASE",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.bouncycastle:bcpkix-jdk18on",
|
||||
"moduleUrl": "https://www.bouncycastle.org/java.html",
|
||||
"moduleVersion": "1.77",
|
||||
"moduleLicense": "Bouncy Castle Licence",
|
||||
"moduleLicenseUrl": "https://www.bouncycastle.org/licence.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.bouncycastle:bcprov-jdk18on",
|
||||
"moduleUrl": "https://www.bouncycastle.org/java.html",
|
||||
"moduleVersion": "1.77",
|
||||
"moduleLicense": "Bouncy Castle Licence",
|
||||
"moduleLicenseUrl": "https://www.bouncycastle.org/licence.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.bouncycastle:bcutil-jdk18on",
|
||||
"moduleUrl": "https://www.bouncycastle.org/java.html",
|
||||
"moduleVersion": "1.77",
|
||||
"moduleLicense": "Bouncy Castle Licence",
|
||||
"moduleLicenseUrl": "https://www.bouncycastle.org/licence.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.commonmark:commonmark",
|
||||
"moduleVersion": "0.21.0",
|
||||
"moduleLicense": "BSD 2-Clause License",
|
||||
"moduleLicenseUrl": "https://opensource.org/licenses/BSD-2-Clause"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.eclipse.angus:angus-activation",
|
||||
"moduleUrl": "https://www.eclipse.org",
|
||||
"moduleVersion": "2.0.1",
|
||||
"moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception",
|
||||
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.glassfish.jaxb:jaxb-core",
|
||||
"moduleUrl": "https://www.eclipse.org",
|
||||
"moduleVersion": "4.0.4",
|
||||
"moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception",
|
||||
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.glassfish.jaxb:jaxb-runtime",
|
||||
"moduleUrl": "https://www.eclipse.org",
|
||||
"moduleVersion": "4.0.4",
|
||||
"moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception",
|
||||
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.glassfish.jaxb:txw2",
|
||||
"moduleUrl": "https://eclipse-ee4j.github.io/jaxb-ri/",
|
||||
"moduleVersion": "4.0.4",
|
||||
"moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception",
|
||||
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.hdrhistogram:HdrHistogram",
|
||||
"moduleUrl": "http://hdrhistogram.github.io/HdrHistogram/",
|
||||
"moduleVersion": "2.1.12",
|
||||
"moduleLicense": "Public Domain, per Creative Commons CC0",
|
||||
"moduleLicenseUrl": "http://creativecommons.org/publicdomain/zero/1.0/"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.hibernate.common:hibernate-commons-annotations",
|
||||
"moduleUrl": "http://hibernate.org",
|
||||
"moduleVersion": "6.0.6.Final",
|
||||
"moduleLicense": "GNU Library General Public License v2.1 or later",
|
||||
"moduleLicenseUrl": "http://www.opensource.org/licenses/LGPL-2.1"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.hibernate.orm:hibernate-core",
|
||||
"moduleUrl": "https://www.hibernate.org/orm/6.4",
|
||||
"moduleVersion": "6.4.1.Final",
|
||||
"moduleLicense": "GNU Library General Public License v2.1 or later",
|
||||
"moduleLicenseUrl": "https://www.opensource.org/licenses/LGPL-2.1"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.jboss.logging:jboss-logging",
|
||||
"moduleUrl": "http://www.jboss.org",
|
||||
"moduleVersion": "3.5.3.Final",
|
||||
"moduleLicense": "Public Domain",
|
||||
"moduleLicenseUrl": "http://repository.jboss.org/licenses/cc0-1.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.latencyutils:LatencyUtils",
|
||||
"moduleUrl": "http://latencyutils.github.io/LatencyUtils/",
|
||||
"moduleVersion": "2.0.3",
|
||||
"moduleLicense": "Public Domain, per Creative Commons CC0",
|
||||
"moduleLicenseUrl": "http://creativecommons.org/publicdomain/zero/1.0/"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.slf4j:jul-to-slf4j",
|
||||
"moduleUrl": "http://www.slf4j.org",
|
||||
"moduleVersion": "2.0.9",
|
||||
"moduleLicense": "MIT License",
|
||||
"moduleLicenseUrl": "http://www.opensource.org/licenses/mit-license.php"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.slf4j:slf4j-api",
|
||||
"moduleUrl": "http://www.slf4j.org",
|
||||
"moduleVersion": "2.0.9",
|
||||
"moduleLicense": "MIT License",
|
||||
"moduleLicenseUrl": "http://www.opensource.org/licenses/mit-license.php"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springdoc:springdoc-openapi-starter-common",
|
||||
"moduleVersion": "2.2.0",
|
||||
"moduleLicense": "The Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springdoc:springdoc-openapi-starter-webmvc-api",
|
||||
"moduleVersion": "2.2.0",
|
||||
"moduleLicense": "The Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springdoc:springdoc-openapi-starter-webmvc-ui",
|
||||
"moduleVersion": "2.2.0",
|
||||
"moduleLicense": "The Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.boot:spring-boot",
|
||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.boot:spring-boot-actuator",
|
||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.boot:spring-boot-actuator-autoconfigure",
|
||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.boot:spring-boot-autoconfigure",
|
||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.boot:spring-boot-devtools",
|
||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.boot:spring-boot-starter",
|
||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.boot:spring-boot-starter-actuator",
|
||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.boot:spring-boot-starter-aop",
|
||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.boot:spring-boot-starter-data-jpa",
|
||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.boot:spring-boot-starter-jdbc",
|
||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.boot:spring-boot-starter-json",
|
||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.boot:spring-boot-starter-logging",
|
||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.boot:spring-boot-starter-security",
|
||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.boot:spring-boot-starter-thymeleaf",
|
||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.boot:spring-boot-starter-tomcat",
|
||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.boot:spring-boot-starter-web",
|
||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.data:spring-data-commons",
|
||||
"moduleUrl": "https://spring.io/projects/spring-data",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.data:spring-data-jpa",
|
||||
"moduleUrl": "https://projects.spring.io/spring-data-jpa",
|
||||
"moduleVersion": "3.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.security:spring-security-config",
|
||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||
"moduleVersion": "6.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.security:spring-security-core",
|
||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||
"moduleVersion": "6.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.security:spring-security-crypto",
|
||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||
"moduleVersion": "6.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework.security:spring-security-web",
|
||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||
"moduleVersion": "6.2.1",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework:spring-aop",
|
||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||
"moduleVersion": "6.1.2",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework:spring-aspects",
|
||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||
"moduleVersion": "6.1.2",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework:spring-beans",
|
||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||
"moduleVersion": "6.1.2",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework:spring-context",
|
||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||
"moduleVersion": "6.1.2",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework:spring-core",
|
||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||
"moduleVersion": "6.1.2",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework:spring-expression",
|
||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||
"moduleVersion": "6.1.2",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework:spring-jcl",
|
||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||
"moduleVersion": "6.1.2",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework:spring-jdbc",
|
||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||
"moduleVersion": "6.1.2",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework:spring-orm",
|
||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||
"moduleVersion": "6.1.2",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework:spring-tx",
|
||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||
"moduleVersion": "6.1.2",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework:spring-web",
|
||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||
"moduleVersion": "6.1.2",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.springframework:spring-webmvc",
|
||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||
"moduleVersion": "6.1.2",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.thymeleaf.extras:thymeleaf-extras-springsecurity5",
|
||||
"moduleVersion": "3.1.2.RELEASE",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.thymeleaf:thymeleaf",
|
||||
"moduleVersion": "3.1.2.RELEASE",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.thymeleaf:thymeleaf-spring5",
|
||||
"moduleVersion": "3.1.2.RELEASE",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.thymeleaf:thymeleaf-spring6",
|
||||
"moduleVersion": "3.1.2.RELEASE",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.unbescape:unbescape",
|
||||
"moduleUrl": "http://www.unbescape.org",
|
||||
"moduleVersion": "1.1.6.RELEASE",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.webjars:swagger-ui",
|
||||
"moduleUrl": "http://webjars.org",
|
||||
"moduleVersion": "5.2.0",
|
||||
"moduleLicense": "Apache 2.0",
|
||||
"moduleLicenseUrl": "https://github.com/swagger-api/swagger-ui"
|
||||
},
|
||||
{
|
||||
"moduleName": "org.yaml:snakeyaml",
|
||||
"moduleUrl": "https://bitbucket.org/snakeyaml/snakeyaml",
|
||||
"moduleVersion": "2.2",
|
||||
"moduleLicense": "Apache License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
},
|
||||
{
|
||||
"moduleName": "xml-apis:xml-apis",
|
||||
"moduleUrl": "http://xml.apache.org/commons/components/external/",
|
||||
"moduleVersion": "1.4.01",
|
||||
"moduleLicense": "The W3C License",
|
||||
"moduleLicenseUrl": "http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/java-binding.zip"
|
||||
},
|
||||
{
|
||||
"moduleName": "xml-apis:xml-apis-ext",
|
||||
"moduleUrl": "http://xml.apache.org/commons/components/external/",
|
||||
"moduleVersion": "1.3.04",
|
||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -11,6 +11,13 @@ body, select, textarea {
|
||||
color: rgb(var(--base-font-color)) !important;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #add8e6;
|
||||
}
|
||||
a:hover {
|
||||
color: #87ceeb; /* Slightly brighter blue on hover for accessibility */
|
||||
}
|
||||
|
||||
.dark-card {
|
||||
background-color: rgb(var(--body-background-color)) !important;
|
||||
color: rgb(var(--base-font-color)) !important;
|
||||
|
||||
3
src/main/resources/static/images/book.svg
Normal file
3
src/main/resources/static/images/book.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-book" viewBox="0 0 16 16">
|
||||
<path d="M1 2.828c.885-.37 2.154-.769 3.388-.893 1.33-.134 2.458.063 3.112.752v9.746c-.935-.53-2.12-.603-3.213-.493-1.18.12-2.37.461-3.287.811zm7.5-.141c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 770 B |
292
src/main/resources/static/images/flags/rs.svg
Normal file
292
src/main/resources/static/images/flags/rs.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 180 KiB |
1
src/main/resources/static/images/flags/tw.svg
Normal file
1
src/main/resources/static/images/flags/tw.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="900" height="600"><g fill-rule="evenodd"><path d="M0 0h900v600H0z" fill="#fe0000"/><path d="M0 0h450v300H0z" fill="#000095"/></g><path d="M225 37.5l-56.25 209.928L322.428 93.75 112.5 150l209.928 56.25L168.75 52.572 225 262.5l56.25-209.928L127.572 206.25 337.5 150 127.572 93.75 281.25 247.428 225 37.5" fill="#fff" paint-order="markers fill stroke"/><circle cy="150" cx="225" r="60" fill="#fff" stroke="#000095" stroke-width="7.5"/></svg>
|
||||
|
After Width: | Height: | Size: 485 B |
@@ -18,7 +18,7 @@ function compareVersions(version1, version2) {
|
||||
|
||||
|
||||
async function getLatestReleaseVersion() {
|
||||
const url = "https://api.github.com/repos/Frooodle/Stirling-PDF/releases/latest";
|
||||
const url = "https://api.github.com/repos/Stirling-Tools/Stirling-PDF/releases/latest";
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
|
||||
@@ -61,9 +61,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
//Sort languages by alphabet
|
||||
const list = Array.from(document.querySelector('.dropdown-menu[aria-labelledby="languageDropdown"]').children).filter(child => child.matches('a'));
|
||||
list.sort(function(a, b) {
|
||||
var A = a.textContent.toUpperCase();
|
||||
var B = b.textContent.toUpperCase();
|
||||
return (A < B) ? -1 : (A > B) ? 1 : 0;
|
||||
return a.textContent.toUpperCase().localeCompare(b.textContent.toUpperCase());
|
||||
}).forEach(node => document.querySelector('.dropdown-menu[aria-labelledby="languageDropdown"]').appendChild(node));
|
||||
|
||||
});
|
||||
@@ -171,6 +171,26 @@ class PdfActionsManager {
|
||||
|
||||
div.appendChild(insertFileButtonRightContainer);
|
||||
|
||||
const adaptPageNumber = (pageNumber, div) => {
|
||||
const pageNumberElement = document.createElement('span');
|
||||
pageNumberElement.classList.add('page-number');
|
||||
pageNumberElement.textContent = pageNumber;
|
||||
|
||||
div.insertBefore(pageNumberElement, div.firstChild);
|
||||
};
|
||||
|
||||
div.addEventListener('mouseenter', () => {
|
||||
const pageNumber = Array.from(div.parentNode.children).indexOf(div) + 1;
|
||||
adaptPageNumber(pageNumber, div);
|
||||
});
|
||||
|
||||
div.addEventListener('mouseleave', () => {
|
||||
const pageNumberElement = div.querySelector('.page-number');
|
||||
if (pageNumberElement) {
|
||||
div.removeChild(pageNumberElement);
|
||||
}
|
||||
});
|
||||
|
||||
return div;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,20 +209,21 @@ class PdfContainer {
|
||||
|
||||
async exportPdf() {
|
||||
const pdfDoc = await PDFLib.PDFDocument.create();
|
||||
for (var i=0; i<this.pagesContainer.childNodes.length; i++) {
|
||||
const img = this.pagesContainer.childNodes[i].querySelector("img");
|
||||
if (!img) continue;
|
||||
const pages = await pdfDoc.copyPages(img.doc, [img.pageIdx])
|
||||
const page = pages[0];
|
||||
const pageContainers = this.pagesContainer.querySelectorAll('.page-container'); // Select all .page-container elements
|
||||
for (var i = 0; i < pageContainers.length; i++) {
|
||||
const img = pageContainers[i].querySelector("img"); // Find the img element within each .page-container
|
||||
if (!img) continue;
|
||||
const pages = await pdfDoc.copyPages(img.doc, [img.pageIdx])
|
||||
const page = pages[0];
|
||||
|
||||
const rotation = img.style.rotate;
|
||||
if (rotation) {
|
||||
const rotationAngle = parseInt(rotation.replace(/[^\d-]/g, ''));
|
||||
page.setRotation(PDFLib.degrees(page.getRotation().angle + rotationAngle))
|
||||
}
|
||||
const rotation = img.style.rotate;
|
||||
if (rotation) {
|
||||
const rotationAngle = parseInt(rotation.replace(/[^\d-]/g, ''));
|
||||
page.setRotation(PDFLib.degrees(page.getRotation().angle + rotationAngle))
|
||||
}
|
||||
|
||||
pdfDoc.addPage(page);
|
||||
}
|
||||
pdfDoc.addPage(page);
|
||||
}
|
||||
const pdfBytes = await pdfDoc.save();
|
||||
const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
|
||||
const url = URL.createObjectURL(pdfBlob);
|
||||
|
||||
@@ -57,14 +57,14 @@ function validatePipeline() {
|
||||
}
|
||||
|
||||
function updateValidateButton(isValid) {
|
||||
var validateButton = document.getElementById('validateButton');
|
||||
if (isValid) {
|
||||
validateButton.classList.remove('btn-danger');
|
||||
validateButton.classList.add('btn-success');
|
||||
} else {
|
||||
validateButton.classList.remove('btn-success');
|
||||
validateButton.classList.add('btn-danger');
|
||||
}
|
||||
var validateButton = document.getElementById('validateButton');
|
||||
if (isValid) {
|
||||
validateButton.classList.remove('btn-danger');
|
||||
validateButton.classList.add('btn-success');
|
||||
} else {
|
||||
validateButton.classList.remove('btn-success');
|
||||
validateButton.classList.add('btn-danger');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -131,34 +131,34 @@ document.getElementById('submitConfigBtn').addEventListener('click', function()
|
||||
console.log("formData", formData);
|
||||
|
||||
fetch('api/v1/pipeline/handleData', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => {
|
||||
// Save the response to use it later
|
||||
const responseToUseLater = response;
|
||||
.then(response => {
|
||||
// Save the response to use it later
|
||||
const responseToUseLater = response;
|
||||
|
||||
return response.blob().then(blob => {
|
||||
let url = window.URL.createObjectURL(blob);
|
||||
let a = document.createElement('a');
|
||||
a.href = url;
|
||||
return response.blob().then(blob => {
|
||||
let url = window.URL.createObjectURL(blob);
|
||||
let a = document.createElement('a');
|
||||
a.href = url;
|
||||
|
||||
// Use responseToUseLater instead of response
|
||||
const contentDisposition = responseToUseLater.headers.get('Content-Disposition');
|
||||
let filename = 'download';
|
||||
if (contentDisposition && contentDisposition.indexOf('attachment') !== -1) {
|
||||
filename = decodeURIComponent(contentDisposition.split('filename=')[1].replace(/"/g, '')).trim();
|
||||
}
|
||||
a.download = filename;
|
||||
// Use responseToUseLater instead of response
|
||||
const contentDisposition = responseToUseLater.headers.get('Content-Disposition');
|
||||
let filename = 'download';
|
||||
if (contentDisposition && contentDisposition.indexOf('attachment') !== -1) {
|
||||
filename = decodeURIComponent(contentDisposition.split('filename=')[1].replace(/"/g, '')).trim();
|
||||
}
|
||||
a.download = filename;
|
||||
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -182,10 +182,11 @@ fetch('v1/api-docs')
|
||||
// Group operations by tags
|
||||
Object.keys(data.paths).forEach(operationPath => {
|
||||
let operation = data.paths[operationPath].post;
|
||||
if(!operation || !operation.description) {
|
||||
if (!operation || !operation.description) {
|
||||
console.log(operationPath);
|
||||
}
|
||||
if (operation && !ignoreOperations.includes(operationPath) && !operation.description.includes("Type:MISO")) {
|
||||
//!operation.description.includes("Type:MISO")
|
||||
if (operation && !ignoreOperations.includes(operationPath)) {
|
||||
let operationTag = operation.tags[0]; // This assumes each operation has exactly one tag
|
||||
if (!operationsByTag[operationTag]) {
|
||||
operationsByTag[operationTag] = [];
|
||||
@@ -193,6 +194,12 @@ fetch('v1/api-docs')
|
||||
operationsByTag[operationTag].push(operationPath);
|
||||
}
|
||||
});
|
||||
|
||||
// Sort operations within each tag alphabetically
|
||||
Object.keys(operationsByTag).forEach(tag => {
|
||||
operationsByTag[tag].sort();
|
||||
});
|
||||
|
||||
// Specify the order of tags
|
||||
let tagOrder = ["General", "Security", "Convert", "Misc", "Filter"];
|
||||
|
||||
@@ -209,12 +216,12 @@ fetch('v1/api-docs')
|
||||
operationPathDisplay = operationPath.replace(new RegExp("api/v1/" + tag.toLowerCase() + "/", 'i'), "");
|
||||
|
||||
|
||||
if(operationPath.includes("/convert")){
|
||||
if (operationPath.includes("/convert")) {
|
||||
operationPathDisplay = operationPathDisplay.replace(/^\//, '').replaceAll("/", " to ");
|
||||
} else {
|
||||
operationPathDisplay = operationPathDisplay.replace(/\//g, ''); // Remove slashes
|
||||
}
|
||||
operationPathDisplay = operationPathDisplay.replaceAll(" ","-");
|
||||
operationPathDisplay = operationPathDisplay.replaceAll(" ", "-");
|
||||
option.textContent = operationPathDisplay;
|
||||
option.value = operationPath; // Keep the value with slashes for querying
|
||||
group.appendChild(option);
|
||||
@@ -234,37 +241,43 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
|
||||
listItem.className = "list-group-item";
|
||||
let hasSettings = false;
|
||||
if (apiDocs[selectedOperation] && apiDocs[selectedOperation].post) {
|
||||
const postMethod = apiDocs[selectedOperation].post;
|
||||
const postMethod = apiDocs[selectedOperation].post;
|
||||
|
||||
// Check if parameters exist
|
||||
if (postMethod.parameters && postMethod.parameters.length > 0) {
|
||||
hasSettings = true;
|
||||
} else if (postMethod.requestBody && postMethod.requestBody.content['multipart/form-data']) {
|
||||
// Extract the reference key
|
||||
const refKey = postMethod.requestBody.content['multipart/form-data'].schema['$ref'].split('/').pop();
|
||||
// Check if the referenced schema exists and has properties
|
||||
if (apiSchemas[refKey] && Object.keys(apiSchemas[refKey].properties).length > 0) {
|
||||
hasSettings = true;
|
||||
}
|
||||
}
|
||||
// Check if parameters exist
|
||||
if (postMethod.parameters && postMethod.parameters.length > 0) {
|
||||
hasSettings = true;
|
||||
} else if (postMethod.requestBody && postMethod.requestBody.content['multipart/form-data']) {
|
||||
// Extract the reference key
|
||||
const refKey = postMethod.requestBody.content['multipart/form-data'].schema['$ref'].split('/').pop();
|
||||
// Check if the referenced schema exists and has properties more than just its input file
|
||||
if (apiSchemas[refKey]) {
|
||||
const properties = apiSchemas[refKey].properties;
|
||||
const propertyKeys = Object.keys(properties);
|
||||
|
||||
// Check if there's more than one property or if there's exactly one property and its format is not 'binary'
|
||||
if (propertyKeys.length > 1 || (propertyKeys.length === 1 && properties[propertyKeys[0]].format !== 'binary')) {
|
||||
hasSettings = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
listItem.innerHTML = `
|
||||
<div class="d-flex justify-content-between align-items-center w-100">
|
||||
<div class="operationName">${selectedOperation}</div>
|
||||
<div class="arrows d-flex">
|
||||
<button class="btn btn-secondary move-up ms-1"><span>↑</span></button>
|
||||
<button class="btn btn-secondary move-down ms-1"><span>↓</span></button>
|
||||
<button class="btn ${hasSettings ? 'btn-warning' : 'btn-secondary'} pipelineSettings ms-1" ${hasSettings ? "" : "disabled"}>
|
||||
<span style="color: ${hasSettings ? "white" : "grey"};">⚙️</span>
|
||||
</button>
|
||||
<button class="btn btn-danger remove ms-1"><span>X</span></button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
<div class="d-flex justify-content-between align-items-center w-100">
|
||||
<div class="operationName">${selectedOperation}</div>
|
||||
<div class="arrows d-flex">
|
||||
<button class="btn btn-secondary move-up ms-1"><span>↑</span></button>
|
||||
<button class="btn btn-secondary move-down ms-1"><span>↓</span></button>
|
||||
<button class="btn ${hasSettings ? 'btn-warning' : 'btn-secondary'} pipelineSettings ms-1" ${hasSettings ? "" : "disabled"}>
|
||||
<span style="color: ${hasSettings ? "white" : "grey"};">⚙️</span>
|
||||
</button>
|
||||
<button class="btn btn-danger remove ms-1"><span>X</span></button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
||||
pipelineList.appendChild(listItem);
|
||||
@@ -273,6 +286,7 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
|
||||
event.preventDefault();
|
||||
if (listItem.previousElementSibling) {
|
||||
pipelineList.insertBefore(listItem, listItem.previousElementSibling);
|
||||
updateConfigInDropdown();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -280,13 +294,16 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
|
||||
event.preventDefault();
|
||||
if (listItem.nextElementSibling) {
|
||||
pipelineList.insertBefore(listItem.nextElementSibling, listItem);
|
||||
updateConfigInDropdown();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
listItem.querySelector('.remove').addEventListener('click', function(event) {
|
||||
event.preventDefault();
|
||||
pipelineList.removeChild(listItem);
|
||||
hideOrShowPipelineHeader();
|
||||
updateConfigInDropdown();
|
||||
});
|
||||
|
||||
listItem.querySelector('.pipelineSettings').addEventListener('click', function(event) {
|
||||
@@ -306,15 +323,15 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
|
||||
|
||||
// Combine operationData and requestBodyData into a single array
|
||||
operationData = operationData.concat(Object.keys(requestBodyData).map(key => ({
|
||||
name: key,
|
||||
schema: requestBodyData[key]
|
||||
name: key,
|
||||
schema: requestBodyData[key]
|
||||
})));
|
||||
|
||||
pipelineSettingsContent.innerHTML = '';
|
||||
|
||||
operationData.forEach(parameter => {
|
||||
// If the parameter name is 'fileInput', return early to skip the rest of this iteration
|
||||
if (parameter.name === 'fileInput') return;
|
||||
if (parameter.name === 'fileInput') return;
|
||||
|
||||
let parameterDiv = document.createElement('div');
|
||||
parameterDiv.className = "mb-3";
|
||||
@@ -325,8 +342,8 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
|
||||
parameterLabel.setAttribute('for', parameter.name);
|
||||
parameterDiv.appendChild(parameterLabel);
|
||||
|
||||
let defaultValue = parameter.schema.example;
|
||||
if (defaultValue === undefined) defaultValue = parameter.schema.default;
|
||||
let defaultValue = parameter.schema.example;
|
||||
if (defaultValue === undefined) defaultValue = parameter.schema.default;
|
||||
|
||||
let parameterInput;
|
||||
|
||||
@@ -357,7 +374,7 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
|
||||
parameterInput = document.createElement('input');
|
||||
parameterInput.type = 'text';
|
||||
parameterInput.className = "form-control";
|
||||
parameterInput.value = "FileInputPathToBeInputtedManuallyOffline";
|
||||
parameterInput.value = "FileInputPathToBeInputtedManuallyForOffline";
|
||||
} else {
|
||||
parameterInput = document.createElement('input');
|
||||
parameterInput.type = 'text';
|
||||
@@ -379,8 +396,9 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
|
||||
break;
|
||||
case 'array':
|
||||
case 'object':
|
||||
//TODO compare to doc and check if fileInput array? parameter.schema.format === 'binary'
|
||||
parameterInput = document.createElement('textarea');
|
||||
parameterInput.placeholder = `Enter a JSON formatted ${parameter.schema.type}`;
|
||||
parameterInput.placeholder = `Enter a JSON formatted ${parameter.schema.type}, If this is a fileInput, it is not currently supported`;
|
||||
parameterInput.className = "form-control";
|
||||
break;
|
||||
default:
|
||||
@@ -419,41 +437,47 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
|
||||
pipelineSettingsContent.appendChild(parameterDiv);
|
||||
});
|
||||
|
||||
let saveButton = document.createElement('button');
|
||||
saveButton.textContent = "Save Settings";
|
||||
saveButton.className = "btn btn-primary";
|
||||
saveButton.addEventListener('click', function(event) {
|
||||
event.preventDefault();
|
||||
let settings = {};
|
||||
operationData.forEach(parameter => {
|
||||
if(parameter.name !== "fileInput"){
|
||||
let value = document.getElementById(parameter.name).value;
|
||||
switch (parameter.schema.type) {
|
||||
case 'number':
|
||||
case 'integer':
|
||||
settings[parameter.name] = Number(value);
|
||||
break;
|
||||
case 'boolean':
|
||||
settings[parameter.name] = document.getElementById(parameter.name).checked;
|
||||
break;
|
||||
case 'array':
|
||||
case 'object':
|
||||
try {
|
||||
settings[parameter.name] = JSON.parse(value);
|
||||
} catch (err) {
|
||||
console.error(`Invalid JSON format for ${parameter.name}`);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
settings[parameter.name] = value;
|
||||
if(hasSettings) {
|
||||
let saveButton = document.createElement('button');
|
||||
saveButton.textContent = saveSettings;
|
||||
saveButton.className = "btn btn-primary";
|
||||
saveButton.addEventListener('click', function(event) {
|
||||
event.preventDefault();
|
||||
let settings = {};
|
||||
operationData.forEach(parameter => {
|
||||
if (parameter.name !== "fileInput") {
|
||||
let value = document.getElementById(parameter.name).value;
|
||||
switch (parameter.schema.type) {
|
||||
case 'number':
|
||||
case 'integer':
|
||||
settings[parameter.name] = Number(value);
|
||||
break;
|
||||
case 'boolean':
|
||||
settings[parameter.name] = document.getElementById(parameter.name).checked;
|
||||
break;
|
||||
case 'array':
|
||||
case 'object':
|
||||
if (value === null || value === '') {
|
||||
settings[parameter.name] = '';
|
||||
} else {
|
||||
try {
|
||||
settings[parameter.name] = JSON.parse(value);
|
||||
} catch (err) {
|
||||
console.error(`Invalid JSON format for ${parameter.name}`);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
settings[parameter.name] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
operationSettings[operation] = settings;
|
||||
//pipelineSettingsModal.style.display = "none";
|
||||
});
|
||||
operationSettings[operation] = settings;
|
||||
//pipelineSettingsModal.style.display = "none";
|
||||
});
|
||||
pipelineSettingsContent.appendChild(saveButton);
|
||||
|
||||
pipelineSettingsContent.appendChild(saveButton);
|
||||
saveButton.click();
|
||||
}
|
||||
//pipelineSettingsModal.style.display = "block";
|
||||
|
||||
//pipelineSettingsModal.getElementsByClassName("close")[0].onclick = function() {
|
||||
@@ -466,144 +490,182 @@ document.getElementById('addOperationBtn').addEventListener('click', function()
|
||||
// }
|
||||
//}
|
||||
}
|
||||
showpipelineSettingsModal(selectedOperation);
|
||||
updateConfigInDropdown();
|
||||
hideOrShowPipelineHeader();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
function updateConfigInDropdown() {
|
||||
let pipelineSelect = document.getElementById('pipelineSelect');
|
||||
let selectedOption = pipelineSelect.options[pipelineSelect.selectedIndex];
|
||||
|
||||
// Get the current configuration as JSON
|
||||
let pipelineConfigJson = configToJson();
|
||||
console.log("pipelineConfigJson", pipelineConfigJson);
|
||||
if (!pipelineConfigJson) {
|
||||
console.error("Failed to update configuration: Invalid configuration");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the value of the selected option with the new configuration
|
||||
selectedOption.value = pipelineConfigJson;
|
||||
|
||||
}
|
||||
|
||||
var saveBtn = document.getElementById('savePipelineBtn');
|
||||
|
||||
// Remove any existing event listeners
|
||||
saveBtn.removeEventListener('click', savePipeline);
|
||||
|
||||
// Add the event listener
|
||||
saveBtn.addEventListener('click', savePipeline);
|
||||
console.log("saveBtn", saveBtn)
|
||||
|
||||
function configToJson() {
|
||||
if (!validatePipeline()) {
|
||||
return null; // Return null if validation fails
|
||||
}
|
||||
|
||||
var pipelineName = document.getElementById('pipelineName').value;
|
||||
let pipelineList = document.getElementById('pipelineList').children;
|
||||
let pipelineConfig = {
|
||||
"name": pipelineName,
|
||||
"pipeline": [],
|
||||
"_examples": {
|
||||
"outputDir": "{outputFolder}/{folderName}",
|
||||
"outputFileName": "{filename}-{pipelineName}-{date}-{time}"
|
||||
},
|
||||
"outputDir": "{outputFolder}",
|
||||
"outputFileName": "{filename}"
|
||||
};
|
||||
|
||||
for (let i = 0; i < pipelineList.length; i++) {
|
||||
let operationName = pipelineList[i].querySelector('.operationName').textContent;
|
||||
let parameters = operationSettings[operationName] || {};
|
||||
|
||||
parameters['fileInput'] = 'automated';
|
||||
|
||||
pipelineConfig.pipeline.push({
|
||||
"operation": operationName,
|
||||
"parameters": parameters
|
||||
});
|
||||
}
|
||||
|
||||
return JSON.stringify(pipelineConfig, null, 2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function savePipeline() {
|
||||
let pipelineConfigJson = configToJson();
|
||||
if (!pipelineConfigJson) {
|
||||
console.error("Failed to save pipeline: Invalid configuration");
|
||||
return;
|
||||
}
|
||||
|
||||
let pipelineName = document.getElementById('pipelineName').value;
|
||||
console.log("Downloading...");
|
||||
let a = document.createElement('a');
|
||||
a.href = URL.createObjectURL(new Blob([pipelineConfigJson], { type: 'application/json' }));
|
||||
a.download = pipelineName + '.json';
|
||||
a.style.display = 'none';
|
||||
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
}
|
||||
|
||||
|
||||
async function processPipelineConfig(configString) {
|
||||
console.log("configString", configString);
|
||||
let pipelineConfig = JSON.parse(configString);
|
||||
let pipelineList = document.getElementById('pipelineList');
|
||||
|
||||
while (pipelineList.firstChild) {
|
||||
pipelineList.removeChild(pipelineList.firstChild);
|
||||
}
|
||||
document.getElementById('pipelineName').value = pipelineConfig.name
|
||||
for (const operationConfig of pipelineConfig.pipeline) {
|
||||
let operationsDropdown = document.getElementById('operationsDropdown');
|
||||
operationsDropdown.value = operationConfig.operation;
|
||||
operationSettings[operationConfig.operation] = operationConfig.parameters;
|
||||
|
||||
// assuming addOperation is async
|
||||
await new Promise((resolve) => {
|
||||
document.getElementById('addOperationBtn').addEventListener('click', resolve, { once: true });
|
||||
document.getElementById('addOperationBtn').click();
|
||||
});
|
||||
|
||||
let lastOperation = pipelineList.lastChild;
|
||||
|
||||
Object.keys(operationConfig.parameters).forEach(parameterName => {
|
||||
let input = document.getElementById(parameterName);
|
||||
if (input) {
|
||||
switch (input.type) {
|
||||
case 'checkbox':
|
||||
input.checked = operationConfig.parameters[parameterName];
|
||||
break;
|
||||
case 'number':
|
||||
input.value = operationConfig.parameters[parameterName].toString();
|
||||
break;
|
||||
case 'file':
|
||||
if (parameterName !== 'fileInput') {
|
||||
// Create a new file input element
|
||||
let newInput = document.createElement('input');
|
||||
newInput.type = 'file';
|
||||
newInput.id = parameterName;
|
||||
|
||||
// Add the new file input to the main page (change the selector according to your needs)
|
||||
document.querySelector('#main').appendChild(newInput);
|
||||
}
|
||||
break;
|
||||
case 'text':
|
||||
case 'textarea':
|
||||
default:
|
||||
input.value = JSON.stringify(operationConfig.parameters[parameterName]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
document.getElementById('uploadPipelineBtn').addEventListener('click', function() {
|
||||
document.getElementById('uploadPipelineInput').click();
|
||||
});
|
||||
|
||||
document.getElementById('uploadPipelineInput').addEventListener('change', function(e) {
|
||||
let reader = new FileReader();
|
||||
reader.onload = function(event) {
|
||||
processPipelineConfig(event.target.result);
|
||||
};
|
||||
reader.readAsText(e.target.files[0]);
|
||||
hideOrShowPipelineHeader();
|
||||
});
|
||||
|
||||
document.getElementById('pipelineSelect').addEventListener('change', function(e) {
|
||||
let selectedPipelineJson = e.target.value; // assuming the selected value is the JSON string of the pipeline config
|
||||
processPipelineConfig(selectedPipelineJson);
|
||||
});
|
||||
|
||||
|
||||
var saveBtn = document.getElementById('savePipelineBtn');
|
||||
function hideOrShowPipelineHeader() {
|
||||
var pipelineHeader = document.getElementById('pipelineHeader');
|
||||
var pipelineList = document.getElementById('pipelineList');
|
||||
|
||||
// Remove any existing event listeners
|
||||
saveBtn.removeEventListener('click', savePipeline);
|
||||
|
||||
// Add the event listener
|
||||
saveBtn.addEventListener('click', savePipeline);
|
||||
console.log("saveBtn", saveBtn)
|
||||
function savePipeline() {
|
||||
|
||||
if (validatePipeline() === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
var pipelineName = document.getElementById('pipelineName').value;
|
||||
let pipelineList = document.getElementById('pipelineList').children;
|
||||
let pipelineConfig = {
|
||||
"name": pipelineName,
|
||||
"pipeline": [],
|
||||
"_examples": {
|
||||
"outputDir": "{outputFolder}/{folderName}",
|
||||
"outputFileName": "{filename}-{pipelineName}-{date}-{time}"
|
||||
},
|
||||
"outputDir": "{outputFolder}",
|
||||
"outputFileName": "{filename}"
|
||||
};
|
||||
|
||||
for (let i = 0; i < pipelineList.length; i++) {
|
||||
let operationName = pipelineList[i].querySelector('.operationName').textContent;
|
||||
let parameters = operationSettings[operationName] || {};
|
||||
|
||||
parameters['fileInput'] = 'automated';
|
||||
|
||||
pipelineConfig.pipeline.push({
|
||||
"operation": operationName,
|
||||
"parameters": parameters
|
||||
});
|
||||
}
|
||||
console.log("Downloading..");
|
||||
let a = document.createElement('a');
|
||||
a.href = URL.createObjectURL(new Blob([JSON.stringify(pipelineConfig, null, 2)], {
|
||||
type: 'application/json'
|
||||
}));
|
||||
a.download = pipelineName + '.json';
|
||||
a.style.display = 'none';
|
||||
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
}
|
||||
|
||||
async function processPipelineConfig(configString) {
|
||||
let pipelineConfig = JSON.parse(configString);
|
||||
let pipelineList = document.getElementById('pipelineList');
|
||||
|
||||
while (pipelineList.firstChild) {
|
||||
pipelineList.removeChild(pipelineList.firstChild);
|
||||
}
|
||||
document.getElementById('pipelineName').value = pipelineConfig.name
|
||||
for (const operationConfig of pipelineConfig.pipeline) {
|
||||
let operationsDropdown = document.getElementById('operationsDropdown');
|
||||
operationsDropdown.value = operationConfig.operation;
|
||||
operationSettings[operationConfig.operation] = operationConfig.parameters;
|
||||
|
||||
// assuming addOperation is async
|
||||
await new Promise((resolve) => {
|
||||
document.getElementById('addOperationBtn').addEventListener('click', resolve, { once: true });
|
||||
document.getElementById('addOperationBtn').click();
|
||||
});
|
||||
|
||||
let lastOperation = pipelineList.lastChild;
|
||||
|
||||
Object.keys(operationConfig.parameters).forEach(parameterName => {
|
||||
let input = document.getElementById(parameterName);
|
||||
if (input) {
|
||||
switch (input.type) {
|
||||
case 'checkbox':
|
||||
input.checked = operationConfig.parameters[parameterName];
|
||||
break;
|
||||
case 'number':
|
||||
input.value = operationConfig.parameters[parameterName].toString();
|
||||
break;
|
||||
case 'file':
|
||||
if (parameterName !== 'fileInput') {
|
||||
// Create a new file input element
|
||||
let newInput = document.createElement('input');
|
||||
newInput.type = 'file';
|
||||
newInput.id = parameterName;
|
||||
|
||||
// Add the new file input to the main page (change the selector according to your needs)
|
||||
document.querySelector('#main').appendChild(newInput);
|
||||
}
|
||||
break;
|
||||
case 'text':
|
||||
case 'textarea':
|
||||
default:
|
||||
input.value = JSON.stringify(operationConfig.parameters[parameterName]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
document.getElementById('uploadPipelineBtn').addEventListener('click', function() {
|
||||
document.getElementById('uploadPipelineInput').click();
|
||||
});
|
||||
|
||||
document.getElementById('uploadPipelineInput').addEventListener('change', function(e) {
|
||||
let reader = new FileReader();
|
||||
reader.onload = function(event) {
|
||||
processPipelineConfig(event.target.result);
|
||||
};
|
||||
reader.readAsText(e.target.files[0]);
|
||||
hideOrShowPipelineHeader();
|
||||
});
|
||||
|
||||
document.getElementById('pipelineSelect').addEventListener('change', function(e) {
|
||||
let selectedPipelineJson = e.target.value; // assuming the selected value is the JSON string of the pipeline config
|
||||
processPipelineConfig(selectedPipelineJson);
|
||||
});
|
||||
|
||||
|
||||
function hideOrShowPipelineHeader() {
|
||||
var pipelineHeader = document.getElementById('pipelineHeader');
|
||||
var pipelineList = document.getElementById('pipelineList');
|
||||
|
||||
if (pipelineList.children.length === 0) {
|
||||
// Hide the pipeline header if there are no items in the pipeline list
|
||||
pipelineHeader.style.display = 'none';
|
||||
} else {
|
||||
// Show the pipeline header if there are items in the pipeline list
|
||||
pipelineHeader.style.display = 'block';
|
||||
}
|
||||
if (pipelineList.children.length === 0) {
|
||||
// Hide the pipeline header if there are no items in the pipeline list
|
||||
pipelineHeader.style.display = 'none';
|
||||
} else {
|
||||
// Show the pipeline header if there are items in the pipeline list
|
||||
pipelineHeader.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!doctype html>
|
||||
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{account.title})}"></th:block>
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{account.title}, header=#{account.header})}"></th:block>
|
||||
|
||||
<body>
|
||||
<th:block th:insert="~{fragments/common :: game}"></th:block>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{adminUserSettings.title})}"></th:block>
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{adminUserSettings.title}, header=#{adminUserSettings.header})}"></th:block>
|
||||
|
||||
<body>
|
||||
<th:block th:insert="~{fragments/common :: game}"></th:block>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{autoSplitPDF.title})}"></th:block>
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{autoSplitPDF.title}, header=#{autoSplitPDF.header})}"></th:block>
|
||||
|
||||
|
||||
<body>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!doctype html>
|
||||
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{changeCreds.title})}"></th:block>
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{changeCreds.title}, header=#{changeCreds.header})}"></th:block>
|
||||
|
||||
<body>
|
||||
<th:block th:insert="~{fragments/common :: game}"></th:block>
|
||||
|
||||
30
src/main/resources/templates/convert/book-to-pdf.html
Normal file
30
src/main/resources/templates/convert/book-to-pdf.html
Normal file
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{BookToPDF.title}, header=#{BookToPDF.header})}"></th:block>
|
||||
|
||||
<body>
|
||||
<th:block th:insert="~{fragments/common :: game}"></th:block>
|
||||
<div id="page-container">
|
||||
<div id="content-wrap">
|
||||
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
|
||||
<br> <br>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<h2 th:text="#{BookToPDF.header}"></h2>
|
||||
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/book/pdf}">
|
||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
|
||||
<br>
|
||||
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{BookToPDF.submit}"></button>
|
||||
|
||||
</form>
|
||||
<p class="mt-3" th:text="#{BookToPDF.help}"></p>
|
||||
<p class="mt-3" th:text="#{BookToPDF.credit}"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:insert="~{fragments/footer.html :: footer}"></div>
|
||||
</div>
|
||||
</body>
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{fileToPDF.title})}"></th:block>
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{fileToPDF.title}, header=#{fileToPDF.header})}"></th:block>
|
||||
|
||||
|
||||
<body>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{HTMLToPDF.title})}"></th:block>
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{HTMLToPDF.title}, header=#{HTMLToPDF.header})}"></th:block>
|
||||
|
||||
<body>
|
||||
<th:block th:insert="~{fragments/common :: game}"></th:block>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{imageToPDF.title})}"></th:block>
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{imageToPDF.title}, header=#{imageToPDF.header})}"></th:block>
|
||||
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user