diff --git a/.github/scripts/check_duplicates.py b/.github/scripts/check_duplicates.py
new file mode 100644
index 00000000..9c919414
--- /dev/null
+++ b/.github/scripts/check_duplicates.py
@@ -0,0 +1,51 @@
+import sys
+
+
+def find_duplicate_keys(file_path):
+ """
+ Finds duplicate keys in a properties file and returns their occurrences.
+
+ This function reads a properties file, identifies any keys that occur more than
+ once, and returns a dictionary with these keys and the line numbers of their occurrences.
+
+ Parameters:
+ file_path (str): The path to the properties file to be checked.
+
+ Returns:
+ dict: A dictionary where each key is a duplicated key in the file, and the value is a list
+ of line numbers where the key occurs.
+ """
+ with open(file_path, "r", encoding="utf-8") as file:
+ lines = file.readlines()
+
+ keys = {}
+ duplicates = {}
+
+ for line_number, line in enumerate(lines, start=1):
+ line = line.strip()
+ if line and not line.startswith("#") and "=" in line:
+ key = line.split("=", 1)[0].strip()
+ if key in keys:
+ # If the key already exists, add the current line number
+ duplicates.setdefault(key, []).append(line_number)
+ # Also add the first instance of the key if not already done
+ if keys[key] not in duplicates[key]:
+ duplicates[key].insert(0, keys[key])
+ else:
+ # Store the line number of the first instance of the key
+ keys[key] = line_number
+
+ return duplicates
+
+
+if __name__ == "__main__":
+ failed = False
+ for ar in sys.argv[1:]:
+ duplicates = find_duplicate_keys(ar)
+ if duplicates:
+ for key, lines in duplicates.items():
+ lines_str = ", ".join(map(str, lines))
+ print(f"{key} duplicated in {ar} on lines {lines_str}")
+ failed = True
+ if failed:
+ sys.exit(1)
diff --git a/.github/scripts/check_tabulator.py b/.github/scripts/check_tabulator.py
new file mode 100644
index 00000000..eb408ad6
--- /dev/null
+++ b/.github/scripts/check_tabulator.py
@@ -0,0 +1,84 @@
+"""check_tabulator.py"""
+import argparse
+import sys
+
+
+def check_tabs(file_path):
+ """
+ Checks for tabs in the specified file.
+
+ Args:
+ file_path (str): The path to the file to be checked.
+
+ Returns:
+ bool: True if tabs are found, False otherwise.
+ """
+ with open(file_path, "r", encoding="utf-8") as file:
+ content = file.read()
+
+ if "\t" in content:
+ print(f"Tab found in {file_path}")
+ return True
+ return False
+
+
+def replace_tabs_with_spaces(file_path, replace_with=" "):
+ """
+ Replaces tabs with a specified number of spaces in the file.
+
+ Args:
+ file_path (str): The path to the file where tabs will be replaced.
+ replace_with (str): The character(s) to replace tabs with. Defaults to two spaces.
+ """
+ with open(file_path, "r", encoding="utf-8") as file:
+ content = file.read()
+
+ updated_content = content.replace("\t", replace_with)
+
+ with open(file_path, "w", encoding="utf-8") as file:
+ file.write(updated_content)
+
+
+def main():
+ """
+ Main function to replace tabs with spaces in the provided files.
+ The replacement character and files to check are taken from command line arguments.
+ """
+ # Create ArgumentParser instance
+ parser = argparse.ArgumentParser(
+ description="Replace tabs in files with specified characters."
+ )
+
+ # Define optional argument `--replace_with`
+ parser.add_argument(
+ "--replace_with",
+ default=" ",
+ help="Character(s) to replace tabs with. Default is two spaces.",
+ )
+
+ # Define argument for file paths
+ parser.add_argument("files", metavar="FILE", nargs="+", help="Files to process.")
+
+ # Parse arguments
+ args = parser.parse_args()
+
+ # Extract replacement characters and files from the parsed arguments
+ replace_with = args.replace_with
+ files_checked = args.files
+
+ error = False
+
+ for file_path in files_checked:
+ if check_tabs(file_path):
+ replace_tabs_with_spaces(file_path, replace_with)
+ error = True
+
+ if error:
+ print("Error: Originally found tabs in HTML files, now replaced.")
+ sys.exit(1)
+
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/.github/scripts/gradle_to_chart.py b/.github/scripts/gradle_to_chart.py
new file mode 100644
index 00000000..4d7a667f
--- /dev/null
+++ b/.github/scripts/gradle_to_chart.py
@@ -0,0 +1,67 @@
+import re
+import yaml
+
+# Paths to the files
+chart_yaml_path = "chart/stirling-pdf/Chart.yaml"
+gradle_path = "build.gradle"
+
+
+def get_chart_version(path):
+ """
+ Reads the appVersion from Chart.yaml.
+
+ Args:
+ path (str): The file path to the Chart.yaml.
+
+ Returns:
+ str: The appVersion if found, otherwise an empty string.
+ """
+ with open(path, encoding="utf-8") as file:
+ chart_yaml = yaml.safe_load(file)
+ return chart_yaml.get("appVersion", "")
+
+
+def get_gradle_version(path):
+ """
+ Extracts the version from build.gradle.
+
+ Args:
+ path (str): The file path to the build.gradle.
+
+ Returns:
+ str: The version if found, otherwise an empty string.
+ """
+ with open(path, encoding="utf-8") as file:
+ for line in file:
+ if "version =" in line:
+ # Extracts the value after 'version ='
+ return re.search(r'version\s*=\s*[\'"](.+?)[\'"]', line).group(1)
+ return ""
+
+
+def update_chart_version(path, new_version):
+ """
+ Updates the appVersion in Chart.yaml with a new version.
+
+ Args:
+ path (str): The file path to the Chart.yaml.
+ new_version (str): The new version to update to.
+ """
+ with open(path, encoding="utf-8") as file:
+ chart_yaml = yaml.safe_load(file)
+ chart_yaml["appVersion"] = new_version
+ with open(path, "w", encoding="utf-8") as file:
+ yaml.safe_dump(chart_yaml, file)
+
+
+# Main logic
+chart_version = get_chart_version(chart_yaml_path)
+gradle_version = get_gradle_version(gradle_path)
+
+if chart_version != gradle_version:
+ print(
+ f"Versions do not match. Updating Chart.yaml from {chart_version} to {gradle_version}."
+ )
+ update_chart_version(chart_yaml_path, gradle_version)
+else:
+ print("Versions match. No update required.")
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 74d1f8f5..f4d37599 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -2,9 +2,15 @@ name: "Build repo"
on:
push:
- branches: [ "main" ]
+ branches: ["main"]
+ paths-ignore:
+ - ".github/**"
+ - "**/*.md"
pull_request:
- branches: [ "main" ]
+ branches: ["main"]
+ paths-ignore:
+ - ".github/**"
+ - "**/*.md"
jobs:
build:
@@ -19,16 +25,18 @@ jobs:
fail-fast: false
steps:
- - name: Checkout repository
- uses: actions/checkout@v3
+ - name: Checkout repository
+ uses: actions/checkout@v4
- - name: Set up JDK 17
- uses: actions/setup-java@v3
- with:
- java-version: '17'
- distribution: 'temurin'
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: "17"
+ distribution: "temurin"
- - uses: gradle/gradle-build-action@v2.4.2
- with:
- gradle-version: 7.6
- arguments: build --no-build-cache
+ - uses: gradle/actions/setup-gradle@v3
+ with:
+ gradle-version: 7.6
+
+ - name: Build with Gradle
+ run: ./gradlew build --no-build-cache
diff --git a/.github/workflows/licenses-update.yml b/.github/workflows/licenses-update.yml
index 991ccafd..a3996bc6 100644
--- a/.github/workflows/licenses-update.yml
+++ b/.github/workflows/licenses-update.yml
@@ -5,7 +5,7 @@ on:
branches:
- main
paths:
- - 'build.gradle'
+ - "build.gradle"
permissions:
contents: write
@@ -17,13 +17,15 @@ jobs:
steps:
- name: Check out code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Set up JDK 17
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
- java-version: '17'
- distribution: 'adopt'
+ java-version: "17"
+ distribution: "adopt"
+
+ - uses: gradle/actions/setup-gradle@v3
- name: Run Gradle Command
run: ./gradlew clean generateLicenseReport
@@ -32,17 +34,29 @@ jobs:
run: |
mv build/reports/dependency-license/index.json src/main/resources/static/3rdPartyLicenses.json
- - name: Check for Changes
- id: git-check
+ - name: Set up git config
+ run: |
+ git config --global user.email "GitHub Action "
+ git config --global user.name "GitHub Action "
+
+ - name: Run git add
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
+ git diff --staged --quiet || echo "CHANGES_DETECTED=true" >> $GITHUB_ENV
+ - name: Create Pull Request
+ if: env.CHANGES_DETECTED == 'true'
+ uses: peter-evans/create-pull-request@v6
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ commit-message: "Update 3rd Party Licenses"
+ committer: GitHub Action
+ author: GitHub Action
+ signoff: true
+ branch: update-3rd-party-licenses
+ title: "Update 3rd Party Licenses"
+ body: |
+ Auto-generated by [create-pull-request][1]
+ [1]: https://github.com/peter-evans/create-pull-request
+ draft: false
+ delete-branch: true
diff --git a/.github/workflows/push-docker.yml b/.github/workflows/push-docker.yml
index 6dff5cbb..f8fc4200 100644
--- a/.github/workflows/push-docker.yml
+++ b/.github/workflows/push-docker.yml
@@ -6,6 +6,7 @@ on:
branches:
- master
- main
+
permissions:
contents: read
packages: write
@@ -13,139 +14,99 @@ jobs:
push:
runs-on: ubuntu-latest
steps:
+ - uses: actions/checkout@v4
- - uses: actions/checkout@v3.5.2
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: "17"
+ distribution: "temurin"
- - name: Set up JDK 17
- uses: actions/setup-java@v3.11.0
- with:
- java-version: '17'
- distribution: 'temurin'
+ - uses: gradle/actions/setup-gradle@v3
+ with:
+ gradle-version: 7.6
+ - name: Run Gradle Command
+ run: ./gradlew clean build
+ env:
+ DOCKER_ENABLE_SECURITY: false
- - uses: gradle/gradle-build-action@v2.4.2
- env:
- DOCKER_ENABLE_SECURITY: false
- with:
- gradle-version: 7.6
- arguments: clean build
+ - name: Set up Docker Buildx
+ id: buildx
+ uses: docker/setup-buildx-action@v3
- - name: Make Gradle wrapper executable
- run: chmod +x gradlew
+ - name: Get version number
+ id: versionNumber
+ run: echo "versionNumber=$(./gradlew printVersion --quiet | tail -1)" >> $GITHUB_OUTPUT
- - name: Get version number
- id: versionNumber
- run: echo "::set-output name=versionNumber::$(./gradlew printVersion --quiet | tail -1)"
+ - name: Login to Docker Hub
+ uses: docker/login-action@v3
+ with:
+ username: ${{ secrets.DOCKER_HUB_USERNAME }}
+ password: ${{ secrets.DOCKER_HUB_API }}
- - name: Login to Docker Hub
- uses: docker/login-action@v2.1.0
- with:
- username: ${{ secrets.DOCKER_HUB_USERNAME }}
- password: ${{ secrets.DOCKER_HUB_API }}
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ github.token }}
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v2.1.0
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ github.token }}
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
- - name: Convert repository owner to lowercase
- id: repoowner
- run: echo "::set-output name=lowercase::$(echo ${{ github.repository_owner }} | awk '{print tolower($0)}')"
+ - name: Convert repository owner to lowercase
+ id: repoowner
+ run: echo "lowercase=$(echo ${{ github.repository_owner }} | awk '{print tolower($0)}')" >> $GITHUB_OUTPUT
- - name: Generate tags
- id: meta
- uses: docker/metadata-action@v4.4.0
- with:
- images: |
- ${{ secrets.DOCKER_HUB_USERNAME }}/s-pdf
- ghcr.io/${{ steps.repoowner.outputs.lowercase }}/s-pdf
- tags: |
- type=raw,value=${{ steps.versionNumber.outputs.versionNumber }},enable=${{ github.ref == 'refs/heads/master' }}
- type=raw,value=latest,enable=${{ github.ref == 'refs/heads/master' }}
- type=raw,value=alpha,enable=${{ github.ref == 'refs/heads/main' }}
+ - name: Generate tags
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: |
+ ${{ secrets.DOCKER_HUB_USERNAME }}/s-pdf
+ ghcr.io/${{ steps.repoowner.outputs.lowercase }}/s-pdf
+ tags: |
+ type=raw,value=${{ steps.versionNumber.outputs.versionNumber }},enable=${{ github.ref == 'refs/heads/master' }}
+ type=raw,value=latest,enable=${{ github.ref == 'refs/heads/master' }}
+ type=raw,value=alpha,enable=${{ github.ref == 'refs/heads/main' }}
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v2.1.0
+ - name: Build and push main Dockerfile
+ uses: docker/build-push-action@v5
+ with:
+ builder: ${{ steps.buildx.outputs.name }}
+ context: .
+ file: ./Dockerfile
+ push: true
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
+ build-args: VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
+ platforms: linux/amd64,linux/arm64/v8
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v2.5.0
+ - name: Generate tags ultra-lite
+ id: meta2
+ uses: docker/metadata-action@v5
+ if: github.ref != 'refs/heads/main'
+ with:
+ images: |
+ ${{ secrets.DOCKER_HUB_USERNAME }}/s-pdf
+ ghcr.io/${{ steps.repoowner.outputs.lowercase }}/s-pdf
+ tags: |
+ type=raw,value=${{ steps.versionNumber.outputs.versionNumber }}-ultra-lite,enable=${{ github.ref == 'refs/heads/master' }}
+ type=raw,value=latest-ultra-lite,enable=${{ github.ref == 'refs/heads/master' }}
- - name: Build and push main Dockerfile
- uses: docker/build-push-action@v4.0.0
- with:
- context: .
- dockerfile: ./Dockerfile
- push: true
- cache-from: type=gha
- cache-to: type=gha,mode=max
- tags: ${{ steps.meta.outputs.tags }}
- labels: ${{ steps.meta.outputs.labels }}
- build-args:
- VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
- platforms: linux/amd64,linux/arm64/v8
-
-
-
- - name: Generate tags ultra-lite
- id: meta2
- uses: docker/metadata-action@v4.4.0
- if: github.ref != 'refs/heads/main'
- with:
- images: |
- ${{ secrets.DOCKER_HUB_USERNAME }}/s-pdf
- ghcr.io/${{ steps.repoowner.outputs.lowercase }}/s-pdf
- tags: |
- type=raw,value=${{ steps.versionNumber.outputs.versionNumber }}-ultra-lite,enable=${{ github.ref == 'refs/heads/master' }}
- type=raw,value=latest-ultra-lite,enable=${{ github.ref == 'refs/heads/master' }}
-
-
- - name: Build and push Dockerfile-ultra-lite
- uses: docker/build-push-action@v4.0.0
- if: github.ref != 'refs/heads/main'
- with:
- context: .
- file: ./Dockerfile-ultra-lite
- push: true
- cache-from: type=gha
- cache-to: type=gha,mode=max
- tags: ${{ steps.meta2.outputs.tags }}
- labels: ${{ steps.meta2.outputs.labels }}
- build-args:
- VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
- platforms: linux/amd64,linux/arm64/v8
-
-
-
- - name: Generate tags lite
- id: meta3
- uses: docker/metadata-action@v4.4.0
- if: github.ref != 'refs/heads/main'
- with:
- images: |
- ${{ secrets.DOCKER_HUB_USERNAME }}/s-pdf
- ghcr.io/${{ steps.repoowner.outputs.lowercase }}/s-pdf
- tags: |
- type=raw,value=${{ steps.versionNumber.outputs.versionNumber }}-lite,enable=${{ github.ref == 'refs/heads/master' }}
- type=raw,value=latest-lite,enable=${{ github.ref == 'refs/heads/master' }}
-
-
- - name: Build and push Dockerfile-lite
- uses: docker/build-push-action@v4.0.0
- if: github.ref != 'refs/heads/main'
- with:
- context: .
- file: ./Dockerfile-lite
- push: true
- cache-from: type=gha
- cache-to: type=gha,mode=max
- tags: ${{ steps.meta3.outputs.tags }}
- labels: ${{ steps.meta3.outputs.labels }}
- build-args:
- VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
- platforms: linux/amd64,linux/arm64/v8
- - name: Build and Push Helm Chart
- run: |
- helm package chart/stirling-pdf
- helm push stirling-pdf-chart-1.0.0.tgz oci://registry-1.docker.io/frooodle
+ - name: Build and push Dockerfile-ultra-lite
+ uses: docker/build-push-action@v5
+ if: github.ref != 'refs/heads/main'
+ with:
+ context: .
+ file: ./Dockerfile-ultra-lite
+ push: true
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+ tags: ${{ steps.meta2.outputs.tags }}
+ labels: ${{ steps.meta2.outputs.labels }}
+ build-args: VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
+ platforms: linux/amd64,linux/arm64/v8
diff --git a/.github/workflows/releaseArtifacts.yml b/.github/workflows/releaseArtifacts.yml
index 5042141a..f9b5f2b0 100644
--- a/.github/workflows/releaseArtifacts.yml
+++ b/.github/workflows/releaseArtifacts.yml
@@ -1,6 +1,7 @@
name: Release Artifacts
on:
+ workflow_dispatch:
release:
types: [created]
permissions:
@@ -14,44 +15,61 @@ jobs:
enable_security: [true, false]
include:
- enable_security: true
- file_suffix: '-with-login'
+ file_suffix: "-with-login"
- enable_security: false
- file_suffix: ''
+ file_suffix: ""
steps:
- - uses: actions/checkout@v3.5.2
+ - uses: actions/checkout@v4
- - name: Set up JDK 17
- uses: actions/setup-java@v3.11.0
- with:
- java-version: '17'
- distribution: 'temurin'
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: "17"
+ distribution: "temurin"
- - name: Grant execute permission for gradlew
- run: chmod +x gradlew
+ - uses: gradle/actions/setup-gradle@v3
+ with:
+ gradle-version: 7.6
- - name: Generate jar (With Security=${{ matrix.enable_security }})
- run: ./gradlew clean createExe
- env:
- DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }}
+ - name: Generate jar (With Security=${{ matrix.enable_security }})
+ run: ./gradlew clean createExe
+ env:
+ DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }}
- - name: Upload binaries to release
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GITHUB_TOKEN }}
- file: ./build/launch4j/Stirling-PDF.exe
- asset_name: Stirling-PDF${{ matrix.file_suffix }}.exe
- tag: ${{ github.ref }}
- overwrite: true
+ - name: Get version number
+ id: versionNumber
+ run: echo "versionNumber=$(./gradlew printVersion --quiet | tail -1)" >> $GITHUB_OUTPUT
- - name: Get version number
- id: versionNumber
- run: echo "::set-output name=versionNumber::$(./gradlew printVersion --quiet | tail -1)"
+ - name: Rename binarie
+ if: matrix.file_suffix != ''
+ run: cp ./build/launch4j/Stirling-PDF.exe ./build/launch4j/Stirling-PDF${{ matrix.file_suffix }}.exe
- - name: Upload jar binaries to release
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GITHUB_TOKEN }}
- file: ./build/libs/Stirling-PDF-${{ steps.versionNumber.outputs.versionNumber }}.jar
- asset_name: Stirling-PDF${{ matrix.file_suffix }}.jar
- tag: ${{ github.ref }}
- overwrite: true
+ - name: Upload Assets binarie
+ uses: actions/upload-artifact@v4
+ with:
+ path: ./build/launch4j/Stirling-PDF${{ matrix.file_suffix }}.exe
+ name: Stirling-PDF${{ matrix.file_suffix }}.exe
+ overwrite: true
+ retention-days: 1
+ if-no-files-found: error
+ - name: Upload binaries to release
+ uses: softprops/action-gh-release@v2
+ with:
+ files: ./build/launch4j/Stirling-PDF${{ matrix.file_suffix }}.exe
+
+ - name: Rename jar binaries
+ run: cp ./build/libs/Stirling-PDF-${{ steps.versionNumber.outputs.versionNumber }}.jar ./build/libs/Stirling-PDF${{ matrix.file_suffix }}.jar
+
+ - name: Upload Assets jar binaries
+ uses: actions/upload-artifact@v4
+ with:
+ path: ./build/libs/Stirling-PDF${{ matrix.file_suffix }}.jar
+ name: Stirling-PDF${{ matrix.file_suffix }}.jar
+ overwrite: true
+ retention-days: 1
+ if-no-files-found: error
+
+ - name: Upload jar binaries to release
+ uses: softprops/action-gh-release@v2
+ with:
+ files: ./build/libs/Stirling-PDF${{ matrix.file_suffix }}.jar
diff --git a/.github/workflows/swagger.yml b/.github/workflows/swagger.yml
index 60c7aa1d..88e6df7e 100644
--- a/.github/workflows/swagger.yml
+++ b/.github/workflows/swagger.yml
@@ -5,33 +5,35 @@ on:
push:
branches:
- master
+
jobs:
push:
-
runs-on: ubuntu-latest
steps:
+ - uses: actions/checkout@v4
- - uses: actions/checkout@v3.5.2
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: "17"
+ distribution: "temurin"
- - name: Set up JDK 17
- uses: actions/setup-java@v3.11.0
- with:
- java-version: '17'
- distribution: 'temurin'
+ - uses: gradle/actions/setup-gradle@v3
- - name: Grant execute permission for gradlew
- run: chmod +x gradlew
+ - name: Generate Swagger documentation
+ run: ./gradlew generateOpenApiDocs
- - name: Generate Swagger documentation
- run: ./gradlew generateOpenApiDocs
+ - name: Upload Swagger Documentation to SwaggerHub
+ run: ./gradlew swaggerhubUpload
+ env:
+ SWAGGERHUB_API_KEY: ${{ secrets.SWAGGERHUB_API_KEY }}
- - name: Upload Swagger Documentation to SwaggerHub
- run: ./gradlew swaggerhubUpload
- env:
- SWAGGERHUB_API_KEY: ${{ secrets.SWAGGERHUB_API_KEY }}
+ - name: Get version number
+ id: versionNumber
+ run: echo "versionNumber=$(./gradlew printVersion --quiet | tail -1)" >> $GITHUB_OUTPUT
- - name: Set API version as published and default on SwaggerHub
- run: |
- curl -X PUT -H "Authorization: ${SWAGGERHUB_API_KEY}" "https://api.swaggerhub.com/apis/Frooodle/Stirling-PDF/${{ steps.versionNumber.outputs.versionNumber }}/settings/lifecycle" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"published\":true,\"default\":true}"
- env:
- SWAGGERHUB_API_KEY: ${{ secrets.SWAGGERHUB_API_KEY }}
\ No newline at end of file
+ - name: Set API version as published and default on SwaggerHub
+ run: |
+ curl -X PUT -H "Authorization: ${SWAGGERHUB_API_KEY}" "https://api.swaggerhub.com/apis/Frooodle/Stirling-PDF/${{ steps.versionNumber.outputs.versionNumber }}/settings/lifecycle" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"published\":true,\"default\":true}"
+ env:
+ SWAGGERHUB_API_KEY: ${{ secrets.SWAGGERHUB_API_KEY }}
diff --git a/.github/workflows/sync_files.yml b/.github/workflows/sync_files.yml
new file mode 100644
index 00000000..ac1556cd
--- /dev/null
+++ b/.github/workflows/sync_files.yml
@@ -0,0 +1,90 @@
+name: Sync Files
+
+on:
+ push:
+ branches:
+ - main
+ paths:
+ - "build.gradle"
+ - "src/main/resources/messages_*.properties"
+ - "scripts/translation_status.toml"
+
+permissions:
+ contents: write
+ pull-requests: write
+
+jobs:
+ sync-versions:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4.1.1
+ - name: Set up Python
+ uses: actions/setup-python@v5.1.0
+ with:
+ python-version: "3.x"
+ - name: Install dependencies
+ run: pip install pyyaml
+ - name: Sync versions
+ run: python .github/scripts/gradle_to_chart.py
+ - name: Set up git config
+ run: |
+ git config --global user.email "GitHub Action "
+ git config --global user.name "GitHub Action "
+ - name: Run git add
+ run: |
+ git add .
+ git diff --staged --quiet || git commit -m ":floppy_disk: Sync Versions
+ > Made via sync_files.yml" || echo "no changes"
+ - name: Create Pull Request
+ uses: peter-evans/create-pull-request@v6.0.1
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ commit-message: Update files
+ committer: GitHub Action
+ author: GitHub Action
+ signoff: true
+ branch: sync_version
+ title: ":floppy_disk: Update Version"
+ body: |
+ Auto-generated by [create-pull-request][1]
+
+ [1]: https://github.com/peter-evans/create-pull-request
+ draft: false
+ delete-branch: true
+ sync-readme:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4.1.1
+ - name: Set up Python
+ uses: actions/setup-python@v5.1.0
+ with:
+ python-version: "3.x"
+ - name: Install dependencies
+ run: pip install tomlkit
+ - name: Sync README
+ run: python scripts/counter_translation.py
+ - name: Set up git config
+ run: |
+ git config --global user.email "GitHub Action "
+ git config --global user.name "GitHub Action "
+ - name: Run git add
+ run: |
+ git add .
+ git diff --staged --quiet || git commit -m ":memo: Sync README
+ > Made via sync_files.yml" || echo "no changes"
+ - name: Create Pull Request
+ uses: peter-evans/create-pull-request@v6.0.1
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ commit-message: Update files
+ committer: GitHub Action
+ author: GitHub Action
+ signoff: true
+ branch: sync_readme
+ title: ":memo: Update README: Translation Progress Table"
+ body: |
+ Auto-generated by [create-pull-request][1]
+
+ [1]: https://github.com/peter-evans/create-pull-request
+ draft: false
+ delete-branch: true
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 1920a339..eef33335 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -3,54 +3,36 @@ name: Docker Compose Tests
on:
pull_request:
paths:
- - 'src/**'
- - '**.gradle'
- - '!src/main/java/resources/messages*'
- - 'exampleYmlFiles/**'
- - 'Dockerfile'
- - 'Dockerfile**'
+ - "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: Checkout Repository
+ uses: actions/checkout@v4
- - name: Set up Java 17
- uses: actions/setup-java@v2
- with:
- java-version: '17'
- distribution: 'adopt'
+ - name: Set up Java 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: "17"
+ distribution: "adopt"
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v1
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
- - name: Run Docker Compose Tests
- run: |
- chmod +x ./gradlew
+ - name: Install Docker Compose
+ run: |
+ sudo curl -SL "https://github.com/docker/compose/releases/download/v2.26.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
+ # sudo chmod +x /usr/local/bin/docker-compose
- - 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
+ - name: Run Docker Compose Tests
+ run: |
+ chmod +x ./test.sh
+ ./test.sh
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 00000000..e397fc5d
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,37 @@
+repos:
+ - repo: https://github.com/astral-sh/ruff-pre-commit
+ rev: v0.2.1
+ hooks:
+ - id: ruff
+ args:
+ - --fix
+ - --line-length=127
+ files: ^((.github/scripts)/.+)?[^/]+\.py$
+ - id: ruff-format
+ files: ^((.github/scripts)/.+)?[^/]+\.py$
+ - repo: https://github.com/codespell-project/codespell
+ rev: v2.2.6
+ hooks:
+ - id: codespell
+ args:
+ - --ignore-words-list=
+ - --skip="./.*,*.csv,*.json,*.ambr"
+ - --quiet-level=2
+ files: \.(properties|html|css|js|py|md)$
+ exclude: (.vscode|.devcontainer|src/main/resources|Dockerfile)
+ - repo: local
+ hooks:
+ - id: check-duplicate-properties-keys
+ name: Check Duplicate Properties Keys
+ entry: python .github/scripts/check_duplicates.py
+ language: python
+ files: ^(src)/.+\.properties$
+ - repo: local
+ hooks:
+ - id: check-html-tabs
+ name: Check HTML for tabs
+ # args: ["--replace_with= "]
+ entry: python .github/scripts/check_tabulator.py
+ language: python
+ exclude: ^src/main/resources/static/pdfjs/
+ files: ^.*(\.html|\.css|\.js)$
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3befe050..646bdddb 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -27,6 +27,10 @@ Please make sure your Pull Request adheres to the following guidelines:
If you would like to add or modify a translation, please see [How to add new languages to Stirling-PDF](HowToAddNewLanguage.md). Also, please create a Pull Request so others can use it!
+## Docs
+
+Documentation for Stirling-PDF is handled in a seperate repository. Please see [Docs repository](https://github.com/Stirling-Tools/Stirling-Tools.github.io) or use "edit this page"-button at the bottom of each page at [https://stirlingtools.com/docs/](https://stirlingtools.com/docs/).
+
## Fixing Bugs or Adding a New Feature
First, make sure you've read the section [Pull Requests](#pull-requests).
diff --git a/Dockerfile b/Dockerfile
index 4a520613..651a16d7 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,19 +1,46 @@
# Main stage
-FROM alpine:3.19.1
+FROM alpine:20240329
+
+# Copy necessary files
+COPY scripts /scripts
+COPY pipeline /pipeline
+COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
+#COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto/
+COPY build/libs/*.jar app.jar
+
+ARG VERSION_TAG
+
+
+# Set Environment Variables
+ENV DOCKER_ENABLE_SECURITY=false \
+ VERSION_TAG=$VERSION_TAG \
+ JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75" \
+ HOME=/home/stirlingpdfuser \
+ PUID=1000 \
+ PGID=1000 \
+ UMASK=022
+
# JDK for app
RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories && \
+ apk update && \
apk add --no-cache \
ca-certificates \
tzdata \
tini \
+ openssl \
+openssl-dev \
bash \
curl \
openjdk17-jre \
+ su-exec \
+ shadow \
# Doc conversion
libreoffice@testing \
+# pdftohtml
+ poppler-utils \
# OCR MY PDF (unpaper for descew and other advanced featues)
ocrmypdf \
tesseract-ocr-data-eng \
@@ -24,46 +51,20 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et
wget https://bootstrap.pypa.io/get-pip.py -qO - | python3 - --break-system-packages --no-cache-dir --upgrade && \
# uno unoconv and HTML
pip install --break-system-packages --no-cache-dir --upgrade unoconv WeasyPrint && \
- mv /usr/share/tessdata /usr/share/tessdata-original
-
-
-
-ARG VERSION_TAG
-
-# Set Environment Variables
-ENV DOCKER_ENABLE_SECURITY=false \
- HOME=/home/stirlingpdfuser \
- VERSION_TAG=$VERSION_TAG \
- JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75"
-# PUID=1000 \
-# PGID=1000 \
-# UMASK=022 \
-
-# Copy necessary files
-COPY scripts /scripts
-COPY pipeline /pipeline
-COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto
-COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto
-COPY build/libs/*.jar app.jar
-
-# Create user and group
-##RUN groupadd -g $PGID stirlingpdfgroup && \
-## useradd -u $PUID -g stirlingpdfgroup -s /bin/sh stirlingpdfuser && \
-## mkdir -p $HOME && chown stirlingpdfuser:stirlingpdfgroup $HOME && \
-# Set up necessary directories and permissions
-RUN mkdir -p /configs /logs /customFiles /pipeline/watchedFolders /pipeline/finishedFolders && \
-##&& \
-## chown -R stirlingpdfuser:stirlingpdfgroup /scripts /usr/share/fonts/opentype/noto /usr/share/tesseract-ocr /configs /customFiles && \
-## chown -R stirlingpdfuser:stirlingpdfgroup /usr/share/tesseract-ocr-original && \
-# Set font cache and permissions
+ mv /usr/share/tessdata /usr/share/tessdata-original && \
+ mkdir -p $HOME /configs /logs /customFiles /pipeline/watchedFolders /pipeline/finishedFolders && \
fc-cache -f -v && \
- chmod +x /scripts/*
-## chown stirlingpdfuser:stirlingpdfgroup /app.jar && \
-## chmod +x /scripts/init.sh
+ chmod +x /scripts/* && \
+ chmod +x /scripts/init.sh && \
+# User permissions
+ addgroup -S stirlingpdfgroup && adduser -S stirlingpdfuser -G stirlingpdfgroup && \
+ chown -R stirlingpdfuser:stirlingpdfgroup $HOME /scripts /usr/share/fonts/opentype/noto /configs /customFiles /pipeline && \
+ chown stirlingpdfuser:stirlingpdfgroup /app.jar && \
+ tesseract --list-langs && \
+ rm -rf /var/cache/apk/*
EXPOSE 8080
# Set user and run command
-##USER stirlingpdfuser
ENTRYPOINT ["tini", "--", "/scripts/init.sh"]
CMD ["java", "-Dfile.encoding=UTF-8", "-jar", "/app.jar"]
diff --git a/Dockerfile-lite b/Dockerfile-lite
deleted file mode 100644
index f7dfa219..00000000
--- a/Dockerfile-lite
+++ /dev/null
@@ -1,61 +0,0 @@
-# use alpine
-FROM alpine:3.19.1
-
-ARG VERSION_TAG
-
-# Set Environment Variables
-ENV DOCKER_ENABLE_SECURITY=false \
- HOME=/home/stirlingpdfuser \
- VERSION_TAG=$VERSION_TAG \
- JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75"
-# PUID=1000 \
-# PGID=1000 \
-# UMASK=022 \
-
-# Copy necessary files
-COPY scripts/download-security-jar.sh /scripts/download-security-jar.sh
-COPY scripts/init-without-ocr.sh /scripts/init-without-ocr.sh
-COPY pipeline /pipeline
-COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto
-COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto
-COPY build/libs/*.jar app.jar
-
-RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
- echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \
- echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories && \
- apk add --no-cache \
- ca-certificates \
- tzdata \
- tini \
- bash \
- curl \
- openjdk17-jre \
-# Doc conversion
- libreoffice@testing \
-# python and pip
- python3 && \
- wget https://bootstrap.pypa.io/get-pip.py -qO - | python3 - --break-system-packages --no-cache-dir --upgrade && \
-# uno unoconv and HTML
- pip install --break-system-packages --no-cache-dir --upgrade unoconv WeasyPrint && \
-# Create user and group
-#RUN groupadd -g $PGID stirlingpdfgroup && \
-# useradd -u $PUID -g stirlingpdfgroup -s /bin/sh stirlingpdfuser && \
-# mkdir -p $HOME && chown stirlingpdfuser:stirlingpdfgroup $HOME
-# Set up necessary directories and permissions
- mkdir -p /configs /logs /customFiles /pipeline/watchedFolders /pipeline/finishedFolders && \
-# chown -R stirlingpdfuser:stirlingpdfgroup /usr/share/fonts/opentype/noto /configs /customFiles
-# Set font cache and permissions
- fc-cache -f -v && \
- chmod +x /scripts/*.sh
-# chown stirlingpdfuser:stirlingpdfgroup /app.jar
-
-# Set environment variables
-ENV ENDPOINTS_GROUPS_TO_REMOVE=OpenCV,OCRmyPDF
-ENV DOCKER_ENABLE_SECURITY=false
-
-EXPOSE 8080
-
-# Run the application
-#USER stirlingpdfuser
-ENTRYPOINT ["tini", "--", "/scripts/init-without-ocr.sh"]
-CMD ["java", "-Dfile.encoding=UTF-8", "-jar", "/app.jar"]
diff --git a/Dockerfile-ultra-lite b/Dockerfile-ultra-lite
index d602a361..eed8d783 100644
--- a/Dockerfile-ultra-lite
+++ b/Dockerfile-ultra-lite
@@ -7,10 +7,10 @@ ARG VERSION_TAG
ENV DOCKER_ENABLE_SECURITY=false \
HOME=/home/stirlingpdfuser \
VERSION_TAG=$VERSION_TAG \
- JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75"
-# PUID=1000 \
-# PGID=1000 \
-# UMASK=022 \
+ JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75" \
+ PUID=1000 \
+ PGID=1000 \
+ UMASK=022
# Copy necessary files
COPY scripts/download-security-jar.sh /scripts/download-security-jar.sh
@@ -18,16 +18,10 @@ COPY scripts/init-without-ocr.sh /scripts/init-without-ocr.sh
COPY pipeline /pipeline
COPY build/libs/*.jar app.jar
-# Create user and group using Alpine's addgroup and adduser
-#RUN addgroup -g $PGID stirlingpdfgroup && \
-# adduser -u $PUID -G stirlingpdfgroup -s /bin/sh -D stirlingpdfuser && \
-# mkdir -p $HOME && chown stirlingpdfuser:stirlingpdfgroup $HOME
+
# Set up necessary directories and permissions
-#RUN mkdir -p /scripts /configs /customFiles && \
-# chown -R stirlingpdfuser:stirlingpdfgroup /scripts /configs /customFiles /logs /pipeline /pipeline/defaultWebUIConfigs /pipeline/watchedFolders /pipeline/finishedFolders
+
RUN mkdir /configs /logs /customFiles && \
-# Set font cache and permissions
-#RUN chown stirlingpdfuser:stirlingpdfgroup /app.jar
chmod +x /scripts/*.sh && \
apk add --no-cache \
ca-certificates \
@@ -35,10 +29,16 @@ RUN mkdir /configs /logs /customFiles && \
tini \
bash \
curl \
+ su-exec \
+ shadow \
openjdk17-jre && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \
- echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories
+ echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories && \
+ # User permissions
+ addgroup -S stirlingpdfgroup && adduser -S stirlingpdfuser -G stirlingpdfgroup && \
+ chown -R stirlingpdfuser:stirlingpdfgroup $HOME /scripts /configs /customFiles /pipeline && \
+ chown stirlingpdfuser:stirlingpdfgroup /app.jar
# Set environment variables
ENV ENDPOINTS_GROUPS_TO_REMOVE=CLI
diff --git a/FolderScanning.md b/FolderScanning.md
index 6b743a7f..140c9f5f 100644
--- a/FolderScanning.md
+++ b/FolderScanning.md
@@ -1,13 +1,5 @@
## User Guide for Local Directory Scanning and File Processing
-### Whilst Pipelines are in alpha...
-You must enable this alpha functionality by setting
-```yaml
-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/`
diff --git a/HowToAddNewLanguage.md b/HowToAddNewLanguage.md
index 9f8e3f39..73cad0e9 100644
--- a/HowToAddNewLanguage.md
+++ b/HowToAddNewLanguage.md
@@ -12,7 +12,7 @@ https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/temp
and add a flag svg file to
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
+If your language isn't represented by a flag just find whichever closely matches it, such as for Arabic i chose Saudi Arabia
For example to add Polish you would add
@@ -32,7 +32,20 @@ Copy and rename it to messages_{your data-language-code here}.properties, in the
Then simply translate all property entries within that file and make a PR into main for others to use!
-If you do not have a java IDE i am happy to verify the changes worked once you raise PR (but wont be able to verify the translations themselves)
+If you do not have a java IDE i am happy to verify the changes worked once you raise PR (but won't be able to verify the translations themselves)
+## Handling Untranslatable Strings
+Sometimes, certain strings in the properties file may not require translation because they are the same in the target language or are universal (like names of protocols, certain terminologies, etc.). To ensure accurate statistics for language progress, these strings should be added to the `ignore_translation.toml` file located in the `scripts` directory. This will exclude them from the translation progress calculations.
+For example, if the English string error=Error does not need translation in Polish, add it to the ignore_translation.toml under the Polish section:
+
+```toml
+[pl_PL]
+ignore = [
+ "language.direction", # Existing entries
+ "error" # Add new entries here
+]
+```
+
+Make sure to place the entry under the correct language section. This helps maintain the accuracy of translation progress statistics and ensures that the translation tool or scripts do not misinterpret the completion rate.
diff --git a/HowToUseOCR.md b/HowToUseOCR.md
index 388ab438..8607c28d 100644
--- a/HowToUseOCR.md
+++ b/HowToUseOCR.md
@@ -2,8 +2,8 @@
This document provides instructions on how to add additional language packs for the OCR tab in Stirling-PDF, both inside and outside of Docker.
-## My OCR used to work and now doesnt!
-Please update your tesseract docker volume path version from 4.00 to 5
+## My OCR used to work and now doesn't!
+The paths have changed for the tessadata locations on new docker images, please use ``/usr/share/tessdata`` (Others should still work for backwards compatibility but might not)
## How does the OCR Work
Stirling-PDF uses [OCRmyPDF](https://github.com/ocrmypdf/OCRmyPDF) which in turn uses tesseract for its text recognition.
diff --git a/LocalRunGuide.md b/LocalRunGuide.md
index 3c9b2716..e0851d62 100644
--- a/LocalRunGuide.md
+++ b/LocalRunGuide.md
@@ -42,7 +42,7 @@ For Debian-based systems, you can use the following command:
```bash
sudo apt-get update
-sudo apt-get install -y git automake autoconf libtool libleptonica-dev pkg-config zlib1g-dev make g++ java-17-openjdk python3 python3-pip
+sudo apt-get install -y git automake autoconf libtool libleptonica-dev pkg-config zlib1g-dev make g++ openjdk-17-jdk python3 python3-pip
```
For Fedora-based systems use this command:
@@ -65,7 +65,7 @@ sudo make install
```
### Step 3: Install Additional Software
-Next we need to install LibreOffice for conversions, ocrmypdf for OCR, and opencv for patern recognition functionality.
+Next we need to install LibreOffice for conversions, ocrmypdf for OCR, and opencv for pattern recognition functionality.
Install the following software:
@@ -95,7 +95,7 @@ For Debian-based systems, you can use the following command:
```bash
sudo apt-get install -y libreoffice-writer libreoffice-calc libreoffice-impress unpaper ocrmypdf
-pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint
+pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint --break-system-packages
```
For Fedora:
@@ -264,7 +264,7 @@ sudo systemctl restart stirlingpdf.service
Remember to set the necessary environment variables before running the project if you want to customize the application the list can be seen in the main readme.
-You can do this in the terminal by using the `export` command or -D arguements to java -jar command:
+You can do this in the terminal by using the `export` command or -D argument to java -jar command:
```bash
export APP_HOME_NAME="Stirling PDF"
diff --git a/PipelineFeature.md b/PipelineFeature.md
index 8d51c3c5..7edbb089 100644
--- a/PipelineFeature.md
+++ b/PipelineFeature.md
@@ -1,13 +1,6 @@
# Pipeline Configuration and Usage Tutorial
-
-## Whilst Pipelines are in alpha...
-You must enable this alpha functionality by setting
-```yaml
-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.
-
+- Configure the pipeline config file and input files to run files against it
+- For reuse, download the config file and re-upload it when needed, or place it in /pipeline/defaultWebUIConfigs/ to auto-load in the web UI for all users
## Steps to Configure and Use Your Pipeline
@@ -40,3 +33,12 @@ To true like in the above for your `/config/settings.yml` file, after restarting
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.
+
+
+### Current Limitations
+- Cannot have more than one of the same operation
+- Cannot input additional files via UI
+- All files and operations run in serial mode
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 5876a7e2..31b34009 100644
--- a/README.md
+++ b/README.md
@@ -1,34 +1,35 @@
-
Stirling-PDF
-
+
+
Stirling-PDF
[![Docker Pulls](https://img.shields.io/docker/pulls/frooodle/s-pdf)](https://hub.docker.com/r/frooodle/s-pdf)
[![Discord](https://img.shields.io/discord/1068636748814483718?label=Discord)](https://discord.gg/Cn8pWhQRxZ)
[![Docker Image Version (tag latest semver)](https://img.shields.io/docker/v/frooodle/s-pdf/latest)](https://github.com/Stirling-Tools/Stirling-PDF/)
[![GitHub Repo stars](https://img.shields.io/github/stars/stirling-tools/stirling-pdf?style=social)](https://github.com/Stirling-Tools/stirling-pdf)
[![Paypal Donate](https://img.shields.io/badge/Paypal%20Donate-yellow?style=flat&logo=paypal)](https://www.paypal.com/paypalme/froodleplex)
-[![Github Sponser](https://img.shields.io/badge/Github%20Sponsor-yellow?style=flat&logo=github)](https://github.com/sponsors/Frooodle)
+[![Github Sponsor](https://img.shields.io/badge/Github%20Sponsor-yellow?style=flat&logo=github)](https://github.com/sponsors/Frooodle)
[![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](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.
+This is a robust, locally hosted web-based PDF manipulation tool using Docker. It enables you to carry out various operations on PDF files, including splitting, merging, converting, reorganizing, adding images, rotating, compressing, and more. This locally hosted web application has evolved to encompass a comprehensive set of features, addressing all your PDF requirements.
-Stirling PDF makes no outbound calls for any record keeping or tracking.
+Stirling PDF does not initiate any outbound calls for record-keeping or tracking purposes.
All files and PDFs exist either exclusively on the client side, reside in server memory only during task execution, or temporarily reside in a file solely for the execution of the task. Any file downloaded by the user will have been deleted from the server by that point.
-![stirling-home](images/stirling-home.png)
+![stirling-home](images/stirling-home.jpg)
## Features
+
- Dark mode support.
- 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/Stirling-Tools/Stirling-PDF/tree/main#login-authentication) for documentation)
-
## **PDF Features**
### **Page Operations**
+
- View and modify PDFs - View multi page PDFs with custom viewing sorting and searching. Plus on page edit features like annotate, draw and adding text and images. (Using PDF.js with Joxit and Liberation.Liberation fonts)
- Full interactive GUI for merging/splitting/rotating/moving PDFs and their pages.
- Merge multiple PDFs together into a single resultant file.
@@ -45,6 +46,7 @@ All files and PDFs exist either exclusively on the client side, reside in server
- Convert PDF to a single page.
### **Conversion Operations**
+
- Convert PDFs to and from images.
- Convert any common file to PDF (using LibreOffice).
- Convert PDF to Word/Powerpoint/Others (using LibreOffice).
@@ -53,6 +55,7 @@ All files and PDFs exist either exclusively on the client side, reside in server
- Markdown to PDF.
### **Security & Permissions**
+
- Add and remove passwords.
- Change/set PDF Permissions.
- Add watermark(s).
@@ -61,6 +64,7 @@ All files and PDFs exist either exclusively on the client side, reside in server
- Auto-redact text.
### **Other Operations**
+
- Add/Generate/Write signatures.
- Repair PDFs.
- Detect and remove blank pages.
@@ -77,11 +81,11 @@ All files and PDFs exist either exclusively on the client side, reside in server
- Flatten PDFs.
- 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/Stirling-Tools/Stirling-PDF/blob/main/Endpoint-groups.md)
Demo of the app is available [here](https://stirlingpdf.io). username: demo, password: demo
## Technologies used
+
- Spring Boot + Thymeleaf
- [PDFBox](https://github.com/apache/pdfbox/tree/trunk)
- [LibreOffice](https://www.libreoffice.org/discover/libreoffice/) for advanced conversions
@@ -94,19 +98,21 @@ Demo of the app is available [here](https://stirlingpdf.io). username: demo, pas
## How to use
### Locally
+
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.
+Stirling PDF has 2 different versions, a Full version and ultra-Lite version. 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/Stirling-Tools/Stirling-PDF/blob/main/Version-groups.md)
For people that don't mind about space optimization just use the latest tag.
![Docker Image Size (tag)](https://img.shields.io/docker/image-size/frooodle/s-pdf/latest?label=Stirling-PDF%20Full)
-![Docker Image Size (tag)](https://img.shields.io/docker/image-size/frooodle/s-pdf/latest-lite?label=Stirling-PDF%20Lite)
![Docker Image Size (tag)](https://img.shields.io/docker/image-size/frooodle/s-pdf/latest-ultra-lite?label=Stirling-PDF%20Ultra-Lite)
Docker Run
+
```bash
docker run -d \
-p 8080:8080 \
@@ -114,6 +120,8 @@ docker run -d \
-v /location/of/extraConfigs:/configs \
-v /location/of/logs:/logs \
-e DOCKER_ENABLE_SECURITY=false \
+ -e INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false \
+ -e LANGS=en_GB \
--name stirling-pdf \
frooodle/s-pdf:latest
@@ -122,7 +130,9 @@ docker run -d \
-v /location/of/customFiles:/customFiles \
```
+
Docker Compose
+
```yaml
version: '3.3'
services:
@@ -137,59 +147,68 @@ services:
# - /location/of/logs:/logs/
environment:
- DOCKER_ENABLE_SECURITY=false
+ - INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false
+ - LANGS=en_GB
```
Note: Podman is CLI-compatible with Docker, so simply replace "docker" with "podman".
## Enable OCR/Compression feature
+
Please view https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToUseOCR.md
## Supported Languages
-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)
-- Simplified Chinese (简体中文) (zh_CN)
-- Traditional Chinese (繁體中文) (zh_TW)
-- Catalan (Català) (ca_CA)
-- Italian (Italiano) (it_IT)
-- Swedish (Svenska) (sv_SE)
-- Polish (Polski) (pl_PL)
-- Romanian (Română) (ro_RO)
-- Korean (한국어) (ko_KR)
-- Portuguese Brazilian (Português) (pt_BR)
-- Russian (Русский) (ru_RU)
-- Basque (Euskara) (eu_ES)
-- Japanese (日本語) (ja_JP)
-- Dutch (Nederlands) (nl_NL)
-- Greek (el_GR)
-- 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)
+Stirling PDF currently supports 27!
+
+| Language | Progress |
+| ------------------------------------------- | -------------------------------------- |
+| English (English) (en_GB) | ![100%](https://geps.dev/progress/100) |
+| English (US) (en_US) | ![100%](https://geps.dev/progress/100) |
+| Arabic (العربية) (ar_AR) | ![42%](https://geps.dev/progress/42) |
+| German (Deutsch) (de_DE) | ![99%](https://geps.dev/progress/99) |
+| French (Français) (fr_FR) | ![91%](https://geps.dev/progress/91) |
+| Spanish (Español) (es_ES) | ![99%](https://geps.dev/progress/99) |
+| Simplified Chinese (简体中文) (zh_CN) | ![98%](https://geps.dev/progress/98) |
+| Traditional Chinese (繁體中文) (zh_TW) | ![98%](https://geps.dev/progress/98) |
+| Catalan (Català) (ca_CA) | ![51%](https://geps.dev/progress/51) |
+| Italian (Italiano) (it_IT) | ![99%](https://geps.dev/progress/99) |
+| Swedish (Svenska) (sv_SE) | ![42%](https://geps.dev/progress/42) |
+| Polish (Polski) (pl_PL) | ![44%](https://geps.dev/progress/44) |
+| Romanian (Română) (ro_RO) | ![41%](https://geps.dev/progress/41) |
+| Korean (한국어) (ko_KR) | ![91%](https://geps.dev/progress/91) |
+| Portuguese Brazilian (Português) (pt_BR) | ![64%](https://geps.dev/progress/64) |
+| Russian (Русский) (ru_RU) | ![90%](https://geps.dev/progress/90) |
+| Basque (Euskara) (eu_ES) | ![66%](https://geps.dev/progress/66) |
+| Japanese (日本語) (ja_JP) | ![91%](https://geps.dev/progress/91) |
+| Dutch (Nederlands) (nl_NL) | ![88%](https://geps.dev/progress/88) |
+| Greek (Ελληνικά) (el_GR) | ![89%](https://geps.dev/progress/89) |
+| Turkish (Türkçe) (tr_TR) | ![99%](https://geps.dev/progress/99) |
+| Indonesia (Bahasa Indonesia) (id_ID) | ![82%](https://geps.dev/progress/82) |
+| Hindi (हिंदी) (hi_IN) | ![82%](https://geps.dev/progress/82) |
+| Hungarian (Magyar) (hu_HU) | ![81%](https://geps.dev/progress/81) |
+| Bulgarian (Български) (bg_BG) | ![75%](https://geps.dev/progress/75) |
+| Sebian Latin alphabet (Srpski) (sr_LATN_RS) | ![84%](https://geps.dev/progress/84) |
+| Ukrainian (Українська) (uk_UA) | ![90%](https://geps.dev/progress/90) |
## Contributing (creating issues, translations, fixing bugs, etc.)
Please see our [Contributing Guide](CONTRIBUTING.md)!
## Customisation
+
Stirling PDF allows easy customization of the app.
Includes things like
-- Custom application name
-- Custom slogans, icons, images, and even custom HTML (via file overrides)
+- Custom application name
+- Custom slogans, icons, HTML, images CSS etc (via file overrides)
There are two options for this, either using the generated settings file ``settings.yml``
This file is located in the ``/configs`` directory and follows standard YAML formatting
Environment variables are also supported and would override the settings file
For example in the settings.yml you have
+
```yaml
system:
defaultLocale: 'en-US'
@@ -198,6 +217,7 @@ system:
To have this via an environment variable you would have ``SYSTEM_DEFAULTLOCALE``
The Current list of settings is
+
```yaml
security:
enableLogin: false # set to 'true' to enable login
@@ -207,6 +227,9 @@ 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
customStaticFilePath: '/customFiles/static/' # Directory path for custom static files
+ showUpdate: true # see when a new update is available
+ showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
+ customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files
#ui:
# appName: exampleAppName # Application's visible name
@@ -220,25 +243,35 @@ endpoints:
metrics:
enabled: true # 'true' to enable Info APIs endpoints (view http://localhost:8080/swagger-ui/index.html#/API to learn more), 'false' to disable
```
+
+There is an additional config file ``/configs/custom_settings.yml`` were users familiar with java and spring application.properties can input their own settings on-top of Stirling-PDFs existing ones
+
### 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/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
+
- ``SYSTEM_ROOTURIPATH`` ie set to ``/pdf-app`` to Set the application's root URI to ``localhost:8080/pdf-app``
- ``SYSTEM_CONNECTIONTIMEOUTMINUTES`` to set custom connection timeout values
- ``DOCKER_ENABLE_SECURITY`` to tell docker to download security jar (required as true for auth login)
+- ``INSTALL_BOOK_AND_ADVANCED_HTML_OPS`` to download calibre onto stirling-pdf enabling pdf to/from book and advanced html conversion
+- ``LANGS`` to define custom font libraries to install for use for document conversions
## 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/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
+
![stirling-login](images/login-light.png)
+
### Prerequisites:
+
- User must have the folder ./configs volumed within docker so that it is retained during updates.
-- Docker uses must download the security jar version by setting ``DOCKER_ENABLE_SECURITY`` to ``true`` in environment variables.
+- Docker users must download the security jar version by setting ``DOCKER_ENABLE_SECURITY`` to ``true`` in environment variables.
- Then either enable login via the settings.yml file or via setting ``SECURITY_ENABLE_LOGIN`` to ``true``
- Now the initial user will be generated with username ``admin`` and password ``stirling``. On login you will be forced to change the password to a new one. You can also use the environment variables ``SECURITY_INITIALLOGIN_USERNAME`` and ``SECURITY_INITIALLOGIN_PASSWORD`` to set your own straight away (Recommended to remove them after user creation).
@@ -252,20 +285,22 @@ To add new users go to the bottom of Account settings and hit 'Admin Settings',
For API usage you must provide a header with 'X-API-Key' and the associated API key for that user.
-
## FAQ
### Q1: What are your planned features?
+
- Progress bar/Tracking
- Full custom logic pipelines to combine multiple operations together.
- Folder support with auto scanning to perform operations on
- Redact text (Via UI not just automated way)
- Add Forms
- Multi page layout (Stich PDF pages together) support x rows y columns and custom page sizing
-- Fill forms mannual and automatic
+- Fill forms manually or automatically
### Q2: Why is my application downloading .htm files?
+
This is an issue caused commonly by your NGINX configuration. The default file upload size for NGINX is 1MB, you need to add the following in your Nginx sites-available file. ``client_max_body_size SIZE;`` Where "SIZE" is 50M for example for 50MB files.
### Q3: Why is my download timing out
+
NGINX has timeout values by default so if you are running Stirling-PDF behind NGINX you may need to set a timeout value such as adding the config ``proxy_read_timeout 3600;``
diff --git a/Version-groups.md b/Version-groups.md
index 5515e16c..8c37e22d 100644
--- a/Version-groups.md
+++ b/Version-groups.md
@@ -1,64 +1,52 @@
-|Technology | Ultra-Lite | Lite | Full |
-|----------------|:----------:|:----:|:----:|
-| Java | ✔️ | ✔️ | ✔️ |
-| JavaScript | ✔️ | ✔️ | ✔️ |
-| Libre | | ✔️ | ✔️ |
-| Python | | | ✔️ |
-| OpenCV | | | ✔️ |
-| OCRmyPDF | | | ✔️ |
+| Technology | Ultra-Lite | Full |
+|----------------|:----------:|:----:|
+| Java | ✔️ | ✔️ |
+| JavaScript | ✔️ | ✔️ |
+| Libre | | ✔️ |
+| Python | | ✔️ |
+| OpenCV | | ✔️ |
+| OCRmyPDF | | ✔️ |
-
-
-
-
-Operation | Ultra-Lite | Lite | Full
---------------------|------------|------|-----
-add-page-numbers | ✔️ | ✔️ | ✔️
-add-password | ✔️ | ✔️ | ✔️
-add-image | ✔️ | ✔️ | ✔️
-add-watermark | ✔️ | ✔️ | ✔️
-adjust-contrast | ✔️ | ✔️ | ✔️
-auto-split-pdf | ✔️ | ✔️ | ✔️
-auto-redact | ✔️ | ✔️ | ✔️
-auto-rename | ✔️ | ✔️ | ✔️
-cert-sign | ✔️ | ✔️ | ✔️
-crop | ✔️ | ✔️ | ✔️
-change-metadata | ✔️ | ✔️ | ✔️
-change-permissions | ✔️ | ✔️ | ✔️
-compare | ✔️ | ✔️ | ✔️
-extract-page | ✔️ | ✔️ | ✔️
-extract-images | ✔️ | ✔️ | ✔️
-flatten | ✔️ | ✔️ | ✔️
-get-info-on-pdf | ✔️ | ✔️ | ✔️
-img-to-pdf | ✔️ | ✔️ | ✔️
-markdown-to-pdf | ✔️ | ✔️ | ✔️
-merge-pdfs | ✔️ | ✔️ | ✔️
-multi-page-layout | ✔️ | ✔️ | ✔️
-overlay-pdf | ✔️ | ✔️ | ✔️
-pdf-organizer | ✔️ | ✔️ | ✔️
-pdf-to-csv | ✔️ | ✔️ | ✔️
-pdf-to-img | ✔️ | ✔️ | ✔️
-pdf-to-single-page | ✔️ | ✔️ | ✔️
-remove-pages | ✔️ | ✔️ | ✔️
-remove-password | ✔️ | ✔️ | ✔️
-rotate-pdf | ✔️ | ✔️ | ✔️
-sanitize-pdf | ✔️ | ✔️ | ✔️
-scale-pages | ✔️ | ✔️ | ✔️
-sign | ✔️ | ✔️ | ✔️
-show-javascript | ✔️ | ✔️ | ✔️
-split-by-size-or-count | ✔️ | ✔️ | ✔️
-split-pdf-by-sections | ✔️ | ✔️ | ✔️
-split-pdfs | ✔️ | ✔️ | ✔️
-file-to-pdf | | ✔️ | ✔️
-pdf-to-html | | ✔️ | ✔️
-pdf-to-presentation | | ✔️ | ✔️
-pdf-to-text | | ✔️ | ✔️
-pdf-to-word | | ✔️ | ✔️
-pdf-to-xml | | ✔️ | ✔️
-repair | | ✔️ | ✔️
-xlsx-to-pdf | | ✔️ | ✔️
-compress-pdf | | | ✔️
-extract-image-scans | | | ✔️
-ocr-pdf | | | ✔️
-pdf-to-pdfa | | | ✔️
-remove-blanks | | | ✔️
+Operation | Ultra-Lite | Full
+-------------------------|------------|-----
+add-page-numbers | ✔️ | ✔️
+add-password | ✔️ | ✔️
+add-image | ✔️ | ✔️
+add-watermark | ✔️ | ✔️
+adjust-contrast | ✔️ | ✔️
+auto-split-pdf | ✔️ | ✔️
+auto-redact | ✔️ | ✔️
+auto-rename | ✔️ | ✔️
+cert-sign | ✔️ | ✔️
+crop | ✔️ | ✔️
+change-metadata | ✔️ | ✔️
+change-permissions | ✔️ | ✔️
+compare | ✔️ | ✔️
+extract-page | ✔️ | ✔️
+extract-images | ✔️ | ✔️
+flatten | ✔️ | ✔️
+get-info-on-pdf | ✔️ | ✔️
+img-to-pdf | ✔️ | ✔️
+markdown-to-pdf | ✔️ | ✔️
+merge-pdfs | ✔️ | ✔️
+multi-page-layout | ✔️ | ✔️
+overlay-pdf | ✔️ | ✔️
+pdf-organizer | ✔️ | ✔️
+pdf-to-csv | ✔️ | ✔️
+pdf-to-img | ✔️ | ✔️
+pdf-to-single-page | ✔️ | ✔️
+remove-pages | ✔️ | ✔️
+remove-password | ✔️ | ✔️
+rotate-pdf | ✔️ | ✔️
+sanitize-pdf | ✔️ | ✔️
+scale-pages | ✔️ | ✔️
+sign | ✔️ | ✔️
+show-javascript | ✔️ | ✔️
+split-by-size-or-count | ✔️ | ✔️
+split-pdf-by-sections | ✔️ | ✔️
+split-pdfs | ✔️ | ✔️
+compress-pdf | | ✔️
+extract-image-scans | | ✔️
+ocr-pdf | | ✔️
+pdf-to-pdfa | | ✔️
+remove-blanks | | ✔️
diff --git a/build.gradle b/build.gradle
index 727b2b53..66817266 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,18 +1,18 @@
plugins {
id 'java'
- id 'org.springframework.boot' version '3.2.2'
+ id 'org.springframework.boot' version '3.2.4'
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.25.0'
- id 'com.github.jk1.dependency-license-report' version '2.5'
+ id 'com.github.jk1.dependency-license-report' version '2.6'
}
import com.github.jk1.license.render.*
group = 'stirling.software'
-version = '0.21.0'
+version = '0.23.2'
sourceCompatibility = '17'
repositories {
@@ -20,7 +20,6 @@ repositories {
}
-
licenseReport {
renderers = [new JsonReportRenderer()]
}
@@ -48,7 +47,6 @@ openApi {
outputFileName = "SwaggerDoc.json"
}
-
launch4j {
icon = "${projectDir}/src/main/resources/static/favicon.ico"
@@ -87,26 +85,27 @@ spotless {
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.1.2'
+ implementation 'ch.qos.logback:logback-classic:1.5.3'
+ implementation 'ch.qos.logback:logback-core:1.5.3'
+ implementation 'org.springframework:spring-webmvc:6.1.5'
- implementation("io.github.pixee:java-security-toolkit:1.1.2")
+ implementation("io.github.pixee:java-security-toolkit:1.1.3")
implementation 'org.yaml:snakeyaml:2.2'
- implementation 'org.springframework.boot:spring-boot-starter-web:3.2.2'
- implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.2.2'
+ implementation 'org.springframework.boot:spring-boot-starter-web:3.2.4'
+ implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.2.4'
if (System.getenv('DOCKER_ENABLE_SECURITY') != 'false') {
- implementation 'org.springframework.boot:spring-boot-starter-security:3.2.2'
+ implementation 'org.springframework.boot:spring-boot-starter-security:3.2.4'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.RELEASE'
- implementation "org.springframework.boot:spring-boot-starter-data-jpa:3.2.2"
+ implementation "org.springframework.boot:spring-boot-starter-data-jpa:3.2.4"
+ implementation 'org.springframework.boot:spring-boot-starter-oauth2-client:3.2.4'
//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.2'
+ testImplementation 'org.springframework.boot:spring-boot-starter-test:3.2.4'
// Batik
implementation 'org.apache.xmlgraphics:batik-all:1.17'
@@ -139,28 +138,30 @@ dependencies {
exclude group: 'commons-logging', module: 'commons-logging'
}
- implementation ('org.apache.pdfbox:pdfbox:3.0.1'){
+ implementation ('org.apache.pdfbox:pdfbox:3.0.2'){
exclude group: 'commons-logging', module: 'commons-logging'
}
- implementation ('org.apache.pdfbox:xmpbox:3.0.1'){
+ implementation ('org.apache.pdfbox:xmpbox:3.0.2'){
exclude group: 'commons-logging', module: 'commons-logging'
}
implementation 'org.bouncycastle:bcprov-jdk18on:1.77'
implementation 'org.bouncycastle:bcpkix-jdk18on:1.77'
- implementation 'org.springframework.boot:spring-boot-starter-actuator:3.2.2'
- implementation 'io.micrometer:micrometer-core:1.12.2'
- implementation group: 'com.google.zxing', name: 'core', version: '3.5.2'
+ implementation 'org.springframework.boot:spring-boot-starter-actuator:3.2.4'
+ implementation 'io.micrometer:micrometer-core:1.12.4'
+ implementation group: 'com.google.zxing', name: 'core', version: '3.5.3'
// https://mvnrepository.com/artifact/org.commonmark/commonmark
- implementation 'org.commonmark:commonmark:0.21.0'
- implementation 'org.commonmark:commonmark-ext-gfm-tables:0.21.0'
+ implementation 'org.commonmark:commonmark:0.22.0'
+ implementation 'org.commonmark:commonmark-ext-gfm-tables:0.22.0'
// https://mvnrepository.com/artifact/com.github.vladimir-bukhtoyarov/bucket4j-core
implementation 'com.github.vladimir-bukhtoyarov:bucket4j-core:7.6.0'
- developmentOnly("org.springframework.boot:spring-boot-devtools:3.2.2")
- compileOnly 'org.projectlombok:lombok:1.18.30'
- annotationProcessor 'org.projectlombok:lombok:1.18.28'
+ implementation 'com.fathzer:javaluator:3.0.3'
+
+ developmentOnly("org.springframework.boot:spring-boot-devtools:3.2.4")
+ compileOnly 'org.projectlombok:lombok:1.18.32'
+ annotationProcessor 'org.projectlombok:lombok:1.18.32'
}
tasks.withType(JavaCompile) {
diff --git a/chart/stirling-pdf/Chart.yaml b/chart/stirling-pdf/Chart.yaml
index 686d2422..52220bcd 100644
--- a/chart/stirling-pdf/Chart.yaml
+++ b/chart/stirling-pdf/Chart.yaml
@@ -1,6 +1,7 @@
apiVersion: v2
-appVersion: 0.14.2
-description: locally hosted web application that allows you to perform various operations on PDF files
+appVersion: 0.23.2
+description: locally hosted web application that allows you to perform various operations
+ on PDF files
home: https://github.com/Stirling-Tools/Stirling-PDF
keywords:
- stirling-pdf
diff --git a/chart/stirling-pdf/values.yaml b/chart/stirling-pdf/values.yaml
index 3c4ca888..e9e00c3e 100644
--- a/chart/stirling-pdf/values.yaml
+++ b/chart/stirling-pdf/values.yaml
@@ -16,11 +16,11 @@ commonLabels: {}
# team_name: dev
envs: []
-# - name: PP_HOME_NAME
+# - name: UI_APP_NAME
# value: "Stirling PDF"
-# - name: APP_HOME_DESCRIPTION
+# - name: UI_HOME_DESCRIPTION
# value: "Your locally hosted one-stop-shop for all your PDF needs."
-# - name: APP_NAVBAR_NAME
+# - name: UI_APP_NAVBAR_NAME
# value: "Stirling PDF"
# - name: ALLOW_GOOGLE_VISIBILITY
# value: "true"
diff --git a/exampleYmlFiles/docker-compose-latest-lite-security.yml b/exampleYmlFiles/docker-compose-latest-lite-security.yml
deleted file mode 100644
index 90e4c5bf..00000000
--- a/exampleYmlFiles/docker-compose-latest-lite-security.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-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
diff --git a/exampleYmlFiles/docker-compose-latest-lite.yml b/exampleYmlFiles/docker-compose-latest-lite.yml
deleted file mode 100644
index e40f873d..00000000
--- a/exampleYmlFiles/docker-compose-latest-lite.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-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
diff --git a/exampleYmlFiles/docker-compose-latest-security-with-sso.yml b/exampleYmlFiles/docker-compose-latest-security-with-sso.yml
new file mode 100644
index 00000000..41241b15
--- /dev/null
+++ b/exampleYmlFiles/docker-compose-latest-security-with-sso.yml
@@ -0,0 +1,39 @@
+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/tessdata:rw
+ - /stirling/latest/config:/configs:rw
+ - /stirling/latest/logs:/logs:rw
+ environment:
+ DOCKER_ENABLE_SECURITY: "true"
+ SECURITY_ENABLELOGIN: "true"
+ SECURITY_OAUTH2_ENABLED: "true"
+ SECURITY_OAUTH2_AUTOCREATEUSER: "true" # This is set to true to allow auto-creation of non-existing users in Striling-PDF
+ SECURITY_OAUTH2_ISSUER: "https://accounts.google.com" # Change with any other provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point
+ SECURITY_OAUTH2_CLIENTID: ".apps.googleusercontent.com" # Client ID from your provider
+ SECURITY_OAUTH2_CLIENTSECRET: "" # Client Secret from your provider
+ PUID: 1002
+ PGID: 1002
+ UMASK: "022"
+ 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
diff --git a/exampleYmlFiles/docker-compose-latest-security.yml b/exampleYmlFiles/docker-compose-latest-security.yml
index 513bb582..82014b8e 100644
--- a/exampleYmlFiles/docker-compose-latest-security.yml
+++ b/exampleYmlFiles/docker-compose-latest-security.yml
@@ -15,12 +15,15 @@ services:
ports:
- 8080:8080
volumes:
- - /stirling/latest/data:/usr/share/tesseract-ocr/5/tessdata:rw
+ - /stirling/latest/data:/usr/share/tessdata:rw
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
SECURITY_ENABLELOGIN: "true"
+ PUID: 1002
+ PGID: 1002
+ UMASK: "022"
SYSTEM_DEFAULTLOCALE: en-US
UI_APPNAME: Stirling-PDF
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest with Security
diff --git a/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml b/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml
index b7848696..c0dd09ce 100644
--- a/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml
+++ b/exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml
@@ -15,7 +15,7 @@ services:
ports:
- 8080:8080
volumes:
- - /stirling/latest/data:/usr/share/tesseract-ocr/5/tessdata:rw
+ - /stirling/latest/data:/usr/share/tessdata:rw
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:
diff --git a/exampleYmlFiles/docker-compose-latest.yml b/exampleYmlFiles/docker-compose-latest.yml
index d506e424..c2593332 100644
--- a/exampleYmlFiles/docker-compose-latest.yml
+++ b/exampleYmlFiles/docker-compose-latest.yml
@@ -15,12 +15,14 @@ services:
ports:
- 8080:8080
volumes:
- - /stirling/latest/data:/usr/share/tesseract-ocr/5/tessdata:rw
+ - /stirling/latest/data:/usr/share/tessdata:rw
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "false"
SECURITY_ENABLELOGIN: "false"
+ LANGS: "en_GB,en_US,ar_AR,de_DE,fr_FR,es_ES,zh_CN,zh_TW,ca_CA,it_IT,sv_SE,pl_PL,ro_RO,ko_KR,pt_BR,ru_RU,el_GR,hi_IN,hu_HU,tr_TR,id_ID"
+ INSTALL_BOOK_AND_ADVANCED_HTML_OPS: "true"
SYSTEM_DEFAULTLOCALE: en-US
UI_APPNAME: Stirling-PDF
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest
diff --git a/images/stirling-home.jpg b/images/stirling-home.jpg
new file mode 100644
index 00000000..0b28f6ee
Binary files /dev/null and b/images/stirling-home.jpg differ
diff --git a/images/stirling-home.png b/images/stirling-home.png
deleted file mode 100644
index c01af6f9..00000000
Binary files a/images/stirling-home.png and /dev/null differ
diff --git a/pipeline/defaultWebUIConfigs/split-rotate-auto-rename.json b/pipeline/defaultWebUIConfigs/split-rotate-auto-rename.json
index 3a989296..71a08e98 100644
--- a/pipeline/defaultWebUIConfigs/split-rotate-auto-rename.json
+++ b/pipeline/defaultWebUIConfigs/split-rotate-auto-rename.json
@@ -6,7 +6,8 @@
"parameters": {
"horizontalDivisions": 2,
"verticalDivisions": 2,
- "fileInput": "automated"
+ "fileInput": "automated",
+ "merge": false
}
},
{
@@ -30,4 +31,4 @@
},
"outputDir": "{outputFolder}",
"outputFileName": "{filename}"
-}
\ No newline at end of file
+}
diff --git a/scripts/counter_translation.py b/scripts/counter_translation.py
new file mode 100644
index 00000000..a4b6255b
--- /dev/null
+++ b/scripts/counter_translation.py
@@ -0,0 +1,192 @@
+"""A script to update language progress status in README.md based on
+properties file comparison.
+
+This script compares default properties file with others in a directory to
+determine language progress.
+It then updates README.md based on provided progress list.
+
+Author: Ludy87
+
+Example:
+ To use this script, simply run it from command line:
+ $ python counter_translation.py
+""" # noqa: D205
+
+import glob
+import os
+import re
+
+import tomlkit
+import tomlkit.toml_file
+
+
+def convert_to_multiline(data: tomlkit.TOMLDocument) -> tomlkit.TOMLDocument:
+ """Converts 'ignore' and 'missing' arrays to multiline arrays and sorts the first-level keys of the TOML document.
+ Enhances readability and consistency in the TOML file by ensuring arrays contain unique and sorted entries.
+
+ Parameters:
+ data (tomlkit.TOMLDocument): The original TOML document containing the data.
+
+ Returns:
+ tomlkit.TOMLDocument: A new TOML document with sorted keys and properly formatted arrays.
+ """ # noqa: D205
+ sorted_data = tomlkit.document()
+ for key in sorted(data.keys()):
+ value = data[key]
+ if isinstance(value, dict):
+ new_table = tomlkit.table()
+ for subkey in ("ignore", "missing"):
+ if subkey in value:
+ # Convert the list to a set to remove duplicates, sort it, and convert to multiline for readability
+ unique_sorted_array = sorted(set(value[subkey]))
+ array = tomlkit.array()
+ array.multiline(True)
+ for item in unique_sorted_array:
+ array.append(item)
+ new_table[subkey] = array
+ sorted_data[key] = new_table
+ else:
+ # Add other types of data unchanged
+ sorted_data[key] = value
+ return sorted_data
+
+
+def write_readme(progress_list: list[tuple[str, int]]) -> None:
+ """Updates the progress status in the README.md file based
+ on the provided progress list.
+
+ Parameters:
+ progress_list (list[tuple[str, int]]): A list of tuples containing
+ language and progress percentage.
+
+ Returns:
+ None
+ """ # noqa: D205
+ with open("README.md", encoding="utf-8") as file:
+ content = file.readlines()
+
+ for i, line in enumerate(content[2:], start=2):
+ for progress in progress_list:
+ language, value = progress
+ if language in line:
+ if match := re.search(r"\!\[(\d+(\.\d+)?)%\]\(.*\)", line):
+ content[i] = line.replace(
+ match.group(0),
+ f"![{value}%](https://geps.dev/progress/{value})",
+ )
+
+ with open("README.md", "w", encoding="utf-8") as file:
+ file.writelines(content)
+
+
+def compare_files(default_file_path, file_paths, translation_status_file) -> list[tuple[str, int]]:
+ """Compares the default properties file with other
+ properties files in the directory.
+
+ Parameters:
+ default_file_path (str): The path to the default properties file.
+ files_directory (str): The directory containing other properties files.
+
+ Returns:
+ list[tuple[str, int]]: A list of tuples containing
+ language and progress percentage.
+ """ # noqa: D205
+ num_lines = sum(
+ 1 for line in open(default_file_path, encoding="utf-8") if line.strip() and not line.strip().startswith("#")
+ )
+
+ result_list = []
+ sort_translation_status: tomlkit.TOMLDocument
+
+ # read toml
+ with open(translation_status_file, encoding="utf-8") as f:
+ sort_translation_status = tomlkit.parse(f.read())
+
+ for file_path in file_paths:
+ language = os.path.basename(file_path).split("messages_", 1)[1].split(".properties", 1)[0]
+
+ fails = 0
+ if "en_GB" in language or "en_US" in language:
+ result_list.append(("en_GB", 100))
+ result_list.append(("en_US", 100))
+ continue
+
+ if language not in sort_translation_status:
+ sort_translation_status[language] = tomlkit.table()
+
+ if (
+ "ignore" not in sort_translation_status[language]
+ or len(sort_translation_status[language].get("ignore", [])) < 1
+ ):
+ sort_translation_status[language]["ignore"] = tomlkit.array(["language.direction"])
+
+ # if "missing" not in sort_translation_status[language]:
+ # sort_translation_status[language]["missing"] = tomlkit.array()
+ # elif "language.direction" in sort_translation_status[language]["missing"]:
+ # sort_translation_status[language]["missing"].remove("language.direction")
+
+ with open(default_file_path, encoding="utf-8") as default_file, open(file_path, encoding="utf-8") as file:
+ for _ in range(5):
+ next(default_file)
+ try:
+ next(file)
+ except StopIteration:
+ fails = num_lines
+
+ for line_num, (line_default, line_file) in enumerate(zip(default_file, file), start=6):
+ try:
+ # Ignoring empty lines and lines start with #
+ if line_default.strip() == "" or line_default.startswith("#"):
+ continue
+
+ default_key, default_value = line_default.split("=", 1)
+ file_key, file_value = line_file.split("=", 1)
+ if (
+ default_value.strip() == file_value.strip()
+ and default_key.strip() not in sort_translation_status[language]["ignore"]
+ ):
+ print(f"{language}: Line {line_num} is missing the translation.")
+ # if default_key.strip() not in sort_translation_status[language]["missing"]:
+ # missing_array = tomlkit.array()
+ # missing_array.append(default_key.strip())
+ # missing_array.multiline(True)
+ # sort_translation_status[language]["missing"].extend(missing_array)
+ fails += 1
+ # elif default_key.strip() in sort_translation_status[language]["ignore"]:
+ # if default_key.strip() in sort_translation_status[language]["missing"]:
+ # sort_translation_status[language]["missing"].remove(default_key.strip())
+ if default_value.strip() != file_value.strip():
+ # if default_key.strip() in sort_translation_status[language]["missing"]:
+ # sort_translation_status[language]["missing"].remove(default_key.strip())
+ if default_key.strip() in sort_translation_status[language]["ignore"]:
+ sort_translation_status[language]["ignore"].remove(default_key.strip())
+
+ except IndexError:
+ pass
+
+ print(f"{language}: {fails} out of {num_lines} lines are not translated.")
+ result_list.append(
+ (
+ language,
+ int((num_lines - fails) * 100 / num_lines),
+ )
+ )
+ translation_status = convert_to_multiline(sort_translation_status)
+ with open(translation_status_file, "w", encoding="utf-8") as file:
+ file.write(tomlkit.dumps(translation_status))
+
+ unique_data = list(set(result_list))
+ unique_data.sort(key=lambda x: x[1], reverse=True)
+
+ return unique_data
+
+
+if __name__ == "__main__":
+ directory = os.path.join(os.getcwd(), "src", "main", "resources")
+ messages_file_paths = glob.glob(os.path.join(directory, "messages_*.properties"))
+ reference_file = os.path.join(directory, "messages_en_GB.properties")
+
+ scripts_directory = os.path.join(os.getcwd(), "scripts")
+ translation_state_file = os.path.join(scripts_directory, "translation_status.toml")
+
+ write_readme(compare_files(reference_file, messages_file_paths, translation_state_file))
diff --git a/scripts/detect-blank-pages.py b/scripts/detect-blank-pages.py
deleted file mode 100644
index 4ca724c2..00000000
--- a/scripts/detect-blank-pages.py
+++ /dev/null
@@ -1,37 +0,0 @@
-import cv2
-import sys
-import argparse
-import numpy as np
-
-def is_blank_image(image_path, threshold=10, white_percent=99, white_value=255, blur_size=5):
- image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
-
- if image is None:
- print(f"Error: Unable to read the image file: {image_path}")
- return False
-
- # Apply Gaussian blur to reduce noise
- blurred_image = cv2.GaussianBlur(image, (blur_size, blur_size), 0)
-
- _, thresholded_image = cv2.threshold(blurred_image, white_value - threshold, white_value, cv2.THRESH_BINARY)
-
- # Calculate the percentage of white pixels in the thresholded image
- white_pixels = np.sum(thresholded_image == white_value)
- white_pixel_percentage = (white_pixels / thresholded_image.size) * 100
-
- print(f"Page has white pixel percent of {white_pixel_percentage}")
- return white_pixel_percentage >= white_percent
-
-
-if __name__ == "__main__":
- parser = argparse.ArgumentParser(description='Detect if an image is considered blank or not.')
- parser.add_argument('image_path', help='The path to the image file.')
- parser.add_argument('-t', '--threshold', type=int, default=10, help='Threshold for determining white pixels. The default value is 10.')
- parser.add_argument('-w', '--white_percent', type=float, default=99, help='The percentage of white pixels for an image to be considered blank. The default value is 99.')
- args = parser.parse_args()
-
- blank = is_blank_image(args.image_path, args.threshold, args.white_percent)
-
- # Return code 1: The image is considered blank.
- # Return code 0: The image is not considered blank.
- sys.exit(int(blank))
diff --git a/scripts/download-security-jar.sh b/scripts/download-security-jar.sh
index e786ce6b..42ca2b5a 100644
--- a/scripts/download-security-jar.sh
+++ b/scripts/download-security-jar.sh
@@ -14,6 +14,8 @@ if [ "$DOCKER_ENABLE_SECURITY" = "true" ] && [ "$VERSION_TAG" != "alpha" ]; then
if [ $? -eq 0 ]; then # checks if curl was successful
rm -f app.jar
ln -s app-security.jar app.jar
+ chown stirlingpdfuser:stirlingpdfgroup app.jar || true
+ chmod 755 app.jar || true
fi
fi
fi
diff --git a/scripts/init-without-ocr.sh b/scripts/init-without-ocr.sh
index 2aced6a4..761dd08d 100644
--- a/scripts/init-without-ocr.sh
+++ b/scripts/init-without-ocr.sh
@@ -1,6 +1,34 @@
-#!/bin/sh
+#!/bin/bash
+
+# Update the user and group IDs as per environment variables
+if [ ! -z "$PUID" ] && [ "$PUID" != "$(id -u stirlingpdfuser)" ]; then
+ usermod -o -u "$PUID" stirlingpdfuser || true
+fi
+
+
+if [ ! -z "$PGID" ] && [ "$PGID" != "$(getent group stirlingpdfgroup | cut -d: -f3)" ]; then
+ groupmod -o -g "$PGID" stirlingpdfgroup || true
+fi
+umask "$UMASK" || true
+
+if [[ "$INSTALL_BOOK_AND_ADVANCED_HTML_OPS" == "true" ]]; then
+ apk add --no-cache calibre@testing
+fi
/scripts/download-security-jar.sh
-# Run the main command
-exec "$@"
\ No newline at end of file
+if [[ -n "$LANGS" ]]; then
+ /scripts/installFonts.sh $LANGS
+fi
+
+echo "Setting permissions and ownership for necessary directories..."
+# Attempt to change ownership of directories and files
+if chown -R stirlingpdfuser:stirlingpdfgroup $HOME /logs /scripts /usr/share/fonts/opentype/noto /configs /customFiles /pipeline /app.jar; then
+ chmod -R 755 /logs /scripts /usr/share/fonts/opentype/noto /configs /customFiles /pipeline /app.jar || true
+ # If chown succeeds, execute the command as stirlingpdfuser
+ exec su-exec stirlingpdfuser "$@"
+else
+ # If chown fails, execute the command without changing the user context
+ echo "[WARN] Chown failed, running as host user"
+ exec "$@"
+fi
diff --git a/scripts/init.sh b/scripts/init.sh
index ea8fd359..b0e2a095 100644
--- a/scripts/init.sh
+++ b/scripts/init.sh
@@ -17,14 +17,15 @@ fi
if [[ -n "$TESSERACT_LANGS" ]]; then
# Convert comma-separated values to a space-separated list
LANGS=$(echo $TESSERACT_LANGS | tr ',' ' ')
-
+ pattern='^[a-zA-Z]{2,4}(_[a-zA-Z]{2,4})?$'
# Install each language pack
for LANG in $LANGS; do
- apt-get install -y "tesseract-ocr-$LANG"
+ if [[ $LANG =~ $pattern ]]; then
+ apk add --no-cache "tesseract-ocr-data-$LANG"
+ else
+ echo "Skipping invalid language code"
+ fi
done
fi
-/scripts/download-security-jar.sh
-
-# Run the main command
-exec "$@"
+/scripts/init-without-ocr.sh "$@"
\ No newline at end of file
diff --git a/scripts/installFonts.sh b/scripts/installFonts.sh
new file mode 100644
index 00000000..d7eb7af6
--- /dev/null
+++ b/scripts/installFonts.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+
+LANGS=$1
+
+# Function to install a font package
+install_font() {
+ echo "Installing font package: $1"
+ if ! apk add "$1" --no-cache; then
+ echo "Failed to install $1"
+ fi
+}
+
+# Install common fonts used across many languages
+#common_fonts=(
+# font-terminus
+# font-dejavu
+# font-noto
+# font-noto-cjk
+# font-awesome
+# font-noto-extra
+#)
+#
+#for font in "${common_fonts[@]}"; do
+# install_font $font
+#done
+
+# Map languages to specific font packages
+declare -A language_fonts=(
+ ["ar_AR"]="font-noto-arabic"
+ ["zh_CN"]="font-isas-misc"
+ ["zh_TW"]="font-isas-misc"
+ ["ja_JP"]="font-noto font-noto-thai font-noto-tibetan font-ipa font-sony-misc font-jis-misc"
+ ["ru_RU"]="font-vollkorn font-misc-cyrillic font-mutt-misc font-screen-cyrillic font-winitzki-cyrillic font-cronyx-cyrillic"
+ ["sr_LATN_RS"]="font-vollkorn font-misc-cyrillic font-mutt-misc font-screen-cyrillic font-winitzki-cyrillic font-cronyx-cyrillic"
+ ["uk_UA"]="font-vollkorn font-misc-cyrillic font-mutt-misc font-screen-cyrillic font-winitzki-cyrillic font-cronyx-cyrillic"
+ ["ko_KR"]="font-noto font-noto-thai font-noto-tibetan"
+ ["el_GR"]="font-noto"
+ ["hi_IN"]="font-noto-devanagari"
+ ["bg_BG"]="font-vollkorn font-misc-cyrillic"
+ ["GENERAL"]="font-terminus font-dejavu font-noto font-noto-cjk font-awesome font-noto-extra"
+)
+
+# Install fonts for other languages which generally do not need special packages beyond 'font-noto'
+other_langs=("en_GB" "en_US" "de_DE" "fr_FR" "es_ES" "ca_CA" "it_IT" "pt_BR" "nl_NL" "sv_SE" "pl_PL" "ro_RO" "hu_HU" "tr_TR" "id_ID" "eu_ES")
+if [[ $LANGS == "ALL" ]]; then
+ # Install all fonts from the language_fonts map
+ for fonts in "${language_fonts[@]}"; do
+ for font in $fonts; do
+ install_font $font
+ done
+ done
+else
+ # Split comma-separated languages and install necessary fonts
+ IFS=',' read -ra LANG_CODES <<< "$LANGS"
+ for code in "${LANG_CODES[@]}"; do
+ if [[ " ${other_langs[@]} " =~ " ${code} " ]]; then
+ install_font font-noto
+ else
+ fonts_to_install=${language_fonts[$code]}
+ if [ ! -z "$fonts_to_install" ]; then
+ for font in $fonts_to_install; do
+ install_font $font
+ done
+ fi
+ fi
+ done
+fi
diff --git a/scripts/translation_status.toml b/scripts/translation_status.toml
new file mode 100644
index 00000000..335ef567
--- /dev/null
+++ b/scripts/translation_status.toml
@@ -0,0 +1,154 @@
+[ar_AR]
+ignore = [
+ 'language.direction',
+]
+
+[bg_BG]
+ignore = [
+ 'language.direction',
+]
+
+[ca_CA]
+ignore = [
+ 'language.direction',
+]
+
+[de_DE]
+ignore = [
+ 'AddStampRequest.alphabet',
+ 'AddStampRequest.position',
+ 'PDFToBook.selectText.1',
+ 'PDFToText.tags',
+ 'addPageNumbers.selectText.3',
+ 'alphabet',
+ 'certSign.name',
+ 'language.direction',
+ 'licenses.version',
+ 'pipeline.title',
+ 'pipelineOptions.pipelineHeader',
+ 'sponsor',
+ 'text',
+ 'watermark.type.1',
+]
+
+[el_GR]
+ignore = [
+ 'language.direction',
+]
+
+[es_ES]
+ignore = [
+ 'adminUserSettings.roles',
+ 'color',
+ 'language.direction',
+ 'no',
+ 'showJS.tags',
+]
+
+[eu_ES]
+ignore = [
+ 'language.direction',
+]
+
+[fr_FR]
+ignore = [
+ 'language.direction',
+]
+
+[hi_IN]
+ignore = [
+ 'language.direction',
+]
+
+[hu_HU]
+ignore = [
+ 'language.direction',
+]
+
+[id_ID]
+ignore = [
+ 'language.direction',
+]
+
+[it_IT]
+ignore = [
+ 'font',
+ 'language.direction',
+ 'no',
+ 'password',
+ 'pipeline.title',
+ 'pipelineOptions.pipelineHeader',
+ 'removePassword.selectText.2',
+ 'showJS.tags',
+ 'sponsor',
+]
+
+[ja_JP]
+ignore = [
+ 'language.direction',
+]
+
+[ko_KR]
+ignore = [
+ 'language.direction',
+]
+
+[nl_NL]
+ignore = [
+ 'language.direction',
+]
+
+[pl_PL]
+ignore = [
+ 'language.direction',
+]
+
+[pt_BR]
+ignore = [
+ 'language.direction',
+]
+
+[pt_PT]
+ignore = [
+ 'language.direction',
+]
+
+[ro_RO]
+ignore = [
+ 'language.direction',
+]
+
+[ru_RU]
+ignore = [
+ 'language.direction',
+]
+
+[sr_LATN_RS]
+ignore = [
+ 'language.direction',
+]
+
+[sv_SE]
+ignore = [
+ 'language.direction',
+]
+
+[tr_TR]
+ignore = [
+ 'language.direction',
+]
+
+[uk_UA]
+ignore = [
+ 'language.direction',
+]
+
+[zh_CN]
+ignore = [
+ 'language.direction',
+]
+
+[zh_TW]
+ignore = [
+ 'language.direction',
+]
diff --git a/src/main/java/stirling/software/SPDF/SPdfApplication.java b/src/main/java/stirling/software/SPDF/SPdfApplication.java
index 62cbfe10..fb682998 100644
--- a/src/main/java/stirling/software/SPDF/SPdfApplication.java
+++ b/src/main/java/stirling/software/SPDF/SPdfApplication.java
@@ -1,10 +1,17 @@
package stirling.software.SPDF;
+import java.io.IOException;
import java.nio.file.Files;
+import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;
@@ -14,14 +21,25 @@ import io.github.pixee.security.SystemCommand;
import jakarta.annotation.PostConstruct;
import stirling.software.SPDF.config.ConfigInitializer;
-import stirling.software.SPDF.utils.GeneralUtils;
+import stirling.software.SPDF.model.ApplicationProperties;
@SpringBootApplication
@EnableScheduling
public class SPdfApplication {
+ private static final Logger logger = LoggerFactory.getLogger(SPdfApplication.class);
+
@Autowired private Environment env;
+ @Autowired ApplicationProperties applicationProperties;
+
+ private static String serverPortStatic;
+
+ @Value("${server.port:8080}")
+ public void setServerPortStatic(String port) {
+ SPdfApplication.serverPortStatic = port;
+ }
+
@PostConstruct
public void init() {
// Check if the BROWSER_OPEN environment variable is set to true
@@ -30,7 +48,7 @@ public class SPdfApplication {
if (browserOpen) {
try {
- String url = "http://localhost:" + getPort();
+ String url = "http://localhost:" + getNonStaticPort();
String os = System.getProperty("os.name").toLowerCase();
Runtime rt = Runtime.getRuntime();
@@ -39,45 +57,75 @@ public class SPdfApplication {
SystemCommand.runCommand(rt, "rundll32 url.dll,FileProtocolHandler " + url);
}
} catch (Exception e) {
- e.printStackTrace();
+ logger.error("Error opening browser: {}", e.getMessage());
}
}
+ logger.info("Running configs {}", applicationProperties.toString());
}
- public static void main(String[] args) {
+ public static void main(String[] args) throws IOException, InterruptedException {
+
SpringApplication app = new SpringApplication(SPdfApplication.class);
app.addInitializers(new ConfigInitializer());
+ Map propertyFiles = new HashMap<>();
+
+ // stirling pdf settings file
if (Files.exists(Paths.get("configs/settings.yml"))) {
- app.setDefaultProperties(
- Collections.singletonMap(
- "spring.config.additional-location", "file:configs/settings.yml"));
+ propertyFiles.put("spring.config.additional-location", "file:configs/settings.yml");
} else {
- System.out.println(
+ logger.warn(
"External configuration file 'configs/settings.yml' does not exist. Using default configuration and environment configuration instead.");
}
+
+ // custom javs settings file
+ if (Files.exists(Paths.get("configs/custom_settings.yml"))) {
+ String existing = propertyFiles.getOrDefault("spring.config.additional-location", "");
+ if (!existing.isEmpty()) {
+ existing += ",";
+ }
+ propertyFiles.put(
+ "spring.config.additional-location",
+ existing + "file:configs/custom_settings.yml");
+ } else {
+ logger.warn("Custom configuration file 'configs/custom_settings.yml' does not exist.");
+ }
+
+ if (!propertyFiles.isEmpty()) {
+ app.setDefaultProperties(
+ Collections.singletonMap(
+ "spring.config.additional-location",
+ propertyFiles.get("spring.config.additional-location")));
+ }
+
app.run(args);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ Thread.currentThread().interrupt();
+ throw new RuntimeException("Thread interrupted while sleeping", e);
}
- GeneralUtils.createDir("customFiles/static/");
- GeneralUtils.createDir("customFiles/templates/");
-
- System.out.println("Stirling-PDF Started.");
-
- String url = "http://localhost:" + getPort();
- System.out.println("Navigate to " + url);
+ try {
+ Files.createDirectories(Path.of("customFiles/static/"));
+ Files.createDirectories(Path.of("customFiles/templates/"));
+ } catch (Exception e) {
+ logger.error("Error creating directories: {}", e.getMessage());
+ }
+ printStartupLogs();
}
- public static String getPort() {
- String port = System.getProperty("local.server.port");
- if (port == null || port.isEmpty()) {
- port = "8080";
- }
- return port;
+ private static void printStartupLogs() {
+ logger.info("Stirling-PDF Started.");
+ String url = "http://localhost:" + getStaticPort();
+ logger.info("Navigate to {}", url);
+ }
+
+ public static String getStaticPort() {
+ return serverPortStatic;
+ }
+
+ public String getNonStaticPort() {
+ return serverPortStatic;
}
}
diff --git a/src/main/java/stirling/software/SPDF/config/AppConfig.java b/src/main/java/stirling/software/SPDF/config/AppConfig.java
index 65e98b7f..16618e1e 100644
--- a/src/main/java/stirling/software/SPDF/config/AppConfig.java
+++ b/src/main/java/stirling/software/SPDF/config/AppConfig.java
@@ -6,18 +6,35 @@ import java.nio.file.Paths;
import java.util.Properties;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+import org.thymeleaf.spring6.SpringTemplateEngine;
import stirling.software.SPDF.model.ApplicationProperties;
@Configuration
+@Lazy
public class AppConfig {
@Autowired ApplicationProperties applicationProperties;
+ @Bean
+ @ConditionalOnProperty(
+ name = "system.customHTMLFiles",
+ havingValue = "true",
+ matchIfMissing = false)
+ public SpringTemplateEngine templateEngine(ResourceLoader resourceLoader) {
+ SpringTemplateEngine templateEngine = new SpringTemplateEngine();
+ templateEngine.addTemplateResolver(new FileFallbackTemplateResolver(resourceLoader));
+ return templateEngine;
+ }
+
@Bean(name = "loginEnabled")
public boolean loginEnabled() {
return applicationProperties.getSecurity().getEnableLogin();
@@ -79,9 +96,16 @@ public class AppConfig {
@Bean(name = "bookAndHtmlFormatsInstalled")
public boolean bookAndHtmlFormatsInstalled() {
- return applicationProperties
- .getSystem()
- .getCustomApplications()
- .isInstallBookAndHtmlFormats();
+ String installOps = System.getProperty("INSTALL_BOOK_AND_ADVANCED_HTML_OPS");
+ if (installOps == null) {
+ installOps = System.getenv("INSTALL_BOOK_AND_ADVANCED_HTML_OPS");
+ }
+ return "true".equalsIgnoreCase(installOps);
+ }
+
+ @ConditionalOnMissingClass("stirling.software.SPDF.config.security.SecurityConfiguration")
+ @Bean(name = "activSecurity")
+ public boolean missingActivSecurity() {
+ return false;
}
}
diff --git a/src/main/java/stirling/software/SPDF/config/AppUpdateService.java b/src/main/java/stirling/software/SPDF/config/AppUpdateService.java
new file mode 100644
index 00000000..7c7a9a49
--- /dev/null
+++ b/src/main/java/stirling/software/SPDF/config/AppUpdateService.java
@@ -0,0 +1,25 @@
+package stirling.software.SPDF.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Service;
+
+import stirling.software.SPDF.model.ApplicationProperties;
+
+@Service
+class AppUpdateService {
+
+ @Autowired private ApplicationProperties applicationProperties;
+
+ @Autowired(required = false)
+ ShowAdminInterface showAdmin;
+
+ @Bean(name = "shouldShow")
+ @Scope("request")
+ public boolean shouldShow() {
+ boolean showUpdate = applicationProperties.getSystem().getShowUpdate();
+ boolean showAdminResult = (showAdmin != null) ? showAdmin.getShowUpdateOnlyAdmins() : true;
+ return showUpdate && showAdminResult;
+ }
+}
diff --git a/src/main/java/stirling/software/SPDF/config/ConfigInitializer.java b/src/main/java/stirling/software/SPDF/config/ConfigInitializer.java
index a5d05999..394baeb1 100644
--- a/src/main/java/stirling/software/SPDF/config/ConfigInitializer.java
+++ b/src/main/java/stirling/software/SPDF/config/ConfigInitializer.java
@@ -1,20 +1,18 @@
package stirling.software.SPDF.config;
-import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
+import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
-import java.util.Optional;
+import java.util.Map;
import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Collectors;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
@@ -26,12 +24,12 @@ public class ConfigInitializer
public void initialize(ConfigurableApplicationContext applicationContext) {
try {
ensureConfigExists();
- } catch (IOException e) {
+ } catch (Exception e) {
throw new RuntimeException("Failed to initialize application configuration", e);
}
}
- public void ensureConfigExists() throws IOException {
+ public void ensureConfigExists() throws IOException, URISyntaxException {
// Define the path to the external config directory
Path destPath = Paths.get("configs", "settings.yml");
@@ -51,93 +49,154 @@ public class ConfigInitializer
}
}
} else {
- // If user file exists, we need to merge it with the template from the classpath
- List templateLines;
- try (InputStream in =
- getClass().getClassLoader().getResourceAsStream("settings.yml.template")) {
- templateLines =
- new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))
- .lines()
- .collect(Collectors.toList());
- }
+ Path templatePath =
+ Paths.get(
+ getClass()
+ .getClassLoader()
+ .getResource("settings.yml.template")
+ .toURI());
+ Path userPath = Paths.get("configs", "settings.yml");
- mergeYamlFiles(templateLines, destPath, destPath);
+ List templateLines = Files.readAllLines(templatePath);
+ List userLines =
+ Files.exists(userPath) ? Files.readAllLines(userPath) : new ArrayList<>();
+
+ Map templateEntries = extractEntries(templateLines);
+ Map userEntries = extractEntries(userLines);
+
+ List mergedLines = mergeConfigs(templateLines, templateEntries, userEntries);
+ mergedLines = cleanInvalidYamlEntries(mergedLines);
+ Files.write(userPath, mergedLines);
+ }
+
+ Path customSettingsPath = Paths.get("configs", "custom_settings.yml");
+ if (!Files.exists(customSettingsPath)) {
+ Files.createFile(customSettingsPath);
}
}
- public void mergeYamlFiles(List templateLines, Path userFilePath, Path outputPath)
- throws IOException {
- List userLines = Files.readAllLines(userFilePath);
+ private static Map extractEntries(List lines) {
+ Map entries = new HashMap<>();
+ StringBuilder currentEntry = new StringBuilder();
+ String currentKey = null;
+ int blockIndent = -1;
+
+ for (String line : lines) {
+ if (line.trim().isEmpty()) {
+ if (currentKey != null) {
+ currentEntry.append(line).append("\n");
+ }
+ continue;
+ }
+
+ int indentLevel = getIndentationLevel(line);
+ if (line.trim().startsWith("#")) {
+ if (indentLevel <= blockIndent || blockIndent == -1) {
+ if (currentKey != null) {
+ entries.put(currentKey, currentEntry.toString().trim());
+ currentEntry = new StringBuilder();
+ }
+ currentKey = line.trim().replaceAll("#", "").split(":")[0].trim();
+ blockIndent = indentLevel;
+ }
+ currentEntry.append(line).append("\n");
+ } else if (indentLevel == 0 || indentLevel <= blockIndent) {
+ if (currentKey != null) {
+ entries.put(currentKey, currentEntry.toString().trim());
+ currentEntry = new StringBuilder();
+ }
+ currentKey = line.split(":")[0].trim();
+ blockIndent = indentLevel;
+ currentEntry.append(line).append("\n");
+ } else {
+ currentEntry.append(line).append("\n");
+ }
+ }
+
+ if (currentKey != null) {
+ entries.put(currentKey, currentEntry.toString().trim());
+ }
+
+ return entries;
+ }
+
+ private static List mergeConfigs(
+ List templateLines,
+ Map templateEntries,
+ Map userEntries) {
List mergedLines = new ArrayList<>();
- boolean insideAutoGenerated = false;
- boolean beforeFirstKey = true;
+ Set handledKeys = new HashSet<>();
- Function isCommented = line -> line.trim().startsWith("#");
- Function extractKey =
- line -> {
- String[] parts = line.split(":");
- return parts.length > 0 ? parts[0].trim().replace("#", "").trim() : "";
- };
-
- Set userKeys = userLines.stream().map(extractKey).collect(Collectors.toSet());
+ String currentBlockKey = null;
+ int blockIndent = -1;
for (String line : templateLines) {
- String key = extractKey.apply(line);
-
- if ("AutomaticallyGenerated:".equalsIgnoreCase(line.trim())) {
- insideAutoGenerated = true;
- mergedLines.add(line);
- continue;
- } else if (insideAutoGenerated && line.trim().isEmpty()) {
- insideAutoGenerated = false;
+ if (line.trim().isEmpty()) {
mergedLines.add(line);
continue;
}
- if (beforeFirstKey && (isCommented.apply(line) || line.trim().isEmpty())) {
- // Handle top comments and empty lines before the first key.
+ int indentLevel = getIndentationLevel(line);
+ if (indentLevel == 0 || (indentLevel <= blockIndent && !line.trim().startsWith("#"))) {
+ currentBlockKey = line.split(":")[0].trim();
+ blockIndent = indentLevel;
+ }
+
+ if (userEntries.containsKey(currentBlockKey)
+ && !handledKeys.contains(currentBlockKey)) {
+ mergedLines.add(userEntries.get(currentBlockKey));
+ handledKeys.add(currentBlockKey);
+ } else if (!handledKeys.contains(currentBlockKey)) {
mergedLines.add(line);
- continue;
- }
-
- if (!key.isEmpty()) beforeFirstKey = false;
-
- if (userKeys.contains(key)) {
- // If user has any version (commented or uncommented) of this key, skip the
- // template line
- Optional userValue =
- userLines.stream()
- .filter(
- l ->
- extractKey.apply(l).equalsIgnoreCase(key)
- && !isCommented.apply(l))
- .findFirst();
- if (userValue.isPresent()) mergedLines.add(userValue.get());
- continue;
- }
-
- if (isCommented.apply(line) || line.trim().isEmpty() || !userKeys.contains(key)) {
- mergedLines.add(
- line); // If line is commented, empty or key not present in user's file,
- // retain the
- // template line
- continue;
}
}
- // Add any additional uncommented user lines that are not present in the
- // template
- for (String userLine : userLines) {
- String userKey = extractKey.apply(userLine);
- boolean isPresentInTemplate =
- templateLines.stream()
- .map(extractKey)
- .anyMatch(templateKey -> templateKey.equalsIgnoreCase(userKey));
- if (!isPresentInTemplate && !isCommented.apply(userLine)) {
- mergedLines.add(userLine);
+ return mergedLines;
+ }
+
+ private static List cleanInvalidYamlEntries(List lines) {
+ List cleanedLines = new ArrayList<>();
+ for (int i = 0; i < lines.size(); i++) {
+ String line = lines.get(i);
+ String trimmedLine = line.trim();
+
+ if (trimmedLine.startsWith("#")
+ || !trimmedLine.endsWith(":")
+ || trimmedLine.contains(" ")) {
+ cleanedLines.add(line);
+ continue;
}
+
+ if (isKeyWithoutChildrenOrValue(i, lines)) {
+ continue;
+ }
+
+ cleanedLines.add(line);
+ }
+ return cleanedLines;
+ }
+
+ private static boolean isKeyWithoutChildrenOrValue(int currentIndex, List lines) {
+ if (currentIndex + 1 < lines.size()) {
+ String currentLine = lines.get(currentIndex);
+ String nextLine = lines.get(currentIndex + 1);
+ int currentIndentation = getIndentationLevel(currentLine);
+ int nextIndentation = getIndentationLevel(nextLine);
+
+ // If the next line is less or equally indented, it's not a child or value
+ return nextIndentation <= currentIndentation;
}
- Files.write(outputPath, mergedLines, StandardCharsets.UTF_8);
+ // If it's the last line, then it definitely has no children or value
+ return true;
+ }
+
+ private static int getIndentationLevel(String line) {
+ int count = 0;
+ for (char ch : line.toCharArray()) {
+ if (ch == ' ') count++;
+ else break;
+ }
+ return count;
}
}
diff --git a/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java b/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java
index f82c189f..b145b478 100644
--- a/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java
+++ b/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java
@@ -129,7 +129,7 @@ public class EndpointConfiguration {
addEndpointToGroup("Other", "sign");
addEndpointToGroup("Other", "flatten");
addEndpointToGroup("Other", "repair");
- addEndpointToGroup("Other", "remove-blanks");
+ addEndpointToGroup("Other", REMOVE_BLANKS);
addEndpointToGroup("Other", "remove-annotations");
addEndpointToGroup("Other", "compare");
addEndpointToGroup("Other", "add-page-numbers");
@@ -140,14 +140,12 @@ public class EndpointConfiguration {
// CLI
addEndpointToGroup("CLI", "compress-pdf");
addEndpointToGroup("CLI", "extract-image-scans");
- addEndpointToGroup("CLI", "remove-blanks");
addEndpointToGroup("CLI", "repair");
addEndpointToGroup("CLI", "pdf-to-pdfa");
addEndpointToGroup("CLI", "file-to-pdf");
addEndpointToGroup("CLI", "xlsx-to-pdf");
addEndpointToGroup("CLI", "pdf-to-word");
addEndpointToGroup("CLI", "pdf-to-presentation");
- addEndpointToGroup("CLI", "pdf-to-text");
addEndpointToGroup("CLI", "pdf-to-html");
addEndpointToGroup("CLI", "pdf-to-xml");
addEndpointToGroup("CLI", "ocr-pdf");
@@ -155,6 +153,7 @@ public class EndpointConfiguration {
addEndpointToGroup("CLI", "url-to-pdf");
addEndpointToGroup("CLI", "book-to-pdf");
addEndpointToGroup("CLI", "pdf-to-book");
+ addEndpointToGroup("CLI", "pdf-to-rtf");
// Calibre
addEndpointToGroup("Calibre", "book-to-pdf");
@@ -162,13 +161,13 @@ public class EndpointConfiguration {
// python
addEndpointToGroup("Python", "extract-image-scans");
- addEndpointToGroup("Python", "remove-blanks");
+ addEndpointToGroup("Python", REMOVE_BLANKS);
addEndpointToGroup("Python", "html-to-pdf");
addEndpointToGroup("Python", "url-to-pdf");
// openCV
addEndpointToGroup("OpenCV", "extract-image-scans");
- addEndpointToGroup("OpenCV", "remove-blanks");
+ addEndpointToGroup("OpenCV", REMOVE_BLANKS);
// LibreOffice
addEndpointToGroup("LibreOffice", "repair");
@@ -176,7 +175,7 @@ public class EndpointConfiguration {
addEndpointToGroup("LibreOffice", "xlsx-to-pdf");
addEndpointToGroup("LibreOffice", "pdf-to-word");
addEndpointToGroup("LibreOffice", "pdf-to-presentation");
- addEndpointToGroup("LibreOffice", "pdf-to-text");
+ addEndpointToGroup("LibreOffice", "pdf-to-rtf");
addEndpointToGroup("LibreOffice", "pdf-to-html");
addEndpointToGroup("LibreOffice", "pdf-to-xml");
@@ -218,6 +217,8 @@ public class EndpointConfiguration {
addEndpointToGroup("Java", "split-by-size-or-count");
addEndpointToGroup("Java", "overlay-pdf");
addEndpointToGroup("Java", "split-pdf-by-sections");
+ addEndpointToGroup("Java", REMOVE_BLANKS);
+ addEndpointToGroup("Java", "pdf-to-text");
// Javascript
addEndpointToGroup("Javascript", "pdf-organizer");
@@ -244,4 +245,6 @@ public class EndpointConfiguration {
}
}
}
+
+ private static final String REMOVE_BLANKS = "remove-blanks";
}
diff --git a/src/main/java/stirling/software/SPDF/config/FileFallbackTemplateResolver.java b/src/main/java/stirling/software/SPDF/config/FileFallbackTemplateResolver.java
new file mode 100644
index 00000000..be6e28a7
--- /dev/null
+++ b/src/main/java/stirling/software/SPDF/config/FileFallbackTemplateResolver.java
@@ -0,0 +1,48 @@
+package stirling.software.SPDF.config;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+import org.thymeleaf.IEngineConfiguration;
+import org.thymeleaf.templateresolver.AbstractConfigurableTemplateResolver;
+import org.thymeleaf.templateresource.ClassLoaderTemplateResource;
+import org.thymeleaf.templateresource.FileTemplateResource;
+import org.thymeleaf.templateresource.ITemplateResource;
+
+public class FileFallbackTemplateResolver extends AbstractConfigurableTemplateResolver {
+
+ private final ResourceLoader resourceLoader;
+
+ public FileFallbackTemplateResolver(ResourceLoader resourceLoader) {
+ super();
+ this.resourceLoader = resourceLoader;
+ setSuffix(".html");
+ }
+
+ // Note this does not work in local IDE, Prod jar only.
+ @Override
+ protected ITemplateResource computeTemplateResource(
+ IEngineConfiguration configuration,
+ String ownerTemplate,
+ String template,
+ String resourceName,
+ String characterEncoding,
+ Map templateResolutionAttributes) {
+ Resource resource =
+ resourceLoader.getResource("file:./customFiles/templates/" + resourceName);
+ try {
+ if (resource.exists() && resource.isReadable()) {
+ return new FileTemplateResource(resource.getFile().getPath(), characterEncoding);
+ }
+ } catch (IOException e) {
+
+ }
+
+ return new ClassLoaderTemplateResource(
+ Thread.currentThread().getContextClassLoader(),
+ "classpath:/templates/" + resourceName,
+ characterEncoding);
+ }
+}
diff --git a/src/main/java/stirling/software/SPDF/config/PostStartupProcesses.java b/src/main/java/stirling/software/SPDF/config/PostStartupProcesses.java
deleted file mode 100644
index 2041cf95..00000000
--- a/src/main/java/stirling/software/SPDF/config/PostStartupProcesses.java
+++ /dev/null
@@ -1,69 +0,0 @@
-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("bookAndHtmlFormatsInstalled")
- private boolean bookAndHtmlFormatsInstalled;
-
- private static final Logger logger = LoggerFactory.getLogger(PostStartupProcesses.class);
-
- @PostConstruct
- public void runInstallCommandBasedOnEnvironment() throws IOException, InterruptedException {
- List> commands = new ArrayList<>();
- // Checking for DOCKER_INSTALL_BOOK_FORMATS environment variable
- if (bookAndHtmlFormatsInstalled) {
- List tmpList = new ArrayList<>();
-
- tmpList = new ArrayList<>();
- tmpList.addAll(Arrays.asList("apk add --no-cache calibre"));
- commands.add(tmpList);
- }
-
- if (!commands.isEmpty()) {
- // Run the command
- if (runningInDocker) {
- List tmpList = new ArrayList<>();
-
- for (List 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.");
- }
- }
- }
-}
diff --git a/src/main/java/stirling/software/SPDF/config/ShowAdminInterface.java b/src/main/java/stirling/software/SPDF/config/ShowAdminInterface.java
new file mode 100644
index 00000000..e49376e2
--- /dev/null
+++ b/src/main/java/stirling/software/SPDF/config/ShowAdminInterface.java
@@ -0,0 +1,7 @@
+package stirling.software.SPDF.config;
+
+public interface ShowAdminInterface {
+ default boolean getShowUpdateOnlyAdmins() {
+ return true;
+ }
+}
diff --git a/src/main/java/stirling/software/SPDF/config/security/AppUpdateAuthService.java b/src/main/java/stirling/software/SPDF/config/security/AppUpdateAuthService.java
new file mode 100644
index 00000000..0da07c61
--- /dev/null
+++ b/src/main/java/stirling/software/SPDF/config/security/AppUpdateAuthService.java
@@ -0,0 +1,46 @@
+package stirling.software.SPDF.config.security;
+
+import java.util.Optional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Service;
+
+import stirling.software.SPDF.config.ShowAdminInterface;
+import stirling.software.SPDF.model.ApplicationProperties;
+import stirling.software.SPDF.model.User;
+import stirling.software.SPDF.repository.UserRepository;
+
+@Service
+class AppUpdateAuthService implements ShowAdminInterface {
+
+ @Autowired private UserRepository userRepository;
+ @Autowired private ApplicationProperties applicationProperties;
+
+ public boolean getShowUpdateOnlyAdmins() {
+ boolean showUpdate = applicationProperties.getSystem().getShowUpdate();
+ if (!showUpdate) {
+ return showUpdate;
+ }
+
+ boolean showUpdateOnlyAdmin = applicationProperties.getSystem().getShowUpdateOnlyAdmin();
+
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+
+ if (authentication == null || !authentication.isAuthenticated()) {
+ return !showUpdateOnlyAdmin;
+ }
+
+ if (authentication.getName().equalsIgnoreCase("anonymousUser")) {
+ return !showUpdateOnlyAdmin;
+ }
+
+ Optional user = userRepository.findByUsername(authentication.getName());
+ if (user.isPresent() && showUpdateOnlyAdmin) {
+ return "ROLE_ADMIN".equals(user.get().getRolesAsString());
+ }
+
+ return showUpdate;
+ }
+}
diff --git a/src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationFailureHandler.java b/src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationFailureHandler.java
index cbdf7d26..f4f5a37d 100644
--- a/src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationFailureHandler.java
+++ b/src/main/java/stirling/software/SPDF/config/security/CustomAuthenticationFailureHandler.java
@@ -1,6 +1,7 @@
package stirling.software.SPDF.config.security;
import java.io.IOException;
+import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
@@ -12,15 +13,19 @@ import org.springframework.stereotype.Component;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
+import stirling.software.SPDF.model.User;
@Component
public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
@Autowired private final LoginAttemptService loginAttemptService;
- @Autowired
- public CustomAuthenticationFailureHandler(LoginAttemptService loginAttemptService) {
+ @Autowired private final UserService userService; // Inject the UserService
+
+ public CustomAuthenticationFailureHandler(
+ LoginAttemptService loginAttemptService, UserService userService) {
this.loginAttemptService = loginAttemptService;
+ this.userService = userService;
}
@Override
@@ -33,17 +38,27 @@ public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationF
logger.error("Failed login attempt from IP: " + ip);
String username = request.getParameter("username");
- if (loginAttemptService.loginAttemptCheck(username)) {
- setDefaultFailureUrl("/login?error=locked");
-
- } else {
- if (exception.getClass().isAssignableFrom(BadCredentialsException.class)) {
- setDefaultFailureUrl("/login?error=badcredentials");
- } else if (exception.getClass().isAssignableFrom(LockedException.class)) {
+ if (!isDemoUser(username)) {
+ if (loginAttemptService.loginAttemptCheck(username)) {
setDefaultFailureUrl("/login?error=locked");
+
+ } else {
+ if (exception.getClass().isAssignableFrom(LockedException.class)) {
+ setDefaultFailureUrl("/login?error=locked");
+ }
}
}
+ if (exception.getClass().isAssignableFrom(BadCredentialsException.class)) {
+ setDefaultFailureUrl("/login?error=badcredentials");
+ }
super.onAuthenticationFailure(request, response, exception);
}
+
+ private boolean isDemoUser(String username) {
+ Optional user = userService.findByUsernameIgnoreCase(username);
+ return user.isPresent()
+ && user.get().getAuthorities().stream()
+ .anyMatch(authority -> "ROLE_DEMO_USER".equals(authority.getAuthority()));
+ }
}
diff --git a/src/main/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandler.java b/src/main/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandler.java
new file mode 100644
index 00000000..300eee00
--- /dev/null
+++ b/src/main/java/stirling/software/SPDF/config/security/CustomLogoutSuccessHandler.java
@@ -0,0 +1,39 @@
+package stirling.software.SPDF.config.security;
+
+import java.io.IOException;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.session.SessionRegistry;
+import org.springframework.security.core.session.SessionRegistryImpl;
+import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
+
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
+
+public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
+ @Bean
+ public SessionRegistry sessionRegistry() {
+ return new SessionRegistryImpl();
+ }
+
+ @Override
+ public void onLogoutSuccess(
+ HttpServletRequest request, HttpServletResponse response, Authentication authentication)
+ throws IOException, ServletException {
+ HttpSession session = request.getSession(false);
+ if (session != null) {
+ String sessionId = session.getId();
+ sessionRegistry().removeSessionInformation(sessionId);
+ }
+
+ if (request.getParameter("oauth2AutoCreateDisabled") != null) {
+ response.sendRedirect(
+ request.getContextPath() + "/login?error=oauth2AutoCreateDisabled");
+ } else {
+ response.sendRedirect(request.getContextPath() + "/login?logout=true");
+ }
+ }
+}
diff --git a/src/main/java/stirling/software/SPDF/config/security/FirstLoginFilter.java b/src/main/java/stirling/software/SPDF/config/security/FirstLoginFilter.java
index b272327a..5936ea3f 100644
--- a/src/main/java/stirling/software/SPDF/config/security/FirstLoginFilter.java
+++ b/src/main/java/stirling/software/SPDF/config/security/FirstLoginFilter.java
@@ -39,7 +39,7 @@ public class FirstLoginFilter extends OncePerRequestFilter {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.isAuthenticated()) {
- Optional user = userService.findByUsername(authentication.getName());
+ Optional user = userService.findByUsernameIgnoreCase(authentication.getName());
if ("GET".equalsIgnoreCase(method)
&& user.isPresent()
&& user.get().isFirstLogin()
diff --git a/src/main/java/stirling/software/SPDF/config/security/InitialSecuritySetup.java b/src/main/java/stirling/software/SPDF/config/security/InitialSecuritySetup.java
index 3b396b15..b483ba10 100644
--- a/src/main/java/stirling/software/SPDF/config/security/InitialSecuritySetup.java
+++ b/src/main/java/stirling/software/SPDF/config/security/InitialSecuritySetup.java
@@ -38,7 +38,7 @@ public class InitialSecuritySetup {
initialUsername, initialPassword, Role.ADMIN.getRoleId(), true);
}
}
- if (!userService.usernameExists(Role.INTERNAL_API_USER.getRoleId())) {
+ if (!userService.usernameExistsIgnoreCase(Role.INTERNAL_API_USER.getRoleId())) {
userService.saveUser(
Role.INTERNAL_API_USER.getRoleId(),
UUID.randomUUID().toString(),
@@ -50,7 +50,7 @@ public class InitialSecuritySetup {
@PostConstruct
public void initSecretKey() throws IOException {
String secretKey = applicationProperties.getAutomaticallyGenerated().getKey();
- if (secretKey == null || secretKey.isEmpty()) {
+ if (!isValidUUID(secretKey)) {
secretKey = UUID.randomUUID().toString(); // Generating a random UUID as the secret key
saveKeyToConfig(secretKey);
}
@@ -85,4 +85,16 @@ public class InitialSecuritySetup {
// Write back to the file
Files.write(path, lines);
}
+
+ private boolean isValidUUID(String uuid) {
+ if (uuid == null) {
+ return false;
+ }
+ try {
+ UUID.fromString(uuid);
+ return true;
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ }
}
diff --git a/src/main/java/stirling/software/SPDF/config/security/SecurityConfiguration.java b/src/main/java/stirling/software/SPDF/config/security/SecurityConfiguration.java
index ca88dcb9..8eb80cdc 100644
--- a/src/main/java/stirling/software/SPDF/config/security/SecurityConfiguration.java
+++ b/src/main/java/stirling/software/SPDF/config/security/SecurityConfiguration.java
@@ -1,7 +1,11 @@
package stirling.software.SPDF.config.security;
+import java.io.IOException;
+import java.util.*;
+
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
@@ -9,15 +13,35 @@ import org.springframework.security.authentication.dao.DaoAuthenticationProvider
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
+import org.springframework.security.core.session.SessionRegistry;
+import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.oauth2.client.registration.ClientRegistration;
+import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
+import org.springframework.security.oauth2.client.registration.ClientRegistrations;
+import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
+import org.springframework.security.oauth2.core.user.OAuth2User;
+import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.savedrequest.NullRequestCache;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
+import stirling.software.SPDF.model.ApplicationProperties;
+import stirling.software.SPDF.model.User;
import stirling.software.SPDF.repository.JPATokenRepositoryImpl;
@Configuration
@@ -38,12 +62,19 @@ public class SecurityConfiguration {
@Qualifier("loginEnabled")
public boolean loginEnabledValue;
+ @Autowired ApplicationProperties applicationProperties;
+
@Autowired private UserAuthenticationFilter userAuthenticationFilter;
@Autowired private LoginAttemptService loginAttemptService;
@Autowired private FirstLoginFilter firstLoginFilter;
+ @Bean
+ public SessionRegistry sessionRegistry() {
+ return new SessionRegistryImpl();
+ }
+
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.addFilterBefore(userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
@@ -53,6 +84,15 @@ public class SecurityConfiguration {
http.csrf(csrf -> csrf.disable());
http.addFilterBefore(rateLimitingFilter(), UsernamePasswordAuthenticationFilter.class);
http.addFilterAfter(firstLoginFilter, UsernamePasswordAuthenticationFilter.class);
+ http.sessionManagement(
+ sessionManagement ->
+ sessionManagement
+ .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
+ .maximumSessions(10)
+ .maxSessionsPreventsLogin(false)
+ .sessionRegistry(sessionRegistry())
+ .expiredUrl("/login?logout=true"));
+
http.formLogin(
formLogin ->
formLogin
@@ -62,16 +102,27 @@ public class SecurityConfiguration {
.defaultSuccessUrl("/")
.failureHandler(
new CustomAuthenticationFailureHandler(
- loginAttemptService))
+ loginAttemptService, userService))
.permitAll())
.requestCache(requestCache -> requestCache.requestCache(new NullRequestCache()))
.logout(
logout ->
logout.logoutRequestMatcher(
new AntPathRequestMatcher("/logout"))
- .logoutSuccessUrl("/login?logout=true")
+ .logoutSuccessHandler(new CustomLogoutSuccessHandler())
.invalidateHttpSession(true) // Invalidate session
- .deleteCookies("JSESSIONID", "remember-me"))
+ .deleteCookies("JSESSIONID", "remember-me")
+ .addLogoutHandler(
+ (request, response, authentication) -> {
+ HttpSession session =
+ request.getSession(false);
+ if (session != null) {
+ String sessionId = session.getId();
+ sessionRegistry()
+ .removeSessionInformation(
+ sessionId);
+ }
+ }))
.rememberMe(
rememberMeConfigurer ->
rememberMeConfigurer // Use the configurator directly
@@ -95,6 +146,7 @@ public class SecurityConfiguration {
: uri;
return trimmedUri.startsWith("/login")
+ || trimmedUri.startsWith("/oauth")
|| trimmedUri.endsWith(".svg")
|| trimmedUri.startsWith(
"/register")
@@ -111,6 +163,49 @@ public class SecurityConfiguration {
.authenticated())
.userDetailsService(userDetailsService)
.authenticationProvider(authenticationProvider());
+
+ // Handle OAUTH2 Logins
+ if (applicationProperties.getSecurity().getOAUTH2().getEnabled()) {
+
+ http.oauth2Login(
+ oauth2 ->
+ oauth2.loginPage("/oauth2")
+ /*
+ This Custom handler is used to check if the OAUTH2 user trying to log in, already exists in the database.
+ If user exists, login proceeds as usual. If user does not exist, then it is autocreated but only if 'OAUTH2AutoCreateUser'
+ is set as true, else login fails with an error message advising the same.
+ */
+ .successHandler(
+ new AuthenticationSuccessHandler() {
+ @Override
+ public void onAuthenticationSuccess(
+ HttpServletRequest request,
+ HttpServletResponse response,
+ Authentication authentication)
+ throws ServletException, IOException {
+ OAuth2User oauthUser =
+ (OAuth2User)
+ authentication
+ .getPrincipal();
+ if (userService.processOAuth2PostLogin(
+ oauthUser.getAttribute("email"),
+ applicationProperties
+ .getSecurity()
+ .getOAUTH2()
+ .getAutoCreateUser())) {
+ response.sendRedirect("/");
+ } else {
+ response.sendRedirect(
+ "/logout?oauth2AutoCreateDisabled=true");
+ }
+ }
+ })
+ // Add existing Authorities from the database
+ .userInfoEndpoint(
+ userInfoEndpoint ->
+ userInfoEndpoint.userAuthoritiesMapper(
+ userAuthoritiesMapper())));
+ }
} else {
http.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(authz -> authz.anyRequest().permitAll());
@@ -119,6 +214,65 @@ public class SecurityConfiguration {
return http.build();
}
+ // Client Registration Repository for OAUTH2 OIDC Login
+ @Bean
+ @ConditionalOnProperty(
+ value = "security.oauth2.enabled",
+ havingValue = "true",
+ matchIfMissing = false)
+ public ClientRegistrationRepository clientRegistrationRepository() {
+ return new InMemoryClientRegistrationRepository(this.oidcClientRegistration());
+ }
+
+ private ClientRegistration oidcClientRegistration() {
+ return ClientRegistrations.fromOidcIssuerLocation(
+ applicationProperties.getSecurity().getOAUTH2().getIssuer())
+ .registrationId("oidc")
+ .clientId(applicationProperties.getSecurity().getOAUTH2().getClientId())
+ .clientSecret(applicationProperties.getSecurity().getOAUTH2().getClientSecret())
+ .scope("openid", "profile", "email")
+ .userNameAttributeName("email")
+ .clientName("OIDC")
+ .build();
+ }
+
+ /*
+ This following function is to grant Authorities to the OAUTH2 user from the values stored in the database.
+ This is required for the internal; 'hasRole()' function to give out the correct role.
+ */
+ @Bean
+ @ConditionalOnProperty(
+ value = "security.oauth2.enabled",
+ havingValue = "true",
+ matchIfMissing = false)
+ GrantedAuthoritiesMapper userAuthoritiesMapper() {
+ return (authorities) -> {
+ Set mappedAuthorities = new HashSet<>();
+
+ authorities.forEach(
+ authority -> {
+ // Add existing OAUTH2 Authorities
+ mappedAuthorities.add(new SimpleGrantedAuthority(authority.getAuthority()));
+
+ // Add Authorities from database for existing user, if user is present.
+ if (authority instanceof OAuth2UserAuthority oauth2Auth) {
+ Optional userOpt =
+ userService.findByUsernameIgnoreCase(
+ (String) oauth2Auth.getAttributes().get("email"));
+ if (userOpt.isPresent()) {
+ User user = userOpt.get();
+ if (user != null) {
+ mappedAuthorities.add(
+ new SimpleGrantedAuthority(
+ userService.findRole(user).getAuthority()));
+ }
+ }
+ }
+ });
+ return mappedAuthorities;
+ };
+ }
+
@Bean
public IPRateLimitingFilter rateLimitingFilter() {
int maxRequestsPerIp = 1000000; // Example limit TODO add config level
@@ -137,4 +291,9 @@ public class SecurityConfiguration {
public PersistentTokenRepository persistentTokenRepository() {
return new JPATokenRepositoryImpl();
}
+
+ @Bean
+ public boolean activSecurity() {
+ return true;
+ }
}
diff --git a/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java b/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java
index 47423eb6..244efed3 100644
--- a/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java
+++ b/src/main/java/stirling/software/SPDF/config/security/UserAuthenticationFilter.java
@@ -82,7 +82,7 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.getWriter()
.write(
- "Authentication required. Please provide a X-API-KEY in request header.\nThis is found in Settings -> Account Settings -> API Key\nAlternativly you can disable authentication if this is unexpected");
+ "Authentication required. Please provide a X-API-KEY in request header.\nThis is found in Settings -> Account Settings -> API Key\nAlternatively you can disable authentication if this is unexpected");
return;
}
}
diff --git a/src/main/java/stirling/software/SPDF/config/security/UserBasedRateLimitingFilter.java b/src/main/java/stirling/software/SPDF/config/security/UserBasedRateLimitingFilter.java
index 7b3b9b4e..89107697 100644
--- a/src/main/java/stirling/software/SPDF/config/security/UserBasedRateLimitingFilter.java
+++ b/src/main/java/stirling/software/SPDF/config/security/UserBasedRateLimitingFilter.java
@@ -1,5 +1,6 @@
package stirling.software.SPDF.config.security;
+import io.github.pixee.security.Newlines;
import java.io.IOException;
import java.time.Duration;
import java.util.Map;
@@ -125,12 +126,12 @@ public class UserBasedRateLimitingFilter extends OncePerRequestFilter {
ConsumptionProbe probe = userBucket.tryConsumeAndReturnRemaining(1);
if (probe.isConsumed()) {
- response.setHeader("X-Rate-Limit-Remaining", Long.toString(probe.getRemainingTokens()));
+ response.setHeader("X-Rate-Limit-Remaining", Newlines.stripAll(Long.toString(probe.getRemainingTokens())));
filterChain.doFilter(request, response);
} else {
long waitForRefill = probe.getNanosToWaitForRefill() / 1_000_000_000;
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
- response.setHeader("X-Rate-Limit-Retry-After-Seconds", String.valueOf(waitForRefill));
+ response.setHeader("X-Rate-Limit-Retry-After-Seconds", Newlines.stripAll(String.valueOf(waitForRefill)));
response.getWriter().write("Rate limit exceeded for POST requests.");
}
}
diff --git a/src/main/java/stirling/software/SPDF/config/security/UserService.java b/src/main/java/stirling/software/SPDF/config/security/UserService.java
index 60b3ebef..7d57f8f6 100644
--- a/src/main/java/stirling/software/SPDF/config/security/UserService.java
+++ b/src/main/java/stirling/software/SPDF/config/security/UserService.java
@@ -21,6 +21,7 @@ import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
import stirling.software.SPDF.model.Authority;
import stirling.software.SPDF.model.Role;
import stirling.software.SPDF.model.User;
+import stirling.software.SPDF.repository.AuthorityRepository;
import stirling.software.SPDF.repository.UserRepository;
@Service
@@ -28,8 +29,28 @@ public class UserService implements UserServiceInterface {
@Autowired private UserRepository userRepository;
+ @Autowired private AuthorityRepository authorityRepository;
+
@Autowired private PasswordEncoder passwordEncoder;
+ // Handle OAUTH2 login and user auto creation.
+ public boolean processOAuth2PostLogin(String username, boolean autoCreateUser) {
+ Optional existUser = userRepository.findByUsernameIgnoreCase(username);
+ if (existUser.isPresent()) {
+ return true;
+ }
+ if (autoCreateUser) {
+ User user = new User();
+ user.setUsername(username);
+ user.setEnabled(true);
+ user.setFirstLogin(false);
+ user.addAuthority(new Authority(Role.USER.getRoleId(), user));
+ userRepository.save(user);
+ return true;
+ }
+ return false;
+ }
+
public Authentication getAuthentication(String apiKey) {
User user = getUserByApiKey(apiKey);
if (user == null) {
@@ -62,7 +83,7 @@ public class UserService implements UserServiceInterface {
public User addApiKeyToUser(String username) {
User user =
userRepository
- .findByUsername(username)
+ .findByUsernameIgnoreCase(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
user.setApiKey(generateApiKey());
@@ -76,7 +97,7 @@ public class UserService implements UserServiceInterface {
public String getApiKeyForUser(String username) {
User user =
userRepository
- .findByUsername(username)
+ .findByUsernameIgnoreCase(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
return user.getApiKey();
}
@@ -103,7 +124,7 @@ public class UserService implements UserServiceInterface {
}
public boolean validateApiKeyForUser(String username, String apiKey) {
- Optional userOpt = userRepository.findByUsername(username);
+ Optional userOpt = userRepository.findByUsernameIgnoreCase(username);
return userOpt.isPresent() && userOpt.get().getApiKey().equals(apiKey);
}
@@ -136,7 +157,7 @@ public class UserService implements UserServiceInterface {
}
public void deleteUser(String username) {
- Optional userOpt = userRepository.findByUsername(username);
+ Optional userOpt = userRepository.findByUsernameIgnoreCase(username);
if (userOpt.isPresent()) {
for (Authority authority : userOpt.get().getAuthorities()) {
if (authority.getAuthority().equals(Role.INTERNAL_API_USER.getRoleId())) {
@@ -151,12 +172,16 @@ public class UserService implements UserServiceInterface {
return userRepository.findByUsername(username).isPresent();
}
+ public boolean usernameExistsIgnoreCase(String username) {
+ return userRepository.findByUsernameIgnoreCase(username).isPresent();
+ }
+
public boolean hasUsers() {
return userRepository.count() > 0;
}
public void updateUserSettings(String username, Map updates) {
- Optional userOpt = userRepository.findByUsername(username);
+ Optional userOpt = userRepository.findByUsernameIgnoreCase(username);
if (userOpt.isPresent()) {
User user = userOpt.get();
Map settingsMap = user.getSettings();
@@ -176,6 +201,14 @@ public class UserService implements UserServiceInterface {
return userRepository.findByUsername(username);
}
+ public Optional findByUsernameIgnoreCase(String username) {
+ return userRepository.findByUsernameIgnoreCase(username);
+ }
+
+ public Authority findRole(User user) {
+ return authorityRepository.findByUserId(user.getId());
+ }
+
public void changeUsername(User user, String newUsername) {
user.setUsername(newUsername);
userRepository.save(user);
@@ -191,7 +224,17 @@ public class UserService implements UserServiceInterface {
userRepository.save(user);
}
+ public void changeRole(User user, String newRole) {
+ Authority userAuthority = this.findRole(user);
+ userAuthority.setAuthority(newRole);
+ authorityRepository.save(userAuthority);
+ }
+
public boolean isPasswordCorrect(User user, String currentPassword) {
return passwordEncoder.matches(currentPassword, user.getPassword());
}
+
+ public boolean isUsernameValid(String username) {
+ return username.matches("[a-zA-Z0-9]+");
+ }
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/MergeController.java b/src/main/java/stirling/software/SPDF/controller/api/MergeController.java
index ad742137..1719d325 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/MergeController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/MergeController.java
@@ -38,7 +38,7 @@ public class MergeController {
private static final Logger logger = LoggerFactory.getLogger(MergeController.class);
- private PDDocument mergeDocuments(List documents) throws IOException {
+ public PDDocument mergeDocuments(List documents) throws IOException {
PDDocument mergedDoc = new PDDocument();
for (PDDocument doc : documents) {
for (PDPage page : doc.getPages()) {
diff --git a/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java b/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java
index 88bdcd91..a1e80af3 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/RearrangePagesPDFController.java
@@ -2,6 +2,7 @@ package stirling.software.SPDF.controller.api;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import org.apache.pdfbox.Loader;
@@ -50,7 +51,9 @@ public class RearrangePagesPDFController {
String[] pageOrderArr = pagesToDelete.split(",");
List pagesToRemove =
- GeneralUtils.parsePageList(pageOrderArr, document.getNumberOfPages());
+ GeneralUtils.parsePageList(pageOrderArr, document.getNumberOfPages(), false);
+
+ Collections.sort(pagesToRemove);
for (int i = pagesToRemove.size() - 1; i >= 0; i--) {
int pageIndex = pagesToRemove.get(i);
@@ -192,7 +195,7 @@ public class RearrangePagesPDFController {
if (sortType != null && sortType.length() > 0) {
newPageOrder = processSortTypes(sortType, totalPages);
} else {
- newPageOrder = GeneralUtils.parsePageList(pageOrderArr, totalPages);
+ newPageOrder = GeneralUtils.parsePageList(pageOrderArr, totalPages, false);
}
logger.info("newPageOrder = " + newPageOrder);
logger.info("totalPages = " + totalPages);
diff --git a/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java b/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java
index a69dea34..51efa644 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/SplitPDFController.java
@@ -27,7 +27,9 @@ import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
+import stirling.software.SPDF.model.PdfMetadata;
import stirling.software.SPDF.model.api.PDFWithPageNums;
+import stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -49,10 +51,17 @@ public class SplitPDFController {
// open the pdf document
PDDocument document = Loader.loadPDF(file.getBytes());
+ PdfMetadata metadata = PdfUtils.extractMetadataFromPdf(document);
+ int totalPages = document.getNumberOfPages();
+ List pageNumbers = request.getPageNumbersList(document, false);
+ System.out.println(
+ pageNumbers.stream().map(String::valueOf).collect(Collectors.joining(",")));
+ if (!pageNumbers.contains(totalPages - 1)) {
+ // Create a mutable ArrayList so we can add to it
+ pageNumbers = new ArrayList<>(pageNumbers);
+ pageNumbers.add(totalPages - 1);
+ }
- List pageNumbers = request.getPageNumbersList(document, true);
- if (!pageNumbers.contains(document.getNumberOfPages() - 1))
- pageNumbers.add(document.getNumberOfPages() - 1);
logger.info(
"Splitting PDF into pages: {}",
pageNumbers.stream().map(String::valueOf).collect(Collectors.joining(",")));
@@ -65,10 +74,13 @@ public class SplitPDFController {
for (int i = previousPageNumber; i <= splitPoint; i++) {
PDPage page = document.getPage(i);
splitDocument.addPage(page);
- logger.debug("Adding page {} to split document", i);
+ logger.info("Adding page {} to split document", i);
}
previousPageNumber = splitPoint + 1;
+ // Transfer metadata to split pdf
+ PdfUtils.setMetadataToPdf(splitDocument, metadata);
+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
splitDocument.save(baos);
diff --git a/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java b/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java
index 3deb798e..3682aaf7 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySectionsController.java
@@ -53,8 +53,21 @@ public class SplitPdfBySectionsController {
// Process the PDF based on split parameters
int horiz = request.getHorizontalDivisions() + 1;
int verti = request.getVerticalDivisions() + 1;
-
+ boolean merge = request.isMerge();
List splitDocuments = splitPdfPages(sourceDocument, verti, horiz);
+
+ String filename =
+ Filenames.toSimpleFileName(file.getOriginalFilename())
+ .replaceFirst("[.][^.]+$", "");
+ if (merge) {
+ MergeController mergeController = new MergeController();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ mergeController.mergeDocuments(splitDocuments).save(baos);
+ return WebResponseUtils.bytesToWebResponse(
+ baos.toByteArray(),
+ filename + "_split.pdf",
+ MediaType.APPLICATION_OCTET_STREAM);
+ }
for (PDDocument doc : splitDocuments) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
doc.save(baos);
@@ -65,9 +78,6 @@ public class SplitPdfBySectionsController {
sourceDocument.close();
Path zipFile = Files.createTempFile("split_documents", ".zip");
- String filename =
- Filenames.toSimpleFileName(file.getOriginalFilename())
- .replaceFirst("[.][^.]+$", "");
byte[] data;
try (ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipFile))) {
diff --git a/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java b/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java
index 45d2dd38..40ac2d16 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/SplitPdfBySizeController.java
@@ -4,8 +4,6 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@@ -41,117 +39,137 @@ public class SplitPdfBySizeController {
+ " if 10MB and each page is 1MB and you enter 2MB then 5 docs each 2MB (rounded so that it accepts 1.9MB but not 2.1MB) Input:PDF Output:ZIP-PDF Type:SISO")
public ResponseEntity autoSplitPdf(@ModelAttribute SplitPdfBySizeOrCountRequest request)
throws Exception {
- List splitDocumentsBoas = new ArrayList();
MultipartFile file = request.getFileInput();
- PDDocument sourceDocument = Loader.loadPDF(file.getBytes());
-
- // 0 = size, 1 = page count, 2 = doc count
- int type = request.getSplitType();
- String value = request.getSplitValue();
-
- if (type == 0) { // Split by size
- long maxBytes = GeneralUtils.convertSizeToBytes(value);
- long currentSize = 0;
- PDDocument currentDoc = new PDDocument();
-
- for (PDPage page : sourceDocument.getPages()) {
- ByteArrayOutputStream pageOutputStream = new ByteArrayOutputStream();
- PDDocument tempDoc = new PDDocument();
- tempDoc.addPage(page);
- tempDoc.save(pageOutputStream);
- tempDoc.close();
-
- long pageSize = pageOutputStream.size();
- if (currentSize + pageSize > maxBytes) {
- // Save and reset current document
- splitDocumentsBoas.add(currentDocToByteArray(currentDoc));
- currentDoc = new PDDocument();
- currentSize = 0;
- }
-
- currentDoc.addPage(page);
- currentSize += pageSize;
- }
- // Add the last document if it contains any pages
- if (currentDoc.getPages().getCount() != 0) {
- splitDocumentsBoas.add(currentDocToByteArray(currentDoc));
- }
- } else if (type == 1) { // Split by page count
- int pageCount = Integer.parseInt(value);
- int currentPageCount = 0;
- PDDocument currentDoc = new PDDocument();
-
- for (PDPage page : sourceDocument.getPages()) {
- currentDoc.addPage(page);
- currentPageCount++;
-
- if (currentPageCount == pageCount) {
- // Save and reset current document
- splitDocumentsBoas.add(currentDocToByteArray(currentDoc));
- currentDoc = new PDDocument();
- currentPageCount = 0;
- }
- }
- // Add the last document if it contains any pages
- if (currentDoc.getPages().getCount() != 0) {
- splitDocumentsBoas.add(currentDocToByteArray(currentDoc));
- }
- } else if (type == 2) { // Split by doc count
- int documentCount = Integer.parseInt(value);
- int totalPageCount = sourceDocument.getNumberOfPages();
- int pagesPerDocument = totalPageCount / documentCount;
- int extraPages = totalPageCount % documentCount;
- int currentPageIndex = 0;
-
- for (int i = 0; i < documentCount; i++) {
- PDDocument currentDoc = new PDDocument();
- int pagesToAdd = pagesPerDocument + (i < extraPages ? 1 : 0);
-
- for (int j = 0; j < pagesToAdd; j++) {
- currentDoc.addPage(sourceDocument.getPage(currentPageIndex++));
- }
-
- splitDocumentsBoas.add(currentDocToByteArray(currentDoc));
- }
- } else {
- throw new IllegalArgumentException("Invalid argument for split type");
- }
-
- sourceDocument.close();
-
Path zipFile = Files.createTempFile("split_documents", ".zip");
String filename =
Filenames.toSimpleFileName(file.getOriginalFilename())
.replaceFirst("[.][^.]+$", "");
- byte[] data;
+ byte[] data = null;
+ try (ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipFile));
+ PDDocument sourceDocument = Loader.loadPDF(file.getBytes())) {
- try (ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipFile))) {
- for (int i = 0; i < splitDocumentsBoas.size(); i++) {
- String fileName = filename + "_" + (i + 1) + ".pdf";
- ByteArrayOutputStream baos = splitDocumentsBoas.get(i);
- byte[] pdf = baos.toByteArray();
+ int type = request.getSplitType();
+ String value = request.getSplitValue();
- ZipEntry pdfEntry = new ZipEntry(fileName);
- zipOut.putNextEntry(pdfEntry);
- zipOut.write(pdf);
- zipOut.closeEntry();
+ if (type == 0) {
+ long maxBytes = GeneralUtils.convertSizeToBytes(value);
+ handleSplitBySize(sourceDocument, maxBytes, zipOut, filename);
+ } else if (type == 1) {
+ int pageCount = Integer.parseInt(value);
+ handleSplitByPageCount(sourceDocument, pageCount, zipOut, filename);
+ } else if (type == 2) {
+ int documentCount = Integer.parseInt(value);
+ handleSplitByDocCount(sourceDocument, documentCount, zipOut, filename);
+ } else {
+ throw new IllegalArgumentException("Invalid argument for split type");
}
+
} catch (Exception e) {
e.printStackTrace();
} finally {
data = Files.readAllBytes(zipFile);
- Files.delete(zipFile);
+ Files.deleteIfExists(zipFile);
}
return WebResponseUtils.bytesToWebResponse(
data, filename + ".zip", MediaType.APPLICATION_OCTET_STREAM);
}
- private ByteArrayOutputStream currentDocToByteArray(PDDocument document) throws IOException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- document.save(baos);
- document.close();
- return baos;
+ private void handleSplitBySize(
+ PDDocument sourceDocument, long maxBytes, ZipOutputStream zipOut, String baseFilename)
+ throws IOException {
+ long currentSize = 0;
+ PDDocument currentDoc = new PDDocument();
+ int fileIndex = 1;
+
+ for (int pageIndex = 0; pageIndex < sourceDocument.getNumberOfPages(); pageIndex++) {
+ PDPage page = sourceDocument.getPage(pageIndex);
+ ByteArrayOutputStream pageOutputStream = new ByteArrayOutputStream();
+
+ try (PDDocument tempDoc = new PDDocument()) {
+ PDPage importedPage = tempDoc.importPage(page); // This creates a new PDPage object
+ tempDoc.save(pageOutputStream);
+ }
+
+ long pageSize = pageOutputStream.size();
+ if (currentSize + pageSize > maxBytes) {
+ if (currentDoc.getNumberOfPages() > 0) {
+ saveDocumentToZip(currentDoc, zipOut, baseFilename, fileIndex++);
+ currentDoc.close(); // Make sure to close the document
+ currentDoc = new PDDocument();
+ currentSize = 0;
+ }
+ }
+
+ PDPage newPage = new PDPage(page.getCOSObject()); // Re-create the page
+ currentDoc.addPage(newPage);
+ currentSize += pageSize;
+ }
+
+ if (currentDoc.getNumberOfPages() != 0) {
+ saveDocumentToZip(currentDoc, zipOut, baseFilename, fileIndex++);
+ currentDoc.close();
+ }
+ }
+
+ private void handleSplitByPageCount(
+ PDDocument sourceDocument, int pageCount, ZipOutputStream zipOut, String baseFilename)
+ throws IOException {
+ int currentPageCount = 0;
+ PDDocument currentDoc = new PDDocument();
+ int fileIndex = 1;
+ for (PDPage page : sourceDocument.getPages()) {
+ currentDoc.addPage(page);
+ currentPageCount++;
+
+ if (currentPageCount == pageCount) {
+ // Save and reset current document
+ saveDocumentToZip(currentDoc, zipOut, baseFilename, fileIndex++);
+ currentDoc = new PDDocument();
+ currentPageCount = 0;
+ }
+ }
+ // Add the last document if it contains any pages
+ if (currentDoc.getPages().getCount() != 0) {
+ saveDocumentToZip(currentDoc, zipOut, baseFilename, fileIndex++);
+ }
+ }
+
+ private void handleSplitByDocCount(
+ PDDocument sourceDocument,
+ int documentCount,
+ ZipOutputStream zipOut,
+ String baseFilename)
+ throws IOException {
+ int totalPageCount = sourceDocument.getNumberOfPages();
+ int pagesPerDocument = totalPageCount / documentCount;
+ int extraPages = totalPageCount % documentCount;
+ int currentPageIndex = 0;
+ int fileIndex = 1;
+ for (int i = 0; i < documentCount; i++) {
+ PDDocument currentDoc = new PDDocument();
+ int pagesToAdd = pagesPerDocument + (i < extraPages ? 1 : 0);
+
+ for (int j = 0; j < pagesToAdd; j++) {
+ currentDoc.addPage(sourceDocument.getPage(currentPageIndex++));
+ }
+
+ saveDocumentToZip(currentDoc, zipOut, baseFilename, fileIndex++);
+ }
+ }
+
+ private void saveDocumentToZip(
+ PDDocument document, ZipOutputStream zipOut, String baseFilename, int index)
+ throws IOException {
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ document.save(outStream);
+ document.close(); // Close the document to free resources
+
+ // Create a new zip entry
+ ZipEntry zipEntry = new ZipEntry(baseFilename + "_" + index + ".pdf");
+ zipOut.putNextEntry(zipEntry);
+ zipOut.write(outStream.toByteArray());
+ zipOut.closeEntry();
}
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/UserController.java b/src/main/java/stirling/software/SPDF/controller/api/UserController.java
index ce15d19c..f5b7b159 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/UserController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/UserController.java
@@ -10,6 +10,9 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
+import org.springframework.security.core.session.SessionInformation;
+import org.springframework.security.core.session.SessionRegistry;
+import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
@@ -28,7 +31,6 @@ import jakarta.servlet.http.HttpServletResponse;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.model.Role;
import stirling.software.SPDF.model.User;
-import stirling.software.SPDF.model.api.user.UpdateUserDetails;
import stirling.software.SPDF.model.api.user.UsernameAndPass;
@Controller
@@ -41,7 +43,7 @@ public class UserController {
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
@PostMapping("/register")
public String register(@ModelAttribute UsernameAndPass requestModel, Model model) {
- if (userService.usernameExists(requestModel.getUsername())) {
+ if (userService.usernameExistsIgnoreCase(requestModel.getUsername())) {
model.addAttribute("error", "Username already exists");
return "register";
}
@@ -50,66 +52,25 @@ public class UserController {
return "redirect:/login?registered=true";
}
- @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
- @PostMapping("/change-username-and-password")
- public RedirectView changeUsernameAndPassword(
- Principal principal,
- @ModelAttribute UpdateUserDetails requestModel,
- HttpServletRequest request,
- HttpServletResponse response,
- RedirectAttributes redirectAttributes) {
-
- String currentPassword = requestModel.getPassword();
- String newPassword = requestModel.getNewPassword();
- String newUsername = requestModel.getNewUsername();
-
- if (principal == null) {
- return new RedirectView("/change-creds?messageType=notAuthenticated");
- }
-
- Optional userOpt = userService.findByUsername(principal.getName());
-
- if (userOpt == null || userOpt.isEmpty()) {
- return new RedirectView("/change-creds?messageType=userNotFound");
- }
-
- User user = userOpt.get();
-
- if (!userService.isPasswordCorrect(user, currentPassword)) {
- return new RedirectView("/change-creds?messageType=incorrectPassword");
- }
-
- if (!user.getUsername().equals(newUsername) && userService.usernameExists(newUsername)) {
- return new RedirectView("/change-creds?messageType=usernameExists");
- }
-
- userService.changePassword(user, newPassword);
- if (newUsername != null
- && newUsername.length() > 0
- && !user.getUsername().equals(newUsername)) {
- userService.changeUsername(user, newUsername);
- }
- userService.changeFirstUse(user, false);
-
- // Logout using Spring's utility
- new SecurityContextLogoutHandler().logout(request, response, null);
-
- return new RedirectView("/login?messageType=credsUpdated");
- }
-
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
@PostMapping("/change-username")
public RedirectView changeUsername(
Principal principal,
- @RequestParam String currentPassword,
- @RequestParam String newUsername,
+ @RequestParam(name = "currentPassword") String currentPassword,
+ @RequestParam(name = "newUsername") String newUsername,
HttpServletRequest request,
HttpServletResponse response,
RedirectAttributes redirectAttributes) {
+
+ if (!userService.isUsernameValid(newUsername)) {
+ return new RedirectView("/account?messageType=invalidUsername");
+ }
+
if (principal == null) {
return new RedirectView("/account?messageType=notAuthenticated");
}
+ // The username MUST be unique when renaming
Optional userOpt = userService.findByUsername(principal.getName());
if (userOpt == null || userOpt.isEmpty()) {
@@ -118,6 +79,10 @@ public class UserController {
User user = userOpt.get();
+ if (user.getUsername().equals(newUsername)) {
+ return new RedirectView("/account?messageType=usernameExists");
+ }
+
if (!userService.isPasswordCorrect(user, currentPassword)) {
return new RedirectView("/account?messageType=incorrectPassword");
}
@@ -133,15 +98,48 @@ public class UserController {
// Logout using Spring's utility
new SecurityContextLogoutHandler().logout(request, response, null);
- return new RedirectView("/login?messageType=credsUpdated");
+ return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED);
+ }
+
+ @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
+ @PostMapping("/change-password-on-login")
+ public RedirectView changePasswordOnLogin(
+ Principal principal,
+ @RequestParam(name = "currentPassword") String currentPassword,
+ @RequestParam(name = "newPassword") String newPassword,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ RedirectAttributes redirectAttributes) {
+ if (principal == null) {
+ return new RedirectView("/change-creds?messageType=notAuthenticated");
+ }
+
+ Optional userOpt = userService.findByUsernameIgnoreCase(principal.getName());
+
+ if (userOpt == null || userOpt.isEmpty()) {
+ return new RedirectView("/change-creds?messageType=userNotFound");
+ }
+
+ User user = userOpt.get();
+
+ if (!userService.isPasswordCorrect(user, currentPassword)) {
+ return new RedirectView("/change-creds?messageType=incorrectPassword");
+ }
+
+ userService.changePassword(user, newPassword);
+ userService.changeFirstUse(user, false);
+ // Logout using Spring's utility
+ new SecurityContextLogoutHandler().logout(request, response, null);
+
+ return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED);
}
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
@PostMapping("/change-password")
public RedirectView changePassword(
Principal principal,
- @RequestParam String currentPassword,
- @RequestParam String newPassword,
+ @RequestParam(name = "currentPassword") String currentPassword,
+ @RequestParam(name = "newPassword") String newPassword,
HttpServletRequest request,
HttpServletResponse response,
RedirectAttributes redirectAttributes) {
@@ -149,7 +147,7 @@ public class UserController {
return new RedirectView("/account?messageType=notAuthenticated");
}
- Optional userOpt = userService.findByUsername(principal.getName());
+ Optional userOpt = userService.findByUsernameIgnoreCase(principal.getName());
if (userOpt == null || userOpt.isEmpty()) {
return new RedirectView("/account?messageType=userNotFound");
@@ -166,7 +164,7 @@ public class UserController {
// Logout using Spring's utility
new SecurityContextLogoutHandler().logout(request, response, null);
- return new RedirectView("/login?messageType=credsUpdated");
+ return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED);
}
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
@@ -192,13 +190,25 @@ public class UserController {
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/admin/saveUser")
public RedirectView saveUser(
- @RequestParam String username,
- @RequestParam String password,
- @RequestParam String role,
+ @RequestParam(name = "username") String username,
+ @RequestParam(name = "password") String password,
+ @RequestParam(name = "role") String role,
@RequestParam(name = "forceChange", required = false, defaultValue = "false")
boolean forceChange) {
- if (userService.usernameExists(username)) {
+ if (!userService.isUsernameValid(username)) {
+ return new RedirectView("/addUsers?messageType=invalidUsername");
+ }
+
+ Optional userOpt = userService.findByUsernameIgnoreCase(username);
+
+ if (userOpt.isPresent()) {
+ User user = userOpt.get();
+ if (user != null && user.getUsername().equalsIgnoreCase(username)) {
+ return new RedirectView("/addUsers?messageType=usernameExists");
+ }
+ }
+ if (userService.usernameExistsIgnoreCase(username)) {
return new RedirectView("/addUsers?messageType=usernameExists");
}
try {
@@ -217,20 +227,80 @@ public class UserController {
return new RedirectView("/addUsers"); // Redirect to account page after adding the user
}
+ @PreAuthorize("hasRole('ROLE_ADMIN')")
+ @PostMapping("/admin/changeRole")
+ public RedirectView changeRole(
+ @RequestParam(name = "username") String username,
+ @RequestParam(name = "role") String role,
+ Authentication authentication) {
+
+ Optional userOpt = userService.findByUsernameIgnoreCase(username);
+
+ if (!userOpt.isPresent()) {
+ return new RedirectView("/addUsers?messageType=userNotFound");
+ }
+ if (!userService.usernameExistsIgnoreCase(username)) {
+ return new RedirectView("/addUsers?messageType=userNotFound");
+ }
+ // Get the currently authenticated username
+ String currentUsername = authentication.getName();
+
+ // Check if the provided username matches the current session's username
+ if (currentUsername.equalsIgnoreCase(username)) {
+ return new RedirectView("/addUsers?messageType=downgradeCurrentUser");
+ }
+ try {
+ // Validate the role
+ Role roleEnum = Role.fromString(role);
+ if (roleEnum == Role.INTERNAL_API_USER) {
+ // If the role is INTERNAL_API_USER, reject the request
+ return new RedirectView("/addUsers?messageType=invalidRole");
+ }
+ } catch (IllegalArgumentException e) {
+ // If the role ID is not valid, redirect with an error message
+ return new RedirectView("/addUsers?messageType=invalidRole");
+ }
+ User user = userOpt.get();
+
+ userService.changeRole(user, role);
+ return new RedirectView("/addUsers"); // Redirect to account page after adding the user
+ }
+
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/admin/deleteUser/{username}")
- public String deleteUser(@PathVariable String username, Authentication authentication) {
+ public RedirectView deleteUser(
+ @PathVariable(name = "username") String username, Authentication authentication) {
+
+ if (!userService.usernameExistsIgnoreCase(username)) {
+ return new RedirectView("/addUsers?messageType=deleteUsernameExists");
+ }
// Get the currently authenticated username
String currentUsername = authentication.getName();
// Check if the provided username matches the current session's username
- if (currentUsername.equals(username)) {
- throw new IllegalArgumentException("Cannot delete currently logined in user.");
+ if (currentUsername.equalsIgnoreCase(username)) {
+ return new RedirectView("/addUsers?messageType=deleteCurrentUser");
}
-
+ invalidateUserSessions(username);
userService.deleteUser(username);
- return "redirect:/addUsers";
+ return new RedirectView("/addUsers");
+ }
+
+ @Autowired private SessionRegistry sessionRegistry;
+
+ private void invalidateUserSessions(String username) {
+ for (Object principal : sessionRegistry.getAllPrincipals()) {
+ if (principal instanceof UserDetails) {
+ UserDetails userDetails = (UserDetails) principal;
+ if (userDetails.getUsername().equals(username)) {
+ for (SessionInformation session :
+ sessionRegistry.getAllSessions(principal, false)) {
+ session.expireNow();
+ }
+ }
+ }
+ }
}
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
@@ -261,4 +331,6 @@ public class UserController {
}
return ResponseEntity.ok(apiKey);
}
+
+ private static final String LOGIN_MESSAGETYPE_CREDSUPDATED = "/login?messageType=credsUpdated";
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertBookToPDFController.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertBookToPDFController.java
index 05784a15..41e6520d 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertBookToPDFController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertBookToPDFController.java
@@ -37,7 +37,7 @@ public class ConvertBookToPDFController {
if (!bookAndHtmlFormatsInstalled) {
throw new IllegalArgumentException(
- "bookAndHtmlFormatsInstalled flag is False, this functionality is not avaiable");
+ "bookAndHtmlFormatsInstalled flag is False, this functionality is not available");
}
if (fileInput == null) {
diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java
index 86a70472..9fa357f7 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertImgPDFController.java
@@ -6,10 +6,6 @@ import java.net.URLConnection;
import org.apache.pdfbox.rendering.ImageType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.core.io.ByteArrayResource;
-import org.springframework.core.io.Resource;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
@@ -39,7 +35,7 @@ public class ConvertImgPDFController {
summary = "Convert PDF to image(s)",
description =
"This endpoint converts a PDF file to image(s) with the specified image format, color type, and DPI. Users can choose to get a single image or multiple images. Input:PDF Output:Image Type:SI-Conditional")
- public ResponseEntity convertToImage(@ModelAttribute ConvertToImageRequest request)
+ public ResponseEntity convertToImage(@ModelAttribute ConvertToImageRequest request)
throws IOException {
MultipartFile file = request.getFileInput();
String imageFormat = request.getImageFormat();
@@ -76,22 +72,15 @@ public class ConvertImgPDFController {
// TODO Auto-generated catch block
e.printStackTrace();
}
+
if (singleImage) {
- HttpHeaders headers = new HttpHeaders();
- headers.setContentType(MediaType.parseMediaType(getMediaType(imageFormat)));
- ResponseEntity response =
- new ResponseEntity<>(new ByteArrayResource(result), headers, HttpStatus.OK);
- return response;
+ String docName = filename + "." + imageFormat;
+ MediaType mediaType = MediaType.parseMediaType(getMediaType(imageFormat));
+ return WebResponseUtils.bytesToWebResponse(result, docName, mediaType);
} else {
- ByteArrayResource resource = new ByteArrayResource(result);
- // return the Resource in the response
- return ResponseEntity.ok()
- .header(
- HttpHeaders.CONTENT_DISPOSITION,
- "attachment; filename=" + filename + "_convertedToImages.zip")
- .contentType(MediaType.APPLICATION_OCTET_STREAM)
- .contentLength(resource.contentLength())
- .body(resource);
+ String zipFilename = filename + "_convertedToImages.zip";
+ return WebResponseUtils.bytesToWebResponse(
+ result, zipFilename, MediaType.APPLICATION_OCTET_STREAM);
}
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToBookController.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToBookController.java
index 28793d48..c8b9dd4d 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToBookController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToBookController.java
@@ -45,7 +45,7 @@ public class ConvertPDFToBookController {
if (!bookAndHtmlFormatsInstalled) {
throw new IllegalArgumentException(
- "bookAndHtmlFormatsInstalled flag is False, this functionality is not avaiable");
+ "bookAndHtmlFormatsInstalled flag is False, this functionality is not available");
}
if (fileInput == null) {
diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToHtml.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToHtml.java
new file mode 100644
index 00000000..beafd389
--- /dev/null
+++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToHtml.java
@@ -0,0 +1,32 @@
+package stirling.software.SPDF.controller.api.converters;
+
+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.PDFFile;
+import stirling.software.SPDF.utils.PDFToFile;
+
+@RestController
+@Tag(name = "Convert", description = "Convert APIs")
+@RequestMapping("/api/v1/convert")
+public class ConvertPDFToHtml {
+
+ @PostMapping(consumes = "multipart/form-data", value = "/pdf/html")
+ @Operation(
+ summary = "Convert PDF to HTML",
+ description =
+ "This endpoint converts a PDF file to HTML format. Input:PDF Output:HTML Type:SISO")
+ public ResponseEntity processPdfToHTML(@ModelAttribute PDFFile request)
+ throws Exception {
+ MultipartFile inputFile = request.getFileInput();
+ PDFToFile pdfToFile = new PDFToFile();
+ return pdfToFile.processPdfToHtml(inputFile);
+ }
+}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java
index 798c5f44..030ede95 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToOffice.java
@@ -29,18 +29,6 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Convert", description = "Convert APIs")
public class ConvertPDFToOffice {
- @PostMapping(consumes = "multipart/form-data", value = "/pdf/html")
- @Operation(
- summary = "Convert PDF to HTML",
- description =
- "This endpoint converts a PDF file to HTML format. Input:PDF Output:HTML Type:SISO")
- public ResponseEntity processPdfToHTML(@ModelAttribute PDFFile request)
- throws Exception {
- MultipartFile inputFile = request.getFileInput();
- PDFToFile pdfToFile = new PDFToFile();
- return pdfToFile.processPdfToOfficeFormat(inputFile, "html", "writer_pdf_import");
- }
-
@PostMapping(consumes = "multipart/form-data", value = "/pdf/presentation")
@Operation(
summary = "Convert PDF to Presentation format",
diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java
index 41498413..aec4e347 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertPDFToPDFA.java
@@ -16,7 +16,7 @@ import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
-import stirling.software.SPDF.model.api.PDFFile;
+import stirling.software.SPDF.model.api.converters.PdfToPdfARequest;
import stirling.software.SPDF.utils.ProcessExecutor;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -31,8 +31,10 @@ public class ConvertPDFToPDFA {
summary = "Convert a PDF to a PDF/A",
description =
"This endpoint converts a PDF file to a PDF/A file. PDF/A is a format designed for long-term archiving of digital documents. Input:PDF Output:PDF Type:SISO")
- public ResponseEntity pdfToPdfA(@ModelAttribute PDFFile request) throws Exception {
+ public ResponseEntity pdfToPdfA(@ModelAttribute PdfToPdfARequest request)
+ throws Exception {
MultipartFile inputFile = request.getFileInput();
+ String outputFormat = request.getOutputFormat();
// Save the uploaded file to a temporary location
Path tempInputFile = Files.createTempFile("input_", ".pdf");
@@ -47,7 +49,7 @@ public class ConvertPDFToPDFA {
command.add("--skip-text");
command.add("--tesseract-timeout=0");
command.add("--output-type");
- command.add("pdfa");
+ command.add(outputFormat.toString());
command.add(tempInputFile.toString());
command.add(tempOutputFile.toString());
diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java
index c2d25973..815018e8 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertWebsiteToPDF.java
@@ -6,8 +6,6 @@ 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;
@@ -28,10 +26,6 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@RequestMapping("/api/v1/convert")
public class ConvertWebsiteToPDF {
- @Autowired
- @Qualifier("bookAndHtmlFormatsInstalled")
- private boolean bookAndHtmlFormatsInstalled;
-
@PostMapping(consumes = "multipart/form-data", value = "/url/pdf")
@Operation(
summary = "Convert a URL to a PDF",
@@ -53,11 +47,7 @@ public class ConvertWebsiteToPDF {
// Prepare the OCRmyPDF command
List command = new ArrayList<>();
- if (!bookAndHtmlFormatsInstalled) {
- command.add("weasyprint");
- } else {
- command.add("wkhtmltopdf");
- }
+ command.add("weasyprint");
command.add(URL);
command.add(tempOutputFile.toString());
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java
index 2dc6c8a3..f0fb7b02 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/AutoRenameController.java
@@ -130,7 +130,7 @@ public class AutoRenameController {
// Sanitize the header string by removing characters not allowed in a filename.
if (header != null && header.length() < 255) {
- header = header.replaceAll("[/\\\\?%*:|\"<>]", "");
+ header = header.replaceAll("[/\\\\?%*:|\"<>]", "").trim();
return WebResponseUtils.pdfDocToWebResponse(document, header + ".pdf");
} else {
logger.info("File has no good title to be found");
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java
index 32f39c04..0b578d8f 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/AutoSplitPdfController.java
@@ -58,7 +58,7 @@ public class AutoSplitPdfController {
PDDocument document = Loader.loadPDF(file.getBytes());
PDFRenderer pdfRenderer = new PDFRenderer(document);
-
+ pdfRenderer.setSubsamplingAllowed(true);
List splitDocuments = new ArrayList<>();
List splitDocumentsBoas = new ArrayList<>();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java
index a813ba79..eaac72a0 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/BlankPageController.java
@@ -59,7 +59,7 @@ public class BlankPageController {
List pagesToKeepIndex = new ArrayList<>();
int pageIndex = 0;
PDFRenderer pdfRenderer = new PDFRenderer(document);
-
+ pdfRenderer.setSubsamplingAllowed(true);
for (PDPage page : pages) {
logger.info("checking page " + pageIndex);
textStripper.setStartPage(pageIndex + 1);
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java
index 82a2c72f..9e3d6a99 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/CompressController.java
@@ -2,9 +2,7 @@ package stirling.software.SPDF.controller.api.misc;
import java.awt.Image;
import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -75,194 +73,208 @@ public class CompressController {
long inputFileSize = Files.size(tempInputFile);
// Prepare the output file path
- Path tempOutputFile = Files.createTempFile("output_", ".pdf");
-
- // Determine initial optimization level based on expected size reduction, only if in
- // autoMode
- if (autoMode) {
- double sizeReductionRatio = expectedOutputSize / (double) inputFileSize;
- if (sizeReductionRatio > 0.7) {
- optimizeLevel = 1;
- } else if (sizeReductionRatio > 0.5) {
- optimizeLevel = 2;
- } else if (sizeReductionRatio > 0.35) {
- optimizeLevel = 3;
- } else {
- optimizeLevel = 3;
- }
- }
-
- boolean sizeMet = false;
- while (!sizeMet && optimizeLevel <= 4) {
- // Prepare the Ghostscript command
- List command = new ArrayList<>();
- command.add("gs");
- command.add("-sDEVICE=pdfwrite");
- command.add("-dCompatibilityLevel=1.4");
-
- switch (optimizeLevel) {
- case 1:
- command.add("-dPDFSETTINGS=/prepress");
- break;
- case 2:
- command.add("-dPDFSETTINGS=/printer");
- break;
- case 3:
- command.add("-dPDFSETTINGS=/ebook");
- break;
- case 4:
- command.add("-dPDFSETTINGS=/screen");
- break;
- default:
- command.add("-dPDFSETTINGS=/default");
- }
-
- command.add("-dNOPAUSE");
- command.add("-dQUIET");
- command.add("-dBATCH");
- command.add("-sOutputFile=" + tempOutputFile.toString());
- command.add(tempInputFile.toString());
-
- ProcessExecutorResult returnCode =
- ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT)
- .runCommandWithOutputHandling(command);
-
- // Check if file size is within expected size or not auto mode so instantly finish
- long outputFileSize = Files.size(tempOutputFile);
- if (outputFileSize <= expectedOutputSize || !autoMode) {
- sizeMet = true;
- } else {
- // Increase optimization level for next iteration
- optimizeLevel++;
- if (autoMode && optimizeLevel > 3) {
- System.out.println("Skipping level 4 due to bad results in auto mode");
- sizeMet = true;
- } else if (optimizeLevel == 5) {
+ Path tempOutputFile = null;
+ byte[] pdfBytes;
+ try {
+ tempOutputFile = Files.createTempFile("output_", ".pdf");
+ // Determine initial optimization level based on expected size reduction, only if in
+ // autoMode
+ if (autoMode) {
+ double sizeReductionRatio = expectedOutputSize / (double) inputFileSize;
+ if (sizeReductionRatio > 0.7) {
+ optimizeLevel = 1;
+ } else if (sizeReductionRatio > 0.5) {
+ optimizeLevel = 2;
+ } else if (sizeReductionRatio > 0.35) {
+ optimizeLevel = 3;
} else {
- System.out.println(
- "Increasing ghostscript optimisation level to " + optimizeLevel);
+ optimizeLevel = 3;
}
}
- }
- if (expectedOutputSize != null && autoMode) {
- long outputFileSize = Files.size(tempOutputFile);
- if (outputFileSize > expectedOutputSize) {
- try (PDDocument doc = Loader.loadPDF(new File(tempOutputFile.toString()))) {
- long previousFileSize = 0;
- double scaleFactor = 1.0;
- while (true) {
- for (PDPage page : doc.getPages()) {
- PDResources res = page.getResources();
+ boolean sizeMet = false;
+ while (!sizeMet && optimizeLevel <= 4) {
+ // Prepare the Ghostscript command
+ List command = new ArrayList<>();
+ command.add("gs");
+ command.add("-sDEVICE=pdfwrite");
+ command.add("-dCompatibilityLevel=1.4");
- for (COSName name : res.getXObjectNames()) {
- PDXObject xobj = res.getXObject(name);
- if (xobj instanceof PDImageXObject) {
- PDImageXObject image = (PDImageXObject) xobj;
+ switch (optimizeLevel) {
+ case 1:
+ command.add("-dPDFSETTINGS=/prepress");
+ break;
+ case 2:
+ command.add("-dPDFSETTINGS=/printer");
+ break;
+ case 3:
+ command.add("-dPDFSETTINGS=/ebook");
+ break;
+ case 4:
+ command.add("-dPDFSETTINGS=/screen");
+ break;
+ default:
+ command.add("-dPDFSETTINGS=/default");
+ }
- // Get the image in BufferedImage format
- BufferedImage bufferedImage = image.getImage();
+ command.add("-dNOPAUSE");
+ command.add("-dQUIET");
+ command.add("-dBATCH");
+ command.add("-sOutputFile=" + tempOutputFile.toString());
+ command.add(tempInputFile.toString());
- // Calculate the new dimensions
- int newWidth = (int) (bufferedImage.getWidth() * scaleFactor);
- int newHeight = (int) (bufferedImage.getHeight() * scaleFactor);
+ ProcessExecutorResult returnCode =
+ ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT)
+ .runCommandWithOutputHandling(command);
- // If the new dimensions are zero, skip this iteration
- if (newWidth == 0 || newHeight == 0) {
- continue;
+ // Check if file size is within expected size or not auto mode so instantly finish
+ long outputFileSize = Files.size(tempOutputFile);
+ if (outputFileSize <= expectedOutputSize || !autoMode) {
+ sizeMet = true;
+ } else {
+ // Increase optimization level for next iteration
+ optimizeLevel++;
+ if (autoMode && optimizeLevel > 4) {
+ System.out.println("Skipping level 5 due to bad results in auto mode");
+ sizeMet = true;
+ } else {
+ System.out.println(
+ "Increasing ghostscript optimisation level to " + optimizeLevel);
+ }
+ }
+ }
+
+ if (expectedOutputSize != null && autoMode) {
+ long outputFileSize = Files.size(tempOutputFile);
+ byte[] fileBytes = Files.readAllBytes(tempOutputFile);
+ if (outputFileSize > expectedOutputSize) {
+ try (PDDocument doc = Loader.loadPDF(fileBytes)) {
+ long previousFileSize = 0;
+ double scaleFactorConst = 0.9f;
+ double scaleFactor = 0.9f;
+ while (true) {
+ for (PDPage page : doc.getPages()) {
+ PDResources res = page.getResources();
+ if (res != null && res.getXObjectNames() != null) {
+ for (COSName name : res.getXObjectNames()) {
+ PDXObject xobj = res.getXObject(name);
+ if (xobj != null && xobj instanceof PDImageXObject) {
+ PDImageXObject image = (PDImageXObject) xobj;
+
+ // Get the image in BufferedImage format
+ BufferedImage bufferedImage = image.getImage();
+
+ // Calculate the new dimensions
+ int newWidth =
+ (int)
+ (bufferedImage.getWidth()
+ * scaleFactorConst);
+ int newHeight =
+ (int)
+ (bufferedImage.getHeight()
+ * scaleFactorConst);
+
+ // If the new dimensions are zero, skip this iteration
+ if (newWidth == 0 || newHeight == 0) {
+ continue;
+ }
+
+ // Otherwise, proceed with the scaling
+ Image scaledImage =
+ bufferedImage.getScaledInstance(
+ newWidth,
+ newHeight,
+ Image.SCALE_SMOOTH);
+
+ // Convert the scaled image back to a BufferedImage
+ BufferedImage scaledBufferedImage =
+ new BufferedImage(
+ newWidth,
+ newHeight,
+ BufferedImage.TYPE_INT_RGB);
+ scaledBufferedImage
+ .getGraphics()
+ .drawImage(scaledImage, 0, 0, null);
+
+ // Compress the scaled image
+ ByteArrayOutputStream compressedImageStream =
+ new ByteArrayOutputStream();
+ ImageIO.write(
+ scaledBufferedImage,
+ "jpeg",
+ compressedImageStream);
+ byte[] imageBytes = compressedImageStream.toByteArray();
+ compressedImageStream.close();
+
+ PDImageXObject compressedImage =
+ PDImageXObject.createFromByteArray(
+ doc,
+ imageBytes,
+ image.getCOSObject().toString());
+
+ // Replace the image in the resources with the
+ // compressed
+ // version
+ res.put(name, compressedImage);
+ }
}
-
- // Otherwise, proceed with the scaling
- Image scaledImage =
- bufferedImage.getScaledInstance(
- newWidth, newHeight, Image.SCALE_SMOOTH);
-
- // Convert the scaled image back to a BufferedImage
- BufferedImage scaledBufferedImage =
- new BufferedImage(
- newWidth,
- newHeight,
- BufferedImage.TYPE_INT_RGB);
- scaledBufferedImage
- .getGraphics()
- .drawImage(scaledImage, 0, 0, null);
-
- // Compress the scaled image
- ByteArrayOutputStream compressedImageStream =
- new ByteArrayOutputStream();
- ImageIO.write(
- scaledBufferedImage, "jpeg", compressedImageStream);
- byte[] imageBytes = compressedImageStream.toByteArray();
- compressedImageStream.close();
-
- // Convert compressed image back to PDImageXObject
- ByteArrayInputStream bais =
- new ByteArrayInputStream(imageBytes);
- PDImageXObject compressedImage =
- PDImageXObject.createFromByteArray(
- doc,
- imageBytes,
- image.getCOSObject().toString());
-
- // Replace the image in the resources with the compressed
- // version
- res.put(name, compressedImage);
}
}
- }
- // save the document to tempOutputFile again
- doc.save(tempOutputFile.toString());
+ // save the document to tempOutputFile again
+ doc.save(tempOutputFile.toString());
- long currentSize = Files.size(tempOutputFile);
- // Check if the overall PDF size is still larger than expectedOutputSize
- if (currentSize > expectedOutputSize) {
- // Log the current file size and scaleFactor
+ long currentSize = Files.size(tempOutputFile);
+ // Check if the overall PDF size is still larger than expectedOutputSize
+ if (currentSize > expectedOutputSize) {
+ // Log the current file size and scaleFactor
- System.out.println(
- "Current file size: "
- + FileUtils.byteCountToDisplaySize(currentSize));
- System.out.println("Current scale factor: " + scaleFactor);
+ System.out.println(
+ "Current file size: "
+ + FileUtils.byteCountToDisplaySize(currentSize));
+ System.out.println("Current scale factor: " + scaleFactor);
- // The file is still too large, reduce scaleFactor and try again
- scaleFactor *= 0.9; // reduce scaleFactor by 10%
- // Avoid scaleFactor being too small, causing the image to shrink to 0
- if (scaleFactor < 0.2 || previousFileSize == currentSize) {
- throw new RuntimeException(
- "Could not reach the desired size without excessively degrading image quality, lowest size recommended is "
- + FileUtils.byteCountToDisplaySize(currentSize)
- + ", "
- + currentSize
- + " bytes");
+ // The file is still too large, reduce scaleFactor and try again
+ scaleFactor *= 0.9f; // reduce scaleFactor by 10%
+ // Avoid scaleFactor being too small, causing the image to shrink to
+ // 0
+ if (scaleFactor < 0.2f || previousFileSize == currentSize) {
+ throw new RuntimeException(
+ "Could not reach the desired size without excessively degrading image quality, lowest size recommended is "
+ + FileUtils.byteCountToDisplaySize(currentSize)
+ + ", "
+ + currentSize
+ + " bytes");
+ }
+ previousFileSize = currentSize;
+ } else {
+ // The file is small enough, break the loop
+ break;
}
- previousFileSize = currentSize;
- } else {
- // The file is small enough, break the loop
- break;
}
}
}
}
+
+ // Read the optimized PDF file
+ pdfBytes = Files.readAllBytes(tempOutputFile);
+
+ // Check if optimized file is larger than the original
+ if (pdfBytes.length > inputFileSize) {
+ // Log the occurrence
+ logger.warn(
+ "Optimized file is larger than the original. Returning the original file instead.");
+
+ // Read the original file again
+ pdfBytes = Files.readAllBytes(tempInputFile);
+ }
+ } finally {
+ // Clean up the temporary files
+ Files.delete(tempInputFile);
+ Files.delete(tempOutputFile);
}
- // Read the optimized PDF file
- byte[] pdfBytes = Files.readAllBytes(tempOutputFile);
-
- // Check if optimized file is larger than the original
- if (pdfBytes.length > inputFileSize) {
- // Log the occurrence
- logger.warn(
- "Optimized file is larger than the original. Returning the original file instead.");
-
- // Read the original file again
- pdfBytes = Files.readAllBytes(tempInputFile);
- }
-
- // Clean up the temporary files
- Files.delete(tempInputFile);
- Files.delete(tempOutputFile);
-
// Return the optimized PDF as a response
String outputFilename =
Filenames.toSimpleFileName(inputFile.getOriginalFilename())
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java
index da684280..9ed00dd8 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/ExtractImageScansController.java
@@ -9,7 +9,6 @@ import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@@ -73,111 +72,151 @@ public class ExtractImageScansController {
List images = new ArrayList<>();
- // Check if input file is a PDF
- if ("pdf".equalsIgnoreCase(extension)) {
- // Load PDF document
- try (PDDocument document = Loader.loadPDF(form.getFileInput().getBytes())) {
- PDFRenderer pdfRenderer = new PDFRenderer(document);
- int pageCount = document.getNumberOfPages();
- images = new ArrayList<>();
+ List tempImageFiles = new ArrayList<>();
+ Path tempInputFile = null;
+ Path tempZipFile = null;
+ List tempDirs = new ArrayList<>();
- // Create images of all pages
- for (int i = 0; i < pageCount; i++) {
- // Create temp file to save the image
- Path tempFile = Files.createTempFile("image_", ".png");
+ try {
+ // Check if input file is a PDF
+ if ("pdf".equalsIgnoreCase(extension)) {
+ // Load PDF document
+ try (PDDocument document = Loader.loadPDF(form.getFileInput().getBytes())) {
+ PDFRenderer pdfRenderer = new PDFRenderer(document);
+ pdfRenderer.setSubsamplingAllowed(true);
+ int pageCount = document.getNumberOfPages();
+ images = new ArrayList<>();
- // Render image and save as temp file
- BufferedImage image = pdfRenderer.renderImageWithDPI(i, 300);
- ImageIO.write(image, "png", tempFile.toFile());
+ // Create images of all pages
+ for (int i = 0; i < pageCount; i++) {
+ // Create temp file to save the image
+ Path tempFile = Files.createTempFile("image_", ".png");
- // Add temp file path to images list
- images.add(tempFile.toString());
+ // Render image and save as temp file
+ BufferedImage image = pdfRenderer.renderImageWithDPI(i, 300);
+ ImageIO.write(image, "png", tempFile.toFile());
+
+ // Add temp file path to images list
+ images.add(tempFile.toString());
+ tempImageFiles.add(tempFile);
+ }
}
+ } else {
+ tempInputFile = Files.createTempFile("input_", "." + extension);
+ Files.copy(
+ form.getFileInput().getInputStream(),
+ tempInputFile,
+ StandardCopyOption.REPLACE_EXISTING);
+ // Add input file path to images list
+ images.add(tempInputFile.toString());
}
- } else {
- Path tempInputFile = Files.createTempFile("input_", "." + extension);
- Files.copy(
- form.getFileInput().getInputStream(),
- tempInputFile,
- StandardCopyOption.REPLACE_EXISTING);
- // Add input file path to images list
- images.add(tempInputFile.toString());
- }
- List processedImageBytes = new ArrayList<>();
+ List processedImageBytes = new ArrayList<>();
- // Process each image
- for (int i = 0; i < images.size(); i++) {
+ // Process each image
+ for (int i = 0; i < images.size(); i++) {
- Path tempDir = Files.createTempDirectory("openCV_output");
- List command =
- new ArrayList<>(
- Arrays.asList(
- "python3",
- "./scripts/split_photos.py",
- images.get(i),
- tempDir.toString(),
- "--angle_threshold",
- String.valueOf(form.getAngleThreshold()),
- "--tolerance",
- String.valueOf(form.getTolerance()),
- "--min_area",
- String.valueOf(form.getMinArea()),
- "--min_contour_area",
- String.valueOf(form.getMinContourArea()),
- "--border_size",
- String.valueOf(form.getBorderSize())));
+ Path tempDir = Files.createTempDirectory("openCV_output");
+ tempDirs.add(tempDir);
+ List command =
+ new ArrayList<>(
+ Arrays.asList(
+ "python3",
+ "./scripts/split_photos.py",
+ images.get(i),
+ tempDir.toString(),
+ "--angle_threshold",
+ String.valueOf(form.getAngleThreshold()),
+ "--tolerance",
+ String.valueOf(form.getTolerance()),
+ "--min_area",
+ String.valueOf(form.getMinArea()),
+ "--min_contour_area",
+ String.valueOf(form.getMinContourArea()),
+ "--border_size",
+ String.valueOf(form.getBorderSize())));
- // Run CLI command
- ProcessExecutorResult returnCode =
- ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV)
- .runCommandWithOutputHandling(command);
+ // Run CLI command
+ ProcessExecutorResult returnCode =
+ ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV)
+ .runCommandWithOutputHandling(command);
- // Read the output photos in temp directory
- List tempOutputFiles = Files.list(tempDir).sorted().collect(Collectors.toList());
- for (Path tempOutputFile : tempOutputFiles) {
- byte[] imageBytes = Files.readAllBytes(tempOutputFile);
- processedImageBytes.add(imageBytes);
+ // Read the output photos in temp directory
+ List tempOutputFiles = Files.list(tempDir).sorted().toList();
+ for (Path tempOutputFile : tempOutputFiles) {
+ byte[] imageBytes = Files.readAllBytes(tempOutputFile);
+ processedImageBytes.add(imageBytes);
+ }
+ // Clean up the temporary directory
+ FileUtils.deleteDirectory(tempDir.toFile());
}
- // Clean up the temporary directory
- FileUtils.deleteDirectory(tempDir.toFile());
- }
- // Create zip file if multiple images
- if (processedImageBytes.size() > 1) {
- String outputZipFilename = fileName.replaceFirst("[.][^.]+$", "") + "_processed.zip";
- Path tempZipFile = Files.createTempFile("output_", ".zip");
+ // Create zip file if multiple images
+ if (processedImageBytes.size() > 1) {
+ String outputZipFilename =
+ fileName.replaceFirst(REPLACEFIRST, "") + "_processed.zip";
+ tempZipFile = Files.createTempFile("output_", ".zip");
- try (ZipOutputStream zipOut =
- new ZipOutputStream(new FileOutputStream(tempZipFile.toFile()))) {
- // Add processed images to the zip
- for (int i = 0; i < processedImageBytes.size(); i++) {
- ZipEntry entry =
- new ZipEntry(
- fileName.replaceFirst("[.][^.]+$", "")
- + "_"
- + (i + 1)
- + ".png");
- zipOut.putNextEntry(entry);
- zipOut.write(processedImageBytes.get(i));
- zipOut.closeEntry();
+ try (ZipOutputStream zipOut =
+ new ZipOutputStream(new FileOutputStream(tempZipFile.toFile()))) {
+ // Add processed images to the zip
+ for (int i = 0; i < processedImageBytes.size(); i++) {
+ ZipEntry entry =
+ new ZipEntry(
+ fileName.replaceFirst(REPLACEFIRST, "")
+ + "_"
+ + (i + 1)
+ + ".png");
+ zipOut.putNextEntry(entry);
+ zipOut.write(processedImageBytes.get(i));
+ zipOut.closeEntry();
+ }
+ }
+
+ byte[] zipBytes = Files.readAllBytes(tempZipFile);
+
+ // Clean up the temporary zip file
+ Files.delete(tempZipFile);
+
+ return WebResponseUtils.bytesToWebResponse(
+ zipBytes, outputZipFilename, MediaType.APPLICATION_OCTET_STREAM);
+ } else {
+ // Return the processed image as a response
+ byte[] imageBytes = processedImageBytes.get(0);
+ return WebResponseUtils.bytesToWebResponse(
+ imageBytes,
+ fileName.replaceFirst(REPLACEFIRST, "") + ".png",
+ MediaType.IMAGE_PNG);
+ }
+ } finally {
+ // Cleanup logic for all temporary files and directories
+ tempImageFiles.forEach(
+ path -> {
+ try {
+ Files.deleteIfExists(path);
+ } catch (IOException e) {
+ logger.error("Failed to delete temporary image file: " + path, e);
+ }
+ });
+
+ if (tempZipFile != null && Files.exists(tempZipFile)) {
+ try {
+ Files.delete(tempZipFile);
+ } catch (IOException e) {
+ logger.error("Failed to delete temporary zip file: " + tempZipFile, e);
}
}
- byte[] zipBytes = Files.readAllBytes(tempZipFile);
-
- // Clean up the temporary zip file
- Files.delete(tempZipFile);
-
- return WebResponseUtils.bytesToWebResponse(
- zipBytes, outputZipFilename, MediaType.APPLICATION_OCTET_STREAM);
- } else {
- // Return the processed image as a response
- byte[] imageBytes = processedImageBytes.get(0);
- return WebResponseUtils.bytesToWebResponse(
- imageBytes,
- fileName.replaceFirst("[.][^.]+$", "") + ".png",
- MediaType.IMAGE_PNG);
+ tempDirs.forEach(
+ dir -> {
+ try {
+ FileUtils.deleteDirectory(dir.toFile());
+ } catch (IOException e) {
+ logger.error("Failed to delete temporary directory: " + dir, e);
+ }
+ });
}
}
+
+ private static final String REPLACEFIRST = "[.][^.]+$";
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanControllerWIP.java b/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanControllerWIP.java
index 789bf17e..2400c0d3 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanControllerWIP.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanControllerWIP.java
@@ -1,27 +1,29 @@
package stirling.software.SPDF.controller.api.misc;
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
import java.awt.Color;
+import java.awt.GradientPaint;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Path2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
-import java.awt.image.RescaleOp;
import java.io.ByteArrayOutputStream;
-import java.io.File;
import java.io.IOException;
import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Random;
-import javax.imageio.ImageIO;
-
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
-import org.apache.pdfbox.pdmodel.PDPage;
-import org.apache.pdfbox.pdmodel.PDPageContentStream;
-import org.apache.pdfbox.pdmodel.common.PDRectangle;
-import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
+import org.apache.pdfbox.pdmodel.graphics.image.JPEGFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
@@ -29,6 +31,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
@@ -39,6 +42,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.PDFFile;
+import stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -48,97 +52,39 @@ public class FakeScanControllerWIP {
private static final Logger logger = LoggerFactory.getLogger(FakeScanControllerWIP.class);
- // TODO
+ // TODO finish
+ @PostMapping(consumes = "multipart/form-data", value = "/fake-scan")
@Hidden
- // @PostMapping(consumes = "multipart/form-data", value = "/fakeScan")
@Operation(
summary = "Repair a PDF file",
description =
"This endpoint repairs a given PDF file by running Ghostscript command. The PDF is first saved to a temporary location, repaired, read back, and then returned as a response.")
- public ResponseEntity repairPdf(@ModelAttribute PDFFile request) throws IOException {
+ public ResponseEntity fakeScan(@ModelAttribute PDFFile request) throws IOException {
MultipartFile inputFile = request.getFileInput();
+ // Load the PDF document
PDDocument document = Loader.loadPDF(inputFile.getBytes());
- PDFRenderer pdfRenderer = new PDFRenderer(document);
- for (int page = 0; page < document.getNumberOfPages(); ++page) {
- BufferedImage image = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB);
- ImageIO.write(image, "png", new File("scanned-" + (page + 1) + ".png"));
+ PDFRenderer renderer = new PDFRenderer(document);
+ List images = new ArrayList<>();
+ // Convert each page to an image
+ for (int i = 0; i < document.getNumberOfPages(); i++) {
+ BufferedImage image = renderer.renderImageWithDPI(i, 150, ImageType.GRAY);
+ images.add(processImage(image));
}
document.close();
- // Constants
- int scannedness = 90; // Value between 0 and 100
- int dirtiness = 0; // Value between 0 and 100
-
- // Load the source image
- BufferedImage sourceImage = ImageIO.read(new File("scanned-1.png"));
-
- // Create the destination image
- BufferedImage destinationImage =
- new BufferedImage(
- sourceImage.getWidth(), sourceImage.getHeight(), sourceImage.getType());
-
- // Apply a brightness and contrast effect based on the "scanned-ness"
- float scaleFactor = 1.0f + (scannedness / 100.0f) * 0.5f; // Between 1.0 and 1.5
- float offset = scannedness * 1.5f; // Between 0 and 150
- BufferedImageOp op = new RescaleOp(scaleFactor, offset, null);
- op.filter(sourceImage, destinationImage);
-
- // Apply a rotation effect
- double rotationRequired =
- Math.toRadians(
- (new SecureRandom().nextInt(3 - 1)
- + 1)); // Random angle between 1 and 3 degrees
- double locationX = destinationImage.getWidth() / 2;
- double locationY = destinationImage.getHeight() / 2;
- AffineTransform tx =
- AffineTransform.getRotateInstance(rotationRequired, locationX, locationY);
- AffineTransformOp rotateOp = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
- destinationImage = rotateOp.filter(destinationImage, null);
-
- // Apply a blur effect based on the "scanned-ness"
- float blurIntensity = scannedness / 100.0f * 0.2f; // Between 0.0 and 0.2
- float[] matrix = {
- blurIntensity, blurIntensity, blurIntensity,
- blurIntensity, blurIntensity, blurIntensity,
- blurIntensity, blurIntensity, blurIntensity
- };
- BufferedImageOp blurOp =
- new ConvolveOp(new Kernel(3, 3, matrix), ConvolveOp.EDGE_NO_OP, null);
- destinationImage = blurOp.filter(destinationImage, null);
-
- // Add noise to the image based on the "dirtiness"
- Random random = new SecureRandom();
- for (int y = 0; y < destinationImage.getHeight(); y++) {
- for (int x = 0; x < destinationImage.getWidth(); x++) {
- if (random.nextInt(100) < dirtiness) {
- // Change the pixel color to black randomly based on the "dirtiness"
- destinationImage.setRGB(x, y, Color.BLACK.getRGB());
- }
- }
- }
-
- // Save the image
- ImageIO.write(destinationImage, "PNG", new File("scanned-1.png"));
-
- PDDocument documentOut = new PDDocument();
- for (int page = 1; page <= document.getNumberOfPages(); ++page) {
- BufferedImage bim = ImageIO.read(new File("scanned-" + page + ".png"));
-
- // Adjust the dimensions of the page
- PDPage pdPage = new PDPage(new PDRectangle(bim.getWidth() - 1, bim.getHeight() - 1));
- documentOut.addPage(pdPage);
-
- PDImageXObject pdImage = LosslessFactory.createFromImage(documentOut, bim);
- PDPageContentStream contentStream = new PDPageContentStream(documentOut, pdPage);
-
- // Draw the image with a slight offset and enlarged dimensions
- contentStream.drawImage(pdImage, -1, -1, bim.getWidth() + 2, bim.getHeight() + 2);
- contentStream.close();
- }
+ // Create a new PDF document with the processed images
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- documentOut.save(baos);
- documentOut.close();
+ PDDocument newDocument = new PDDocument();
+ for (BufferedImage img : images) {
+ // PDPageContentStream contentStream = new PDPageContentStream(newDocument, new
+ // PDPage());
+ PDImageXObject pdImage = JPEGFactory.createFromImage(newDocument, img);
+ PdfUtils.addImageToDocument(newDocument, pdImage, "maintainAspectRatio", false);
+ }
+
+ newDocument.save(baos);
+ newDocument.close();
// Return the optimized PDF as a response
String outputFilename =
@@ -147,4 +93,232 @@ public class FakeScanControllerWIP {
+ "_scanned.pdf";
return WebResponseUtils.boasToWebResponse(baos, outputFilename);
}
+
+ public BufferedImage processImage(BufferedImage image) {
+ // Rotation
+
+ image = softenEdges(image, 50);
+ image = rotate(image, 1);
+
+ image = applyGaussianBlur(image, 0.5);
+ addGaussianNoise(image, 0.5);
+ image = linearStretch(image);
+ addDustAndHairs(image, 3);
+ return image;
+ }
+
+ private BufferedImage rotate(BufferedImage image, double rotation) {
+
+ double rotationRequired = Math.toRadians(rotation);
+ double locationX = image.getWidth() / 2;
+ double locationY = image.getHeight() / 2;
+ AffineTransform tx =
+ AffineTransform.getRotateInstance(rotationRequired, locationX, locationY);
+ AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BICUBIC);
+ return op.filter(image, null);
+ }
+
+ private BufferedImage applyGaussianBlur(BufferedImage image, double sigma) {
+ int radius = 3; // Fixed radius size for simplicity
+
+ int size = 2 * radius + 1;
+ float[] data = new float[size * size];
+ double sum = 0.0;
+
+ for (int i = -radius; i <= radius; i++) {
+ for (int j = -radius; j <= radius; j++) {
+ double xDistance = i * i;
+ double yDistance = j * j;
+ double g = Math.exp(-(xDistance + yDistance) / (2 * sigma * sigma));
+ data[(i + radius) * size + j + radius] = (float) g;
+ sum += g;
+ }
+ }
+
+ // Normalize the kernel
+ for (int i = 0; i < data.length; i++) {
+ data[i] /= sum;
+ }
+
+ Kernel kernel = new Kernel(size, size, data);
+ BufferedImageOp op = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
+ return op.filter(image, null);
+ }
+
+ public BufferedImage softenEdges(BufferedImage image, int featherRadius) {
+ int width = image.getWidth();
+ int height = image.getHeight();
+ BufferedImage output = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+
+ Graphics2D g2 = output.createGraphics();
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+ g2.setRenderingHint(
+ RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+
+ g2.drawImage(image, 0, 0, null);
+ g2.setComposite(AlphaComposite.DstIn);
+
+ // Top edge
+ g2.setPaint(
+ new GradientPaint(
+ 0,
+ 0,
+ new Color(0, 0, 0, 1f),
+ 0,
+ featherRadius * 2,
+ new Color(0, 0, 0, 0f)));
+ g2.fillRect(0, 0, width, featherRadius);
+
+ // Bottom edge
+ g2.setPaint(
+ new GradientPaint(
+ 0,
+ height - featherRadius * 2,
+ new Color(0, 0, 0, 0f),
+ 0,
+ height,
+ new Color(0, 0, 0, 1f)));
+ g2.fillRect(0, height - featherRadius, width, featherRadius);
+
+ // Left edge
+ g2.setPaint(
+ new GradientPaint(
+ 0,
+ 0,
+ new Color(0, 0, 0, 1f),
+ featherRadius * 2,
+ 0,
+ new Color(0, 0, 0, 0f)));
+ g2.fillRect(0, 0, featherRadius, height);
+
+ // Right edge
+ g2.setPaint(
+ new GradientPaint(
+ width - featherRadius * 2,
+ 0,
+ new Color(0, 0, 0, 0f),
+ width,
+ 0,
+ new Color(0, 0, 0, 1f)));
+ g2.fillRect(width - featherRadius, 0, featherRadius, height);
+
+ g2.dispose();
+
+ return output;
+ }
+
+ private void addDustAndHairs(BufferedImage image, float intensity) {
+ int width = image.getWidth();
+ int height = image.getHeight();
+ Graphics2D g2d = image.createGraphics();
+ Random random = new SecureRandom();
+
+ // Set rendering hints for better quality
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+ // Calculate the number of artifacts based on intensity
+ int numSpots = (int) (intensity * 10);
+ int numHairs = (int) (intensity * 20);
+
+ // Add spots with more variable sizes
+ g2d.setColor(new Color(100, 100, 100, 50)); // Semi-transparent gray
+ for (int i = 0; i < numSpots; i++) {
+ int x = random.nextInt(width);
+ int y = random.nextInt(height);
+ int ovalSize = 1 + random.nextInt(3); // Base size + variable component
+ if (random.nextFloat() > 0.9) {
+ // 10% chance to get a larger spot
+ ovalSize += random.nextInt(3);
+ }
+ g2d.fill(new Ellipse2D.Double(x, y, ovalSize, ovalSize));
+ }
+
+ // Add hairs
+ g2d.setStroke(new BasicStroke(0.5f)); // Thin stroke for hairs
+ g2d.setColor(new Color(80, 80, 80, 40)); // Slightly lighter and more transparent
+ for (int i = 0; i < numHairs; i++) {
+ int x1 = random.nextInt(width);
+ int y1 = random.nextInt(height);
+ int x2 = x1 + random.nextInt(20) - 10; // Random length and direction
+ int y2 = y1 + random.nextInt(20) - 10;
+ Path2D.Double hair = new Path2D.Double();
+ hair.moveTo(x1, y1);
+ hair.curveTo(x1, y1, (x1 + x2) / 2, (y1 + y2) / 2, x2, y2);
+ g2d.draw(hair);
+ }
+
+ g2d.dispose();
+ }
+
+ private void addGaussianNoise(BufferedImage image, double strength) {
+ Random rand = new SecureRandom();
+ int width = image.getWidth();
+ int height = image.getHeight();
+
+ for (int i = 0; i < width; i++) {
+ for (int j = 0; j < height; j++) {
+ int rgba = image.getRGB(i, j);
+ int alpha = (rgba >> 24) & 0xff;
+ int red = (rgba >> 16) & 0xff;
+ int green = (rgba >> 8) & 0xff;
+ int blue = rgba & 0xff;
+
+ // Apply Gaussian noise
+ red = (int) (red + rand.nextGaussian() * strength);
+ green = (int) (green + rand.nextGaussian() * strength);
+ blue = (int) (blue + rand.nextGaussian() * strength);
+
+ // Clamping values to the 0-255 range
+ red = Math.min(Math.max(0, red), 255);
+ green = Math.min(Math.max(0, green), 255);
+ blue = Math.min(Math.max(0, blue), 255);
+
+ image.setRGB(i, j, (alpha << 24) | (red << 16) | (green << 8) | blue);
+ }
+ }
+ }
+
+ public BufferedImage linearStretch(BufferedImage image) {
+ int width = image.getWidth();
+ int height = image.getHeight();
+ int min = 255;
+ int max = 0;
+
+ // First pass: find the min and max grayscale values
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ int rgb = image.getRGB(x, y);
+ int gray =
+ (int)
+ (((rgb >> 16) & 0xff) * 0.299
+ + ((rgb >> 8) & 0xff) * 0.587
+ + (rgb & 0xff) * 0.114); // Convert to grayscale
+ if (gray < min) min = gray;
+ if (gray > max) max = gray;
+ }
+ }
+
+ // Second pass: stretch the histogram
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ int rgb = image.getRGB(x, y);
+ int alpha = (rgb >> 24) & 0xff;
+ int red = (rgb >> 16) & 0xff;
+ int green = (rgb >> 8) & 0xff;
+ int blue = rgb & 0xff;
+
+ // Apply linear stretch to each channel
+ red = (int) (((red - min) / (float) (max - min)) * 255);
+ green = (int) (((green - min) / (float) (max - min)) * 255);
+ blue = (int) (((blue - min) / (float) (max - min)) * 255);
+
+ // Set new RGB value maintaining the alpha channel
+ rgb = (alpha << 24) | (red << 16) | (green << 8) | blue;
+ image.setRGB(x, y, rgb);
+ }
+ }
+
+ return image;
+ }
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java
new file mode 100644
index 00000000..bdc0a478
--- /dev/null
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/FlattenController.java
@@ -0,0 +1,84 @@
+package stirling.software.SPDF.controller.api.misc;
+
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+
+import org.apache.pdfbox.Loader;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDPageContentStream;
+import org.apache.pdfbox.pdmodel.graphics.image.JPEGFactory;
+import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
+import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
+import org.apache.pdfbox.rendering.ImageType;
+import org.apache.pdfbox.rendering.PDFRenderer;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import io.github.pixee.security.Filenames;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+
+import stirling.software.SPDF.model.PdfMetadata;
+import stirling.software.SPDF.model.api.misc.FlattenRequest;
+import stirling.software.SPDF.utils.PdfUtils;
+import stirling.software.SPDF.utils.WebResponseUtils;
+
+@RestController
+@RequestMapping("/api/v1/misc")
+@Tag(name = "Misc", description = "Miscellaneous APIs")
+public class FlattenController {
+
+ @PostMapping(consumes = "multipart/form-data", value = "/flatten")
+ @Operation(
+ summary = "Flatten PDF form fields or full page",
+ description =
+ "Flattening just PDF form fields or converting each page to images to make text unselectable. Input: PDF, Output: PDF. Type: SISO")
+ public ResponseEntity flatten(@ModelAttribute FlattenRequest request) throws Exception {
+ MultipartFile file = request.getFileInput();
+
+ PDDocument document = Loader.loadPDF(file.getBytes());
+ PdfMetadata metadata = PdfUtils.extractMetadataFromPdf(document);
+ Boolean flattenOnlyForms = request.getFlattenOnlyForms();
+
+ if (Boolean.TRUE.equals(flattenOnlyForms)) {
+ PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
+ if (acroForm != null) {
+ acroForm.flatten();
+ }
+ return WebResponseUtils.pdfDocToWebResponse(
+ document, Filenames.toSimpleFileName(file.getOriginalFilename()));
+ } else {
+ // flatten whole page aka convert each page to image and readd it (making text
+ // unselectable)
+ PDFRenderer pdfRenderer = new PDFRenderer(document);
+ PDDocument newDocument = new PDDocument();
+ int numPages = document.getNumberOfPages();
+ for (int i = 0; i < numPages; i++) {
+ try {
+ BufferedImage image = pdfRenderer.renderImageWithDPI(i, 300, ImageType.RGB);
+ PDPage page = new PDPage();
+ page.setMediaBox(document.getPage(i).getMediaBox());
+ newDocument.addPage(page);
+ try (PDPageContentStream contentStream =
+ new PDPageContentStream(newDocument, page)) {
+ PDImageXObject pdImage = JPEGFactory.createFromImage(newDocument, image);
+ float pageWidth = page.getMediaBox().getWidth();
+ float pageHeight = page.getMediaBox().getHeight();
+
+ contentStream.drawImage(pdImage, 0, 0, pageWidth, pageHeight);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ PdfUtils.setMetadataToPdf(newDocument, metadata);
+ return WebResponseUtils.pdfDocToWebResponse(
+ newDocument, Filenames.toSimpleFileName(file.getOriginalFilename()));
+ }
+ }
+}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java
index 542e3c6d..07947587 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java
@@ -41,7 +41,7 @@ public class OCRController {
private static final Logger logger = LoggerFactory.getLogger(OCRController.class);
public List getAvailableTesseractLanguages() {
- String tessdataDir = "/usr/share/tesseract-ocr/5/tessdata";
+ String tessdataDir = "/usr/share/tessdata";
File[] files = new File(tessdataDir).listFiles();
if (files == null) {
return Collections.emptyList();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java
new file mode 100644
index 00000000..bc0a6715
--- /dev/null
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/PrintFileController.java
@@ -0,0 +1,105 @@
+package stirling.software.SPDF.controller.api.misc;
+
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import java.io.IOException;
+import java.util.Arrays;
+
+import javax.imageio.ImageIO;
+import javax.print.PrintService;
+import javax.print.PrintServiceLookup;
+
+import org.apache.pdfbox.Loader;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.printing.PDFPageable;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ModelAttribute;
+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.tags.Tag;
+
+import stirling.software.SPDF.model.api.misc.PrintFileRequest;
+
+@RestController
+@RequestMapping("/api/v1/misc")
+@Tag(name = "Misc", description = "Miscellaneous APIs")
+public class PrintFileController {
+
+ // TODO
+ // @PostMapping(value = "/print-file", consumes = "multipart/form-data")
+ // @Operation(
+ // summary = "Prints PDF/Image file to a set printer",
+ // description =
+ // "Input of PDF or Image along with a printer name/URL/IP to match against to
+ // send it to (Fire and forget) Input:Any Output:N/A Type:SISO")
+ public ResponseEntity printFile(@ModelAttribute PrintFileRequest request)
+ throws IOException {
+ MultipartFile file = request.getFileInput();
+ String printerName = request.getPrinterName();
+ String contentType = file.getContentType();
+ try {
+ // Find matching printer
+ PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
+ PrintService selectedService =
+ Arrays.stream(services)
+ .filter(
+ service ->
+ service.getName().toLowerCase().contains(printerName))
+ .findFirst()
+ .orElseThrow(
+ () ->
+ new IllegalArgumentException(
+ "No matching printer found"));
+
+ System.out.println("Selected Printer: " + selectedService.getName());
+
+ if ("application/pdf".equals(contentType)) {
+ PDDocument document = Loader.loadPDF(file.getBytes());
+ PrinterJob job = PrinterJob.getPrinterJob();
+ job.setPrintService(selectedService);
+ job.setPageable(new PDFPageable(document));
+ job.print();
+ document.close();
+ } else if (contentType.startsWith("image/")) {
+ BufferedImage image = ImageIO.read(file.getInputStream());
+ PrinterJob job = PrinterJob.getPrinterJob();
+ job.setPrintService(selectedService);
+ job.setPrintable(
+ new Printable() {
+ public int print(
+ Graphics graphics, PageFormat pageFormat, int pageIndex)
+ throws PrinterException {
+ if (pageIndex != 0) {
+ return NO_SUCH_PAGE;
+ }
+ Graphics2D g2d = (Graphics2D) graphics;
+ g2d.translate(
+ pageFormat.getImageableX(), pageFormat.getImageableY());
+ g2d.drawImage(
+ image,
+ 0,
+ 0,
+ (int) pageFormat.getImageableWidth(),
+ (int) pageFormat.getImageableHeight(),
+ null);
+ return PAGE_EXISTS;
+ }
+ });
+ job.print();
+ }
+ return new ResponseEntity<>(
+ "File printed successfully to " + selectedService.getName(), HttpStatus.OK);
+ } catch (Exception e) {
+ System.err.println("Failed to print: " + e.getMessage());
+ return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
+ }
+ }
+}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java
index 3b541b6c..e5d326a9 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java
@@ -88,7 +88,7 @@ public class StampController {
// Load the input PDF
PDDocument document = Loader.loadPDF(pdfFile.getBytes());
- List pageNumbers = request.getPageNumbersList(document, false);
+ List pageNumbers = request.getPageNumbersList(document, true);
for (int pageIndex : pageNumbers) {
int zeroBasedIndex = pageIndex - 1;
diff --git a/src/main/java/stirling/software/SPDF/controller/api/pipeline/ApiDocService.java b/src/main/java/stirling/software/SPDF/controller/api/pipeline/ApiDocService.java
index 02c37e5c..c773c976 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/pipeline/ApiDocService.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/pipeline/ApiDocService.java
@@ -36,7 +36,7 @@ public class ApiDocService {
private String getApiDocsUrl() {
String contextPath = servletContext.getContextPath();
- String port = SPdfApplication.getPort();
+ String port = SPdfApplication.getStaticPort();
return "http://localhost:" + port + contextPath + "/v1/api-docs";
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java
index 0a53daf0..dfa45096 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java
@@ -12,7 +12,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
-import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
@@ -50,9 +49,6 @@ public class PipelineController {
@PostMapping("/handleData")
public ResponseEntity handleData(@ModelAttribute HandleDataRequest request)
throws JsonMappingException, JsonProcessingException {
- if (!Boolean.TRUE.equals(applicationProperties.getSystem().getEnableAlphaFunctionality())) {
- return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
- }
MultipartFile[] files = request.getFileInput();
String jsonString = request.getJson();
diff --git a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineDirectoryProcessor.java b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineDirectoryProcessor.java
index 80fdd71c..c61b29e9 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineDirectoryProcessor.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineDirectoryProcessor.java
@@ -26,7 +26,6 @@ import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
-import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.PipelineConfig;
import stirling.software.SPDF.model.PipelineOperation;
@@ -36,7 +35,6 @@ public class PipelineDirectoryProcessor {
private static final Logger logger = LoggerFactory.getLogger(PipelineDirectoryProcessor.class);
@Autowired private ObjectMapper objectMapper;
@Autowired private ApiDocService apiDocService;
- @Autowired private ApplicationProperties applicationProperties;
final String watchedFoldersDir = "./pipeline/watchedFolders/";
final String finishedFoldersDir = "./pipeline/finishedFolders/";
@@ -45,9 +43,6 @@ public class PipelineDirectoryProcessor {
@Scheduled(fixedRate = 60000)
public void scanFolders() {
- if (!Boolean.TRUE.equals(applicationProperties.getSystem().getEnableAlphaFunctionality())) {
- return;
- }
Path watchedFolderPath = Paths.get(watchedFoldersDir);
if (!Files.exists(watchedFolderPath)) {
try {
diff --git a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java
index c327cdd8..515dd4fe 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineProcessor.java
@@ -64,7 +64,7 @@ public class PipelineProcessor {
private String getBaseUrl() {
String contextPath = servletContext.getContextPath();
- String port = SPdfApplication.getPort();
+ String port = SPdfApplication.getStaticPort();
return "http://localhost:" + port + contextPath + "/";
}
diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java b/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java
index 0f482647..8a2a67c0 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java
@@ -83,6 +83,7 @@ public class RedactController {
if (convertPDFToImage) {
PDDocument imageDocument = new PDDocument();
PDFRenderer pdfRenderer = new PDFRenderer(document);
+ pdfRenderer.setSubsamplingAllowed(true);
for (int page = 0; page < document.getNumberOfPages(); ++page) {
BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB);
PDPage newPage = new PDPage(new PDRectangle(bim.getWidth(), bim.getHeight()));
diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java b/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java
index 6dfbf044..dd2c79da 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java
@@ -54,33 +54,32 @@ public class SanitizeController {
boolean removeLinks = request.isRemoveLinks();
boolean removeFonts = request.isRemoveFonts();
- try (PDDocument document = Loader.loadPDF(inputFile.getBytes())) {
- if (removeJavaScript) {
- sanitizeJavaScript(document);
- }
-
- if (removeEmbeddedFiles) {
- sanitizeEmbeddedFiles(document);
- }
-
- if (removeMetadata) {
- sanitizeMetadata(document);
- }
-
- if (removeLinks) {
- sanitizeLinks(document);
- }
-
- if (removeFonts) {
- sanitizeFonts(document);
- }
-
- return WebResponseUtils.pdfDocToWebResponse(
- document,
- Filenames.toSimpleFileName(inputFile.getOriginalFilename())
- .replaceFirst("[.][^.]+$", "")
- + "_sanitized.pdf");
+ PDDocument document = Loader.loadPDF(inputFile.getBytes());
+ if (removeJavaScript) {
+ sanitizeJavaScript(document);
}
+
+ if (removeEmbeddedFiles) {
+ sanitizeEmbeddedFiles(document);
+ }
+
+ if (removeMetadata) {
+ sanitizeMetadata(document);
+ }
+
+ if (removeLinks) {
+ sanitizeLinks(document);
+ }
+
+ if (removeFonts) {
+ sanitizeFonts(document);
+ }
+
+ return WebResponseUtils.pdfDocToWebResponse(
+ document,
+ Filenames.toSimpleFileName(inputFile.getOriginalFilename())
+ .replaceFirst("[.][^.]+$", "")
+ + "_sanitized.pdf");
}
private void sanitizeJavaScript(PDDocument document) throws IOException {
@@ -140,25 +139,29 @@ public class SanitizeController {
for (PDPage page : allPages) {
PDResources res = page.getResources();
-
- // Remove embedded files from the PDF
- res.getCOSObject().removeItem(COSName.getPDFName("EmbeddedFiles"));
+ if (res != null && res.getCOSObject() != null) {
+ res.getCOSObject().removeItem(COSName.getPDFName("EmbeddedFiles"));
+ }
}
}
private void sanitizeMetadata(PDDocument document) {
- PDMetadata metadata = document.getDocumentCatalog().getMetadata();
- if (metadata != null) {
- document.getDocumentCatalog().setMetadata(null);
+ if (document.getDocumentCatalog() != null) {
+ PDMetadata metadata = document.getDocumentCatalog().getMetadata();
+ if (metadata != null) {
+ document.getDocumentCatalog().setMetadata(null);
+ }
}
}
private void sanitizeLinks(PDDocument document) throws IOException {
for (PDPage page : document.getPages()) {
for (PDAnnotation annotation : page.getAnnotations()) {
- if (annotation instanceof PDAnnotationLink) {
+ if (annotation != null && annotation instanceof PDAnnotationLink) {
PDAction action = ((PDAnnotationLink) annotation).getAction();
- if (action instanceof PDActionLaunch || action instanceof PDActionURI) {
+ if (action != null
+ && (action instanceof PDActionLaunch
+ || action instanceof PDActionURI)) {
((PDAnnotationLink) annotation).setAction(null);
}
}
@@ -168,7 +171,11 @@ public class SanitizeController {
private void sanitizeFonts(PDDocument document) {
for (PDPage page : document.getPages()) {
- page.getResources().getCOSObject().removeItem(COSName.getPDFName("Font"));
+ if (page != null
+ && page.getResources() != null
+ && page.getResources().getCOSObject() != null) {
+ page.getResources().getCOSObject().removeItem(COSName.getPDFName("Font"));
+ }
}
}
}
diff --git a/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java b/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java
index 614dd8a0..bc43bd4b 100644
--- a/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java
+++ b/src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java
@@ -2,12 +2,14 @@ package stirling.software.SPDF.controller.web;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@@ -18,6 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
+import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.Authority;
import stirling.software.SPDF.model.Role;
import stirling.software.SPDF.model.User;
@@ -27,12 +30,19 @@ import stirling.software.SPDF.repository.UserRepository;
@Tag(name = "Account Security", description = "Account Security APIs")
public class AccountWebController {
+ @Autowired ApplicationProperties applicationProperties;
+
@GetMapping("/login")
public String login(HttpServletRequest request, Model model, Authentication authentication) {
if (authentication != null && authentication.isAuthenticated()) {
return "redirect:/";
}
+ model.addAttribute(
+ "oAuth2Enabled", applicationProperties.getSecurity().getOAUTH2().getEnabled());
+
+ model.addAttribute("currentPage", "login");
+
if (request.getParameter("error") != null) {
model.addAttribute("error", request.getParameter("error"));
@@ -53,6 +63,7 @@ public class AccountWebController {
public String showAddUserForm(Model model, Authentication authentication) {
List allUsers = userRepository.findAll();
Iterator iterator = allUsers.iterator();
+ Map roleDetails = Role.getAllRoleDetails();
while (iterator.hasNext()) {
User user = iterator.next();
@@ -60,6 +71,7 @@ public class AccountWebController {
for (Authority authority : user.getAuthorities()) {
if (authority.getAuthority().equals(Role.INTERNAL_API_USER.getRoleId())) {
iterator.remove();
+ roleDetails.remove(Role.INTERNAL_API_USER.getRoleId());
break; // Break out of the inner loop once the user is removed
}
}
@@ -68,6 +80,7 @@ public class AccountWebController {
model.addAttribute("users", allUsers);
model.addAttribute("currentUsername", authentication.getName());
+ model.addAttribute("roleDetails", roleDetails);
return "addUsers";
}
@@ -79,17 +92,32 @@ public class AccountWebController {
}
if (authentication != null && authentication.isAuthenticated()) {
Object principal = authentication.getPrincipal();
+ String username = null;
if (principal instanceof UserDetails) {
// Cast the principal object to UserDetails
UserDetails userDetails = (UserDetails) principal;
// Retrieve username and other attributes
- String username = userDetails.getUsername();
+ username = userDetails.getUsername();
+ // Add oAuth2 Login attributes to the model
+ model.addAttribute("oAuth2Login", false);
+ }
+ if (principal instanceof OAuth2User) {
+ // Cast the principal object to OAuth2User
+ OAuth2User userDetails = (OAuth2User) principal;
+
+ // Retrieve username and other attributes
+ username = userDetails.getAttribute("email");
+
+ // Add oAuth2 Login attributes to the model
+ model.addAttribute("oAuth2Login", true);
+ }
+ if (username != null) {
// Fetch user details from the database
Optional user =
- userRepository.findByUsername(
+ userRepository.findByUsernameIgnoreCase(
username); // Assuming findByUsername method exists
if (!user.isPresent()) {
// Handle error appropriately
@@ -112,6 +140,7 @@ public class AccountWebController {
model.addAttribute("role", user.get().getRolesAsString());
model.addAttribute("settings", settingsJson);
model.addAttribute("changeCredsFlag", user.get().isFirstLogin());
+ model.addAttribute("currentPage", "account");
}
} else {
return "redirect:/";
@@ -138,7 +167,7 @@ public class AccountWebController {
// Fetch user details from the database
Optional user =
- userRepository.findByUsername(
+ userRepository.findByUsernameIgnoreCase(
username); // Assuming findByUsername method exists
if (!user.isPresent()) {
// Handle error appropriately
diff --git a/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java b/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java
index a7c10908..0e1fdf55 100644
--- a/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java
+++ b/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java
@@ -17,6 +17,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
@Controller
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class OtherWebController {
+
@GetMapping("/compress-pdf")
@Hidden
public String compressPdfForm(Model model) {
@@ -53,6 +54,13 @@ public class OtherWebController {
return "misc/add-page-numbers";
}
+ @GetMapping("/fake-scan")
+ @Hidden
+ public String fakeScanForm(Model model) {
+ model.addAttribute("currentPage", "fake-scan");
+ return "misc/fake-scan";
+ }
+
@GetMapping("/extract-images")
@Hidden
public String extractImagesForm(Model model) {
@@ -81,8 +89,15 @@ public class OtherWebController {
return "misc/compare";
}
+ @GetMapping("/print-file")
+ @Hidden
+ public String printFileForm(Model model) {
+ model.addAttribute("currentPage", "print-file");
+ return "misc/print-file";
+ }
+
public List getAvailableTesseractLanguages() {
- String tessdataDir = "/usr/share/tesseract-ocr/5/tessdata";
+ String tessdataDir = "/usr/share/tessdata";
File[] files = new File(tessdataDir).listFiles();
if (files == null) {
return Collections.emptyList();
diff --git a/src/main/java/stirling/software/SPDF/model/ApplicationProperties.java b/src/main/java/stirling/software/SPDF/model/ApplicationProperties.java
index 34c60bbe..ce109299 100644
--- a/src/main/java/stirling/software/SPDF/model/ApplicationProperties.java
+++ b/src/main/java/stirling/software/SPDF/model/ApplicationProperties.java
@@ -118,6 +118,7 @@ public class ApplicationProperties {
private Boolean enableLogin;
private Boolean csrfDisabled;
private InitialLogin initialLogin;
+ private OAUTH2 oauth2;
private int loginAttemptCount;
private long loginResetTimeMinutes;
@@ -145,6 +146,14 @@ public class ApplicationProperties {
this.initialLogin = initialLogin;
}
+ public OAUTH2 getOAUTH2() {
+ return oauth2 != null ? oauth2 : new OAUTH2();
+ }
+
+ public void setOAUTH2(OAUTH2 oauth2) {
+ this.oauth2 = oauth2;
+ }
+
public Boolean getEnableLogin() {
return enableLogin;
}
@@ -165,6 +174,8 @@ public class ApplicationProperties {
public String toString() {
return "Security [enableLogin="
+ enableLogin
+ + ", oauth2="
+ + oauth2
+ ", initialLogin="
+ initialLogin
+ ", csrfDisabled="
@@ -202,6 +213,70 @@ public class ApplicationProperties {
+ "]";
}
}
+
+ public static class OAUTH2 {
+
+ private boolean enabled;
+ private String issuer;
+ private String clientId;
+ private String clientSecret;
+ private boolean autoCreateUser;
+
+ public boolean getEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public String getIssuer() {
+ return issuer;
+ }
+
+ public void setIssuer(String issuer) {
+ this.issuer = issuer;
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public String getClientSecret() {
+ return clientSecret;
+ }
+
+ public void setClientSecret(String clientSecret) {
+ this.clientSecret = clientSecret;
+ }
+
+ public boolean getAutoCreateUser() {
+ return autoCreateUser;
+ }
+
+ public void setAutoCreateUser(boolean autoCreateUser) {
+ this.autoCreateUser = autoCreateUser;
+ }
+
+ @Override
+ public String toString() {
+ return "OAUTH2 [enabled="
+ + enabled
+ + ", issuer="
+ + issuer
+ + ", clientId="
+ + clientId
+ + ", clientSecret="
+ + (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
+ + ", autoCreateUser="
+ + autoCreateUser
+ + "]";
+ }
+ }
}
public static class System {
@@ -210,7 +285,33 @@ public class ApplicationProperties {
private String rootURIPath;
private String customStaticFilePath;
private Integer maxFileSize;
- private CustomApplications customApplications;
+ private boolean showUpdate;
+ private Boolean showUpdateOnlyAdmin;
+ private boolean customHTMLFiles;
+
+ public boolean isCustomHTMLFiles() {
+ return customHTMLFiles;
+ }
+
+ public void setCustomHTMLFiles(boolean customHTMLFiles) {
+ this.customHTMLFiles = customHTMLFiles;
+ }
+
+ public boolean getShowUpdateOnlyAdmin() {
+ return showUpdateOnlyAdmin;
+ }
+
+ public void setShowUpdateOnlyAdmin(boolean showUpdateOnlyAdmin) {
+ this.showUpdateOnlyAdmin = showUpdateOnlyAdmin;
+ }
+
+ public boolean getShowUpdate() {
+ return showUpdate;
+ }
+
+ public void setShowUpdate(boolean showUpdate) {
+ this.showUpdate = showUpdate;
+ }
private Boolean enableAlphaFunctionality;
@@ -262,14 +363,6 @@ 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="
@@ -282,31 +375,14 @@ public class ApplicationProperties {
+ customStaticFilePath
+ ", maxFileSize="
+ maxFileSize
- + ", customApplications="
- + customApplications
+ ", enableAlphaFunctionality="
+ enableAlphaFunctionality
+ + ", showUpdate="
+ + showUpdate
+ + ", showUpdateOnlyAdmin="
+ + showUpdateOnlyAdmin
+ "]";
}
-
- public static class CustomApplications {
- private boolean installBookAndHtmlFormats;
-
- public boolean isInstallBookAndHtmlFormats() {
- return installBookAndHtmlFormats;
- }
-
- public void setInstallBookAndHtmlFormats(boolean installBookAndHtmlFormats) {
- this.installBookAndHtmlFormats = installBookAndHtmlFormats;
- }
-
- @Override
- public String toString() {
- return "CustomApplications [installBookAndHtmlFormats="
- + installBookAndHtmlFormats
- + "]";
- }
- }
}
public static class Ui {
diff --git a/src/main/java/stirling/software/SPDF/model/PdfMetadata.java b/src/main/java/stirling/software/SPDF/model/PdfMetadata.java
new file mode 100644
index 00000000..35054bc8
--- /dev/null
+++ b/src/main/java/stirling/software/SPDF/model/PdfMetadata.java
@@ -0,0 +1,19 @@
+package stirling.software.SPDF.model;
+
+import java.util.Calendar;
+
+import lombok.Builder;
+import lombok.Data;
+
+@Data
+@Builder
+public class PdfMetadata {
+ private String author;
+ private String producer;
+ private String title;
+ private String creator;
+ private String subject;
+ private String keywords;
+ private Calendar creationDate;
+ private Calendar modificationDate;
+}
diff --git a/src/main/java/stirling/software/SPDF/model/Role.java b/src/main/java/stirling/software/SPDF/model/Role.java
index 5100e9dd..02e7dd5f 100644
--- a/src/main/java/stirling/software/SPDF/model/Role.java
+++ b/src/main/java/stirling/software/SPDF/model/Role.java
@@ -1,34 +1,43 @@
package stirling.software.SPDF.model;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
public enum Role {
// Unlimited access
- ADMIN("ROLE_ADMIN", Integer.MAX_VALUE, Integer.MAX_VALUE),
+ ADMIN("ROLE_ADMIN", Integer.MAX_VALUE, Integer.MAX_VALUE, "adminUserSettings.admin"),
// Unlimited access
- USER("ROLE_USER", Integer.MAX_VALUE, Integer.MAX_VALUE),
+ USER("ROLE_USER", Integer.MAX_VALUE, Integer.MAX_VALUE, "adminUserSettings.user"),
// 40 API calls Per Day, 40 web calls
- LIMITED_API_USER("ROLE_LIMITED_API_USER", 40, 40),
+ LIMITED_API_USER("ROLE_LIMITED_API_USER", 40, 40, "adminUserSettings.apiUser"),
// 20 API calls Per Day, 20 web calls
- EXTRA_LIMITED_API_USER("ROLE_EXTRA_LIMITED_API_USER", 20, 20),
+ EXTRA_LIMITED_API_USER("ROLE_EXTRA_LIMITED_API_USER", 20, 20, "adminUserSettings.extraApiUser"),
// 0 API calls per day and 20 web calls
- WEB_ONLY_USER("ROLE_WEB_ONLY_USER", 0, 20),
+ WEB_ONLY_USER("ROLE_WEB_ONLY_USER", 0, 20, "adminUserSettings.webOnlyUser"),
- INTERNAL_API_USER("STIRLING-PDF-BACKEND-API-USER", Integer.MAX_VALUE, Integer.MAX_VALUE),
+ INTERNAL_API_USER(
+ "STIRLING-PDF-BACKEND-API-USER",
+ Integer.MAX_VALUE,
+ Integer.MAX_VALUE,
+ "adminUserSettings.internalApiUser"),
- DEMO_USER("ROLE_DEMO_USER", 100, 100);
+ DEMO_USER("ROLE_DEMO_USER", 100, 100, "adminUserSettings.demoUser");
private final String roleId;
private final int apiCallsPerDay;
private final int webCallsPerDay;
+ private final String roleName;
- Role(String roleId, int apiCallsPerDay, int webCallsPerDay) {
+ Role(String roleId, int apiCallsPerDay, int webCallsPerDay, String roleName) {
this.roleId = roleId;
this.apiCallsPerDay = apiCallsPerDay;
this.webCallsPerDay = webCallsPerDay;
+ this.roleName = roleName;
}
public String getRoleId() {
@@ -43,6 +52,27 @@ public enum Role {
return webCallsPerDay;
}
+ public String getRoleName() {
+ return roleName;
+ }
+
+ public static String getRoleNameByRoleId(String roleId) {
+ // Using the fromString method to get the Role enum based on the roleId
+ Role role = fromString(roleId);
+ // Return the roleName of the found Role enum
+ return role.getRoleName();
+ }
+
+ // Method to retrieve all role IDs and role names
+ public static Map getAllRoleDetails() {
+ // Using LinkedHashMap to preserve order
+ Map roleDetails = new LinkedHashMap<>();
+ for (Role role : Role.values()) {
+ roleDetails.put(role.getRoleId(), role.getRoleName());
+ }
+ return roleDetails;
+ }
+
public static Role fromString(String roleId) {
for (Role role : Role.values()) {
if (role.getRoleId().equalsIgnoreCase(roleId)) {
diff --git a/src/main/java/stirling/software/SPDF/model/User.java b/src/main/java/stirling/software/SPDF/model/User.java
index 253b33da..f6f9e532 100644
--- a/src/main/java/stirling/software/SPDF/model/User.java
+++ b/src/main/java/stirling/software/SPDF/model/User.java
@@ -44,6 +44,9 @@ public class User {
@Column(name = "isFirstLogin")
private Boolean isFirstLogin = false;
+ @Column(name = "roleName")
+ private String roleName;
+
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "user")
private Set authorities = new HashSet<>();
@@ -53,6 +56,10 @@ public class User {
@CollectionTable(name = "user_settings", joinColumns = @JoinColumn(name = "user_id"))
private Map settings = new HashMap<>(); // Key-value pairs of settings.
+ public String getRoleName() {
+ return Role.getRoleNameByRoleId(getRolesAsString());
+ }
+
public boolean isFirstLogin() {
return isFirstLogin != null && isFirstLogin;
}
diff --git a/src/main/java/stirling/software/SPDF/model/api/PDFWithPageNums.java b/src/main/java/stirling/software/SPDF/model/api/PDFWithPageNums.java
index 5e15d64d..7f94791e 100644
--- a/src/main/java/stirling/software/SPDF/model/api/PDFWithPageNums.java
+++ b/src/main/java/stirling/software/SPDF/model/api/PDFWithPageNums.java
@@ -33,13 +33,13 @@ public class PDFWithPageNums extends PDFFile {
// TODO Auto-generated catch block
e.printStackTrace();
}
- return GeneralUtils.parsePageString(pageNumbers, pageCount, zeroCount);
+ return GeneralUtils.parsePageList(pageNumbers, pageCount, zeroCount);
}
@Hidden
public List getPageNumbersList(PDDocument doc, boolean zeroCount) {
int pageCount = 0;
pageCount = doc.getNumberOfPages();
- return GeneralUtils.parsePageString(pageNumbers, pageCount, zeroCount);
+ return GeneralUtils.parsePageList(pageNumbers, pageCount, zeroCount);
}
}
diff --git a/src/main/java/stirling/software/SPDF/model/api/SplitPdfBySectionsRequest.java b/src/main/java/stirling/software/SPDF/model/api/SplitPdfBySectionsRequest.java
index fcc5d5ba..1ff834b4 100644
--- a/src/main/java/stirling/software/SPDF/model/api/SplitPdfBySectionsRequest.java
+++ b/src/main/java/stirling/software/SPDF/model/api/SplitPdfBySectionsRequest.java
@@ -15,4 +15,7 @@ public class SplitPdfBySectionsRequest extends PDFFile {
@Schema(description = "Number of vertical divisions for each PDF page", example = "2")
private int verticalDivisions;
+
+ @Schema(description = "Merge the split documents into a single PDF", example = "true")
+ private boolean merge;
}
diff --git a/src/main/java/stirling/software/SPDF/model/api/converters/PdfToPdfARequest.java b/src/main/java/stirling/software/SPDF/model/api/converters/PdfToPdfARequest.java
new file mode 100644
index 00000000..59535314
--- /dev/null
+++ b/src/main/java/stirling/software/SPDF/model/api/converters/PdfToPdfARequest.java
@@ -0,0 +1,17 @@
+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 PdfToPdfARequest extends PDFFile {
+
+ @Schema(
+ description = "The output PDF/A type",
+ allowableValues = {"pdfa", "pdfa-1"})
+ private String outputFormat;
+}
diff --git a/src/main/java/stirling/software/SPDF/model/api/misc/FlattenRequest.java b/src/main/java/stirling/software/SPDF/model/api/misc/FlattenRequest.java
new file mode 100644
index 00000000..c87d1974
--- /dev/null
+++ b/src/main/java/stirling/software/SPDF/model/api/misc/FlattenRequest.java
@@ -0,0 +1,17 @@
+package stirling.software.SPDF.model.api.misc;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import stirling.software.SPDF.model.api.PDFFile;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FlattenRequest extends PDFFile {
+
+ @Schema(
+ description =
+ "True to flatten only the forms, false to flatten full PDF (Convert page to image)")
+ private Boolean flattenOnlyForms;
+}
diff --git a/src/main/java/stirling/software/SPDF/model/api/misc/PrintFileRequest.java b/src/main/java/stirling/software/SPDF/model/api/misc/PrintFileRequest.java
new file mode 100644
index 00000000..d91c7a9e
--- /dev/null
+++ b/src/main/java/stirling/software/SPDF/model/api/misc/PrintFileRequest.java
@@ -0,0 +1,15 @@
+package stirling.software.SPDF.model.api.misc;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import stirling.software.SPDF.model.api.PDFFile;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class PrintFileRequest extends PDFFile {
+
+ @Schema(description = "Name of printer to match against", required = true)
+ private String printerName;
+}
diff --git a/src/main/java/stirling/software/SPDF/pdf/TextFinder.java b/src/main/java/stirling/software/SPDF/pdf/TextFinder.java
index cdfb5501..f9e339c2 100644
--- a/src/main/java/stirling/software/SPDF/pdf/TextFinder.java
+++ b/src/main/java/stirling/software/SPDF/pdf/TextFinder.java
@@ -19,6 +19,16 @@ public class TextFinder extends PDFTextStripper {
private final boolean wholeWordSearch;
private final List textOccurrences = new ArrayList<>();
+ private class MatchInfo {
+ int startIndex;
+ int matchLength;
+
+ MatchInfo(int startIndex, int matchLength) {
+ this.startIndex = startIndex;
+ this.matchLength = matchLength;
+ }
+ }
+
public TextFinder(String searchText, boolean useRegex, boolean wholeWordSearch)
throws IOException {
this.searchText = searchText.toLowerCase();
@@ -27,36 +37,37 @@ public class TextFinder extends PDFTextStripper {
setSortByPosition(true);
}
- private List findOccurrencesInText(String searchText, String content) {
- List indexes = new ArrayList<>();
+ private List findOccurrencesInText(String searchText, String content) {
+ List matches = new ArrayList<>();
+
Pattern pattern;
if (useRegex) {
// Use regex-based search
pattern =
wholeWordSearch
- ? Pattern.compile("(\\b|_|\\.)" + searchText + "(\\b|_|\\.)")
+ ? Pattern.compile("\\b" + searchText + "\\b")
: Pattern.compile(searchText);
} else {
// Use normal text search
pattern =
wholeWordSearch
- ? Pattern.compile(
- "(\\b|_|\\.)" + Pattern.quote(searchText) + "(\\b|_|\\.)")
+ ? Pattern.compile("\\b" + Pattern.quote(searchText) + "\\b")
: Pattern.compile(Pattern.quote(searchText));
}
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
- indexes.add(matcher.start());
+ matches.add(new MatchInfo(matcher.start(), matcher.end() - matcher.start()));
}
- return indexes;
+ return matches;
}
@Override
protected void writeString(String text, List textPositions) {
- for (Integer index : findOccurrencesInText(searchText, text.toLowerCase())) {
- if (index + searchText.length() <= textPositions.size()) {
+ for (MatchInfo match : findOccurrencesInText(searchText, text.toLowerCase())) {
+ int index = match.startIndex;
+ if (index + match.matchLength <= textPositions.size()) {
// Initial values based on the first character
TextPosition first = textPositions.get(index);
float minX = first.getX();
@@ -65,7 +76,7 @@ public class TextFinder extends PDFTextStripper {
float maxY = first.getY() + first.getHeight();
// Loop over the rest of the characters and adjust bounding box values
- for (int i = index; i < index + searchText.length(); i++) {
+ for (int i = index; i < index + match.matchLength; i++) {
TextPosition position = textPositions.get(i);
minX = Math.min(minX, position.getX());
minY = Math.min(minY, position.getY());
diff --git a/src/main/java/stirling/software/SPDF/repository/AuthorityRepository.java b/src/main/java/stirling/software/SPDF/repository/AuthorityRepository.java
index bbf32a07..41c251e1 100644
--- a/src/main/java/stirling/software/SPDF/repository/AuthorityRepository.java
+++ b/src/main/java/stirling/software/SPDF/repository/AuthorityRepository.java
@@ -9,4 +9,6 @@ import stirling.software.SPDF.model.Authority;
public interface AuthorityRepository extends JpaRepository {
// Set findByUsername(String username);
Set findByUser_Username(String username);
+
+ Authority findByUserId(long user_id);
}
diff --git a/src/main/java/stirling/software/SPDF/repository/UserRepository.java b/src/main/java/stirling/software/SPDF/repository/UserRepository.java
index d63c4cba..ad65f27d 100644
--- a/src/main/java/stirling/software/SPDF/repository/UserRepository.java
+++ b/src/main/java/stirling/software/SPDF/repository/UserRepository.java
@@ -7,6 +7,8 @@ import org.springframework.data.jpa.repository.JpaRepository;
import stirling.software.SPDF.model.User;
public interface UserRepository extends JpaRepository {
+ Optional findByUsernameIgnoreCase(String username);
+
Optional findByUsername(String username);
User findByApiKey(String apiKey);
diff --git a/src/main/java/stirling/software/SPDF/utils/GeneralUtils.java b/src/main/java/stirling/software/SPDF/utils/GeneralUtils.java
index d1a58087..61b72da6 100644
--- a/src/main/java/stirling/software/SPDF/utils/GeneralUtils.java
+++ b/src/main/java/stirling/software/SPDF/utils/GeneralUtils.java
@@ -12,11 +12,12 @@ import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
+import com.fathzer.soft.javaluator.DoubleEvaluator;
+
import io.github.pixee.security.HostValidator;
import io.github.pixee.security.Urls;
@@ -87,6 +88,7 @@ public class GeneralUtils {
}
sizeStr = sizeStr.trim().toUpperCase();
+ sizeStr = sizeStr.replace(",", ".").replace(" ", "");
try {
if (sizeStr.endsWith("KB")) {
return (long)
@@ -115,91 +117,115 @@ public class GeneralUtils {
return null;
}
- public static List parsePageString(String pageOrder, int totalPages) {
- return parsePageString(pageOrder, totalPages, false);
- }
-
- public static List parsePageString(
- String pageOrder, int totalPages, boolean isOneBased) {
- if (pageOrder == null || pageOrder.isEmpty()) {
- return Collections.singletonList(1);
+ public static List parsePageList(String pages, int totalPages, boolean oneBased) {
+ if (pages == null) {
+ return List.of(1); // Default to first page if input is null
}
- if (pageOrder.matches("\\d+")) {
- // Convert the single number string to an integer and return it in a list
- return Collections.singletonList(Integer.parseInt(pageOrder));
+ try {
+ return parsePageList(pages.split(","), totalPages, oneBased);
+ } catch (NumberFormatException e) {
+ return List.of(1); // Default to first page if input is invalid
}
- return parsePageList(pageOrder.split(","), totalPages, isOneBased);
}
- public static List parsePageList(String[] pageOrderArr, int totalPages) {
- return parsePageList(pageOrderArr, totalPages, false);
+ public static List parsePageList(String[] pages, int totalPages) {
+ return parsePageList(pages, totalPages, false);
}
- public static List parsePageList(
- String[] pageOrderArr, int totalPages, boolean isOneBased) {
- List newPageOrder = new ArrayList<>();
+ public static List parsePageList(String[] pages, int totalPages, boolean oneBased) {
+ List result = new ArrayList<>();
+ int offset = oneBased ? 1 : 0;
+ for (String page : pages) {
+ if ("all".equalsIgnoreCase(page)) {
- int adjustmentFactor = isOneBased ? 1 : 0;
-
- // loop through the page order array
- for (String element : pageOrderArr) {
- if ("all".equalsIgnoreCase(element)) {
for (int i = 0; i < totalPages; i++) {
- newPageOrder.add(i + adjustmentFactor);
+ result.add(i + offset);
}
- // As all pages are already added, no need to check further
- break;
- } else if (element.matches("\\d*n\\+?-?\\d*|\\d*\\+?n")) {
- // Handle page order as a function
- int coefficient = 0;
- int constant = 0;
- boolean coefficientExists = false;
- boolean constantExists = false;
-
- if (element.contains("n")) {
- String[] parts = element.split("n");
- if (!"".equals(parts[0]) && parts[0] != null) {
- coefficient = Integer.parseInt(parts[0]);
- coefficientExists = true;
- }
- if (parts.length > 1 && !"".equals(parts[1]) && parts[1] != null) {
- constant = Integer.parseInt(parts[1]);
- constantExists = true;
- }
- } else if (element.contains("+")) {
- constant = Integer.parseInt(element.replace("+", ""));
- constantExists = true;
- }
-
- for (int i = 1; i <= totalPages; i++) {
- int pageNum = coefficientExists ? coefficient * i : i;
- pageNum += constantExists ? constant : 0;
-
- if (pageNum <= totalPages && pageNum > 0) {
- newPageOrder.add(pageNum - adjustmentFactor);
- }
- }
- } else if (element.contains("-")) {
- // split the range into start and end page
- String[] range = element.split("-");
- int start = Integer.parseInt(range[0]);
- int end = Integer.parseInt(range[1]);
- // check if the end page is greater than total pages
- if (end > totalPages) {
- end = totalPages;
- }
- // loop through the range of pages
- for (int j = start; j <= end; j++) {
- // print the current index
- newPageOrder.add(j - adjustmentFactor);
+ } else if (page.contains(",")) {
+ // Split the string into parts, could be single pages or ranges
+ String[] parts = page.split(",");
+ for (String part : parts) {
+ result.addAll(handlePart(part, totalPages, offset));
}
} else {
- // if the element is a single page
- newPageOrder.add(Integer.parseInt(element) - adjustmentFactor);
+ result.addAll(handlePart(page, totalPages, offset));
}
}
+ return new ArrayList<>(
+ new java.util.LinkedHashSet<>(result)); // Remove duplicates and maintain order
+ }
- return newPageOrder;
+ public static List evaluateNFunc(String expression, int maxValue) {
+ List results = new ArrayList<>();
+ DoubleEvaluator evaluator = new DoubleEvaluator();
+
+ // Validate the expression
+ if (!expression.matches("[0-9n+\\-*/() ]+")) {
+ throw new IllegalArgumentException("Invalid expression");
+ }
+
+ int n = 0;
+ while (true) {
+ // Replace 'n' with the current value of n, correctly handling numbers before 'n'
+ String sanitizedExpression = insertMultiplicationBeforeN(expression, n);
+ Double result = evaluator.evaluate(sanitizedExpression);
+
+ // Check if the result is null or not within bounds
+ if (result == null || result <= 0 || result.intValue() > maxValue) {
+ if (n != 0) break;
+ } else {
+ results.add(result.intValue());
+ }
+ n++;
+ }
+
+ return results;
+ }
+
+ private static String insertMultiplicationBeforeN(String expression, int nValue) {
+ // Insert multiplication between a number and 'n' (e.g., "4n" becomes "4*n")
+ String withMultiplication = expression.replaceAll("(\\d)n", "$1*n");
+ // Now replace 'n' with its current value
+ return withMultiplication.replace("n", String.valueOf(nValue));
+ }
+
+ private static List handlePart(String part, int totalPages, int offset) {
+ List partResult = new ArrayList<>();
+
+ // First check for n-syntax because it should not be processed as a range
+ if (part.contains("n")) {
+ partResult = evaluateNFunc(part, totalPages);
+ // Adjust the results according to the offset
+ for (int i = 0; i < partResult.size(); i++) {
+ int adjustedValue = partResult.get(i) - 1 + offset;
+ partResult.set(i, adjustedValue);
+ }
+ } else if (part.contains("-")) {
+ // Process ranges only if it's not n-syntax
+ String[] rangeParts = part.split("-");
+ try {
+ int start = Integer.parseInt(rangeParts[0]);
+ int end = Integer.parseInt(rangeParts[1]);
+ for (int i = start; i <= end; i++) {
+ if (i >= 1 && i <= totalPages) {
+ partResult.add(i - 1 + offset);
+ }
+ }
+ } catch (NumberFormatException e) {
+ // Range is invalid, ignore this part
+ }
+ } else {
+ // This is a single page number
+ try {
+ int pageNum = Integer.parseInt(part.trim());
+ if (pageNum >= 1 && pageNum <= totalPages) {
+ partResult.add(pageNum - 1 + offset);
+ }
+ } catch (NumberFormatException ignored) {
+ // Ignore invalid numbers
+ }
+ }
+ return partResult;
}
public static boolean createDir(String path) {
diff --git a/src/main/java/stirling/software/SPDF/utils/PDFToFile.java b/src/main/java/stirling/software/SPDF/utils/PDFToFile.java
index 43683be8..e52344bf 100644
--- a/src/main/java/stirling/software/SPDF/utils/PDFToFile.java
+++ b/src/main/java/stirling/software/SPDF/utils/PDFToFile.java
@@ -25,6 +25,71 @@ import io.github.pixee.security.Filenames;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
public class PDFToFile {
+
+ public ResponseEntity processPdfToHtml(MultipartFile inputFile)
+ throws IOException, InterruptedException {
+ if (!"application/pdf".equals(inputFile.getContentType())) {
+ return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+ }
+
+ // Get the original PDF file name without the extension
+ String originalPdfFileName = Filenames.toSimpleFileName(inputFile.getOriginalFilename());
+ String pdfBaseName = originalPdfFileName.substring(0, originalPdfFileName.lastIndexOf('.'));
+
+ Path tempInputFile = null;
+ Path tempOutputDir = null;
+ byte[] fileBytes;
+ String fileName = "temp.file";
+
+ try {
+ // Save the uploaded file to a temporary location
+ tempInputFile = Files.createTempFile("input_", ".pdf");
+ Files.copy(
+ inputFile.getInputStream(), tempInputFile, StandardCopyOption.REPLACE_EXISTING);
+
+ // Prepare the output directory
+ tempOutputDir = Files.createTempDirectory("output_");
+
+ // Run the pdftohtml command with complex output
+ List command =
+ new ArrayList<>(
+ Arrays.asList(
+ "pdftohtml", "-c", tempInputFile.toString(), pdfBaseName));
+
+ ProcessExecutorResult returnCode =
+ ProcessExecutor.getInstance(ProcessExecutor.Processes.PDFTOHTML)
+ .runCommandWithOutputHandling(command, tempOutputDir.toFile());
+
+ // Get output files
+ List outputFiles = Arrays.asList(tempOutputDir.toFile().listFiles());
+
+ // Return output files in a ZIP archive
+ fileName = pdfBaseName + "ToHtml.zip";
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream);
+
+ for (File outputFile : outputFiles) {
+ ZipEntry entry = new ZipEntry(outputFile.getName());
+ zipOutputStream.putNextEntry(entry);
+ FileInputStream fis = new FileInputStream(outputFile);
+ IOUtils.copy(fis, zipOutputStream);
+ fis.close();
+ zipOutputStream.closeEntry();
+ }
+
+ zipOutputStream.close();
+ fileBytes = byteArrayOutputStream.toByteArray();
+
+ } finally {
+ // Clean up the temporary files
+ if (tempInputFile != null) Files.delete(tempInputFile);
+ if (tempOutputDir != null) FileUtils.deleteDirectory(tempOutputDir.toFile());
+ }
+
+ return WebResponseUtils.bytesToWebResponse(
+ fileBytes, fileName, MediaType.APPLICATION_OCTET_STREAM);
+ }
+
public ResponseEntity processPdfToOfficeFormat(
MultipartFile inputFile, String outputFormat, String libreOfficeFilter)
throws IOException, InterruptedException {
@@ -39,17 +104,7 @@ public class PDFToFile {
// Validate output format
List allowedFormats =
- Arrays.asList(
- "doc",
- "docx",
- "odt",
- "ppt",
- "pptx",
- "odp",
- "rtf",
- "html",
- "xml",
- "txt:Text");
+ Arrays.asList("doc", "docx", "odt", "ppt", "pptx", "odp", "rtf", "xml", "txt:Text");
if (!allowedFormats.contains(outputFormat)) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
diff --git a/src/main/java/stirling/software/SPDF/utils/PdfUtils.java b/src/main/java/stirling/software/SPDF/utils/PdfUtils.java
index 77814340..225a2c12 100644
--- a/src/main/java/stirling/software/SPDF/utils/PdfUtils.java
+++ b/src/main/java/stirling/software/SPDF/utils/PdfUtils.java
@@ -6,6 +6,7 @@ import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Calendar;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@@ -19,11 +20,8 @@ import javax.imageio.stream.ImageOutputStream;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.cos.COSName;
-import org.apache.pdfbox.pdmodel.PDDocument;
-import org.apache.pdfbox.pdmodel.PDPage;
-import org.apache.pdfbox.pdmodel.PDPageContentStream;
+import org.apache.pdfbox.pdmodel.*;
import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
-import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
@@ -39,6 +37,8 @@ import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
+import stirling.software.SPDF.model.PdfMetadata;
+
public class PdfUtils {
private static final Logger logger = LoggerFactory.getLogger(PdfUtils.class);
@@ -214,6 +214,7 @@ public class PdfUtils {
throws IOException, Exception {
try (PDDocument document = Loader.loadPDF(inputStream)) {
PDFRenderer pdfRenderer = new PDFRenderer(document);
+ pdfRenderer.setSubsamplingAllowed(true);
int pageCount = document.getNumberOfPages();
// Create a ByteArrayOutputStream to save the image(s) to
@@ -335,14 +336,12 @@ public class PdfUtils {
}
}
- private static void addImageToDocument(
+ public static void addImageToDocument(
PDDocument doc, PDImageXObject image, String fitOption, boolean autoRotate)
throws IOException {
boolean imageIsLandscape = image.getWidth() > image.getHeight();
PDRectangle pageSize = PDRectangle.A4;
- System.out.println(fitOption);
-
if (autoRotate && imageIsLandscape) {
pageSize = new PDRectangle(pageSize.getHeight(), pageSize.getWidth());
}
@@ -420,4 +419,28 @@ public class PdfUtils {
logger.info("PDF successfully saved to byte array");
return baos.toByteArray();
}
+
+ public static PdfMetadata extractMetadataFromPdf(PDDocument pdf) {
+ return PdfMetadata.builder()
+ .author(pdf.getDocumentInformation().getAuthor())
+ .producer(pdf.getDocumentInformation().getProducer())
+ .title(pdf.getDocumentInformation().getTitle())
+ .creator(pdf.getDocumentInformation().getCreator())
+ .subject(pdf.getDocumentInformation().getSubject())
+ .keywords(pdf.getDocumentInformation().getKeywords())
+ .creationDate(pdf.getDocumentInformation().getCreationDate())
+ .modificationDate(pdf.getDocumentInformation().getModificationDate())
+ .build();
+ }
+
+ public static void setMetadataToPdf(PDDocument pdf, PdfMetadata pdfMetadata) {
+ pdf.getDocumentInformation().setAuthor(pdfMetadata.getAuthor());
+ pdf.getDocumentInformation().setProducer(pdfMetadata.getProducer());
+ pdf.getDocumentInformation().setTitle(pdfMetadata.getTitle());
+ pdf.getDocumentInformation().setCreator(pdfMetadata.getCreator());
+ pdf.getDocumentInformation().setSubject(pdfMetadata.getSubject());
+ pdf.getDocumentInformation().setKeywords(pdfMetadata.getKeywords());
+ pdf.getDocumentInformation().setCreationDate(pdfMetadata.getCreationDate());
+ pdf.getDocumentInformation().setModificationDate(Calendar.getInstance());
+ }
}
diff --git a/src/main/java/stirling/software/SPDF/utils/ProcessExecutor.java b/src/main/java/stirling/software/SPDF/utils/ProcessExecutor.java
index 2c81dce5..93fdbd54 100644
--- a/src/main/java/stirling/software/SPDF/utils/ProcessExecutor.java
+++ b/src/main/java/stirling/software/SPDF/utils/ProcessExecutor.java
@@ -24,6 +24,7 @@ public class ProcessExecutor {
public enum Processes {
LIBRE_OFFICE,
+ PDFTOHTML,
OCR_MY_PDF,
PYTHON_OPENCV,
GHOSTSCRIPT,
@@ -45,6 +46,7 @@ public class ProcessExecutor {
int semaphoreLimit =
switch (key) {
case LIBRE_OFFICE -> 1;
+ case PDFTOHTML -> 1;
case OCR_MY_PDF -> 2;
case PYTHON_OPENCV -> 8;
case GHOSTSCRIPT -> 16;
@@ -56,9 +58,10 @@ public class ProcessExecutor {
long timeoutMinutes =
switch (key) {
case LIBRE_OFFICE -> 30;
+ case PDFTOHTML -> 20;
case OCR_MY_PDF -> 30;
case PYTHON_OPENCV -> 30;
- case GHOSTSCRIPT -> 5;
+ case GHOSTSCRIPT -> 30;
case WEASYPRINT -> 30;
case INSTALL_APP -> 60;
case CALIBRE -> 30;
@@ -169,27 +172,35 @@ public class ProcessExecutor {
errorReaderThread.join();
outputReaderThread.join();
- if (!liveUpdates) {
- if (outputLines.size() > 0) {
- String outputMessage = String.join("\n", outputLines);
- messages += outputMessage;
+ if (outputLines.size() > 0) {
+ String outputMessage = String.join("\n", outputLines);
+ messages += outputMessage;
+ if (!liveUpdates) {
logger.info("Command output:\n" + outputMessage);
}
+ }
- if (errorLines.size() > 0) {
- String errorMessage = String.join("\n", errorLines);
- messages += errorMessage;
+ if (errorLines.size() > 0) {
+ String errorMessage = String.join("\n", errorLines);
+ messages += errorMessage;
+ if (!liveUpdates) {
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);
+ if (exitCode != 0) {
+ throw new IOException(
+ "Command process failed with exit code "
+ + exitCode
+ + ". Error message: "
+ + errorMessage);
+ }
+ }
+
+ if (exitCode != 0) {
+ throw new IOException(
+ "Command process failed with exit code "
+ + exitCode
+ + "\nLogs: "
+ + messages);
}
} finally {
semaphore.release();
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 1a5d1438..a5f12e64 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -24,8 +24,8 @@ spring.devtools.livereload.enabled=true
spring.thymeleaf.encoding=UTF-8
-server.connection-timeout=${SYSTEM_CONNECTIONTIMEOUTMINUTES:5m}
-spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:300000}
+server.connection-timeout=${SYSTEM_CONNECTIONTIMEOUTMINUTES:20m}
+spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:1200000}
spring.resources.static-locations=file:customFiles/static/
#spring.thymeleaf.prefix=file:/customFiles/templates/,classpath:/templates/
diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties
index 579e649c..e69de29b 100644
--- a/src/main/resources/messages.properties
+++ b/src/main/resources/messages.properties
@@ -1,11 +0,0 @@
-fileToPDF.fileTypesList=Microsoft Word: (DOC, DOCX, DOT, DOTX) \
-Microsoft Excel: (CSV, XLS, XLSX, XLT, XLTX, SLK, DIF) \
-Microsoft PowerPoint: (PPT, PPTX) \
-OpenDocument Formats: (ODT, OTT, ODS, OTS, ODP, OTP, ODG, OTG) \
-Plain Text: (TXT, TEXT, XML) \
-Rich Text Format: (RTF) \
-Images: (BMP, GIF, JPEG, PNG, TIF, PBM, PGM, PPM, RAS, XBM, XPM, SVG, SVM, WMF) \
-HTML: (HTML) \
-Lotus Word Pro: (LWP) \
-StarOffice formats: (SDA, SDC, SDD, SDW, STC, STD, STI, STW, SXD, SXG, SXI, SXW) \
-Other formats: (DBF, FODS, VSD, VOR, VOR3, VOR4, UOP, PCT, PS, PDF)
diff --git a/src/main/resources/messages_ar_AR.properties b/src/main/resources/messages_ar_AR.properties
index bdd14ecd..c6119110 100644
--- a/src/main/resources/messages_ar_AR.properties
+++ b/src/main/resources/messages_ar_AR.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -13,15 +13,17 @@ processTimeWarning=تحذير: يمكن أن تستغرق هذه العملية
pageOrderPrompt=ترتيب الصفحات (أدخل قائمة بأرقام الصفحات مفصولة بفواصل):
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
goToPage=اذهب
-true=\u0635\u062D\u064A\u062D
-false=\u062E\u0637\u0623
-unknown=\u063A\u064A\u0631 \u0645\u0639\u0631\u0648\u0641
-save=\u062D\u0641\u0638
-close=\u0625\u063A\u0644\u0627\u0642
+true=صحيح
+false=خطأ
+unknown=غير معروف
+save=حفظ
+saveToBrowser=Save to Browser
+close=إغلاق
filesSelected=الملفات المحددة
noFavourites=لم تتم إضافة أي مفضلات
+downloadComplete=Download Complete
bored=الانتظار بالملل؟
-alphabet=\u0627\u0644\u0623\u0628\u062C\u062F\u064A\u0629
+alphabet=الأبجدية
downloadPdf=تنزيل PDF
text=نص
font=الخط
@@ -52,16 +54,34 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
+invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
+deleteCurrentUserMessage=Cannot delete currently logged in user.
+deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
+downgradeCurrentUserMessage=لا يمكن خفض دور المستخدم الحالي
+downgradeCurrentUserLongMessage=لا يمكن تخفيض دور المستخدم الحالي. وبالتالي، لن يظهر المستخدم الحالي.
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
+pipeline.header=Pipeline Menu (Beta)
pipeline.uploadButton=Upload Custom
pipeline.configureButton=Configure
pipeline.defaultOption=Custom
pipeline.submitButton=Submit
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
######################
# Pipeline Options #
@@ -87,27 +107,29 @@ navbar.security=الأمان
navbar.other=أخرى
navbar.darkmode=الوضع الداكن
navbar.pageOps=عمليات الصفحة
-navbar.settings=\u0625\u0639\u062F\u0627\u062F\u0627\u062A
+navbar.settings=إعدادات
#############
# SETTINGS #
#############
-settings.title=\u0627\u0644\u0625\u0639\u062F\u0627\u062F\u0627\u062A
-settings.update=\u0627\u0644\u062A\u062D\u062F\u064A\u062B \u0645\u062A\u0627\u062D
-settings.appVersion=\u0625\u0635\u062F\u0627\u0631 \u0627\u0644\u062A\u0637\u0628\u064A\u0642:
-settings.downloadOption.title=\u062A\u062D\u062F\u064A\u062F \u062E\u064A\u0627\u0631 \u0627\u0644\u062A\u0646\u0632\u064A\u0644 (\u0644\u0644\u062A\u0646\u0632\u064A\u0644\u0627\u062A \u0630\u0627\u062A \u0627\u0644\u0645\u0644\u0641 \u0627\u0644\u0648\u0627\u062D\u062F \u063A\u064A\u0631 \u0627\u0644\u0645\u0636\u063A\u0648\u0637):
-settings.downloadOption.1=\u0641\u062A\u062D \u0641\u064A \u0646\u0641\u0633 \u0627\u0644\u0646\u0627\u0641\u0630\u0629
-settings.downloadOption.2=\u0641\u062A\u062D \u0641\u064A \u0646\u0627\u0641\u0630\u0629 \u062C\u062F\u064A\u062F\u0629
-settings.downloadOption.3=\u062A\u0646\u0632\u064A\u0644 \u0627\u0644\u0645\u0644\u0641
-settings.zipThreshold=\u0645\u0644\u0641\u0627\u062A \u0645\u0636\u063A\u0648\u0637\u0629 \u0639\u0646\u062F \u062A\u062C\u0627\u0648\u0632 \u0639\u062F\u062F \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0627\u0644\u062A\u064A \u062A\u0645 \u062A\u0646\u0632\u064A\u0644\u0647\u0627
+settings.title=الإعدادات
+settings.update=التحديث متاح
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
+settings.appVersion=إصدار التطبيق:
+settings.downloadOption.title=تحديد خيار التنزيل (للتنزيلات ذات الملف الواحد غير المضغوط):
+settings.downloadOption.1=فتح في نفس النافذة
+settings.downloadOption.2=فتح في نافذة جديدة
+settings.downloadOption.3=تنزيل الملف
+settings.zipThreshold=ملفات مضغوطة عند تجاوز عدد الملفات التي تم تنزيلها
settings.signOut=Sign Out
settings.accountSettings=Account Settings
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=Change Credentials
changeCreds.header=Update Your Account Details
-changeCreds.changeUserAndPassword=You are using default login credentials. Please enter a new password (and username if wanted)
+changeCreds.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=New Username
changeCreds.oldPassword=Current Password
changeCreds.newPassword=New Password
@@ -142,14 +164,18 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
adminUserSettings.actions=Actions
adminUserSettings.apiUser=Limited API User
+adminUserSettings.extraApiUser=Additional 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.internalApiUser=Internal API User
+adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User
+adminUserSettings.changeUserRole=تغيير دور المستخدم
#############
# HOME-PAGE #
@@ -222,25 +248,25 @@ home.compressPdfs.desc=ضغط ملفات PDF لتقليل حجم الملف.
compressPdfs.tags=squish,small,tiny
-home.changeMetadata.title=\u062A\u063A\u064A\u064A\u0631 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0648\u0635\u0641\u064A\u0629
-home.changeMetadata.desc=\u062A\u063A\u064A\u064A\u0631 / \u0625\u0632\u0627\u0644\u0629 / \u0625\u0636\u0627\u0641\u0629 \u0628\u064A\u0627\u0646\u0627\u062A \u0623\u0648\u0644\u064A\u0629 \u0645\u0646 \u0645\u0633\u062A\u0646\u062F PDF
+home.changeMetadata.title=تغيير البيانات الوصفية
+home.changeMetadata.desc=تغيير / إزالة / إضافة بيانات أولية من مستند PDF
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
-home.fileToPDF.title=\u062A\u062D\u0648\u064A\u0644 \u0627\u0644\u0645\u0644\u0641 \u0625\u0644\u0649 PDF
-home.fileToPDF.desc=\u062A\u062D\u0648\u064A\u0644 \u0623\u064A \u0645\u0644\u0641 \u062A\u0642\u0631\u064A\u0628\u0627 \u0625\u0644\u0649 PDF (DOCX \u0648PNG \u0648XLS \u0648PPT \u0648TXT \u0648\u0627\u0644\u0645\u0632\u064A\u062F)
+home.fileToPDF.title=تحويل الملف إلى PDF
+home.fileToPDF.desc=تحويل أي ملف تقريبا إلى PDF (DOCX وPNG وXLS وPPT وTXT والمزيد)
fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
-home.ocr.title=\u062A\u0634\u063A\u064A\u0644 OCR \u0639\u0644\u0649 PDF \u0648 / \u0623\u0648 \u0645\u0633\u062D \u0636\u0648\u0626\u064A
-home.ocr.desc=\u064A\u0642\u0648\u0645 \u0628\u0631\u0646\u0627\u0645\u062C \u0627\u0644\u062A\u0646\u0638\u064A\u0641 \u0628\u0645\u0633\u062D \u0648\u0627\u0643\u062A\u0634\u0627\u0641 \u0627\u0644\u0646\u0635 \u0645\u0646 \u0627\u0644\u0635\u0648\u0631 \u062F\u0627\u062E\u0644 \u0645\u0644\u0641 PDF \u0648\u064A\u0639\u064A\u062F \u0625\u0636\u0627\u0641\u062A\u0647 \u0643\u0646\u0635
+home.ocr.title=تشغيل OCR على PDF و / أو مسح ضوئي
+home.ocr.desc=يقوم برنامج التنظيف بمسح واكتشاف النص من الصور داخل ملف PDF ويعيد إضافته كنص
ocr.tags=recognition,text,image,scan,read,identify,detection,editable
-home.extractImages.title=\u0627\u0633\u062A\u062E\u0631\u0627\u062C \u0627\u0644\u0635\u0648\u0631
-home.extractImages.desc=\u064A\u0633\u062A\u062E\u0631\u062C \u062C\u0645\u064A\u0639 \u0627\u0644\u0635\u0648\u0631 \u0645\u0646 \u0645\u0644\u0641 PDF \u0648\u064A\u062D\u0641\u0638\u0647\u0627 \u0641\u064A \u0627\u0644\u0631\u0645\u0632 \u0627\u0644\u0628\u0631\u064A\u062F\u064A
+home.extractImages.title=استخراج الصور
+home.extractImages.desc=يستخرج جميع الصور من ملف PDF ويحفظها في الرمز البريدي
extractImages.tags=picture,photo,save,archive,zip,capture,grab
-home.pdfToPDFA.title=\u062A\u062D\u0648\u064A\u0644 \u0645\u0644\u0641\u0627\u062A PDF \u0625\u0644\u0649 PDF / A
-home.pdfToPDFA.desc=\u062A\u062D\u0648\u064A\u0644 PDF \u0625\u0644\u0649 PDF / A \u0644\u0644\u062A\u062E\u0632\u064A\u0646 \u0637\u0648\u064A\u0644 \u0627\u0644\u0645\u062F\u0649
+home.pdfToPDFA.title=تحويل ملفات PDF إلى PDF / A
+home.pdfToPDFA.desc=تحويل PDF إلى PDF / A للتخزين طويل المدى
pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
home.PDFToWord.title=تحويل PDF إلى Word
@@ -392,6 +418,15 @@ home.AddStampRequest.desc=Add text or add image stamps at set locations
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Sign in
+login.header=Sign in
login.signin=Sign in
login.rememberme=Remember me
login.invalid=Invalid username or password.
login.locked=Your account has been locked.
login.signinTitle=Please sign in
+login.ssoSignIn=تسجيل الدخول عبر تسجيل الدخول الأحادي
+login.oauth2AutoCreateDisabled=تم تعطيل مستخدم الإنشاء التلقائي لـ OAuth2
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Convert To Single Page
pageExtracter.title=Extract Pages
pageExtracter.header=Extract Pages
pageExtracter.submit=Extract
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -623,6 +662,18 @@ compare.document.1=المستند 1
compare.document.2=المستند 2
compare.submit=يقارن
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
#sign
sign.title=تسجيل الدخول
@@ -643,6 +694,7 @@ repair.submit=الإصلاح
#flatten
flatten.title=تسطيح
flatten.header=تسوية ملفات PDF
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=تسطيح
@@ -660,38 +712,38 @@ ScannerImageSplit.selectText.10=يضبط حجم الحدود المضافة وا
#OCR
-ocr.title=\u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641 / \u062A\u0646\u0638\u064A\u0641 \u0627\u0644\u0645\u0633\u062D \u0627\u0644\u0636\u0648\u0626\u064A
-ocr.header=\u0645\u0633\u062D \u0627\u0644\u0645\u0633\u062D \u0627\u0644\u0636\u0648\u0626\u064A / \u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641 (\u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641)
-ocr.selectText.1=\u062D\u062F\u062F \u0627\u0644\u0644\u063A\u0627\u062A \u0627\u0644\u062A\u064A \u0633\u064A\u062A\u0645 \u0627\u0643\u062A\u0634\u0627\u0641\u0647\u0627 \u062F\u0627\u062E\u0644 \u0645\u0644\u0641 PDF (\u0627\u0644\u0644\u063A\u0627\u062A \u0627\u0644\u0645\u062F\u0631\u062C\u0629 \u0647\u064A \u062A\u0644\u0643 \u0627\u0644\u062A\u064A \u062A\u0645 \u0627\u0643\u062A\u0634\u0627\u0641\u0647\u0627 \u062D\u0627\u0644\u064A\u064B\u0627):
-ocr.selectText.2=\u0625\u0646\u062A\u0627\u062C \u0645\u0644\u0641 \u0646\u0635\u064A \u064A\u062D\u062A\u0648\u064A \u0639\u0644\u0649 \u0646\u0635 OCR \u0628\u062C\u0627\u0646\u0628 \u0645\u0644\u0641 PDF \u0627\u0644\u0630\u064A \u062A\u0645 \u0625\u0639\u062F\u0627\u062F\u0647 \u0628\u0648\u0627\u0633\u0637\u0629 OCR
-ocr.selectText.3=\u062A\u0645 \u0645\u0633\u062D \u0627\u0644\u0635\u0641\u062D\u0627\u062A \u0627\u0644\u0635\u062D\u064A\u062D\u0629 \u0636\u0648\u0626\u064A\u064B\u0627 \u0628\u0632\u0627\u0648\u064A\u0629 \u0645\u0646\u062D\u0631\u0641\u0629 \u0639\u0646 \u0637\u0631\u064A\u0642 \u062A\u062F\u0648\u064A\u0631\u0647\u0627 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649 \u0641\u064A \u0645\u0643\u0627\u0646\u0647\u0627
-ocr.selectText.4=\u0635\u0641\u062D\u0629 \u0646\u0638\u064A\u0641\u0629 \u0644\u0630\u0644\u0643 \u0645\u0646 \u063A\u064A\u0631 \u0627\u0644\u0645\u062D\u062A\u0645\u0644 \u0623\u0646 \u064A\u062C\u062F OCR \u0646\u0635\u064B\u0627 \u0641\u064A \u0636\u0648\u0636\u0627\u0621 \u0627\u0644\u062E\u0644\u0641\u064A\u0629. (\u0644\u0627 \u064A\u0648\u062C\u062F \u062A\u063A\u064A\u064A\u0631 \u0641\u064A \u0627\u0644\u0625\u062E\u0631\u0627\u062C)
-ocr.selectText.5=\u0635\u0641\u062D\u0629 \u0646\u0638\u064A\u0641\u0629 \u060C \u0644\u0630\u0644\u0643 \u0645\u0646 \u063A\u064A\u0631 \u0627\u0644\u0645\u062D\u062A\u0645\u0644 \u0623\u0646 \u064A\u062C\u062F OCR \u0646\u0635\u064B\u0627 \u0641\u064A \u0636\u0648\u0636\u0627\u0621 \u0627\u0644\u062E\u0644\u0641\u064A\u0629 \u060C \u0648\u064A\u062D\u0627\u0641\u0638 \u0639\u0644\u0649 \u0627\u0644\u062A\u0646\u0638\u064A\u0641 \u0641\u064A \u0627\u0644\u0625\u062E\u0631\u0627\u062C.
-ocr.selectText.6=\u064A\u062A\u062C\u0627\u0647\u0644 \u0627\u0644\u0635\u0641\u062D\u0627\u062A \u0627\u0644\u062A\u064A \u062A\u062D\u062A\u0648\u064A \u0639\u0644\u0649 \u0646\u0635 \u062A\u0641\u0627\u0639\u0644\u064A \u060C \u0641\u0642\u0637 \u0635\u0641\u062D\u0627\u062A OCRs \u0627\u0644\u062A\u064A \u0647\u064A \u0635\u0648\u0631
-ocr.selectText.7=\u0641\u0631\u0636 \u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641 \u060C \u0633\u064A\u0624\u062F\u064A \u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641 \u0639\u0644\u0649 \u0643\u0644 \u0635\u0641\u062D\u0629 \u0625\u0644\u0649 \u0625\u0632\u0627\u0644\u0629 \u062C\u0645\u064A\u0639 \u0639\u0646\u0627\u0635\u0631 \u0627\u0644\u0646\u0635 \u0627\u0644\u0623\u0635\u0644\u064A
-ocr.selectText.8=\u0639\u0627\u062F\u064A (\u062E\u0637\u0623 \u0625\u0630\u0627 \u0643\u0627\u0646 PDF \u064A\u062D\u062A\u0648\u064A \u0639\u0644\u0649 \u0646\u0635)
-ocr.selectText.9=\u0625\u0639\u062F\u0627\u062F\u0627\u062A \u0625\u0636\u0627\u0641\u064A\u0629
-ocr.selectText.10=\u0648\u0636\u0639 \u0627\u0644\u062A\u0639\u0631\u0641 \u0627\u0644\u0636\u0648\u0626\u064A \u0639\u0644\u0649 \u0627\u0644\u062D\u0631\u0648\u0641
+ocr.title=التعرف الضوئي على الحروف / تنظيف المسح الضوئي
+ocr.header=مسح المسح الضوئي / التعرف الضوئي على الحروف (التعرف الضوئي على الحروف)
+ocr.selectText.1=حدد اللغات التي سيتم اكتشافها داخل ملف PDF (اللغات المدرجة هي تلك التي تم اكتشافها حاليًا):
+ocr.selectText.2=إنتاج ملف نصي يحتوي على نص OCR بجانب ملف PDF الذي تم إعداده بواسطة OCR
+ocr.selectText.3=تم مسح الصفحات الصحيحة ضوئيًا بزاوية منحرفة عن طريق تدويرها مرة أخرى في مكانها
+ocr.selectText.4=صفحة نظيفة لذلك من غير المحتمل أن يجد OCR نصًا في ضوضاء الخلفية. (لا يوجد تغيير في الإخراج)
+ocr.selectText.5=صفحة نظيفة ، لذلك من غير المحتمل أن يجد OCR نصًا في ضوضاء الخلفية ، ويحافظ على التنظيف في الإخراج.
+ocr.selectText.6=يتجاهل الصفحات التي تحتوي على نص تفاعلي ، فقط صفحات OCRs التي هي صور
+ocr.selectText.7=فرض التعرف الضوئي على الحروف ، سيؤدي التعرف الضوئي على الحروف على كل صفحة إلى إزالة جميع عناصر النص الأصلي
+ocr.selectText.8=عادي (خطأ إذا كان PDF يحتوي على نص)
+ocr.selectText.9=إعدادات إضافية
+ocr.selectText.10=وضع التعرف الضوئي على الحروف
ocr.selectText.11=إزالة الصور بعد التعرف الضوئي على الحروف (يزيل كل الصور ، يكون مفيدًا فقط إذا كان جزءًا من خطوة التحويل)
ocr.selectText.12=نوع العرض (متقدم)
-ocr.help=\u064A\u0631\u062C\u0649 \u0642\u0631\u0627\u0621\u0629 \u0647\u0630\u0647 \u0627\u0644\u0648\u062B\u0627\u0626\u0642 \u062D\u0648\u0644 \u0643\u064A\u0641\u064A\u0629 \u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0647\u0630\u0627 \u0644\u0644\u063A\u0627\u062A \u0623\u062E\u0631\u0649 \u0648 / \u0623\u0648 \u0627\u0644\u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0644\u064A\u0633 \u0641\u064A \u0639\u0627\u0645\u0644 \u0627\u0644\u0625\u0631\u0633\u0627\u0621
-ocr.credit=\u062A\u0633\u062A\u062E\u062F\u0645 \u0647\u0630\u0647 \u0627\u0644\u062E\u062F\u0645\u0629 OCRmyPDF \u0648 Tesseract \u0644 OCR.
-ocr.submit=\u0645\u0639\u0627\u0644\u062C\u0629 PDF \u0628\u0627\u0633\u062A\u062E\u062F\u0627\u0645 OCR
+ocr.help=يرجى قراءة هذه الوثائق حول كيفية استخدام هذا للغات أخرى و / أو الاستخدام ليس في عامل الإرساء
+ocr.credit=تستخدم هذه الخدمة OCRmyPDF و Tesseract ل OCR.
+ocr.submit=معالجة PDF باستخدام OCR
#extractImages
-extractImages.title=\u0627\u0633\u062A\u062E\u0631\u0627\u062C \u0627\u0644\u0635\u0648\u0631
-extractImages.header=\u0627\u0633\u062A\u062E\u0631\u0627\u062C \u0627\u0644\u0635\u0648\u0631
-extractImages.selectText=\u062D\u062F\u062F \u062A\u0646\u0633\u064A\u0642 \u0627\u0644\u0635\u0648\u0631\u0629 \u0644\u062A\u062D\u0648\u064A\u0644 \u0627\u0644\u0635\u0648\u0631 \u0627\u0644\u0645\u0633\u062A\u062E\u0631\u062C\u0629 \u0625\u0644\u0649
-extractImages.submit=\u0627\u0633\u062A\u062E\u0631\u0627\u062C
+extractImages.title=استخراج الصور
+extractImages.header=استخراج الصور
+extractImages.selectText=حدد تنسيق الصورة لتحويل الصور المستخرجة إلى
+extractImages.submit=استخراج
#File to PDF
-fileToPDF.title=\u0645\u0644\u0641 \u0625\u0644\u0649 PDF
-fileToPDF.header=\u062A\u062D\u0648\u064A\u0644 \u0623\u064A \u0645\u0644\u0641 \u0625\u0644\u0649 PDF
-fileToPDF.credit=\u062A\u0633\u062A\u062E\u062F\u0645 \u0647\u0630\u0647 \u0627\u0644\u062E\u062F\u0645\u0629 \u0644\u064A\u0628\u0631 \u0623\u0648\u0641\u064A\u0633 \u0648\u0623\u0648\u0646\u0648\u0643\u0648\u0646\u0641 \u0644\u062A\u062D\u0648\u064A\u0644 \u0627\u0644\u0645\u0644\u0641\u0627\u062A.
-fileToPDF.supportedFileTypes=\u064A\u062C\u0628 \u0623\u0646 \u062A\u062A\u0636\u0645\u0646 \u0623\u0646\u0648\u0627\u0639 \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0627\u0644\u0645\u062F\u0639\u0648\u0645\u0629 \u0645\u0627 \u064A\u0644\u064A \u0648\u0644\u0643\u0646 \u0644\u0644\u062D\u0635\u0648\u0644 \u0639\u0644\u0649 \u0642\u0627\u0626\u0645\u0629 \u0645\u062D\u062F\u062B\u0629 \u0643\u0627\u0645\u0644\u0629 \u0628\u0627\u0644\u062A\u0646\u0633\u064A\u0642\u0627\u062A \u0627\u0644\u0645\u062F\u0639\u0648\u0645\u0629 \u060C \u064A\u0631\u062C\u0649 \u0627\u0644\u0631\u062C\u0648\u0639 \u0625\u0644\u0649 \u0648\u062B\u0627\u0626\u0642 LibreOffice
-fileToPDF.submit=\u062A\u062D\u0648\u064A\u0644 \u0625\u0644\u0649 PDF
+fileToPDF.title=ملف إلى PDF
+fileToPDF.header=تحويل أي ملف إلى PDF
+fileToPDF.credit=تستخدم هذه الخدمة ليبر أوفيس وأونوكونف لتحويل الملفات.
+fileToPDF.supportedFileTypes=يجب أن تتضمن أنواع الملفات المدعومة ما يلي ولكن للحصول على قائمة محدثة كاملة بالتنسيقات المدعومة ، يرجى الرجوع إلى وثائق LibreOffice
+fileToPDF.submit=تحويل إلى PDF
#compress
@@ -726,11 +778,23 @@ merge.submit=دمج
pdfOrganiser.title=منظم الصفحة
pdfOrganiser.header=منظم صفحات PDF
pdfOrganiser.submit=إعادة ترتيب الصفحات
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=أداة متعددة PDF
multiTool.header=أداة متعددة PDF
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
viewPdf.title=View PDF
@@ -741,6 +805,7 @@ pageRemover.title=مزيل الصفحة
pageRemover.header=مزيل صفحة PDF
pageRemover.pagesToDelete=الصفحات المراد حذفها (أدخل قائمة بأرقام الصفحات مفصولة بفواصل):
pageRemover.submit=حذف الصفحات
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=حدد زاوية الدوران (بمضاعفات 90 درج
rotate.submit=استدارة
-#merge
+#split-pdfs
split.title=انقسام PDF
split.header=تقسيم PDF
split.desc.1=الأرقام التي تحددها هي رقم الصفحة التي تريد تقسيمها
-split.desc.2=على هذا النحو ، سيؤدي تحديد 1،3،7-8 إلى تقسيم مستند من 10 صفحات إلى 6 PDFS منفصلة مع:
+split.desc.2=على هذا النحو ، سيؤدي تحديد 1،3،7-9 إلى تقسيم مستند من 10 صفحات إلى 6 PDFS منفصلة مع:
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.desc.5=المستند رقم 3: الصفحة 4 و 5 و 6 و 7
+split.desc.6=المستند رقم 4: الصفحة 8
+split.desc.7=المستند رقم 5: الصفحة 9
+split.desc.8=المستند رقم 6: الصفحة 10
split.splitPages=أدخل الصفحات المراد تقسيمها:
split.submit=Split
@@ -773,23 +838,23 @@ imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
-imageToPDF.selectText.2=\u062F\u0648\u0631\u0627\u0646 PDF \u062A\u0644\u0642\u0627\u0626\u064A\u064B\u0627
-imageToPDF.selectText.3=\u0627\u0644\u0645\u0646\u0637\u0642 \u0627\u0644\u0645\u062A\u0639\u062F\u062F \u0644\u0644\u0645\u0644\u0641\u0627\u062A (\u0645\u0641\u0639\u0651\u0644 \u0641\u0642\u0637 \u0625\u0630\u0627 \u0643\u0646\u062A \u062A\u0639\u0645\u0644 \u0645\u0639 \u0635\u0648\u0631 \u0645\u062A\u0639\u062F\u062F\u0629)
-imageToPDF.selectText.4=\u062F\u0645\u062C \u0641\u064A \u0645\u0644\u0641 PDF \u0648\u0627\u062D\u062F
-imageToPDF.selectText.5=\u062A\u062D\u0648\u064A\u0644 \u0625\u0644\u0649 \u0645\u0644\u0641\u0627\u062A PDF \u0645\u0646\u0641\u0635\u0644\u0629
+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=\u0646\u0648\u0639 \u0646\u062A\u064A\u062C\u0629 \u0627\u0644\u0635\u0648\u0631\u0629
-pdfToImage.single=\u0635\u0648\u0631\u0629 \u0648\u0627\u062D\u062F\u0629 \u0643\u0628\u064A\u0631\u0629
-pdfToImage.multi=\u0635\u0648\u0631 \u0645\u062A\u0639\u062F\u062F\u0629
-pdfToImage.colorType=\u0646\u0648\u0639 \u0627\u0644\u0644\u0648\u0646
-pdfToImage.color=\u0627\u0644\u0644\u0648\u0646
-pdfToImage.grey=\u062A\u062F\u0631\u062C \u0627\u0644\u0631\u0645\u0627\u062F\u064A
-pdfToImage.blackwhite=\u0623\u0628\u064A\u0636 \u0648\u0623\u0633\u0648\u062F (\u0642\u062F \u064A\u0641\u0642\u062F \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A!)
+pdfToImage.singleOrMultiple=نوع نتيجة الصورة
+pdfToImage.single=صورة واحدة كبيرة
+pdfToImage.multi=صور متعددة
+pdfToImage.colorType=نوع اللون
+pdfToImage.color=اللون
+pdfToImage.grey=تدرج الرمادي
+pdfToImage.blackwhite=أبيض وأسود (قد يفقد البيانات!)
pdfToImage.submit=تحول
@@ -824,10 +889,12 @@ watermark.selectText.3=حجم الخط:
watermark.selectText.4=دوران (0-360):
watermark.selectText.5=widthSpacer (مسافة بين كل علامة مائية أفقيًا):
watermark.selectText.6=heightSpacer (مسافة بين كل علامة مائية عموديًا):
-watermark.selectText.7=\u0627\u0644\u062A\u0639\u062A\u064A\u0645 (0\u066A - 100\u066A):
+watermark.selectText.7=التعتيم (0٪ - 100٪):
watermark.selectText.8=Watermark Type:
watermark.selectText.9=Watermark Image:
watermark.submit=إضافة علامة مائية
+watermark.type.1=Text
+watermark.type.2=Image
#Change permissions
@@ -856,29 +923,31 @@ removePassword.submit=إزالة
#changeMetadata
-changeMetadata.title=\u0627\u0644\u0639\u0646\u0648\u0627\u0646:
-changeMetadata.header=\u062A\u063A\u064A\u064A\u0631 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0648\u0635\u0641\u064A\u0629
-changeMetadata.selectText.1=\u064A\u0631\u062C\u0649 \u062A\u0639\u062F\u064A\u0644 \u0627\u0644\u0645\u062A\u063A\u064A\u0631\u0627\u062A \u0627\u0644\u062A\u064A \u062A\u0631\u063A\u0628 \u0641\u064A \u062A\u063A\u064A\u064A\u0631\u0647\u0627
-changeMetadata.selectText.2=\u062D\u0630\u0641 \u0643\u0644 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0623\u0648\u0644\u064A\u0629
-changeMetadata.selectText.3=\u0625\u0638\u0647\u0627\u0631 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0623\u0648\u0644\u064A\u0629 \u0627\u0644\u0645\u062E\u0635\u0635\u0629:
-changeMetadata.author=\u0627\u0644\u0645\u0624\u0644\u0641:
-changeMetadata.creationDate=\u062A\u0627\u0631\u064A\u062E \u0627\u0644\u0625\u0646\u0634\u0627\u0621 (yyyy / MM / dd HH: mm: ss):
-changeMetadata.creator=\u0627\u0644\u0645\u0646\u0634\u0626:
-changeMetadata.keywords=\u0627\u0644\u0643\u0644\u0645\u0627\u062A \u0627\u0644\u0631\u0626\u064A\u0633\u064A\u0629:
-changeMetadata.modDate=\u062A\u0627\u0631\u064A\u062E \u0627\u0644\u062A\u0639\u062F\u064A\u0644 (yyyy / MM / dd HH: mm: ss):
-changeMetadata.producer=\u0627\u0644\u0645\u0646\u062A\u062C:
-changeMetadata.subject=\u0627\u0644\u0645\u0648\u0636\u0648\u0639:
-changeMetadata.trapped=\u0645\u062D\u0627\u0635\u0631:
-changeMetadata.selectText.4=\u0628\u064A\u0627\u0646\u0627\u062A \u0648\u0635\u0641\u064A\u0629 \u0623\u062E\u0631\u0649:
-changeMetadata.selectText.5=\u0625\u0636\u0627\u0641\u0629 \u0625\u062F\u062E\u0627\u0644 \u0628\u064A\u0627\u0646\u0627\u062A \u0623\u0648\u0644\u064A\u0629 \u0645\u062E\u0635\u0635
-changeMetadata.submit=\u062A\u063A\u064A\u064A\u0631
+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.trapped=محاصر:
+changeMetadata.selectText.4=بيانات وصفية أخرى:
+changeMetadata.selectText.5=إضافة إدخال بيانات أولية مخصص
+changeMetadata.submit=تغيير
#pdfToPDFA
-pdfToPDFA.title=PDF \u0625\u0644\u0649 PDF / A
-pdfToPDFA.header=PDF \u0625\u0644\u0649 PDF / A
-pdfToPDFA.credit=\u062A\u0633\u062A\u062E\u062F\u0645 \u0647\u0630\u0647 \u0627\u0644\u062E\u062F\u0645\u0629 OCRmyPDF \u0644\u062A\u062D\u0648\u064A\u0644 PDF / A.
-pdfToPDFA.submit=\u062A\u062D\u0648\u064A\u0644
+pdfToPDFA.title=PDF إلى PDF / A
+pdfToPDFA.header=PDF إلى PDF / A
+pdfToPDFA.credit=تستخدم هذه الخدمة OCRmyPDF لتحويل PDF / A.
+pdfToPDFA.submit=تحويل
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=تحويل
#PDFToHTML
PDFToHTML.title=PDF إلى HTML
PDFToHTML.header=PDF إلى HTML
-PDFToHTML.credit=تستخدم هذه الخدمة LibreOffice لتحويل الملفات.
+PDFToHTML.credit=تستخدم هذه الخدمة pdftohtml لتحويل الملفات.
PDFToHTML.submit=تحويل
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Choose page to extract table
PDFToCSV.submit=??????
#split-by-size-or-count
+split-by-size-or-count.title=Split PDF 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
@@ -959,6 +1029,15 @@ 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
+split-by-sections.merge=Merge Into One PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Version
licenses.license=License
+# error
+error.sorry=Sorry for the issue!
+error.needHelp=Need help / Found an issue?
+error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
+error.404.head=404 - Page Not Found | Oops, we tripped in the code!
+error.404.1=We can't seem to find the page you're looking for.
+error.404.2=Something went wrong
+error.github=Submit a ticket on GitHub
+error.showStack=Show Stack Trace
+error.copyStack=Copy Stack Trace
+error.githubSubmit=GitHub - Submit a ticket
+error.discordSubmit=Discord - Submit Support post
+
diff --git a/src/main/resources/messages_bg_BG.properties b/src/main/resources/messages_bg_BG.properties
index 9bef411d..ca196110 100644
--- a/src/main/resources/messages_bg_BG.properties
+++ b/src/main/resources/messages_bg_BG.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -17,9 +17,11 @@ true=Вярно
false=Невярно
unknown=Непознат
save=Съхранете
+saveToBrowser=Save to Browser
close=Затворете
filesSelected=избрани файлове
noFavourites=Няма добавени любими
+downloadComplete=Download Complete
bored=Отекчени сте да чакате?
alphabet=Азбука
downloadPdf=Изтеглете PDF
@@ -52,16 +54,34 @@ notAuthenticatedMessage=Потребителят не е автентикира
userNotFoundMessage=Потребителят не е намерен
incorrectPasswordMessage=Текущата парола е неправилна.
usernameExistsMessage=Новият потребител вече съществува.
+invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
+deleteCurrentUserMessage=Cannot delete currently logged in user.
+deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
+downgradeCurrentUserMessage=Не може да се понижи ролята на текущия потребител
+downgradeCurrentUserLongMessage=Не може да се понижи ролята на текущия потребител. Следователно текущият потребител няма да бъде показан.
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
+pipeline.header=Pipeline Menu (Beta)
pipeline.uploadButton=Upload Custom
pipeline.configureButton=Configure
pipeline.defaultOption=Custom
pipeline.submitButton=Submit
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
######################
# Pipeline Options #
@@ -94,6 +114,7 @@ navbar.settings=Настройки
#############
settings.title=Настройки
settings.update=Налична актуализация
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=Версия на приложението:
settings.downloadOption.title=Изберете опция за изтегляне (за изтегляния на един файл без да е архивиран):
settings.downloadOption.1=Отваряне в същия прозорец
@@ -102,12 +123,13 @@ settings.downloadOption.3=Изтегли файл
settings.zipThreshold=Архивирайте файловете, когато броят на изтеглените файлове надвишава
settings.signOut=Изход
settings.accountSettings=Настройки на акаунта
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=Промяна на идентификационните данни
changeCreds.header=Актуализирайте данните за акаунта си
-changeCreds.changeUserAndPassword=Използвате идентификационни данни за вход по подразбиране. Моля, въведете нова парола (и потребителско име, ако искате)
+changeCreds.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=Ново потребителско име
changeCreds.oldPassword=Текуща парола
changeCreds.newPassword=Нова парола
@@ -142,14 +164,18 @@ adminUserSettings.header=Настройки за администраторск
adminUserSettings.admin=Администратор
adminUserSettings.user=Потребител
adminUserSettings.addUser=Добавяне на нов потребител
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.roles=Роли
adminUserSettings.role=Роля
adminUserSettings.actions=Действия
adminUserSettings.apiUser=Ограничен API потребител
+adminUserSettings.extraApiUser=Additional Limited API User
adminUserSettings.webOnlyUser=Само за уеб-потребител
adminUserSettings.demoUser=Demo User (No custom settings)
+adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Принудете потребителя да промени потребителското име/парола при влизане
adminUserSettings.submit=Съхранете потребителя
+adminUserSettings.changeUserRole=Промяна на ролята на потребителя
#############
# HOME-PAGE #
@@ -392,6 +418,15 @@ home.AddStampRequest.desc=Add text or add image stamps at set locations
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Вход
+login.header=Вход
login.signin=Впишете се
login.rememberme=Запомни ме
login.invalid=Невалидно потребителско име или парола.
login.locked=Вашият акаунт е заключен.
login.signinTitle=Моля впишете се
+login.ssoSignIn=Влизане чрез еднократно влизане
+login.oauth2AutoCreateDisabled=OAUTH2 Автоматично създаване на потребител е деактивирано
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Преобразуване към единична стр
pageExtracter.title=Extract Pages
pageExtracter.header=Extract Pages
pageExtracter.submit=Extract
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -623,6 +662,18 @@ compare.document.1=Документ 1
compare.document.2=Документ 2
compare.submit=Сравнявай
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
#sign
sign.title=Подпишете
@@ -643,6 +694,7 @@ repair.submit=Поправи
#flatten
flatten.title=Изравнете
flatten.header=Изравнете PDF-и
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Изравнете
@@ -726,11 +778,23 @@ merge.submit=Обединяване
pdfOrganiser.title=Организатор на страници
pdfOrganiser.header=Организатор на PDF страници
pdfOrganiser.submit=Пренареждане на страниците
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=PDF Мулти инструмент
multiTool.header=PDF Мулти инструмент
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
viewPdf.title=View PDF
@@ -741,6 +805,7 @@ pageRemover.title=Премахване на страници
pageRemover.header=Премахване на PDF страници
pageRemover.pagesToDelete=Страници за изтриване (Въведете списък с номера на страници, разделени със запетая) :
pageRemover.submit=Изтриване на страници
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Изберете ъгъл на въртене (кратно
rotate.submit=Завъртане
-#merge
+#split-pdfs
split.title=Разделяне на PDF
split.header=Разделяне на PDF
split.desc.1=Числата, които избирате, са номера на страницата, на която искате да направите разделяне
-split.desc.2=Така че избирането на 1,3,7-8 ще раздели документ от 10 страници на 6 отделни PDF файла с:
+split.desc.2=Така че избирането на 1,3,7-9 ще раздели документ от 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.desc.5=Документ #3: Страница 4, 5, 6 и 7
+split.desc.6=Документ #4: Страница 8
+split.desc.7=Документ #5: Страница 9
+split.desc.8=Документ #6: Страница 10
split.splitPages=Въведете страници за разделяне:
split.submit=Разделяне
@@ -828,6 +893,8 @@ watermark.selectText.7=Непрозрачност (0% - 100%):
watermark.selectText.8=Тип воден знак:
watermark.selectText.9=Изображение за воден знак:
watermark.submit=Добавяне на воден знак
+watermark.type.1=Text
+watermark.type.2=Image
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF към PDF/A
pdfToPDFA.header=PDF към PDF/A
pdfToPDFA.credit=Тази услуга използва OCRmyPDF за PDF/A преобразуване.
pdfToPDFA.submit=Преобразуване
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Преобразуване
#PDFToHTML
PDFToHTML.title=PDF към HTML
PDFToHTML.header=PDF към HTML
-PDFToHTML.credit=Тази услуга използва LibreOffice за преобразуване на файлове.
+PDFToHTML.credit=Тази услуга използва pdftohtml за преобразуване на файлове.
PDFToHTML.submit=Преобразуване
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Choose page to extract table
PDFToCSV.submit=????????
#split-by-size-or-count
+split-by-size-or-count.title=Split PDF 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
@@ -959,6 +1029,15 @@ 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
+split-by-sections.merge=Merge Into One PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Version
licenses.license=License
+# error
+error.sorry=Sorry for the issue!
+error.needHelp=Need help / Found an issue?
+error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
+error.404.head=404 - Page Not Found | Oops, we tripped in the code!
+error.404.1=We can't seem to find the page you're looking for.
+error.404.2=Something went wrong
+error.github=Submit a ticket on GitHub
+error.showStack=Show Stack Trace
+error.copyStack=Copy Stack Trace
+error.githubSubmit=GitHub - Submit a ticket
+error.discordSubmit=Discord - Submit Support post
+
diff --git a/src/main/resources/messages_ca_CA.properties b/src/main/resources/messages_ca_CA.properties
index e47451b6..41f4f662 100644
--- a/src/main/resources/messages_ca_CA.properties
+++ b/src/main/resources/messages_ca_CA.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -17,9 +17,11 @@ true=Verdader
false=Fals
unknown=Desconegut
save=Desa
+saveToBrowser=Save to Browser
close=Tanca
filesSelected=fitxers seleccionats
noFavourites=No s'ha afegit cap favorit
+downloadComplete=Download Complete
bored=Avorrit esperant?
alphabet=Alfabet
downloadPdf=Descarregueu PDF
@@ -52,16 +54,34 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
+invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
+deleteCurrentUserMessage=Cannot delete currently logged in user.
+deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
+downgradeCurrentUserMessage=No es pot reduir la funció de l'usuari actual
+downgradeCurrentUserLongMessage=No es pot baixar la funció de l'usuari actual. Per tant, no es mostrarà l'usuari actual.
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
+pipeline.header=Pipeline Menu (Beta)
pipeline.uploadButton=Upload Custom
pipeline.configureButton=Configure
pipeline.defaultOption=Custom
pipeline.submitButton=Submit
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
######################
# Pipeline Options #
@@ -94,6 +114,7 @@ navbar.settings=Opcions
#############
settings.title=Opcions
settings.update=Actualització Disponible
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=Versió App:
settings.downloadOption.title=Trieu l'opció de descàrrega (per a descàrregues d'un sol fitxer no zip):
settings.downloadOption.1=Obre mateixa finestra
@@ -102,12 +123,13 @@ settings.downloadOption.3=Descarrega Arxiu
settings.zipThreshold=Comprimiu els fitxers quan el nombre de fitxers baixats superi
settings.signOut=Sortir
settings.accountSettings=Account Settings
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=Change Credentials
changeCreds.header=Update Your Account Details
-changeCreds.changeUserAndPassword=You are using default login credentials. Please enter a new password (and username if wanted)
+changeCreds.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=New Username
changeCreds.oldPassword=Current Password
changeCreds.newPassword=New Password
@@ -142,14 +164,18 @@ adminUserSettings.header=Usuari Admin Opcions Control
adminUserSettings.admin=Admin
adminUserSettings.user=Usuari
adminUserSettings.addUser=Afegir Usuari
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.roles=Rols
adminUserSettings.role=Rol
adminUserSettings.actions=Accions
adminUserSettings.apiUser=Usuari amb API limitada
+adminUserSettings.extraApiUser=Additional Limited API User
adminUserSettings.webOnlyUser=Usuari només WEB
adminUserSettings.demoUser=Demo User (No custom settings)
-adminUserSettings.forceChange=Force user to change username/password on login
+adminUserSettings.internalApiUser=Internal API User
+adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Desar Usuari
+adminUserSettings.changeUserRole=Canvia el rol de l'usuari
#############
# HOME-PAGE #
@@ -392,6 +418,15 @@ home.AddStampRequest.desc=Add text or add image stamps at set locations
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Accedir
+login.header=Accedir
login.signin=Accedir
login.rememberme=Recordar
login.invalid=Nom usuari / password no vàlid
login.locked=Compte bloquejat
login.signinTitle=Autenticat
+login.ssoSignIn=Inicia sessió mitjançant l'inici de sessió ún
+login.oauth2AutoCreateDisabled=L'usuari de creació automàtica OAUTH2 està desactivat
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Convert To Single Page
pageExtracter.title=Extract Pages
pageExtracter.header=Extract Pages
pageExtracter.submit=Extract
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -623,6 +662,18 @@ compare.document.1=Document 1
compare.document.2=Document 2
compare.submit=Comparar
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
#sign
sign.title=Sign
@@ -643,6 +694,7 @@ repair.submit=Reparar
#flatten
flatten.title=Aplanar
flatten.header=Aplana els PDF
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Aplanar
@@ -726,11 +778,23 @@ merge.submit=Fusiona
pdfOrganiser.title=Organitzador de pàgines
pdfOrganiser.header=Organitzador de pàgines PDF
pdfOrganiser.submit=Reorganitza Pàgines
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=PDF Multi Tool
multiTool.header=PDF Multi Tool
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
viewPdf.title=View PDF
@@ -741,6 +805,7 @@ pageRemover.title=Eliminació Pàgines
pageRemover.header=Eliminació Pàgines PDF
pageRemover.pagesToDelete=Pàgines a esborrar (Números de pàgina) :
pageRemover.submit=Esborra Pàgines
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Selecciona l'angle de gir (en múltiples de 90 graus):
rotate.submit=Rota
-#merge
+#split-pdfs
split.title=Divideix PDF
split.header=Divideix PDF
split.desc.1=Els números seleccionats són el número de pàgina en què voleu fer la divisió
-split.desc.2=Per tant, seleccionant 1,3,7-8 dividiria un document de 10 pàgines en 6 PDFS separats amb:
+split.desc.2=Per tant, seleccionant 1,3,7-9 dividiria un document de 10 pàgines en 6 PDFS separats amb:
split.desc.3=Document #1: Pàgina 1
split.desc.4=Document #2: Pàgina 2 i 3
-split.desc.5=Document #3: Pàgina 4, 5 i 6
-split.desc.6=Document #4: Pàgina 7
-split.desc.7=Document #5: Pàgina 8
-split.desc.8=Document #6: Pàgina 9 i 10
+split.desc.5=Document #3: Pàgina 4, 5, 6 i 7
+split.desc.6=Document #4: Pàgina 8
+split.desc.7=Document #5: Pàgina 9
+split.desc.8=Document #6: Pàgina 10
split.splitPages=Introdueix pàgines per dividir-les:
split.submit=Divideix
@@ -828,6 +893,8 @@ watermark.selectText.7=Opacitat (0% - 100%):
watermark.selectText.8=Watermark Type:
watermark.selectText.9=Watermark Image:
watermark.submit=Afegir Marca d'Aigua
+watermark.type.1=Text
+watermark.type.2=Image
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF a PDF/A
pdfToPDFA.header=PDF a PDF/A
pdfToPDFA.credit=Utilitza OCRmyPDF per la conversió a PDF/A
pdfToPDFA.submit=Converteix
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Converteix
#PDFToHTML
PDFToHTML.title=PDF a HTML
PDFToHTML.header=PDF a HTML
-PDFToHTML.credit=Utilitza LibreOffice per a la conversió d'Arxius.
+PDFToHTML.credit=Utilitza pdftohtml per a la conversió d'Arxius.
PDFToHTML.submit=Converteix
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Choose page to extract table
PDFToCSV.submit=Extracte
#split-by-size-or-count
+split-by-size-or-count.title=Split PDF 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
@@ -959,6 +1029,15 @@ 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
+split-by-sections.merge=Merge Into One PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Version
licenses.license=License
+# error
+error.sorry=Sorry for the issue!
+error.needHelp=Need help / Found an issue?
+error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
+error.404.head=404 - Page Not Found | Oops, we tripped in the code!
+error.404.1=We can't seem to find the page you're looking for.
+error.404.2=Something went wrong
+error.github=Submit a ticket on GitHub
+error.showStack=Show Stack Trace
+error.copyStack=Copy Stack Trace
+error.githubSubmit=GitHub - Submit a ticket
+error.discordSubmit=Discord - Submit Support post
+
diff --git a/src/main/resources/messages_de_DE.properties b/src/main/resources/messages_de_DE.properties
index 2f043a7c..6cbd3a29 100644
--- a/src/main/resources/messages_de_DE.properties
+++ b/src/main/resources/messages_de_DE.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -8,7 +8,7 @@ pdfPrompt=PDF auswählen
multiPdfPrompt=PDFs auswählen(2+)
multiPdfDropPrompt=Wählen Sie alle gewünschten PDFs aus (oder ziehen Sie sie per Drag & Drop hierhin)
imgPrompt=Wählen Sie ein Bild
-genericSubmit=Einreichen
+genericSubmit=Absenden
processTimeWarning=Achtung: Abhängig von der Dateigröße kann dieser Prozess bis zu einer Minute dauern
pageOrderPrompt=Seitenreihenfolge (Geben Sie eine durch Komma getrennte Liste von Seitenzahlen ein):
pageSelectionPrompt=Benutzerdefinierte Seitenauswahl (Geben Sie eine durch Kommas getrennte Liste von Seitenzahlen 1,5,6 oder Funktionen wie 2n+1 ein):
@@ -17,9 +17,11 @@ true=Wahr
false=Falsch
unknown=Unbekannt
save=Speichern
+saveToBrowser=Im Browser speichern
close=Schließen
filesSelected=Dateien ausgewählt
noFavourites=Keine Favoriten hinzugefügt
+downloadComplete=Download abgeschlossen
bored=Langeweile beim Warten?
alphabet=Alphabet
downloadPdf=PDF herunterladen
@@ -44,7 +46,7 @@ green=Grün
blue=Blau
custom=benutzerdefiniert...
WorkInProgess=In Arbeit, funktioniert möglicherweise nicht oder ist fehlerhaft. Bitte melden Sie alle Probleme!
-poweredBy=Powered by
+poweredBy=Unterstützt von
yes=Ja
no=Nein
changedCredsMessage=Anmeldedaten geändert!
@@ -52,28 +54,46 @@ notAuthenticatedMessage=Benutzer nicht authentifiziert.
userNotFoundMessage=Benutzer nicht gefunden.
incorrectPasswordMessage=Das Passwort ist falsch.
usernameExistsMessage=Neuer Benutzername existiert bereits.
+invalidUsernameMessage=Ungültiger Benutzername. Der Benutzername darf nur Buchstaben und Zahlen enthalten.
+deleteCurrentUserMessage=Der aktuell angemeldete Benutzer kann nicht gelöscht werden.
+deleteUsernameExistsMessage=Der Benutzername existiert nicht und kann nicht gelöscht werden.
+downgradeCurrentUserMessage=Die Rolle des aktuellen Benutzers kann nicht herabgestuft werden
+downgradeCurrentUserLongMessage=Die Rolle des aktuellen Benutzers kann nicht herabgestuft werden. Daher wird der aktuelle Benutzer nicht angezeigt.
+error=Fehler
+oops=Hoppla!
+help=Hilfe
+goHomepage=Zur Startseite gehen
+joinDiscord=Unserem Discord-Server beitreten
+seeDockerHub=Docker Hub ansehen
+visitGithub=GitHub-Repository besuchen
+donate=Spenden
+color=Farbe
+sponsor=Sponsor
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline-Menü (Alpha)
+pipeline.header=Pipeline-Menü (Beta)
pipeline.uploadButton=Benutzerdefinierter Upload
pipeline.configureButton=Konfigurieren
pipeline.defaultOption=Benutzerdefiniert
pipeline.submitButton=Speichern
+pipeline.help=Hilfe für Pipeline
+pipeline.scanHelp=Hilfe zum Ordnerscan
######################
# Pipeline Options #
######################
pipelineOptions.header=Pipeline-Konfiguration
pipelineOptions.pipelineNameLabel=Pipeline-Name
-pipelineOptions.saveSettings=Save Operation Settings
+pipelineOptions.saveSettings=Operations-Einstellungen speichern
pipelineOptions.pipelineNamePrompt=Geben Sie hier den Namen der Pipeline ein
pipelineOptions.selectOperation=Vorgang auswählen
pipelineOptions.addOperationButton=Vorgang hinzufügen
pipelineOptions.pipelineHeader=Pipeline:
-pipelineOptions.saveButton=Downloaden
+pipelineOptions.saveButton=Herunterladen
pipelineOptions.validateButton=Validieren
@@ -85,7 +105,7 @@ pipelineOptions.validateButton=Validieren
navbar.convert=Konvertieren
navbar.security=Sicherheit
navbar.other=Anderes
-navbar.darkmode=Dark Mode
+navbar.darkmode=Dunkler Modus
navbar.pageOps=Seitenoperationen
navbar.settings=Einstellungen
@@ -94,6 +114,7 @@ navbar.settings=Einstellungen
#############
settings.title=Einstellungen
settings.update=Update verfügbar
+settings.updateAvailable={0} ist die aktuelle installierte Version. Eine neue Version ({1}) ist verfügbar.
settings.appVersion=App-Version:
settings.downloadOption.title=Download-Option wählen (für einzelne Dateien, die keine Zip-Downloads sind):
settings.downloadOption.1=Im selben Fenster öffnen
@@ -102,12 +123,13 @@ settings.downloadOption.3=Datei herunterladen
settings.zipThreshold=Dateien komprimieren, wenn die Anzahl der heruntergeladenen Dateien überschritten wird
settings.signOut=Abmelden
settings.accountSettings=Kontoeinstellungen
-
-
+settings.bored.help=Aktiviert das Easter-Egg-Spiel
+settings.cacheInputs.name=Formulareingaben speichern
+settings.cacheInputs.help=Aktivieren, um zuvor verwendete Eingaben für zukünftige Durchläufe zu speichern
changeCreds.title=Anmeldeinformationen ändern
changeCreds.header=Aktualisieren Sie Ihre Kontodaten
-changeCreds.changeUserAndPassword=Sie verwenden Standard-Anmeldeinformationen. Bitte geben Sie ein neues Passwort (und ggf. einen Benutzernamen) ein.
+changeCreds.changePassword=Sie verwenden die Standard-Zugangsdaten. Bitte geben Sie ein neues Passwort ein.
changeCreds.newUsername=Neuer Benutzername
changeCreds.oldPassword=Aktuelles Passwort
changeCreds.newPassword=Neues Passwort
@@ -128,7 +150,7 @@ account.newPassword=Neues Passwort
account.changePassword=Passwort ändern
account.confirmNewPassword=Neues Passwort bestätigen
account.signOut=Abmelden
-account.yourApiKey=Dein API Schlüssel
+account.yourApiKey=Dein API-Schlüssel
account.syncTitle=Browsereinstellungen mit Konto synchronisieren
account.settingsCompare=Einstellungen vergleichen:
account.property=Eigenschaft
@@ -139,17 +161,21 @@ account.syncToAccount=Synchronisiere Konto <- Browser
adminUserSettings.title=Benutzerkontrolle
adminUserSettings.header=Administrator-Benutzerkontrolle
-adminUserSettings.admin=Admin
+adminUserSettings.admin=Administrator
adminUserSettings.user=Benutzer
adminUserSettings.addUser=Neuen Benutzer hinzufügen
+adminUserSettings.usernameInfo=Der Benutzername darf nur Buchstaben und Zahlen enthalten, keine Leerzeichen oder Sonderzeichen.
adminUserSettings.roles=Rollen
adminUserSettings.role=Rolle
adminUserSettings.actions=Aktion
adminUserSettings.apiUser=Eingeschränkter API-Benutzer
+adminUserSettings.extraApiUser=Zusätzlicher eingeschränkter API-Benutzer
adminUserSettings.webOnlyUser=Nur Web-Benutzer
adminUserSettings.demoUser=Demo-Benutzer (Keine benutzerdefinierten Einstellungen)
+adminUserSettings.internalApiUser=Interner API-Benutzer
adminUserSettings.forceChange=Benutzer dazu zwingen, Benutzernamen/Passwort bei der Anmeldung zu ändern
adminUserSettings.submit=Benutzer speichern
+adminUserSettings.changeUserRole=Benutzerrolle ändern
#############
# HOME-PAGE #
@@ -160,96 +186,96 @@ home.searchBar=Suche nach Funktionen...
home.viewPdf.title=PDF anzeigen
home.viewPdf.desc=Anzeigen, Kommentieren, Text oder Bilder hinzufügen
-viewPdf.tags=view,read,annotate,text,image
+viewPdf.tags=anzeigen,lesen,kommentieren,text,bild
home.multiTool.title=PDF-Multitool
home.multiTool.desc=Seiten zusammenführen, drehen, neu anordnen und entfernen
multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side
home.merge.title=Zusammenführen
-home.merge.desc=Mehrere PDF-Dateien zu einer einzigen zusammenführen.
-merge.tags=merge,Page operations,Back end,server side
+home.merge.desc=Mehrere PDF-Dateien zu einer einzigen zusammenführen
+merge.tags=zusammenführen,seitenvorgänge,back end,serverseite
home.split.title=Aufteilen
-home.split.desc=PDFs in mehrere Dokumente aufteilen.
-split.tags=Page operations,divide,Multi Page,cut,server side
+home.split.desc=PDFs in mehrere Dokumente aufteilen
+split.tags=seitenoperationen,teilen,mehrseitig,ausschneiden,serverseitig
home.rotate.title=Drehen
-home.rotate.desc=Drehen Sie Ihre PDFs ganz einfach.
-rotate.tags=server side
+home.rotate.desc=Drehen Sie Ihre PDFs ganz einfach
+rotate.tags=serverseitig
home.imageToPdf.title=Bild zu PDF
-home.imageToPdf.desc=Konvertieren Sie ein Bild (PNG, JPEG, GIF) in ein PDF.
-imageToPdf.tags=conversion,img,jpg,picture,photo
+home.imageToPdf.desc=Konvertieren Sie ein Bild (PNG, JPEG, GIF) in ein PDF
+imageToPdf.tags=konvertierung,img,jpg,bild,foto
home.pdfToImage.title=PDF zu Bild
-home.pdfToImage.desc=Konvertieren Sie ein PDF in ein Bild (PNG, JPEG, GIF).
-pdfToImage.tags=conversion,img,jpg,picture,photo
+home.pdfToImage.desc=Konvertieren Sie ein PDF in ein Bild (PNG, JPEG, GIF)
+pdfToImage.tags=konvertierung,img,jpg,bild,foto
home.pdfOrganiser.title=Organisieren
-home.pdfOrganiser.desc=Seiten entfernen und Seitenreihenfolge ändern.
-pdfOrganiser.tags=duplex,even,odd,sort,move
+home.pdfOrganiser.desc=Seiten entfernen und Seitenreihenfolge ändern
+pdfOrganiser.tags=duplex,gerade,ungerade,sortieren,verschieben
home.addImage.title=Bild einfügen
-home.addImage.desc=Fügt ein Bild an eine bestimmte Stelle im PDF ein (in Arbeit).
-addImage.tags=img,jpg,picture,photo
+home.addImage.desc=Fügt ein Bild an eine bestimmte Stelle im PDF ein (in Arbeit)
+addImage.tags=img,jpg,bild,foto
home.watermark.title=Wasserzeichen hinzufügen
-home.watermark.desc=Fügen Sie ein eigenes Wasserzeichen zu Ihrem PDF hinzu.
-watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo
+home.watermark.desc=Fügen Sie ein eigenes Wasserzeichen zu Ihrem PDF hinzu
+watermark.tags=text,wiederholend,beschriftung,besitzen,urheberrecht,marke,img,jpg,bild,foto
home.permissions.title=Berechtigungen ändern
-home.permissions.desc=Die Berechtigungen für Ihr PDF-Dokument verändern.
-permissions.tags=read,write,edit,print
+home.permissions.desc=Die Berechtigungen für Ihr PDF-Dokument verändern
+permissions.tags=lesen,schreiben,bearbeiten,drucken
home.removePages.title=Entfernen
-home.removePages.desc=Ungewollte Seiten aus dem PDF entfernen.
-removePages.tags=Remove pages,delete pages
+home.removePages.desc=Ungewollte Seiten aus dem PDF entfernen
+removePages.tags=seiten entfernen,seiten löschen
home.addPassword.title=Passwort hinzufügen
-home.addPassword.desc=Das PDF mit einem Passwort verschlüsseln.
-addPassword.tags=secure,security
+home.addPassword.desc=Das PDF mit einem Passwort verschlüsseln
+addPassword.tags=sicher,sicherheit
home.removePassword.title=Passwort entfernen
-home.removePassword.desc=Den Passwortschutz eines PDFs entfernen.
-removePassword.tags=secure,Decrypt,security,unpassword,delete password
+home.removePassword.desc=Den Passwortschutz eines PDFs entfernen
+removePassword.tags=sichern,entschlüsseln,sicherheit,passwort aufheben,passwort löschen
home.compressPdfs.title=Komprimieren
-home.compressPdfs.desc=PDF komprimieren um die Dateigröße zu reduzieren.
-compressPdfs.tags=squish,small,tiny
+home.compressPdfs.desc=PDF komprimieren um die Dateigröße zu reduzieren
+compressPdfs.tags=komprimieren,verkleinern,minimieren
home.changeMetadata.title=Metadaten ändern
home.changeMetadata.desc=Ändern/Entfernen/Hinzufügen von Metadaten aus einem PDF-Dokument
-changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
+changeMetadata.tags==titel,autor,datum,erstellung,uhrzeit,herausgeber,produzent,statistiken
home.fileToPDF.title=Datei in PDF konvertieren
home.fileToPDF.desc=Konvertieren Sie nahezu jede Datei in PDF (DOCX, PNG, XLS, PPT, TXT und mehr)
-fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
+fileToPDF.tags=transformation,format,dokument,bild,folie,text,konvertierung,büro,dokumente,word,excel,powerpoint
home.ocr.title=Führe OCR/Cleanup-Scans aus
-home.ocr.desc=Cleanup scannt und erkennt Text aus Bildern in einer PDF-Datei und fügt ihn erneut als Text hinzu.
-ocr.tags=recognition,text,image,scan,read,identify,detection,editable
+home.ocr.desc=Cleanup scannt und erkennt Text aus Bildern in einer PDF-Datei und fügt ihn erneut als Text hinzu
+ocr.tags=erkennung,text,bild,scannen,lesen,identifizieren,erkennung,bearbeitbar
home.extractImages.title=Bilder extrahieren
home.extractImages.desc=Extrahiert alle Bilder aus einer PDF-Datei und speichert sie als Zip-Archiv
-extractImages.tags=picture,photo,save,archive,zip,capture,grab
+extractImages.tags=bild,foto,speichern,archivieren,zippen,erfassen,greifen
home.pdfToPDFA.title=PDF zu PDF/A konvertieren
home.pdfToPDFA.desc=PDF zu PDF/A für Langzeitarchivierung konvertieren
-pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
+pdfToPDFA.tags=archiv,langfristig,standard,konvertierung,speicherung,aufbewahrung
home.PDFToWord.title=PDF zu Word
home.PDFToWord.desc=PDF in Word-Formate konvertieren (DOC, DOCX und ODT)
-PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
+PDFToWord.tags=doc,docx,odt,word,transformation,format,konvertierung,office,microsoft,docfile
home.PDFToPresentation.title=PDF zu Präsentation
home.PDFToPresentation.desc=PDF in Präsentationsformate konvertieren (PPT, PPTX und ODP)
-PDFToPresentation.tags=slides,show,office,microsoft
+PDFToPresentation.tags=folien,show,büro,microsoft
home.PDFToText.title=PDF in Text/RTF
home.PDFToText.desc=PDF in Text- oder RTF-Format konvertieren
@@ -257,88 +283,88 @@ PDFToText.tags=richformat,richtextformat,rich text format
home.PDFToHTML.title=PDF in HTML
home.PDFToHTML.desc=PDF in HTML-Format konvertieren
-PDFToHTML.tags=web content,browser friendly
+PDFToHTML.tags=webinhalte,browserfreundlich
home.PDFToXML.title=PDF in XML
home.PDFToXML.desc=PDF in XML-Format konvertieren
-PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
+PDFToXML.tags=datenextraktion,strukturierter inhalt,interop,transformation,konvertierung
home.ScannerImageSplit.title=Gescannte Fotos erkennen/aufteilen
home.ScannerImageSplit.desc=Teilt mehrere Fotos innerhalb eines Fotos/PDF
-ScannerImageSplit.tags=separate,auto-detect,scans,multi-photo,organize
+ScannerImageSplit.tags=separat,automatische erkennung,scans,mehrere fotos,organisieren
home.sign.title=Signieren
home.sign.desc=Fügt PDF-Signaturen durch Zeichnung, Text oder Bild hinzu
-sign.tags=authorize,initials,drawn-signature,text-sign,image-signature
+sign.tags=autorisieren,initialen,gezeichnete signatur,textzeichen,bildsignatur
home.flatten.title=Abflachen
home.flatten.desc=Alle interaktiven Elemente und Formulare aus einem PDF entfernen
-flatten.tags=static,deactivate,non-interactive,streamline
+flatten.tags=statisch,deaktivieren,nicht interaktiv,optimieren
home.repair.title=Reparatur
home.repair.desc=Versucht, ein beschädigtes/kaputtes PDF zu reparieren
-repair.tags=fix,restore,correction,recover
+repair.tags=reparieren,wiederherstellen,korrigieren,wiederherstellen
home.removeBlanks.title=Leere Seiten entfernen
home.removeBlanks.desc=Erkennt und entfernt leere Seiten aus einem Dokument
-removeBlanks.tags=cleanup,streamline,non-content,organize
+removeBlanks.tags=aufräumen,rationalisieren,nicht inhaltsreich,organisieren
home.removeAnnotations.title=Anmerkungen entfernen
home.removeAnnotations.desc=Entfernt alle Kommentare/Anmerkungen aus einem PDF
-removeAnnotations.tags=comments,highlight,notes,markup,remove
+removeAnnotations.tags=kommentare,hervorheben,notizen,markieren,entfernen
home.compare.title=Vergleichen
home.compare.desc=Vergleicht und zeigt die Unterschiede zwischen zwei PDF-Dokumenten an
-compare.tags=differentiate,contrast,changes,analysis
+compare.tags=differenzieren,kontrastieren,verändern,analysieren
home.certSign.title=Mit Zertifikat signieren
home.certSign.desc=Ein PDF mit einem Zertifikat/Schlüssel (PEM/P12) signieren
-certSign.tags=authenticate,PEM,P12,official,encrypt
+certSign.tags=authentifizieren,pem,p12,offiziell,verschlüsseln
home.pageLayout.title=Mehrseitiges Layout
home.pageLayout.desc=Mehrere Seiten eines PDF zu einer Seite zusammenführen
-pageLayout.tags=merge,composite,single-view,organize
+pageLayout.tags=zusammenführen,zusammensetzen,einzelansicht,organisieren
home.scalePages.title=Seitengröße/Skalierung anpassen
home.scalePages.desc=Größe/Skalierung der Seite und/oder des Inhalts ändern
-scalePages.tags=resize,modify,dimension,adapt
+scalePages.tags=größe ändern,ändern,dimensionieren,anpassen
home.pipeline.title=Pipeline (Fortgeschritten)
home.pipeline.desc=Mehrere Aktionen auf ein PDF anwenden, definiert durch ein Pipeline Skript
-pipeline.tags=automate,sequence,scripted,batch-process
+pipeline.tags=automatisieren,sequenzieren,skriptgesteuert,batch prozess
home.add-page-numbers.title=Seitenzahlen hinzufügen
home.add-page-numbers.desc=Hinzufügen von Seitenzahlen an einer bestimmten Stelle
-add-page-numbers.tags=paginate,label,organize,index
+add-page-numbers.tags=paginieren,beschriften,organisieren,indizieren
home.auto-rename.title=PDF automatisch umbenennen
home.auto-rename.desc=PDF-Datei anhand von erkannten Kopfzeilen umbenennen
-auto-rename.tags=auto-detect,header-based,organize,relabel
+auto-rename.tags=automatisch erkennen,header basiert,organisieren,neu kennzeichnen
home.adjust-contrast.title=Farben/Kontrast anpassen
home.adjust-contrast.desc=Kontrast, Sättigung und Helligkeit einer PDF anpassen
-adjust-contrast.tags=color-correction,tune,modify,enhance
+adjust-contrast.tags=farbkorrektur,abstimmung,änderung,verbesserung
home.crop.title=PDF zuschneiden
home.crop.desc=PDF zuschneiden um die Größe zu verändern (Text bleibt erhalten!)
-crop.tags=trim,shrink,edit,shape
+crop.tags=trimmen,verkleinern,bearbeiten,formen
home.autoSplitPDF.title=PDF automatisch teilen
home.autoSplitPDF.desc=Physisch gescannte PDF anhand von Splitter-Seiten und QR-Codes aufteilen
-autoSplitPDF.tags=QR-based,separate,scan-segment,organize
+autoSplitPDF.tags=qr basiert,trennen,segment scannen,organisieren
home.sanitizePdf.title=PDF Bereinigen
home.sanitizePdf.desc=Entfernen von Skripten und anderen Elementen aus PDF-Dateien
-sanitizePdf.tags=clean,secure,safe,remove-threats
+sanitizePdf.tags=sauber,sicher,sicher,bedrohungen entfernen
home.URLToPDF.title=URL/Website zu PDF
home.URLToPDF.desc=Konvertiert jede http(s)URL zu PDF
-URLToPDF.tags=web-capture,save-page,web-to-doc,archive
+URLToPDF.tags=web capture,seite speichern,web to doc,archiv
home.HTMLToPDF.title=HTML zu PDF
home.HTMLToPDF.desc=Konvertiert jede HTML-Datei oder Zip-Archiv zu PDF
-HTMLToPDF.tags=markup,web-content,transformation,convert
+HTMLToPDF.tags=markup,webinhalt,transformation,konvertierung
home.MarkdownToPDF.title=Markdown zu PDF
@@ -353,17 +379,17 @@ getPdfInfo.tags=infomation,daten,statistik
home.extractPage.title=Seite(n) extrahieren
home.extractPage.desc=Extrahiert ausgewählte Seiten aus einer PDF
-extractPage.tags=extrahieren
+extractPage.tags=extrahieren,seite
home.PdfToSinglePage.title=PDF zu einer Seite zusammenfassen
home.PdfToSinglePage.desc=Fügt alle PDF-Seiten zu einer einzigen großen Seite zusammen
-PdfToSinglePage.tags=einzelseite
+PdfToSinglePage.tags=einzelseite,zusammenfassen
home.showJS.title=Javascript anzeigen
home.showJS.desc=Alle Javascript Funktionen in einer PDF anzeigen
-showJS.tags=JS
+showJS.tags=js,javascript
home.autoRedact.title=Automatisch zensieren/schwärzen
home.autoRedact.desc=Automatisches Zensieren (Schwärzen) von Text in einer PDF-Datei basierend auf dem eingegebenen Text
@@ -371,7 +397,7 @@ autoRedact.tags=zensieren,schwärzen
home.tableExtraxt.title=Tabelle extrahieren
home.tableExtraxt.desc=Tabelle aus PDF in CSV extrahieren
-tableExtraxt.tags=CSV
+tableExtraxt.tags=CSV,tabelle,extrahieren
home.autoSizeSplitPDF.title=Teilen nach Größe/Anzahl
@@ -389,7 +415,16 @@ split-by-sections.tags=abschnitte,teilen,bearbeiten
home.AddStampRequest.title=Stempel zu PDF hinzufügen
home.AddStampRequest.desc=Fügen Sie an festgelegten Stellen Text oder Bildstempel hinzu
-AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+AddStampRequest.tags=stempeln,bild hinzufügen,bild zentrieren,wasserzeichen,pdf,einbetten,anpassen
+
+
+home.PDFToBook.title=PDF zum Buch
+home.PDFToBook.desc=Konvertiert PDF mit Calibre in Buch-/Comic-Formate
+PDFToBook.tags=buch,comic,calibre,convert,manga,amazon,kindle
+
+home.BookToPDF.title=Buch als PDF
+home.BookToPDF.desc=Konvertiert Buch-/Comic-Formate mithilfe von Calibre in PDF
+BookToPDF.tags=buch,comic,calibre,convert,manga,amazon,kindle
###########################
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Anmelden
+login.header=Anmelden
login.signin=Anmelden
login.rememberme=Angemeldet bleiben
-login.invalid=Ungültiger Benutzername oder Passwort.
+login.invalid=Benutzername oder Passwort ungültig.
login.locked=Ihr Konto wurde gesperrt.
-login.signinTitle=Bitte melden Sie sich an
+login.signinTitle=Bitte melden Sie sich an.
+login.ssoSignIn=Anmeldung per Single Sign-On
+login.oauth2AutoCreateDisabled=OAUTH2 Benutzer automatisch erstellen deaktiviert
#auto-redact
@@ -414,7 +452,7 @@ autoRedact.textsToRedactLabel=Zu zensierender Text (einer pro Zeile)
autoRedact.textsToRedactPlaceholder=z.B. \nVertraulich \nStreng geheim
autoRedact.useRegexLabel=Regex verwenden
autoRedact.wholeWordSearchLabel=Ganzes Wort suchen
-autoRedact.customPaddingLabel=Benutzerdefinierte Extra-Padding
+autoRedact.customPaddingLabel=Zensierten Bereich vergrößern
autoRedact.convertPDFToImageLabel=PDF in PDF-Bild konvertieren (zum Entfernen von Text hinter dem Kasten)
autoRedact.submitButton=Zensieren
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Zusammenfassen
pageExtracter.title=Seiten extrahieren
pageExtracter.header=Seiten extrahieren
pageExtracter.submit=Extrahieren
+pageExtracter.placeholder=(z.B. 1,2,8 oder 4,7,12-16 oder 2n-1)
#getPdfInfo
@@ -467,16 +506,16 @@ HTMLToPDF.header=HTML zu PDF
HTMLToPDF.help=Akzeptiert HTML-Dateien und ZIPs mit html/css/images etc.
HTMLToPDF.submit=Konvertieren
HTMLToPDF.credit=Verwendet WeasyPrint
-HTMLToPDF.zoom=Zoomstufe zur Darstellung der Website.
-HTMLToPDF.pageWidth=Breite der Seite in Zentimetern. (Leer auf Standard)
-HTMLToPDF.pageHeight=Höhe der Seite in Zentimetern. (Leer auf Standard)
-HTMLToPDF.marginTop=Oberer Rand der Seite in Millimetern. (Leer auf Standard)
-HTMLToPDF.marginBottom=Unterer Rand der Seite in Millimetern. (Leer auf Standard)
-HTMLToPDF.marginLeft=Linker Rand der Seite in Millimetern. (Leer auf Standard)
-HTMLToPDF.marginRight=Linker Rand der Seite in Millimetern. (Leer auf Standard)
-HTMLToPDF.printBackground=Den Hintergrund der Website rendern.
+HTMLToPDF.zoom=Zoomstufe zur Darstellung der Website
+HTMLToPDF.pageWidth=Breite der Seite in Zentimetern (Leer auf Standard)
+HTMLToPDF.pageHeight=Höhe der Seite in Zentimetern (Leer auf Standard)
+HTMLToPDF.marginTop=Oberer Rand der Seite in Millimetern (Leer auf Standard)
+HTMLToPDF.marginBottom=Unterer Rand der Seite in Millimetern (Leer auf Standard)
+HTMLToPDF.marginLeft=Linker Rand der Seite in Millimetern (Leer auf Standard)
+HTMLToPDF.marginRight=Linker Rand der Seite in Millimetern (Leer auf Standard)
+HTMLToPDF.printBackground=Den Hintergrund der Website rendern
HTMLToPDF.defaultHeader=Standardkopfzeile aktivieren (Name und Seitenzahl)
-HTMLToPDF.cssMediaType=CSS-Medientyp der Seite ändern.
+HTMLToPDF.cssMediaType=CSS-Medientyp der Seite ändern
HTMLToPDF.none=Keine
HTMLToPDF.print=Drucken
HTMLToPDF.screen=Bildschirm
@@ -490,7 +529,7 @@ AddStampRequest.stampText=Stempeltext
AddStampRequest.stampImage=Stampelbild
AddStampRequest.alphabet=Alphabet
AddStampRequest.fontSize=Schriftart/Bildgröße
-AddStampRequest.rotation=Rotation
+AddStampRequest.rotation=Drehung
AddStampRequest.opacity=Deckkraft
AddStampRequest.position=Position
AddStampRequest.overrideX=X-Koordinate überschreiben
@@ -577,8 +616,8 @@ pageLayout.submit=Abschicken
#scalePages
scalePages.title=Seitengröße anpassen
scalePages.header=Seitengröße anpassen
-scalePages.pageSize=Format der Seiten des Dokuments.
-scalePages.scaleFactor=Zoomstufe (Ausschnitt) einer Seite.
+scalePages.pageSize=Format der Seiten des Dokuments
+scalePages.scaleFactor=Zoomstufe (Ausschnitt) einer Seite
scalePages.submit=Abschicken
@@ -623,6 +662,18 @@ compare.document.1=Dokument 1
compare.document.2=Dokument 2
compare.submit=Vergleichen
+#BookToPDF
+BookToPDF.title=Bücher und Comics zu PDF
+BookToPDF.header=Buch zu PDF
+BookToPDF.credit=Verwendet Calibre
+BookToPDF.submit=Konvertieren
+
+#PDFToBook
+PDFToBook.title=PDF zu Buch
+PDFToBook.header=PDF zu Buch
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Verwendet Calibre
+PDFToBook.submit=Konvertieren
#sign
sign.title=Signieren
@@ -643,6 +694,7 @@ repair.submit=Reparieren
#flatten
flatten.title=Abflachen
flatten.header=PDFs reduzieren
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Abflachen
@@ -709,7 +761,7 @@ compress.submit=Komprimieren
#Add image
addImage.title=Bild hinzufügen
addImage.header=Ein Bild einfügen
-addImage.everyPage=Jede Seite?
+addImage.everyPage=In jede Seite einfügen?
addImage.upload=Bild hinzufügen
addImage.submit=Bild hinzufügen
@@ -726,11 +778,23 @@ merge.submit=Zusammenführen
pdfOrganiser.title=Seiten anordnen
pdfOrganiser.header=PDF Seitenorganisation
pdfOrganiser.submit=Seiten anordnen
+pdfOrganiser.mode=Modus
+pdfOrganiser.mode.1=Benutzerdefinierte Seitenreihenfolge
+pdfOrganiser.mode.2=Umgekehrte Reihenfolge
+pdfOrganiser.mode.3=Duplex-Sortierung
+pdfOrganiser.mode.4=Heftsortierung
+pdfOrganiser.mode.5=Seitenheftungs-Heftsortierung
+pdfOrganiser.mode.6=Ungerade-Gerade-Teilung
+pdfOrganiser.mode.7=Erste entfernen
+pdfOrganiser.mode.8=Letzte entfernen
+pdfOrganiser.mode.9=Erste und letzte entfernen
+pdfOrganiser.placeholder=(z.B. 1,3,2 oder 4-8,2,10-12 oder 2n-1)
#multiTool
multiTool.title=PDF-Multitool
multiTool.header=PDF-Multitool
+multiTool.uploadPrompts=Bitte PDF hochladen
#view pdf
viewPdf.title=PDF anzeigen
@@ -741,26 +805,27 @@ pageRemover.title=Seiten entfernen
pageRemover.header=PDF Seiten entfernen
pageRemover.pagesToDelete=Seiten zu entfernen (geben Sie eine Kommagetrennte Liste der Seitenzahlen an):
pageRemover.submit=Seiten löschen
+pageRemover.placeholder=(z.B. 1,2,6 oder 1-10,15-30)
#rotate
rotate.title=PDF drehen
rotate.header=PDF drehen
rotate.selectAngle=Wählen Sie den Winkel (in Vielfachen von 90 Grad):
-rotate.submit=Drehen
+rotate.submit=Herunterladen
-#merge
+#split-pdfs
split.title=PDF aufteilen
split.header=PDF aufteilen
split.desc.1=Die Nummern, die Sie auswählen, sind die Seitenzahlen, an denen Sie aufteilen möchten.
-split.desc.2=So würde die Auswahl von 1,3,7-8 ein 10-seitiges Dokument in 6 separate PDFs aufteilen, mit:
+split.desc.2=So würde die Auswahl von 1,3,7-9 ein 10-seitiges Dokument in 6 separate PDFs aufteilen, mit:
split.desc.3=Dokument #1: Seite 1
split.desc.4=Dokument #2: Seite 2 und 3
-split.desc.5=Dokument #3: Seite 4, 5 und 6
-split.desc.6=Dokument #4: Seite 7
-split.desc.7=Dokument #5: Seite 8
-split.desc.8=Dokument #6: Seite 9 und 10
+split.desc.5=Dokument #3: Seite 4, 5, 6 und 7
+split.desc.6=Dokument #4: Seite 8
+split.desc.7=Dokument #5: Seite 9
+split.desc.8=Dokument #6: Seite 10
split.splitPages=Geben Sie die Seiten an, an denen aufgeteilt werden soll:
split.submit=Aufteilen
@@ -828,6 +893,8 @@ watermark.selectText.7=Deckkraft (0% - 100 %):
watermark.selectText.8=Wasserzeichen Typ:
watermark.selectText.9=Wasserzeichen-Bild:
watermark.submit=Wasserzeichen hinzufügen
+watermark.type.1=Text
+watermark.type.2=Bild
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF zu PDF/A
pdfToPDFA.header=PDF zu PDF/A
pdfToPDFA.credit=Dieser Dienst verwendet OCRmyPDF für die PDF/A-Konvertierung
pdfToPDFA.submit=Konvertieren
+pdfToPDFA.tip=Dieser Dienst kann nur einzelne Eingangsdateien verarbeiten.
+pdfToPDFA.outputFormat=Ausgabeformat
#PDFToWord
@@ -906,15 +975,15 @@ PDFToText.submit=Konvertieren
#PDFToHTML
-PDFToHTML.title=PDF in HTML
-PDFToHTML.header=PDF in HTML
-PDFToHTML.credit=Dieser Dienst verwendet LibreOffice für die Dateikonvertierung.
+PDFToHTML.title=PDF zu HTML
+PDFToHTML.header=PDF zu HTML
+PDFToHTML.credit=Dieser Dienst verwendet pdftohtml für die Dateikonvertierung.
PDFToHTML.submit=Konvertieren
#PDFToXML
-PDFToXML.title=PDF in XML
-PDFToXML.header=PDF in XML
+PDFToXML.title=PDF zu XML
+PDFToXML.header=PDF zu XML
PDFToXML.credit=Dieser Dienst verwendet LibreOffice für die Dateikonvertierung.
PDFToXML.submit=Konvertieren
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Seite mit der zu extrahierenden Tabelle wählen
PDFToCSV.submit=Extrahieren
#split-by-size-or-count
+split-by-size-or-count.title=PDF nach Größe oder Anzahl teilen
split-by-size-or-count.header=PDF nach Größe oder Anzahl teilen
split-by-size-or-count.type.label=Teil-Modus wählen
split-by-size-or-count.type.size=Nach Größe
@@ -959,6 +1029,15 @@ split-by-sections.vertical.label=Vertikale Teiler
split-by-sections.horizontal.placeholder=Anzahl horizontaler Teiler eingeben
split-by-sections.vertical.placeholder=Anzahl vertikaler Teiler eingeben
split-by-sections.submit=PDF teilen
+split-by-sections.merge=In eine PDF zusammenfügen
+
+
+#printFile
+printFile.title=Datei drucken
+printFile.header=Datei an Drucker senden
+printFile.selectText.1=Wähle die auszudruckende Datei
+printFile.selectText.2=Druckernamen eingeben
+printFile.submit=Drucken
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Version
licenses.license=Lizenz
+# error
+error.sorry=Entschuldigung für das Problem!
+error.needHelp=Brauchst du Hilfe / Ein Problem gefunden?
+error.contactTip=Wenn du weiterhin Probleme hast, zögere nicht, uns um Hilfe zu bitten. Du kannst ein Ticket auf unserer GitHub-Seite einreichen oder uns über Discord kontaktieren:
+error.404.head=404 - Seite nicht gefunden | Ups, wir sind im Code gestolpert!
+error.404.1=Wir können die gesuchte Seite nicht finden.
+error.404.2=Etwas ist schiefgelaufen
+error.github=Ein Ticket auf GitHub einreichen
+error.showStack=Stack-Trace anzeigen
+error.copyStack=Stack-Trace kopieren
+error.githubSubmit=GitHub - Ein Ticket einreichen
+error.discordSubmit=Discord - Unterstützungsbeitrag einreichen
+
diff --git a/src/main/resources/messages_el_GR.properties b/src/main/resources/messages_el_GR.properties
index fa3c4b65..e4d2537c 100644
--- a/src/main/resources/messages_el_GR.properties
+++ b/src/main/resources/messages_el_GR.properties
@@ -1,80 +1,100 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
language.direction=ltr
-pdfPrompt=\u0395\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE PDF(s)
-multiPdfPrompt=\u0395\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE PDFs (2+)
-multiPdfDropPrompt=\u0395\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE (\u03AE \u03C4\u03C1\u03AC\u03B2\u03B7\u03B3\u03BC\u03B1 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5 \u03BA\u03B1\u03B9 \u03B1\u03C0\u03CC\u03B8\u03B5\u03C3\u03B7) \u03CC\u03BB\u03C9\u03BD \u03C4\u03C9\u03BD PDF \u03C0\u03BF\u03C5 \u03C7\u03C1\u03B5\u03B9\u03AC\u03B6\u03B5\u03C3\u03C4\u03B5
-imgPrompt=\u0395\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE \u0395\u03B9\u03BA\u03CC\u03BD\u03B1\u03C2(\u0395\u03B9\u03BA\u03CC\u03BD\u03C9\u03BD)
-genericSubmit=\u03A5\u03C0\u03BF\u03B2\u03BF\u03BB\u03AE
-processTimeWarning=\u03A0\u03C1\u03BF\u03C3\u03BF\u03C7\u03AE: \u0391\u03C5\u03C4\u03AE \u03B7 \u03B4\u03B9\u03B1\u03B4\u03B9\u03BA\u03B1\u03C3\u03AF\u03B1 \u03BC\u03C0\u03BF\u03C1\u03B5\u03AF \u03BD\u03B1 \u03B4\u03B9\u03B1\u03C1\u03BA\u03AD\u03C3\u03B5\u03B9 \u03AD\u03C9\u03C2 \u03BA\u03B1\u03B9 \u03AD\u03BD\u03B1 \u03BB\u03B5\u03C0\u03C4\u03CC \u03B1\u03BD\u03AC\u03BB\u03BF\u03B3\u03B1 \u03BC\u03B5 \u03C4\u03BF \u03BC\u03AD\u03B3\u03B5\u03B8\u03BF\u03C2 \u03C4\u03BF\u03C5 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5
-pageOrderPrompt=\u03A0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03C3\u03BC\u03AD\u03BD\u03B7 \u03A3\u03B5\u03B9\u03C1\u03AC \u03A3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2 (\u03A0\u03C1\u03BF\u03C3\u03B8\u03AD\u03C3\u03C4\u03B5 \u03BC\u03AF\u03B1 \u03BB\u03AF\u03C3\u03C4\u03B5 \u03B1\u03C0\u03BF \u03B1\u03C1\u03B9\u03B8\u03BC\u03BF\u03CD\u03C2 \u03C3\u03B5\u03BB\u03B9\u03B4\u03CE\u03BD, \u03C7\u03C9\u03C1\u03B9\u03C3\u03BC\u03AD\u03BD\u03B5\u03C2 \u03BC\u03B5 \u03BA\u03CC\u03BC\u03BC\u03B1 \u03AE \u03C3\u03C5\u03BD\u03B1\u03C1\u03C4\u03AE\u03C3\u03B5\u03B9\u03C2 \u03CC\u03C0\u03C9\u03C2 2n+1) :
-pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
-goToPage=Go
-true=\u0391\u03BB\u03B7\u03B8\u03AD\u03C2
-false=\u039B\u03B1\u03BD\u03B8\u03B1\u03C3\u03BC\u03AD\u03BD\u03BF
-unknown=\u0386\u03B3\u03BD\u03C9\u03C3\u03C4\u03BF
-save=\u0391\u03C0\u03BF\u03B8\u03AE\u03BA\u03B5\u03C5\u03C3\u03B7
-close=\u039A\u03BB\u03B5\u03AF\u03C3\u03B9\u03BC\u03BF
-filesSelected=\u03B1\u03C1\u03C7\u03B5\u03AF\u03B1 \u03C0\u03BF\u03C5 \u03B5\u03C0\u03B9\u03BB\u03AD\u03C7\u03B8\u03B7\u03BA\u03B1\u03BD
-noFavourites=\u039A\u03B1\u03BD\u03AD\u03BD\u03B1 \u03B1\u03B3\u03B1\u03C0\u03AE\u03BC\u03B5\u03BD\u03BF \u03B4\u03B5\u03BD \u03AD\u03C7\u03B5\u03B9 \u03C0\u03C1\u03BF\u03C3\u03C4\u03B5\u03B8\u03B5\u03AF
-bored=\u0392\u03B1\u03C1\u03B9\u03AD\u03C3\u03C4\u03B5 \u03BD\u03B1 \u03C0\u03B5\u03C1\u03B9\u03BC\u03AD\u03BD\u03B5\u03C4\u03B5;
-alphabet=\u0391\u03BB\u03C6\u03AC\u03B2\u03B7\u03C4\u03BF
-downloadPdf=\u039A\u03B1\u03C4\u03AD\u03B2\u03B1\u03C3\u03BC\u03B1 \u03C4\u03BF\u03C5 PDF
-text=\u039A\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF
-font=\u0393\u03C1\u03B1\u03BC\u03BC\u03B1\u03C4\u03BF\u03C3\u03B5\u03B9\u03C1\u03AC
-selectFillter=-- \u0395\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE --
-pageNum=\u0391\u03C1\u03B9\u03B8\u03BC\u03CC\u03C2 \u03A3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2
-sizes.small=\u039C\u03B9\u03BA\u03C1\u03CC
-sizes.medium=\u039C\u03B5\u03C3\u03B1\u03AF\u03BF
-sizes.large=\u039C\u03B5\u03B3\u03AC\u03BB\u03BF
-sizes.x-large=\u03A0\u03BF\u03BB\u03CD \u039C\u03B5\u03B3\u03AC\u03BB\u03BF
-error.pdfPassword=\u03A4\u03BF PDF \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF \u03B5\u03AF\u03BD\u03B1\u03B9 \u03BA\u03BB\u03B5\u03B9\u03B4\u03C9\u03BC\u03AD\u03BD\u03BF \u03BC\u03B5 \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC \u03BA\u03B1\u03B9 \u03B5\u03AF\u03C4\u03B5 \u03B4\u03B5\u03BD \u03AD\u03C7\u03B5\u03C4\u03B5 \u03B5\u03B9\u03C3\u03AC\u03B3\u03B5\u03B9 \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC, \u03B5\u03AF\u03C4\u03B5 \u03B5\u03AF\u03BD\u03B1\u03B9 \u03BB\u03B1\u03BD\u03B8\u03B1\u03C3\u03BC\u03AD\u03BD\u03BF\u03C2
-delete=\u0394\u03B9\u03B1\u03B3\u03C1\u03B1\u03C6\u03AE
-username=\u038C\u03BD\u03BF\u03BC\u03B1 \u03A7\u03C1\u03AE\u03C3\u03C4\u03B7
-password=\u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2
-welcome=\u039A\u03B1\u03BB\u03C9\u03C2 \u0389\u03BB\u03B8\u03B1\u03C4\u03B5
+pdfPrompt=Επιλογή PDF(s)
+multiPdfPrompt=Επιλογή PDFs (2+)
+multiPdfDropPrompt=Επιλογή (ή τράβηγμα αρχείου και απόθεση) όλων των PDF που χρειάζεστε
+imgPrompt=Επιλογή Εικόνας(Εικόνων)
+genericSubmit=Υποβολή
+processTimeWarning=Προσοχή: Αυτή η διαδικασία μπορεί να διαρκέσει έως και ένα λεπτό ανάλογα με το μέγεθος του αρχείου
+pageOrderPrompt=Προσαρμοσμένη Σειρά Σελίδας (Προσθέστε μία λίστα απο αριθμούς σελιδών, χωρισμένες με κόμμα ή συναρτήσεις όπως 2n+1) :
+pageSelectionPrompt=Προσαρμοσμένη Επιλογή Σελίδας (Προσθέστε μία λίστα απο αριθμούς σελιδών, χωρισμένες με κόμμα 1,5,6 ή συναρτήσεις όπως 2n+1):
+goToPage=Πήγαινε
+true=Αληθές
+false=Λανθασμένο
+unknown=Άγνωστο
+save=Αποθήκευση
+saveToBrowser=Αποθήκευση στο Browser
+close=Κλείσιμο
+filesSelected=αρχεία που επιλέχθηκαν
+noFavourites=Κανένα αγαπήμενο δεν έχει προστεθεί
+downloadComplete=Η Λήψη Ολοκληρώθηκε
+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=Property
-black=\u039C\u03B1\u03CD\u03C1\u03BF
-white=\u0386\u03C3\u03C0\u03C1\u03BF
-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 problems!
-poweredBy=Powered by
-yes=Yes
-no=No
-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.
-userNotFoundMessage=\u039F \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7\u03C2 \u03B4\u03B5\u03BD \u03B2\u03C1\u03AD\u03B8\u03B7\u03BA\u03B5.
-incorrectPasswordMessage=\u039F \u03C4\u03C1\u03AD\u03C7\u03C9\u03BD \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 \u03B5\u03AF\u03BD\u03B1\u03B9 \u03BB\u03B1\u03BD\u03B8\u03B1\u03C3\u03BC\u03AD\u03BD\u03BF\u03C2.
-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.
+black=Μαύρο
+white=Άσπρο
+red=Κόκκινο
+green=Πράσινο
+blue=Μπλέ
+custom=Προσαρμογή...
+WorkInProgess=Εργασία σε εξέλιξη, Ενδέχεται να μην λειτουργεί ή να έχει λάθη, Παρακαλώ αναφέρετε τυχόν προβλήματα!
+poweredBy=Τροφοδοτείται από
+yes=Ναι
+no=Όχι
+changedCredsMessage=Τα διαπιστευτήρια έχουν αλλάξει!
+notAuthenticatedMessage=Ο χρήστης δεν έχει αυθεντικοποιηθεί.
+userNotFoundMessage=Ο χρήστης δεν βρέθηκε.
+incorrectPasswordMessage=Ο τρέχων κωδικός πρόσβασης είναι λανθασμένος.
+usernameExistsMessage=Το νέο όνομα χρήστη υπάρχει ήδη.
+invalidUsernameMessage=Μη έγκυρο όνομα χρήστη, το όνομα χρήστη πρέπει να περιέχει μόνο αλφαβητικούς χαρακτήρες και αριθμούς.
+deleteCurrentUserMessage=Δεν είναι δυνατή η διαγραφή του τρέχοντος συνδεδεμένου χρήστη.
+deleteUsernameExistsMessage=Το όνομα χρήστη δεν υπάρχει και δεν μπορεί να διαγραφεί.
+downgradeCurrentUserMessage=Δεν είναι δυνατή η υποβάθμιση του ρόλου του τρέχοντος χρήστη
+downgradeCurrentUserLongMessage=Δεν είναι δυνατή η υποβάθμιση του ρόλου του τρέχοντος χρήστη. Ως εκ τούτου, ο τρέχων χρήστης δεν θα εμφανίζεται.
+error=Σφάλμα
+oops=Ωχ!
+help=Βοήθεια
+goHomepage=Πήγαινε στην Αρχική Σελίδα
+joinDiscord=Εγγραφείτε στο Server του Discord μας
+seeDockerHub=Βλέπε το Docker Hub
+visitGithub=Επισκεφθείτε το Αποθετήριο του Github
+donate=Δωρισε
+color=Χρώμα
+sponsor=Yποστηρικτής
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
+pipeline.header=Μενού Pipeline (Beta)
pipeline.uploadButton=Upload Custom
-pipeline.configureButton=Configure
+pipeline.configureButton=Διαμόρφωσε
pipeline.defaultOption=Custom
-pipeline.submitButton=Submit
+pipeline.submitButton=Υποβολή
+pipeline.help=Βοήθεια για το Pipeline
+pipeline.scanHelp=Βοήθεια για Σάρωση Φακέλων
######################
# 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.header=Διαμόρφωση Pipeline
+pipelineOptions.pipelineNameLabel=Όνομα Pipeline
+pipelineOptions.saveSettings=Αποθήκευση Ρυθμίσεων Λειτουργίας
+pipelineOptions.pipelineNamePrompt=Εισαγάγετε το όνομα του pipeline εδώ
+pipelineOptions.selectOperation=Επιλέξτε Λειτουργία
+pipelineOptions.addOperationButton=Προσθήκη λειτουργίας
pipelineOptions.pipelineHeader=Pipeline:
-pipelineOptions.saveButton=Download
-pipelineOptions.validateButton=Validate
+pipelineOptions.saveButton=Λήψη
+pipelineOptions.validateButton=Επικυρώνω
@@ -82,484 +102,503 @@ pipelineOptions.validateButton=Validate
#############
# NAVBAR #
#############
-navbar.convert=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE
-navbar.security=\u0391\u03C3\u03C6\u03AC\u03BB\u03B5\u03B9\u03B1
-navbar.other=\u0394\u03B9\u03AC\u03C6\u03BF\u03C1\u03B1
-navbar.darkmode=\u039C\u03B1\u03CD\u03C1\u03BF \u0398\u03AD\u03BC\u03B1
-navbar.pageOps=\u039B\u03B5\u03B9\u03C4\u03BF\u03C5\u03C1\u03B3\u03AF\u03B5\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2
-navbar.settings=\u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03B9\u03C2
+navbar.convert=Μετατροπή
+navbar.security=Ασφάλεια
+navbar.other=Διάφορα
+navbar.darkmode=Μαύρο Θέμα
+navbar.pageOps=Λειτουργίες σελίδας
+navbar.settings=Ρυθμίσεις
#############
# SETTINGS #
#############
-settings.title=\u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03B9\u03C2
-settings.update=\u03A5\u03C0\u03AC\u03C1\u03C7\u03B5\u03B9 \u03B4\u03B9\u03B1\u03B8\u03AD\u03C3\u03B9\u03BC\u03B7 \u03B5\u03BD\u03B7\u03BC\u03AD\u03C1\u03C9\u03C3\u03B7
-settings.appVersion=\u0388\u03BA\u03B4\u03BF\u03C3\u03B7 \u03B5\u03C6\u03B1\u03C1\u03BC\u03BF\u03B3\u03AE\u03C2: App Version:
-settings.downloadOption.title=\u0395\u03C0\u03B9\u03BB\u03AD\u03BE\u03B5\u03C4\u03B5 \u03C4\u03B7\u03BD \u03B5\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE \u03BB\u03AE\u03C8\u03B7\u03C2 (\u0393\u03B9\u03B1 \u03BB\u03AE\u03C8\u03B5\u03B9\u03C2 \u03BC\u03B5\u03BC\u03BF\u03BD\u03C9\u03BC\u03AD\u03BD\u03C9\u03BD \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD \u03C7\u03C9\u03C1\u03AF\u03C2 zip):
-settings.downloadOption.1=\u0386\u03BD\u03BF\u03B9\u03B3\u03BC\u03B1 \u03C3\u03C4\u03BF \u03AF\u03B4\u03B9\u03BF \u03C0\u03B1\u03C1\u03AC\u03B8\u03C5\u03C1\u03BF
-settings.downloadOption.2=\u0386\u03BD\u03BF\u03B9\u03B3\u03BC\u03B1 \u03C3\u03B5 \u03BD\u03AD\u03BF \u03C0\u03B1\u03C1\u03AC\u03B8\u03C5\u03C1\u03BF
-settings.downloadOption.3=\u039B\u03AE\u03C8\u03B7 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5
-settings.zipThreshold=Zip \u03B1\u03C1\u03C7\u03B5\u03AF\u03B1 \u03CC\u03C4\u03B1\u03BD \u03BF \u03B1\u03C1\u03B9\u03B8\u03BC\u03CC\u03C2 \u03C4\u03C9\u03BD \u03BB\u03B7\u03C6\u03B8\u03AD\u03BD\u03C4\u03C9\u03BD \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD \u03B5\u03AF\u03BD\u03B1\u03B9 \u03C0\u03BF\u03BB\u03CD \u03BC\u03B5\u03B3\u03AC\u03BB\u03BF\u03C2
-settings.signOut=\u0391\u03C0\u03BF\u03C3\u03CD\u03BD\u03B4\u03B5\u03C3\u03B7
-settings.accountSettings=\u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03B9\u03C2 \u039B\u03BF\u03B3\u03B1\u03C1\u03B9\u03B1\u03C3\u03BC\u03BF\u03CD
+settings.title=Ρυθμίσεις
+settings.update=Υπάρχει διαθέσιμη ενημέρωση
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
+settings.appVersion=Έκδοση εφαρμογής:
+settings.downloadOption.title=Επιλέξετε την επιλογή λήψης (Για λήψεις μεμονωμένων αρχείων χωρίς zip):
+settings.downloadOption.1=Άνοιγμα στο ίδιο παράθυρο
+settings.downloadOption.2=Άνοιγμα σε νέο παράθυρο
+settings.downloadOption.3=Λήψη αρχείου
+settings.zipThreshold=Αρχεία Zip όταν ο αριθμός των ληφθέντων αρχείων είναι πολύ μεγάλος
+settings.signOut=Αποσύνδεση
+settings.accountSettings=Ρυθμίσεις Λογαριασμού
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
+
+changeCreds.title=Αλλαγή Διαπιστευτηρίων
+changeCreds.header=Ενημέρωση των λεπτομερειών του Λογαριασμού σας
+changeCreds.changePassword=Χρησιμοποιείτε προεπιλεγμένα διαπιστευτήρια σύνδεσης. Εισαγάγετε έναν νέο κωδικό πρόσβασης
+changeCreds.newUsername=Νέο Όνομα Χρήστη
+changeCreds.oldPassword=Τρέχων Κωδικός Πρόσβασης
+changeCreds.newPassword=Νέος Κωδικός Πρόσβασης
+changeCreds.confirmNewPassword=Επιβεβαίωση Νέου Κωδικού Πρόσβασης
+changeCreds.submit=Υποβολή Αλλαγών
-changeCreds.title=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE \u0394\u03B9\u03B1\u03C0\u03B9\u03C3\u03C4\u03B5\u03C5\u03C4\u03B7\u03C1\u03AF\u03C9\u03BD
-changeCreds.header=\u0395\u03BD\u03B7\u03BC\u03AD\u03C1\u03C9\u03C3\u03B7 \u03C4\u03C9\u03BD \u03BB\u03B5\u03C0\u03C4\u03BF\u03BC\u03B5\u03C1\u03B5\u03B9\u03CE\u03BD \u03C4\u03BF\u03C5 \u039B\u03BF\u03B3\u03B1\u03C1\u03B9\u03B1\u03C3\u03BC\u03BF\u03CD \u03C3\u03B1\u03C2
-changeCreds.changeUserAndPassword=\u03A7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF\u03C4\u03B5 \u03C4\u03B1 \u03C0\u03C1\u03BF\u03B5\u03C0\u03B9\u03BB\u03B5\u03B3\u03BC\u03AD\u03BD\u03B1 \u03B4\u03B9\u03B1\u03C0\u03B9\u03C3\u03C4\u03B5\u03C5\u03C4\u03AE\u03C1\u03B9\u03B1 \u03C3\u03CD\u03BD\u03B4\u03B5\u03C3\u03B7\u03C2. \u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03CE \u03B5\u03B9\u03C3\u03AC\u03B3\u03B5\u03C4\u03B5 \u03BD\u03AD\u03BF \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 (\u03BA\u03B1\u03B9 \u03CC\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 \u03B1\u03BD \u03C4\u03BF \u03B5\u03C0\u03B9\u03B8\u03C5\u03BC\u03B5\u03AF\u03C4\u03B5)
-changeCreds.newUsername=\u039D\u03AD\u03BF \u038C\u03BD\u03BF\u03BC\u03B1 \u03A7\u03C1\u03AE\u03C3\u03C4\u03B7
-changeCreds.oldPassword=\u03A4\u03C1\u03AD\u03C7\u03C9\u03BD \u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03A0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2
-changeCreds.newPassword=\u039D\u03AD\u03BF\u03C2 \u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03A0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2
-changeCreds.confirmNewPassword=\u0395\u03C0\u03B9\u03B2\u03B5\u03B2\u03B1\u03AF\u03C9\u03C3\u03B7 \u039D\u03AD\u03BF\u03C5 \u039A\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD \u03A0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2
-changeCreds.submit=\u03A5\u03C0\u03BF\u03B2\u03BF\u03BB\u03AE \u0391\u03BB\u03BB\u03B1\u03B3\u03CE\u03BD
-
-
-
-account.title=\u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03B9\u03C2 \u039B\u03BF\u03B3\u03B1\u03C1\u03B9\u03B1\u03C3\u03BC\u03BF\u03CD
-account.accountSettings=\u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03B9\u03C2 \u039B\u03BF\u03B3\u03B1\u03C1\u03B9\u03B1\u03C3\u03BC\u03BF\u03CD
-account.adminSettings=\u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03B9\u03C2 \u0394\u03B9\u03B1\u03C7\u03B5\u03B9\u03C1\u03B9\u03C3\u03C4\u03AE - \u03A0\u03C1\u03BF\u03B2\u03BF\u03BB\u03AE \u03BA\u03B1\u03B9 \u03C0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03C7\u03C1\u03B7\u03C3\u03C4\u03CE\u03BD
-account.userControlSettings=\u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03B9\u03C2 \u03A7\u03B5\u03B9\u03C1\u03B9\u03C3\u03BC\u03BF\u03CD \u03A7\u03C1\u03B7\u03C3\u03C4\u03CE\u03BD
-account.changeUsername=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE \u039F\u03BD\u03CC\u03BC\u03B1\u03C4\u03BF\u03C2 \u03A7\u03C1\u03AE\u03C3\u03C4\u03B7
-account.newUsername=\u039d\u03ad\u03bf \u038c\u03bd\u03bf\u03bc\u03b1 \u03a7\u03c1\u03ae\u03c3\u03c4\u03b7
-account.password=\u0395\u03C0\u03B9\u03B2\u03B5\u03B2\u03B1\u03AF\u03C9\u03C3\u03B7 \u039A\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD \u03A0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2
-account.oldPassword=\u03A0\u03B1\u03BB\u03B9\u03CC\u03C2 \u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03A0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2
-account.newPassword=\u039D\u03AD\u03BF\u03C2 \u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03A0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2
-account.changePassword=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE \u039A\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD \u03A0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2
-account.confirmNewPassword=\u0395\u03C0\u03B9\u03B2\u03B5\u03B2\u03B1\u03AF\u03C9\u03C3\u03B7 \u039D\u03AD\u03BF\u03C5 \u039A\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD
-account.signOut=\u0391\u03C0\u03BF\u03C3\u03CD\u03BD\u03B4\u03B5\u03C3\u03B7
-account.yourApiKey=\u03A4\u03BF \u03BA\u03BB\u03B5\u03B9\u03B4\u03AF \u03C3\u03B1\u03C2 \u03B3\u03B9\u03B1 \u03C4\u03B7 \u03B4\u03B9\u03B5\u03C0\u03B1\u03C6\u03AE \u03C0\u03C1\u03BF\u03B3\u03C1\u03B1\u03BC\u03BC\u03B1\u03C4\u03B9\u03C3\u03BC\u03BF\u03CD \u03B5\u03C6\u03B1\u03C1\u03BC\u03BF\u03B3\u03CE\u03BD (API key)
-account.syncTitle=\u03A3\u03C5\u03B3\u03C7\u03C1\u03BF\u03BD\u03B9\u03C3\u03BC\u03CC\u03C2 \u03C4\u03C9\u03BD \u03C1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03C9\u03BD \u03C4\u03BF\u03C5 \u03C6\u03C5\u03BB\u03BB\u03BF\u03BC\u03B5\u03C4\u03C1\u03B7\u03C4\u03AE (Web Browser) \u03BC\u03B5 \u03C4\u03BF\u03BD \u03BB\u03BF\u03B3\u03B1\u03C1\u03B9\u03B1\u03C3\u03BC\u03CC
-account.settingsCompare=\u03A3\u03CD\u03B3\u03BA\u03C1\u03B9\u03C3\u03B7 \u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03C9\u03BD:
+account.title=Ρυθμίσεις Λογαριασμού
+account.accountSettings=Ρυθμίσεις Λογαριασμού
+account.adminSettings=Ρυθμίσεις Διαχειριστή - Προβολή και προσθήκη χρηστών
+account.userControlSettings=Ρυθμίσεις Χειρισμού Χρηστών
+account.changeUsername=Αλλαγή Ονόματος Χρήστη
+account.newUsername=Νέο Όνομα Χρήστη
+account.password=Επιβεβαίωση Κωδικού Πρόσβασης
+account.oldPassword=Παλιός Κωδικός Πρόσβασης
+account.newPassword=Νέος Κωδικός Πρόσβασης
+account.changePassword=Αλλαγή Κωδικού Πρόσβασης
+account.confirmNewPassword=Επιβεβαίωση Νέου Κωδικού
+account.signOut=Αποσύνδεση
+account.yourApiKey=Το κλειδί σας για τη διεπαφή προγραμματισμού εφαρμογών (API key)
+account.syncTitle=Συγχρονισμός των ρυθμίσεων του φυλλομετρητή (Web Browser) με τον λογαριασμό
+account.settingsCompare=Σύγκριση Ρυθμίσεων:
account.property=Property
-account.webBrowserSettings=\u03A1\u03CD\u03B8\u03BC\u03B9\u03C3\u03B7 \u03C6\u03C5\u03BB\u03BB\u03BF\u03BC\u03B5\u03C4\u03C1\u03B7\u03C4\u03AE (Web Browser)
-account.syncToBrowser=\u03A3\u03C5\u03B3\u03C7\u03C1\u03BF\u03BD\u03B9\u03C3\u03BC\u03CC\u03C2 \u039B\u03BF\u03B3\u03B1\u03C1\u03B9\u03B1\u03C3\u03BC\u03BF\u03CD -> \u03A6\u03C5\u03BB\u03BB\u03BF\u03BC\u03B5\u03C4\u03C1\u03B7\u03C4\u03AE (Web Browser)
-account.syncToAccount=\u03A3\u03C5\u03B3\u03C7\u03C1\u03BF\u03BD\u03B9\u03C3\u03BC\u03CC\u03C2 \u039B\u03BF\u03B3\u03B1\u03C1\u03B9\u03B1\u03C3\u03BC\u03BF\u03CD <- \u03A6\u03C5\u03BB\u03BB\u03BF\u03BC\u03B5\u03C4\u03C1\u03B7\u03C4\u03AE (Web Browser)
+account.webBrowserSettings=Ρύθμιση φυλλομετρητή (Web Browser)
+account.syncToBrowser=Συγχρονισμός Λογαριασμού -> Φυλλομετρητή (Web Browser)
+account.syncToAccount=Συγχρονισμός Λογαριασμού <- Φυλλομετρητή (Web Browser)
-adminUserSettings.title=\u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03B9\u03C2 \u03B5\u03BB\u03AD\u03B3\u03C7\u03BF\u03C5 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7
-adminUserSettings.header=\u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03B9\u03C2 \u03B5\u03BB\u03AD\u03B3\u03C7\u03BF\u03C5 \u0394\u03B9\u03B1\u03C7\u03B5\u03B9\u03C1\u03B9\u03C3\u03C4\u03AE
-adminUserSettings.admin=\u0394\u03B9\u03B1\u03C7\u03B5\u03B9\u03C1\u03B9\u03C3\u03C4\u03AE\u03C2
-adminUserSettings.user=\u03A7\u03C1\u03AE\u03C3\u03C4\u03B7\u03C2
-adminUserSettings.addUser=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03BD\u03AD\u03BF\u03C5 \u03A7\u03C1\u03AE\u03C3\u03C4\u03B7
-adminUserSettings.roles=\u03A1\u03CC\u03BB\u03BF\u03B9
-adminUserSettings.role=\u03A1\u03CC\u03BB\u03BF\u03C2
-adminUserSettings.actions=\u0395\u03BD\u03AD\u03C1\u03B3\u03B5\u03B9\u03B5\u03C2
-adminUserSettings.apiUser=\u03A0\u03B5\u03C1\u03B9\u03BF\u03C1\u03B9\u03C3\u03BC\u03AD\u03BD\u03BF\u03C2 \u03A7\u03C1\u03AE\u03C3\u03C4\u03B7\u03C2 \u03B3\u03B9\u03B1 \u03B4\u03B9\u03B5\u03C0\u03B1\u03C6\u03AE \u03C0\u03C1\u03BF\u03B3\u03C1\u03B1\u03BC\u03BC\u03B1\u03C4\u03B9\u03C3\u03BC\u03BF\u03CD \u03B5\u03C6\u03B1\u03C1\u03BC\u03BF\u03B3\u03CE\u03BD (API User)
-adminUserSettings.webOnlyUser=\u03A7\u03C1\u03AE\u03C3\u03C4\u03B7\u03C2 \u03BC\u03CC\u03BD\u03BF \u0399\u03C3\u03C4\u03BF\u03CD
-adminUserSettings.demoUser=Demo User (No custom settings)
-adminUserSettings.forceChange=\u0391\u03BD\u03B1\u03B3\u03BA\u03AC\u03C3\u03C4\u03B5 \u03C4\u03BF\u03BD \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 \u03BD\u03B1 \u03B1\u03BB\u03BB\u03AC\u03BE\u03B5\u03B9 \u03C4\u03BF \u03CC\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7/\u03BA\u03C9\u03B4\u03B9\u03BA\u03CC \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 \u03BA\u03B1\u03C4\u03AC \u03C4\u03B7 \u03C3\u03CD\u03BD\u03B4\u03B5\u03C3\u03B7
-adminUserSettings.submit=\u0391\u03C0\u03BF\u03B8\u03AE\u03BA\u03B5\u03C5\u03C3\u03B7 \u03A7\u03C1\u03AE\u03C3\u03C4\u03B7
+adminUserSettings.title=Ρυθμίσεις ελέγχου χρήστη
+adminUserSettings.header=Ρυθμίσεις ελέγχου Διαχειριστή
+adminUserSettings.admin=Διαχειριστής
+adminUserSettings.user=Χρήστης
+adminUserSettings.addUser=Προσθήκη νέου Χρήστη
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
+adminUserSettings.roles=Ρόλοι
+adminUserSettings.role=Ρόλος
+adminUserSettings.actions=Ενέργειες
+adminUserSettings.apiUser=Περιορισμένος Χρήστης για διεπαφή προγραμματισμού εφαρμογών (API User)
+adminUserSettings.extraApiUser=Πρόσθετος Περιορισμένος Χρήστης για Διεπαφή Προγραμματισμού Εφαρμογών (API User)
+adminUserSettings.webOnlyUser=Χρήστης μόνο Ιστού
+adminUserSettings.demoUser=Demo χρήστης (Χωρίς προσαρμοσμένες ρυθμίσεις)
+adminUserSettings.internalApiUser=Εσωτερικός API χρήστης
+adminUserSettings.forceChange=Αναγκάστε τον χρήστη να αλλάξει το όνομα χρήστη/κωδικό πρόσβασης κατά τη σύνδεση
+adminUserSettings.submit=Αποθήκευση Χρήστη
+adminUserSettings.changeUserRole=Αλλαγή ρόλου χρήστη
#############
# HOME-PAGE #
#############
-home.desc=\u0397 \u03C4\u03BF\u03C0\u03B9\u03BA\u03AC \u03C6\u03B9\u03BB\u03BF\u03BE\u03B5\u03BD\u03BF\u03CD\u03BC\u03B5\u03BD\u03B7 one-stop-shop \u03C3\u03B1\u03C2 \u03B3\u03B9\u03B1 \u03CC\u03BB\u03B5\u03C2 \u03C4\u03B9\u03C2 \u03B1\u03BD\u03AC\u03B3\u03BA\u03B5\u03C2 \u03C3\u03B1\u03C2 \u03C3\u03B5 PDF.
-home.searchBar=Search for features...
+home.desc=Η τοπικά φιλοξενούμενη one-stop-shop σας για όλες τις ανάγκες σας σε PDF.
+home.searchBar=Αναζήτηση για χαρακτηριστικά...
-home.viewPdf.title=\u0395\u03BC\u03C6\u03AC\u03BD\u03B9\u03C3\u03B7 PDF
-home.viewPdf.desc=\u0395\u03BC\u03C6\u03AC\u03BD\u03B9\u03C3\u03B7, \u03C0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03C3\u03C7\u03B5\u03B4\u03AF\u03BF\u03C5, \u03C0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03BA\u03B5\u03B9\u03BC\u03AD\u03BD\u03BF\u03C5 \u03AE \u03B5\u03B9\u03BA\u03CC\u03BD\u03C9\u03BD
+home.viewPdf.title=Εμφάνιση PDF
+home.viewPdf.desc=Εμφάνιση, προσθήκη σχεδίου, προσθήκη κειμένου ή εικόνων
viewPdf.tags=view,read,annotate,text,image
-home.multiTool.title=PDF \u03A0\u03BF\u03BB\u03C5\u03B5\u03C1\u03B3\u03B1\u03BB\u03B5\u03AF\u03BF
-home.multiTool.desc=\u03A3\u03C5\u03B3\u03C7\u03CE\u03BD\u03B5\u03C5\u03C3\u03B7, \u03A0\u03B5\u03C1\u03B9\u03C3\u03C4\u03C1\u03BF\u03C6\u03AE, \u0391\u03BD\u03B1\u03B4\u03B9\u03AC\u03C4\u03B1\u03BE\u03B7 \u03BA\u03B1\u03B9 \u039A\u03B1\u03C4\u03AC\u03C1\u03B3\u03B7\u03C3\u03B7 \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD
+home.multiTool.title=PDF Πολυεργαλείο
+home.multiTool.desc=Συγχώνευση, Περιστροφή, Αναδιάταξη και Κατάργηση σελίδων
multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side,interactive,intractable,move
-home.merge.title=\u03A3\u03C5\u03B3\u03C7\u03CE\u03BD\u03B5\u03C5\u03C3\u03B7
-home.merge.desc=\u03A3\u03C5\u03B3\u03C7\u03CE\u03BD\u03B5\u03C5\u03C3\u03B7 \u03C0\u03BF\u03BB\u03BB\u03CE\u03BD PDF \u03C3\u03B5 \u03AD\u03BD\u03B1 \u03BC\u03B5 \u03B5\u03CD\u03BA\u03BF\u03BB\u03BF \u03C4\u03C1\u03CC\u03C0\u03BF.
+home.merge.title=Συγχώνευση
+home.merge.desc=Συγχώνευση πολλών PDF σε ένα με εύκολο τρόπο.
merge.tags=merge,Page operations,Back end,server side
-home.split.title=\u0394\u03B9\u03B1\u03C7\u03C9\u03C1\u03B9\u03C3\u03BC\u03CC\u03C2
-home.split.desc=\u0394\u03B9\u03B1\u03C7\u03C9\u03C1\u03B9\u03C3\u03BC\u03CC\u03C2 \u03C4\u03C9\u03BD PDF \u03C3\u03B5 \u03C0\u03BF\u03BB\u03BB\u03AC \u03AD\u03B3\u03B3\u03C1\u03B1\u03C6\u03B1.
+home.split.title=Διαχωρισμός
+home.split.desc=Διαχωρισμός των PDF σε πολλά έγγραφα.
split.tags=Page operations,divide,Multi Page,cut,server side
-home.rotate.title=\u03A0\u03B5\u03C1\u03B9\u03C3\u03C4\u03C1\u03BF\u03C6\u03AE
-home.rotate.desc=\u03A0\u03B5\u03C1\u03B9\u03C3\u03C4\u03C1\u03BF\u03C6\u03AE \u03C4\u03C9\u03BD PDF \u03C3\u03B1\u03C2 \u03BC\u03B5 \u03B5\u03CD\u03BA\u03BF\u03BB\u03BF \u03C4\u03C1\u03CC\u03C0\u03BF.
-rotate.tags=server side
+home.rotate.title=Περιστροφή
+home.rotate.desc=Περιστροφή των PDF σας με εύκολο τρόπο.
+rotate.tags=από την πλευρά του server
-home.imageToPdf.title=\u0395\u03B9\u03BA\u03CC\u03BD\u03B1 \u03C3\u03B5 PDF
-home.imageToPdf.desc=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03B5\u03B9\u03BA\u03CC\u03BD\u03B1\u03C2 (PNG, JPEG, GIF) \u03C3\u03B5 PDF.
+home.imageToPdf.title=Εικόνα σε PDF
+home.imageToPdf.desc=Μετατροπή εικόνας (PNG, JPEG, GIF) σε PDF.
imageToPdf.tags=conversion,img,jpg,picture,photo
-home.pdfToImage.title=PDF \u03C3\u03B5 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B1
-home.pdfToImage.desc=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03B5\u03BD\u03CC\u03C2 PDF \u03C3\u03B5 \u03BC\u03AF\u03B1 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B1. (PNG, JPEG, GIF)
+home.pdfToImage.title=PDF σε εικόνα
+home.pdfToImage.desc=Μετατροπή ενός PDF σε μία εικόνα. (PNG, JPEG, GIF)
pdfToImage.tags=conversion,img,jpg,picture,photo
-home.pdfOrganiser.title=\u039F\u03C1\u03B3\u03AC\u03BD\u03C9\u03C3\u03B7
-home.pdfOrganiser.desc=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7/\u0391\u03BD\u03B1\u03B4\u03B9\u03AC\u03C4\u03B1\u03BE\u03B7 \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD \u03BC\u03B5 \u03BF\u03C0\u03BF\u03B9\u03B1\u03B4\u03AE\u03C0\u03BF\u03C4\u03B5 \u03C3\u03B5\u03B9\u03C1\u03AC
+home.pdfOrganiser.title=Οργάνωση
+home.pdfOrganiser.desc=Αφαίρεση/Αναδιάταξη σελίδων με οποιαδήποτε σειρά
pdfOrganiser.tags=duplex,even,odd,sort,move
-home.addImage.title=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u0395\u03B9\u03BA\u03CC\u03BD\u03B1\u03C2
-home.addImage.desc=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03BC\u03B9\u03B1\u03C2 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B1\u03C2 \u03C3\u03B5 \u03BC\u03B9\u03B1 \u03BA\u03B1\u03B8\u03BF\u03C1\u03B9\u03C3\u03BC\u03AD\u03BD\u03B7 \u03B8\u03AD\u03C3\u03B7 \u03C3\u03C4\u03BF PDF
+home.addImage.title=Προσθήκη Εικόνας
+home.addImage.desc=Προσθήκη μιας εικόνας σε μια καθορισμένη θέση στο PDF
addImage.tags=img,jpg,picture,photo
-home.watermark.title=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03A5\u03B4\u03B1\u03C4\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2
-home.watermark.desc=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03B5\u03BD\u03CC\u03C2 \u03C0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03C3\u03BC\u03AD\u03BD\u03BF\u03C5 \u03C5\u03B4\u03B1\u03C4\u03BF\u03B3\u03C1\u03AC\u03C6\u03B7\u03BC\u03B1\u03C4\u03BF\u03C2 \u03C3\u03C4\u03BF \u03AD\u03B3\u03B3\u03C1\u03B1\u03C6\u03CC PDF.
+home.watermark.title=Προσθήκη Υδατογραφήματος
+home.watermark.desc=Προσθήκη ενός προσαρμοσμένου υδατογράφηματος στο έγγραφό PDF.
watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo
-home.permissions.title=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE \u0394\u03B9\u03BA\u03B1\u03B9\u03C9\u03BC\u03AC\u03C4\u03C9\u03BD
-home.permissions.desc=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE \u03C4\u03C9\u03BD \u0394\u03B9\u03BA\u03B1\u03B9\u03C9\u03BC\u03AC\u03C4\u03C9\u03BD \u03C3\u03C4\u03BF \u03AD\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF PDF
+home.permissions.title=Αλλαγή Δικαιωμάτων
+home.permissions.desc=Αλλαγή των Δικαιωμάτων στο έγγραφο PDF
permissions.tags=read,write,edit,print
-home.removePages.title=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7
-home.removePages.desc=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u03BC\u03AE \u03B5\u03C0\u03B9\u03B8\u03C5\u03BC\u03B7\u03C4\u03CE\u03BD \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD \u03B1\u03C0\u03BF \u03C4\u03BF \u03AD\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF PDF.
+home.removePages.title=Αφαίρεση
+home.removePages.desc=Αφαίρεση μή επιθυμητών σελίδων απο το έγγραφο PDF.
removePages.tags=Remove pages,delete pages
-home.addPassword.title=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03BA\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD
-home.addPassword.desc=\u039A\u03C1\u03C5\u03C0\u03C4\u03BF\u03B3\u03C1\u03AC\u03C6\u03B7\u03C3\u03B7 - \u03BA\u03BB\u03B5\u03AF\u03B4\u03C9\u03BC\u03B1 \u03C4\u03BF\u03C5 PDF \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5 \u03BC\u03B5 \u03AD\u03BD\u03B1\u03BD \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC.
+home.addPassword.title=Προσθήκη κωδικού
+home.addPassword.desc=Κρυπτογράφηση - κλείδωμα του PDF αρχείου με έναν κωδικό.
addPassword.tags=secure,security
-home.removePassword.title=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u039A\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD
-home.removePassword.desc=\u039A\u03B1\u03C4\u03AC\u03C1\u03B3\u03AE\u03C3\u03B7 \u03C4\u03B7\u03C2 \u03C0\u03C1\u03BF\u03C3\u03C4\u03B1\u03C3\u03AF\u03B1\u03C2 \u03BC\u03B5 \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 \u03B1\u03C0\u03CC \u03C4\u03BF \u03AD\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF PDF.
+home.removePassword.title=Αφαίρεση Κωδικού
+home.removePassword.desc=Κατάργήση της προστασίας με κωδικό πρόσβασης από το έγγραφο PDF.
removePassword.tags=secure,Decrypt,security,unpassword,delete password
-home.compressPdfs.title=\u03A3\u03C5\u03BC\u03C0\u03AF\u03B5\u03C3\u03B7
-home.compressPdfs.desc=\u03A3\u03C5\u03BC\u03C0\u03AF\u03B5\u03C3\u03B7 \u03C4\u03C9\u03BD \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD PDF \u03B3\u03B9\u03B1 \u03C4\u03B7\u03BD \u03BC\u03B5\u03AF\u03C9\u03C3\u03B7 \u03C4\u03BF\u03C5 \u03BC\u03B5\u03B3\u03AD\u03B8\u03BF\u03C5\u03C2 \u03C4\u03BF\u03C5\u03C2.
+home.compressPdfs.title=Συμπίεση
+home.compressPdfs.desc=Συμπίεση των αρχείων PDF για την μείωση του μεγέθους τους.
compressPdfs.tags=squish,small,tiny
-home.changeMetadata.title=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE \u039C\u03B5\u03C4\u03B1\u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03C9\u03BD
-home.changeMetadata.desc=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE/\u039A\u03B1\u03C4\u03AC\u03C1\u03B3\u03B7\u03C3\u03B7/\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03BC\u03B5\u03C4\u03B1\u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03C9\u03BD \u03B1\u03C0\u03CC \u03AD\u03BD\u03B1 \u03AD\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF PDF.
+home.changeMetadata.title=Αλλαγή Μεταδεδομένων
+home.changeMetadata.desc=Αλλαγή/Κατάργηση/Προσθήκη μεταδεδομένων από ένα έγγραφο PDF.
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
-home.fileToPDF.title=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03B5\u03BD\u03CC\u03C2 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5 \u03C3\u03B5 PDF
-home.fileToPDF.desc=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C3\u03C7\u03B5\u03B4\u03CC\u03BD \u03BF\u03C0\u03BF\u03B9\u03BF\u03C5\u03B4\u03AE\u03C0\u03BF\u03C4\u03B5 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5 \u03C3\u03B5 PDF (DOCX, PNG, XLS, PPT, TXT and more)
+home.fileToPDF.title=Μετατροπή ενός αρχείου σε PDF
+home.fileToPDF.desc=Μετατροπή σχεδόν οποιουδήποτε αρχείου σε PDF (DOCX, PNG, XLS, PPT, TXT and more)
fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
-home.ocr.title=\u03BF\u03C0\u03C4\u03B9\u03BA\u03AE \u03B1\u03BD\u03B1\u03B3\u03BD\u03CE\u03C1\u03B9\u03C3\u03B7 \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03C9\u03BD (OCR) / \u03A3\u03B1\u03C1\u03CE\u03C3\u03B5\u03B9\u03C2 Cleanup
-home.ocr.desc=\u03A4\u03BF Cleanup \u03C3\u03B1\u03C1\u03CE\u03BD\u03B5\u03B9 \u03BA\u03B1\u03B9 \u03B1\u03BD\u03B9\u03C7\u03BD\u03B5\u03CD\u03B5\u03B9 \u03BA\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF \u03B1\u03C0\u03CC \u03B5\u03B9\u03BA\u03CC\u03BD\u03B5\u03C2 \u03BC\u03AD\u03C3\u03B1 \u03C3\u03B5 \u03AD\u03BD\u03B1 PDF \u03BA\u03B1\u03B9 \u03C4\u03BF \u03C0\u03C1\u03BF\u03C3\u03B8\u03AD\u03C4\u03B5\u03B9 \u03BE\u03B1\u03BD\u03AC \u03C9\u03C2 \u03BA\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF
+home.ocr.title=οπτική αναγνώριση χαρακτήρων (OCR) / Σαρώσεις Cleanup
+home.ocr.desc=Το Cleanup σαρώνει και ανιχνεύει κείμενο από εικόνες μέσα σε ένα PDF και το προσθέτει ξανά ως κείμενο
ocr.tags=recognition,text,image,scan,read,identify,detection,editable
-home.extractImages.title=\u0395\u03BE\u03B1\u03B3\u03C9\u03B3\u03AE \u03B5\u03B9\u03BA\u03CC\u03BD\u03C9\u03BD
-home.extractImages.desc=\u0395\u03BE\u03B1\u03B3\u03C9\u03B3\u03AE \u03CC\u03BB\u03C9\u03BD \u03C4\u03C9\u03BD \u03B5\u03B9\u03BA\u03CC\u03BD\u03C9\u03BD \u03B1\u03C0\u03BF \u03AD\u03BD\u03B1 PDF \u03BA\u03B1\u03B9 \u03B1\u03C0\u03BF\u03B8\u03AE\u03BA\u03B5\u03C5\u03C3\u03B7 \u03B1\u03C5\u03C4\u03CE\u03BD \u03C3\u03B5 zip
+home.extractImages.title=Εξαγωγή εικόνων
+home.extractImages.desc=Εξαγωγή όλων των εικόνων απο ένα PDF και αποθήκευση αυτών σε zip
extractImages.tags=picture,photo,save,archive,zip,capture,grab
-home.pdfToPDFA.title=PDF \u03C3\u03B5 PDF/A
-home.pdfToPDFA.desc=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE PDF \u03C3\u03B5 PDF/A \u03B3\u03B9\u03B1 \u03BC\u03B1\u03BA\u03C1\u03BF\u03C7\u03C1\u03CC\u03BD\u03B9\u03B1 \u03B1\u03C0\u03BF\u03B8\u03AE\u03BA\u03B5\u03C5\u03C3\u03B7
+home.pdfToPDFA.title=PDF σε PDF/A
+home.pdfToPDFA.desc=Μετατροπή PDF σε PDF/A για μακροχρόνια αποθήκευση
pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
-home.PDFToWord.title=PDF \u03C3\u03B5 Word
-home.PDFToWord.desc=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C4\u03BF\u03C5 PDF \u03C3\u03B5 Word \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF (DOC, DOCX and ODT)
+home.PDFToWord.title=PDF σε Word
+home.PDFToWord.desc=Μετατροπή του PDF σε Word αρχείο (DOC, DOCX and ODT)
PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
-home.PDFToPresentation.title=PDF \u03C3\u03B5 Powerpoint
-home.PDFToPresentation.desc=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C4\u03BF\u03C5 PDF \u03C3\u03B5 Powerpoint \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF (PPT, PPTX and ODP)
+home.PDFToPresentation.title=PDF σε Powerpoint
+home.PDFToPresentation.desc=Μετατροπή του PDF σε Powerpoint αρχείο (PPT, PPTX and ODP)
PDFToPresentation.tags=slides,show,office,microsoft
-home.PDFToText.title=PDF \u03C3\u03B5 RTF (\u039A\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF)
-home.PDFToText.desc=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C4\u03BF\u03C5 PDF \u03C3\u03B5 \u039A\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF \u03AE \u03C3\u03B5 \u03BC\u03BF\u03C1\u03C6\u03AE RTF
+home.PDFToText.title=PDF σε RTF (Κείμενο)
+home.PDFToText.desc=Μετατροπή του PDF σε Κείμενο ή σε μορφή RTF
PDFToText.tags=richformat,richtextformat,rich text format
-home.PDFToHTML.title=PDF \u03C3\u03B5 HTML
-home.PDFToHTML.desc=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C4\u03BF\u03C5 PDF \u03C3\u03B5 \u03BC\u03BF\u03C1\u03C6\u03AE HTML
+home.PDFToHTML.title=PDF σε HTML
+home.PDFToHTML.desc=Μετατροπή του PDF σε μορφή HTML
PDFToHTML.tags=web content,browser friendly
-home.PDFToXML.title=PDF \u03C3\u03B5 XML
-home.PDFToXML.desc=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C4\u03BF\u03C5 PDF \u03C3\u03B5 \u03BC\u03BF\u03C1\u03C6\u03AE XML
+home.PDFToXML.title=PDF σε XML
+home.PDFToXML.desc=Μετατροπή του PDF σε μορφή XML
PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
-home.ScannerImageSplit.title=\u0391\u03BD\u03AF\u03C7\u03BD\u03B5\u03C5\u03C3\u03B7/\u0394\u03B9\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u03C3\u03B1\u03C1\u03C9\u03BC\u03AD\u03BD\u03C9\u03BD \u03C6\u03C9\u03C4\u03BF\u03B3\u03C1\u03B1\u03C6\u03B9\u03CE\u03BD
-home.ScannerImageSplit.desc=\u0394\u03B9\u03B1\u03C7\u03C9\u03C1\u03AF\u03C3\u03BC\u03CC\u03C2 \u03C0\u03BF\u03BB\u03BB\u03CE\u03BD \u03C6\u03C9\u03C4\u03BF\u03B3\u03C1\u03B1\u03C6\u03AF\u03CE\u03BD \u03BC\u03AD\u03C3\u03B1 \u03B1\u03C0\u03CC \u03BC\u03B9\u03B1 \u03C6\u03C9\u03C4\u03BF\u03B3\u03C1\u03B1\u03C6\u03AF\u03B1/PDF
+home.ScannerImageSplit.title=Ανίχνευση/Διαίρεση σαρωμένων φωτογραφιών
+home.ScannerImageSplit.desc=Διαχωρίσμός πολλών φωτογραφίών μέσα από μια φωτογραφία/PDF
ScannerImageSplit.tags=separate,auto-detect,scans,multi-photo,organize
-home.sign.title=\u03A5\u03C0\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE
-home.sign.desc=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03C5\u03C0\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE\u03C2 \u03C3\u03C4\u03BF PDF \u03BC\u03B5 \u03C3\u03C7\u03AD\u03B4\u03B9\u03BF, \u03BA\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF \u03AE \u03B5\u03B9\u03BA\u03CC\u03BD\u03B1.
+home.sign.title=Υπογραφή
+home.sign.desc=Προσθήκη υπογραφής στο PDF με σχέδιο, κείμενο ή εικόνα.
sign.tags=authorize,initials,drawn-signature,text-sign,image-signature
home.flatten.title=Flatten
-home.flatten.desc=\u039A\u03B1\u03C4\u03AC\u03C1\u03B3\u03B7\u03C3\u03B7 \u03CC\u03BB\u03C9\u03BD \u03C4\u03C9\u03BD \u03B4\u03B9\u03B1\u03B4\u03C1\u03B1\u03C3\u03C4\u03B9\u03BA\u03CE\u03BD \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03C9\u03BD \u03BA\u03B1\u03B9 \u03C6\u03BF\u03C1\u03BC\u03CE\u03BD \u03B1\u03C0\u03CC \u03AD\u03BD\u03B1 PDF
+home.flatten.desc=Κατάργηση όλων των διαδραστικών στοιχείων και φορμών από ένα PDF
flatten.tags=static,deactivate,non-interactive,streamline
-home.repair.title=\u0395\u03C0\u03B9\u03B4\u03B9\u03CC\u03C1\u03B8\u03C9\u03C3\u03B7
-home.repair.desc=\u03A0\u03C1\u03BF\u03C3\u03C0\u03AC\u03B8\u03B5\u03B9\u03B1 \u03B5\u03C0\u03B9\u03B4\u03B9\u03CC\u03C1\u03B8\u03C9\u03C3\u03B7\u03C2 \u03B5\u03BD\u03CC\u03C2 \u03BA\u03B1\u03C4\u03B5\u03C3\u03C4\u03C1\u03B1\u03BC\u03BC\u03AD\u03BD\u03BF\u03C5 PDF
+home.repair.title=Επιδιόρθωση
+home.repair.desc=Προσπάθεια επιδιόρθωσης ενός κατεστραμμένου PDF
repair.tags=fix,restore,correction,recover
-home.removeBlanks.title=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u03BA\u03B5\u03BD\u03CE\u03BD \u03A3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD
-home.removeBlanks.desc=\u0391\u03BD\u03AF\u03C7\u03B5\u03C5\u03C3\u03B7 \u03BA\u03B1\u03B9 \u03B1\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u03BA\u03B5\u03BD\u03CE\u03BD \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD \u03B1\u03C0\u03CC \u03AD\u03BD\u03B1 \u03AD\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF
+home.removeBlanks.title=Αφαίρεση κενών Σελίδων
+home.removeBlanks.desc=Ανίχευση και αφαίρεση κενών σελίδων από ένα έγγραφο
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=\u03A3\u03CD\u03B3\u03BA\u03C1\u03B9\u03C3\u03B7
-home.compare.desc=\u03A3\u03CD\u03B3\u03BA\u03C1\u03B9\u03C3\u03B7 \u03BA\u03B1\u03B9 \u03B5\u03BC\u03C6\u03AC\u03BD\u03B9\u03C3\u03B7 \u03C4\u03C9\u03BD \u03B4\u03B9\u03B1\u03C6\u03BF\u03C1\u03CE\u03BD \u03BC\u03B5\u03C4\u03B1\u03BE\u03CD \u03B4\u03CD\u03BF PDF \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD
+home.compare.title=Σύγκριση
+home.compare.desc=Σύγκριση και εμφάνιση των διαφορών μεταξύ δύο PDF αρχείων
compare.tags=differentiate,contrast,changes,analysis
-home.certSign.title=\u03A5\u03C0\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE \u03BC\u03B5 \u03A0\u03B9\u03C3\u03C4\u03BF\u03C0\u03BF\u03B9\u03B7\u03C4\u03B9\u03BA\u03CC
-home.certSign.desc=\u03A5\u03C0\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE \u03B5\u03BD\u03CC\u03C2 PDF \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5 \u03BC\u03B5 \u03AD\u03BD\u03B1 \u03A0\u03B9\u03C3\u03C4\u03BF\u03C0\u03BF\u03B9\u03B7\u03C4\u03B9\u03BA\u03CC/\u039A\u03BB\u03B5\u03B9\u03B4\u03AF (PEM/P12)
+home.certSign.title=Υπογραφή με Πιστοποιητικό
+home.certSign.desc=Υπογραφή ενός PDF αρχείου με ένα Πιστοποιητικό/Κλειδί (PEM/P12)
certSign.tags=authenticate,PEM,P12,official,encrypt
-home.pageLayout.title=\u0394\u03B9\u03AC\u03C4\u03B1\u03BE\u03B7 \u03C0\u03BF\u03BB\u03BB\u03CE\u03BD \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD
-home.pageLayout.desc=\u03A3\u03C5\u03B3\u03C7\u03CE\u03BD\u03B5\u03C5\u03C3\u03B7 \u03C0\u03BF\u03BB\u03BB\u03B1\u03C0\u03BB\u03CE\u03BD \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD \u03B5\u03BD\u03CC\u03C2 \u03B5\u03B3\u03B3\u03C1\u03AC\u03C6\u03BF\u03C5 PDF \u03C3\u03B5 \u03BC\u03AF\u03B1 \u03BC\u03CC\u03BD\u03BF \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1
+home.pageLayout.title=Διάταξη πολλών σελίδων
+home.pageLayout.desc=Συγχώνευση πολλαπλών σελίδων ενός εγγράφου PDF σε μία μόνο σελίδα
pageLayout.tags=merge,composite,single-view,organize
-home.scalePages.title=\u03A0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03B3\u03AE \u03C4\u03BF\u03C5 \u03BC\u03B5\u03B3\u03AD\u03B8\u03BF\u03C5\u03C2/\u03BA\u03BB\u03AF\u03BC\u03B1\u03BA\u03B1\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2
-home.scalePages.desc=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE \u03C4\u03BF\u03C5 \u03BC\u03B5\u03B3\u03AD\u03B8\u03BF\u03C5\u03C2/\u03BA\u03BB\u03AF\u03BC\u03B1\u03BA\u03B1\u03C2 \u03BC\u03AF\u03B1\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2 \u03BA\u03B1\u03B9/\u03B7 \u03C4\u03BF\u03C5 \u03C0\u03B5\u03C1\u03B9\u03B5\u03C7\u03BF\u03BC\u03AD\u03BD\u03BF\u03C5 \u03C4\u03B7\u03C2.
+home.scalePages.title=Προσαρμογή του μεγέθους/κλίμακας σελίδας
+home.scalePages.desc=Αλλαγή του μεγέθους/κλίμακας μίας σελίδας και/η του περιεχομένου της.
scalePages.tags=resize,modify,dimension,adapt
-home.pipeline.title=Pipeline (\u0393\u03B9\u03B1 \u03C0\u03C1\u03BF\u03C7\u03C9\u03C1\u03B7\u03BC\u03AD\u03BD\u03BF\u03C5\u03C2)
-home.pipeline.desc=\u0395\u03BA\u03C4\u03AD\u03BB\u03B5\u03C3\u03B7 \u03C0\u03BF\u03BB\u03BB\u03B1\u03C0\u03BB\u03CE\u03BD \u03B5\u03BD\u03B5\u03C1\u03B3\u03B5\u03B9\u03CE\u03BD \u03C3\u03B5 \u03B1\u03C1\u03C7\u03B5\u03AF\u03B1 PDF \u03BF\u03C1\u03AF\u03B6\u03BF\u03BD\u03C4\u03B1\u03C2 pipeline scripts
+home.pipeline.title=Pipeline (Για προχωρημένους)
+home.pipeline.desc=Εκτέλεση πολλαπλών ενεργειών σε αρχεία PDF ορίζοντας pipeline scripts
pipeline.tags=automate,sequence,scripted,batch-process
-home.add-page-numbers.title=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03B1\u03C1\u03B9\u03B8\u03BC\u03CE\u03BD \u03C3\u03B5 \u03A3\u03B5\u03BB\u03AF\u03B4\u03B5\u03C2
-home.add-page-numbers.desc=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03B1\u03C1\u03B9\u03B8\u03BC\u03CE\u03BD \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD \u03C3\u03B5 \u03AD\u03BD\u03B1 \u03AD\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF \u03C3\u03B5 \u03BC\u03B9\u03B1 \u03BA\u03B1\u03B8\u03BF\u03C1\u03B9\u03C3\u03BC\u03AD\u03BD\u03B7 \u03B8\u03AD\u03C3\u03B7
+home.add-page-numbers.title=Προσθήκη αριθμών σε Σελίδες
+home.add-page-numbers.desc=Προσθήκη αριθμών σελίδων σε ένα έγγραφο σε μια καθορισμένη θέση
add-page-numbers.tags=paginate,label,organize,index
-home.auto-rename.title=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B7 \u03BC\u03B5\u03C4\u03BF\u03BD\u03BF\u03BC\u03B1\u03C3\u03AF\u03B1 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5 PDF
-home.auto-rename.desc=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B7 \u03BC\u03B5\u03C4\u03BF\u03BD\u03BF\u03BC\u03B1\u03C3\u03AF\u03B1 \u03B5\u03BD\u03CC\u03C2 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5 PDF \u03BC\u03B5 \u03B2\u03AC\u03C3\u03B7 \u03C4\u03B7\u03BD \u03BA\u03B5\u03C6\u03B1\u03BB\u03AF\u03B4\u03B1 \u03C0\u03BF\u03C5 \u03AD\u03C7\u03B5\u03B9 \u03B5\u03BD\u03C4\u03BF\u03C0\u03B9\u03C3\u03C4\u03B5\u03AF
+home.auto-rename.title=Αυτόματη μετονομασία αρχείου PDF
+home.auto-rename.desc=Αυτόματη μετονομασία ενός αρχείου PDF με βάση την κεφαλίδα που έχει εντοπιστεί
auto-rename.tags=auto-detect,header-based,organize,relabel
-home.adjust-contrast.title=\u03A0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03B3\u03AE \u03C7\u03C1\u03C9\u03BC\u03AC\u03C4\u03C9\u03BD/\u0391\u03BD\u03C4\u03AF\u03B8\u03B5\u03C3\u03B7
-home.adjust-contrast.desc=\u03A0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03B3\u03AE \u03C4\u03B7\u03C2 \u03B1\u03BD\u03C4\u03AF\u03B8\u03B5\u03C3\u03B7\u03C2, \u03C4\u03BF\u03C5 \u03BA\u03BF\u03C1\u03B5\u03C3\u03BC\u03BF\u03CD \u03BA\u03B1\u03B9 \u03C4\u03B7\u03C2 \u03C6\u03C9\u03C4\u03B5\u03B9\u03BD\u03CC\u03C4\u03B7\u03C4\u03B1\u03C2 \u03B5\u03BD\u03CC\u03C2 PDF
+home.adjust-contrast.title=Προσαρμογή χρωμάτων/Αντίθεση
+home.adjust-contrast.desc=Προσαρμογή της αντίθεσης, του κορεσμού και της φωτεινότητας ενός PDF
adjust-contrast.tags=color-correction,tune,modify,enhance
-home.crop.title=\u03A0\u03B5\u03C1\u03B9\u03BA\u03BF\u03C0\u03AE PDF
-home.crop.desc=\u03A0\u03B5\u03C1\u03B9\u03BA\u03BF\u03C0\u03AE \u03B5\u03BD\u03CC\u03C2 PDF \u03B3\u03B9\u03B1 \u03BD\u03B1 \u03BC\u03B5\u03B9\u03C9\u03B8\u03B5\u03AF \u03C4\u03BF \u03BC\u03AD\u03B3\u03B5\u03B8\u03CC\u03C2 \u03C4\u03BF\u03C5 (\u03B4\u03B9\u03B1\u03C4\u03B7\u03C1\u03B5\u03AF \u03C4\u03BF \u03BA\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF!)
+home.crop.title=Περικοπή PDF
+home.crop.desc=Περικοπή ενός PDF για να μειωθεί το μέγεθός του (διατηρεί το κείμενο!)
crop.tags=trim,shrink,edit,shape
-home.autoSplitPDF.title=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03BF\u03C2 \u03B4\u03B9\u03B1\u03C7\u03C9\u03C1\u03B9\u03C3\u03BC\u03CC\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD
-home.autoSplitPDF.desc=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03BF\u03C2 \u03B4\u03B9\u03B1\u03C7\u03C9\u03C1\u03B9\u03C3\u03BC\u03CC\u03C2 \u03C3\u03B1\u03C1\u03C9\u03BC\u03AD\u03BD\u03BF\u03C5 PDF \u03BC\u03B5 \u03C6\u03C5\u03C3\u03B9\u03BA\u03CC \u03C3\u03B1\u03C1\u03C9\u03BC\u03AD\u03BD\u03BF \u03B4\u03B9\u03B1\u03C7\u03C9\u03C1\u03B9\u03C3\u03C4\u03AE \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD QR Code
+home.autoSplitPDF.title=Αυτόματος διαχωρισμός σελίδων
+home.autoSplitPDF.desc=Αυτόματος διαχωρισμός σαρωμένου PDF με φυσικό σαρωμένο διαχωριστή σελίδων QR Code
autoSplitPDF.tags=QR-based,separate,scan-segment,organize
-home.sanitizePdf.title=\u0391\u03C0\u03BF\u03BB\u03CD\u03BC\u03B1\u03BD\u03C3\u03B7
-home.sanitizePdf.desc=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u03C3\u03B5\u03BD\u03B1\u03C1\u03AF\u03C9\u03BD \u03BA\u03B1\u03B9 \u03AC\u03BB\u03BB\u03C9\u03BD \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03C9\u03BD \u03B1\u03C0\u03CC \u03B1\u03C1\u03C7\u03B5\u03AF\u03B1 PDF
+home.sanitizePdf.title=Απολύμανση
+home.sanitizePdf.desc=Αφαίρεση σεναρίων και άλλων στοιχείων από αρχεία PDF
sanitizePdf.tags=clean,secure,safe,remove-threats
-home.URLToPDF.title=URL/\u0399\u03C3\u03C4\u03CC\u03C4\u03BF\u03C0\u03BF\u03C2 \u03C3\u03B5 PDF
-home.URLToPDF.desc=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03BF\u03C0\u03BF\u03B9\u03B1\u03B4\u03AE\u03C0\u03BF\u03C4\u03B5 \u03B4\u03B9\u03B5\u03CD\u03B8\u03C5\u03BD\u03C3\u03B7\u03C2 URL http(s) \u03C3\u03B5 PDF
+home.URLToPDF.title=URL/Ιστότοπος σε PDF
+home.URLToPDF.desc=Μετατροπή οποιαδήποτε διεύθυνσης URL http(s) σε PDF
URLToPDF.tags=web-capture,save-page,web-to-doc,archive
-home.HTMLToPDF.title=HTML \u03C3\u03B5 PDF
-home.HTMLToPDF.desc=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03BF\u03C0\u03BF\u03B9\u03BF\u03C5\u03B4\u03AE\u03C0\u03BF\u03C4\u03B5 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5 HTML \u03AE zip \u03C3\u03B5 PDF
+home.HTMLToPDF.title=HTML σε PDF
+home.HTMLToPDF.desc=Μετατροπή οποιουδήποτε αρχείου HTML ή zip σε PDF
HTMLToPDF.tags=markup,web-content,transformation,convert
-home.MarkdownToPDF.title=Markdown \u03C3\u03B5 PDF
-home.MarkdownToPDF.desc=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03BF\u03C0\u03BF\u03B9\u03BF\u03C5\u03B4\u03AE\u03C0\u03BF\u03C4\u03B5 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5 Markdown \u03C3\u03B5 PDF
+home.MarkdownToPDF.title=Markdown σε PDF
+home.MarkdownToPDF.desc=Μετατροπή οποιουδήποτε αρχείου Markdown σε PDF
MarkdownToPDF.tags=markup,web-content,transformation,convert
-home.getPdfInfo.title=\u039B\u03AE\u03C8\u03B7 \u03CC\u03BB\u03C9\u03BD \u03C4\u03C9\u03BD \u03C0\u03BB\u03B7\u03C1\u03BF\u03C6\u03BF\u03C1\u03B9\u03CE\u03BD \u03B1\u03C0\u03CC \u03C4\u03BF PDF
-home.getPdfInfo.desc=\u039B\u03AE\u03C8\u03B7 \u03CC\u03BB\u03C9\u03BD \u03C4\u03C9\u03BD \u03C0\u03B9\u03B8\u03B1\u03BD\u03CE\u03BD \u03C0\u03BB\u03B7\u03C1\u03BF\u03C6\u03BF\u03C1\u03B9\u03CE\u03BD \u03B1\u03C0\u03CC \u03C4\u03B1 \u03B1\u03C1\u03C7\u03B5\u03AF\u03B1 PDF
+home.getPdfInfo.title=Λήψη όλων των πληροφοριών από το PDF
+home.getPdfInfo.desc=Λήψη όλων των πιθανών πληροφοριών από τα αρχεία PDF
getPdfInfo.tags=infomation,data,stats,statistics
-home.extractPage.title=\u0395\u03BE\u03B1\u03B3\u03C9\u03B3\u03AE \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD
-home.extractPage.desc=\u0395\u03BE\u03B1\u03B3\u03C9\u03B3\u03AE \u03C4\u03C9\u03BD \u03B5\u03C0\u03B9\u03BB\u03B5\u03B3\u03BC\u03AD\u03BD\u03C9\u03BD \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD \u03B1\u03C0\u03CC \u03AD\u03BD\u03B1 PDF
+home.extractPage.title=Εξαγωγή σελίδων
+home.extractPage.desc=Εξαγωγή των επιλεγμένων σελίδων από ένα PDF
extractPage.tags=extract
-home.PdfToSinglePage.title=PDF \u03C3\u03B5 \u03BC\u03AF\u03B1 \u03BC\u03B5\u03B3\u03AC\u03BB\u03B7 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1
-home.PdfToSinglePage.desc=\u03A3\u03C5\u03B3\u03C7\u03CE\u03BD\u03B5\u03C5\u03C3\u03B7 \u03CC\u03BB\u03C9\u03BD \u03C4\u03C9\u03BD \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD PDF \u03C3\u03B5 \u03BC\u03B9\u03B1 \u03BC\u03B5\u03B3\u03AC\u03BB\u03B7 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1
+home.PdfToSinglePage.title=PDF σε μία μεγάλη σελίδα
+home.PdfToSinglePage.desc=Συγχώνευση όλων των σελίδων PDF σε μια μεγάλη σελίδα
PdfToSinglePage.tags=single page
-home.showJS.title=\u0395\u03BC\u03C6\u03AC\u03BD\u03B9\u03C3\u03B7 Javascript
-home.showJS.desc=\u0391\u03BD\u03B6\u03AE\u03C4\u03B7\u03C3\u03B7 \u03BA\u03B1\u03B9 \u03B5\u03BC\u03C6\u03AC\u03BD\u03B9\u03C3\u03B7 \u03BA\u03CE\u03B4\u03B9\u03BA\u03B1 Javascript \u03C0\u03BF\u03C5 \u03B5\u03AF\u03BD\u03B1\u03B9 \u03B5\u03BD\u03C3\u03C9\u03BC\u03B1\u03C4\u03C9\u03BC\u03AD\u03BD\u03BF \u03BC\u03AD\u03C3\u03B1 \u03C3\u03B5 \u03AD\u03BD\u03B1 PDF
+home.showJS.title=Εμφάνιση Javascript
+home.showJS.desc=Ανζήτηση και εμφάνιση κώδικα Javascript που είναι ενσωματωμένο μέσα σε ένα PDF
showJS.tags=JS
-home.autoRedact.title=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03BF \u039C\u03B1\u03CD\u03C1\u03B9\u03C3\u03BC\u03B1 \u039A\u03B5\u03B9\u03BC\u03AD\u03BD\u03BF\u03C5
-home.autoRedact.desc=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B7 \u03B5\u03C0\u03B5\u03BE\u03B5\u03C1\u03B3\u03B1\u03C3\u03AF\u03B1 (\u039C\u03B1\u03CD\u03C1\u03B9\u03C3\u03BC\u03B1) \u03BA\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF\u03C5 \u03C3\u03B5 PDF \u03BC\u03B5 \u03B2\u03AC\u03C3\u03B7 \u03C4\u03BF \u03BA\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF \u03B5\u03B9\u03C3\u03B1\u03B3\u03C9\u03B3\u03AE\u03C2
+home.autoRedact.title=Αυτόματο Μαύρισμα Κειμένου
+home.autoRedact.desc=Αυτόματη επεξεργασία (Μαύρισμα) κείμενου σε PDF με βάση το κείμενο εισαγωγής
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
-home.tableExtraxt.title=PDF to CSV
-home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
+home.tableExtraxt.title=PDF σε CSV
+home.tableExtraxt.desc=Εξάγει πίνακες από PDF μετατρέποντάς το σε 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
+home.autoSizeSplitPDF.title=Αυτόματη διαίρεση κατά μέγεθος/πλήθος
+home.autoSizeSplitPDF.desc=Διαχωρίστε ένα μόνο PDF σε πολλά έγγραφα με βάση το μέγεθος, τον αριθμό σελίδων ή τον αριθμό εγγράφων
autoSizeSplitPDF.tags=pdf,split,document,organization
-home.overlay-pdfs.title=Overlay PDFs
-home.overlay-pdfs.desc=Overlays PDFs on-top of another PDF
+home.overlay-pdfs.title=Επικάλυψη PDFs
+home.overlay-pdfs.desc=Επικαλύπτει αρχεία PDF πάνω σε άλλο 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
+home.split-by-sections.title=Διαχωρισμός PDF ανά ενότητες
+home.split-by-sections.desc=Διαχωρίστε κάθε σελίδα ενός PDF σε μικρότερες οριζόντιες και κάθετες ενότητες
split-by-sections.tags=Section Split, Divide, Customize
-home.AddStampRequest.title=Add Stamp to PDF
-home.AddStampRequest.desc=Add text or add image stamps at set locations
+home.AddStampRequest.title=Προσθήκη σφραγίδας σε PDF
+home.AddStampRequest.desc=Προσθέστε κείμενο ή προσθέστε σφραγίδες εικόνας σε καθορισμένες τοποθεσίες
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF σε Book
+home.PDFToBook.desc=Μετατρέπει τις μορφές PDF σε Book/Comic χρησιμοποιώντας calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book σε PDF
+home.BookToPDF.desc=Μετατρέπει τις μορφές Books/Comics σε PDF χρησιμοποιώντας calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
# #
###########################
#login
-login.title=\u0395\u03AF\u03C3\u03BF\u03B4\u03BF\u03C2
-login.signin=\u0395\u03AF\u03C3\u03BF\u03B4\u03BF\u03C2
-login.rememberme=\u039D\u03B1 \u039C\u03B5 \u0398\u03C5\u03BC\u03AC\u03C3\u03B1\u03B9
-login.invalid=\u039B\u03AC\u03B8\u03BF\u03C2 \u03CC\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 \u03AE \u03BA\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2.
-login.locked=\u039F \u03BB\u03BF\u03B3\u03B1\u03C1\u03B9\u03B1\u03C3\u03BC\u03CC\u03C2 \u03C3\u03B1\u03C2 \u03AD\u03C7\u03B5\u03B9 \u03BA\u03BB\u03B5\u03B9\u03B4\u03C9\u03B8\u03B5\u03AF.
-login.signinTitle=\u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03CE, \u03C3\u03C5\u03BD\u03B4\u03B5\u03B8\u03B5\u03AF\u03C4\u03B5
+login.title=Είσοδος
+login.header=Είσοδος
+login.signin=Είσοδος
+login.rememberme=Να Με Θυμάσαι
+login.invalid=Λάθος όνομα χρήστη ή κωδικού πρόσβασης.
+login.locked=Ο λογαριασμός σας έχει κλειδωθεί.
+login.signinTitle=Παρακαλώ, συνδεθείτε
+login.ssoSignIn=Σύνδεση μέσω μοναδικής σύνδεσης
+login.oauth2AutoCreateDisabled=Απενεργοποιήθηκε ο χρήστης αυτόματης δημιουργίας OAUTH2
#auto-redact
-autoRedact.title=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03BF \u039C\u03B1\u03CD\u03C1\u03B9\u03C3\u03BC\u03B1 \u039A\u03B5\u03B9\u03BC\u03AD\u03BD\u03BF\u03C5
-autoRedact.header=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03BF \u039C\u03B1\u03CD\u03C1\u03B9\u03C3\u03BC\u03B1 \u039A\u03B5\u03B9\u03BC\u03AD\u03BD\u03BF\u03C5
-autoRedact.colorLabel=\u03A7\u03C1\u03CE\u03BC\u03B1
-autoRedact.textsToRedactLabel=\u039A\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF \u03B3\u03B9\u03B1 \u03BC\u03B1\u03CD\u03C1\u03B9\u03C3\u03BC\u03B1 (\u03B4\u03B9\u03B1\u03C7\u03C9\u03C1\u03B9\u03C3\u03BC\u03AD\u03BD\u03BF \u03C3\u03B5 \u03B3\u03C1\u03B1\u03BC\u03BC\u03AD\u03C2)
-autoRedact.textsToRedactPlaceholder=\u03C0.\u03C7. \n\u0395\u03BC\u03C0\u03B9\u03C3\u03C4\u03B5\u03C5\u03C4\u03B9\u03BA\u03CC \n\u0391\u03BA\u03C1\u03CE\u03C2 \u03B1\u03C0\u03CC\u03C1\u03C1\u03B7\u03C4\u03BF
-autoRedact.useRegexLabel=\u03A7\u03C1\u03AE\u03C3\u03B7 Regex
-autoRedact.wholeWordSearchLabel=\u0391\u03BD\u03B1\u03B6\u03AE\u03C4\u03B7\u03C3\u03B7 \u03BF\u03BB\u03CC\u03BA\u03BB\u03B7\u03C1\u03B7\u03C2 \u03C4\u03B7\u03C2 \u03BB\u03AD\u03BE\u03B7\u03C2
+autoRedact.title=Αυτόματο Μαύρισμα Κειμένου
+autoRedact.header=Αυτόματο Μαύρισμα Κειμένου
+autoRedact.colorLabel=Χρώμα
+autoRedact.textsToRedactLabel=Κείμενο για μαύρισμα (διαχωρισμένο σε γραμμές)
+autoRedact.textsToRedactPlaceholder=π.χ. \nΕμπιστευτικό \nΑκρώς απόρρητο
+autoRedact.useRegexLabel=Χρήση Regex
+autoRedact.wholeWordSearchLabel=Αναζήτηση ολόκληρης της λέξης
autoRedact.customPaddingLabel=Custom Extra Padding
-autoRedact.convertPDFToImageLabel=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE PDF \u03C3\u03B5 PDF-\u0395\u03B9\u03BA\u03CC\u03BD\u03B1 (\u03A7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF\u03C4\u03B1\u03B9 \u03B3\u03B9\u03B1 \u03C4\u03B7\u03BD \u03B1\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u03BA\u03B5\u03B9\u03BC\u03AD\u03BD\u03BF\u03C5 \u03C0\u03AF\u03C3\u03C9 \u03B1\u03C0\u03CC \u03C4\u03BF \u03C0\u03BB\u03B1\u03AF\u03C3\u03B9\u03BF)
-autoRedact.submitButton=\u03A5\u03C0\u03BF\u03B2\u03BF\u03BB\u03AE
+autoRedact.convertPDFToImageLabel=Μετατροπή PDF σε PDF-Εικόνα (Χρησιμοποιείται για την αφαίρεση κειμένου πίσω από το πλαίσιο)
+autoRedact.submitButton=Υποβολή
#showJS
-showJS.title=\u0395\u03BC\u03C6\u03AC\u03BD\u03B9\u03C3\u03B7 Javascript
-showJS.header=\u0395\u03BC\u03C6\u03AC\u03BD\u03B9\u03C3\u03B7 Javascript
-showJS.downloadJS=\u039B\u03AE\u03C8\u03B7 Javascript
-showJS.submit=\u0395\u03BC\u03C6\u03AC\u03BD\u03B9\u03C3\u03B7
+showJS.title=Εμφάνιση Javascript
+showJS.header=Εμφάνιση Javascript
+showJS.downloadJS=Λήψη Javascript
+showJS.submit=Εμφάνιση
#pdfToSinglePage
-pdfToSinglePage.title=PDF \u03C3\u03B5 \u039C\u03BF\u03BD\u03AE \u03A3\u03B5\u03BB\u03AF\u03B4\u03B1
-pdfToSinglePage.header=PDF \u03C3\u03B5 \u039C\u03BF\u03BD\u03AE \u03A3\u03B5\u03BB\u03AF\u03B4\u03B1
-pdfToSinglePage.submit=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C3\u03B5 \u039C\u03BF\u03BD\u03AE \u03A3\u03B5\u03BB\u03AF\u03B4\u03B1
+pdfToSinglePage.title=PDF σε Μονή Σελίδα
+pdfToSinglePage.header=PDF σε Μονή Σελίδα
+pdfToSinglePage.submit=Μετατροπή σε Μονή Σελίδα
#pageExtracter
-pageExtracter.title=\u0395\u03BE\u03B1\u03B3\u03C9\u03B3\u03AE \u03A3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD
-pageExtracter.header=E\u0395\u03BE\u03B1\u03B3\u03C9\u03B3\u03AE \u03A3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD
-pageExtracter.submit=\u0395\u03BE\u03B1\u03B3\u03C9\u03B3\u03AE
+pageExtracter.title=Εξαγωγή Σελίδων
+pageExtracter.header=EΕξαγωγή Σελίδων
+pageExtracter.submit=Εξαγωγή
+pageExtracter.placeholder=(π.χ. 1,2,8 ή 4,7,12-16 ή 2n-1)
#getPdfInfo
-getPdfInfo.title=\u0391\u03BD\u03AC\u03BA\u03C4\u03B7\u03C3\u03B7 \u03C0\u03BB\u03B7\u03C1\u03BF\u03C6\u03BF\u03C1\u03B9\u03CE\u03BD \u03B1\u03C0\u03CC \u03C4\u03BF PDF
-getPdfInfo.header=\u0391\u03BD\u03AC\u03BA\u03C4\u03B7\u03C3\u03B7 \u03C0\u03BB\u03B7\u03C1\u03BF\u03C6\u03BF\u03C1\u03B9\u03CE\u03BD \u03B1\u03C0\u03CC \u03C4\u03BF PDF
-getPdfInfo.submit=\u0391\u03BD\u03AC\u03BA\u03C4\u03B7\u03C3\u03B7 \u03C0\u03BB\u03B7\u03C1\u03BF\u03C6\u03BF\u03C1\u03B9\u03CE\u03BD
-getPdfInfo.downloadJson=\u039B\u03AE\u03C8\u03B7 JSON
+getPdfInfo.title=Ανάκτηση πληροφοριών από το PDF
+getPdfInfo.header=Ανάκτηση πληροφοριών από το PDF
+getPdfInfo.submit=Ανάκτηση πληροφοριών
+getPdfInfo.downloadJson=Λήψη JSON
#markdown-to-pdf
-MarkdownToPDF.title=Markdown \u03C3\u03B5 PDF
-MarkdownToPDF.header=Markdown \u03C3\u03B5 PDF
-MarkdownToPDF.submit=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE
-MarkdownToPDF.help=\u0395\u03C1\u03B3\u03B1\u03C3\u03AF\u03B1 \u03C3\u03B5 \u03B5\u03BE\u03AD\u03BB\u03B9\u03BE\u03B7
-MarkdownToPDF.credit=\u03A7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF WeasyPrint
+MarkdownToPDF.title=Markdown σε PDF
+MarkdownToPDF.header=Markdown σε PDF
+MarkdownToPDF.submit=Μετατροπή
+MarkdownToPDF.help=Εργασία σε εξέλιξη
+MarkdownToPDF.credit=Χρησιμοποιεί WeasyPrint
#url-to-pdf
-URLToPDF.title=URL \u03C3\u03B5 PDF
-URLToPDF.header=URL \u03C3\u03B5 PDF
-URLToPDF.submit=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE
-URLToPDF.credit=\u03A7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF WeasyPrint
+URLToPDF.title=URL σε PDF
+URLToPDF.header=URL σε PDF
+URLToPDF.submit=Μετατροπή
+URLToPDF.credit=Χρησιμοποιεί WeasyPrint
#html-to-pdf
-HTMLToPDF.title=HTML \u03C3\u03B5 PDF
-HTMLToPDF.header=HTML \u03C3\u03B5 PDF
-HTMLToPDF.help=\u0394\u03AD\u03C7\u03B5\u03C4\u03B1\u03B9 \u03B1\u03C1\u03C7\u03B5\u03AF\u03B1 \u03C4\u03CD\u03C0\u03BF\u03C5 HTML \u03BA\u03B1\u03B9 \u03C4\u03CD\u03C0\u03BF\u03C5 ZIP \u03C0\u03BF\u03C5 \u03C0\u03B5\u03C1\u03B9\u03AD\u03C7\u03BF\u03C5\u03BD html/css/\u03B5\u03B9\u03BA\u03CC\u03BD\u03B5\u03C2 \u03BA.\u03BB\u03C0. \u03C0\u03BF\u03C5 \u03B1\u03C0\u03B1\u03B9\u03C4\u03BF\u03CD\u03BD\u03C4\u03B1\u03B9
-HTMLToPDF.submit=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE
-HTMLToPDF.credit=\u03A7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF WeasyPrint
-HTMLToPDF.zoom=Zoom level for displaying the website.
-HTMLToPDF.pageWidth=Width of the page in centimeters. (Blank to default)
-HTMLToPDF.pageHeight=Height of the page in centimeters. (Blank to default)
-HTMLToPDF.marginTop=Top margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginBottom=Bottom margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginLeft=Left margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginRight=Right margin of the page in millimeters. (Blank to default)
-HTMLToPDF.printBackground=Render the background of websites.
-HTMLToPDF.defaultHeader=Enable Default Header (Name and page number)
-HTMLToPDF.cssMediaType=Change the CSS media type of the page.
-HTMLToPDF.none=None
-HTMLToPDF.print=Print
+HTMLToPDF.title=HTML σε PDF
+HTMLToPDF.header=HTML σε PDF
+HTMLToPDF.help=Δέχεται αρχεία τύπου HTML και τύπου ZIP που περιέχουν html/css/εικόνες κ.λπ. που απαιτούνται
+HTMLToPDF.submit=Μετατροπή
+HTMLToPDF.credit=Χρησιμοποιεί WeasyPrint
+HTMLToPDF.zoom=Επίπεδο ζουμ για την εμφάνιση του ιστότοπου.
+HTMLToPDF.pageWidth=Το πλάτος της σελίδας σε εκατοστά. (Κενό έως προεπιλογή)
+HTMLToPDF.pageHeight=Το ύψος της σελίδας σε εκατοστά. (Κενό έως προεπιλογή)
+HTMLToPDF.marginTop=Το επάνω περιθώριο της σελίδας σε χιλιοστά. (Κενό έως προεπιλογή)
+HTMLToPDF.marginBottom=Κάτω περιθώριο σελίδας σε χιλιοστά. (Κενό έως προεπιλογή)
+HTMLToPDF.marginLeft=Το αριστερό περιθώριο της σελίδας σε χιλιοστά. (Κενό έως προεπιλογή)
+HTMLToPDF.marginRight=Το δεξί περιθώριο της σελίδας σε χιλιοστά. (Κενό έως προεπιλογή)
+HTMLToPDF.printBackground=Αποδώστε το φόντο των ιστοσελίδων.
+HTMLToPDF.defaultHeader=Ενεργοποίηση προεπιλεγμένης κεφαλίδας (Όνομα και αριθμός σελίδας)
+HTMLToPDF.cssMediaType=Αλλάξτε τον τύπο μέσων (media type )CSS της σελίδας.
+HTMLToPDF.none=Κανένα
+HTMLToPDF.print=Εκτύπωσε
HTMLToPDF.screen=Screen
#AddStampRequest
-AddStampRequest.header=Stamp PDF
-AddStampRequest.title=Stamp PDF
-AddStampRequest.stampType=Stamp Type
-AddStampRequest.stampText=Stamp Text
-AddStampRequest.stampImage=Stamp Image
-AddStampRequest.alphabet=Alphabet
-AddStampRequest.fontSize=Font/Image Size
-AddStampRequest.rotation=Rotation
-AddStampRequest.opacity=Opacity
-AddStampRequest.position=Position
-AddStampRequest.overrideX=Override X Coordinate
-AddStampRequest.overrideY=Override Y Coordinate
-AddStampRequest.customMargin=Custom Margin
-AddStampRequest.customColor=Custom Text Color
-AddStampRequest.submit=Submit
+AddStampRequest.header=Σφραγίδα PDF
+AddStampRequest.title=Σφραγίδα PDF
+AddStampRequest.stampType=Τύπος σφραγίδας
+AddStampRequest.stampText=Κείμενο σφραγίδας
+AddStampRequest.stampImage=Εικόνα σφραγίδας
+AddStampRequest.alphabet=Αλφάβητο
+AddStampRequest.fontSize=Μέγεθος γραμματοσειράς/εικόνας
+AddStampRequest.rotation=Περιστροφή
+AddStampRequest.opacity=Αδιαφάνεια
+AddStampRequest.position=Θέση
+AddStampRequest.overrideX=Override Συντεταγμένης X
+AddStampRequest.overrideY=Override Συντεταγμένης Ψ
+AddStampRequest.customMargin=Προσαρμοσμένο Περιθώριο
+AddStampRequest.customColor=Προσαρμοσμένο χρώμα κειμένου
+AddStampRequest.submit=Υποβολή
#sanitizePDF
-sanitizePDF.title=\u0391\u03C0\u03BF\u03BB\u03CD\u03BC\u03B1\u03BD\u03C3\u03B7 PDF
-sanitizePDF.header=\u0391\u03C0\u03BF\u03BB\u03CD\u03BC\u03B1\u03BD\u03C3\u03B7 \u03B5\u03BD\u03CC\u03C2 PDF \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5
-sanitizePDF.selectText.1=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 JavaScript
-sanitizePDF.selectText.2=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u03B5\u03BC\u03C3\u03C9\u03BC\u03B1\u03C4\u03C9\u03BC\u03AD\u03BD\u03C9\u03BD \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD
-sanitizePDF.selectText.3=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u03BC\u03B5\u03C4\u03B1\u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03C9\u03BD
-sanitizePDF.selectText.4=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u03C3\u03C5\u03BD\u03B4\u03AD\u03C3\u03BC\u03C9\u03BD (links)
-sanitizePDF.selectText.5=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u03B3\u03C1\u03B1\u03BC\u03BC\u03B1\u03C4\u03BF\u03C3\u03B5\u03B9\u03C1\u03CE\u03BD
-sanitizePDF.submit=\u0391\u03C0\u03BF\u03BB\u03CD\u03BC\u03B1\u03BD\u03C3\u03B7 PDF
+sanitizePDF.title=Απολύμανση PDF
+sanitizePDF.header=Απολύμανση ενός PDF αρχείου
+sanitizePDF.selectText.1=Αφαίρεση JavaScript
+sanitizePDF.selectText.2=Αφαίρεση εμσωματωμένων αρχείων
+sanitizePDF.selectText.3=Αφαίρεση μεταδεδομένων
+sanitizePDF.selectText.4=Αφαίρεση συνδέσμων (links)
+sanitizePDF.selectText.5=Αφαίρεση γραμματοσειρών
+sanitizePDF.submit=Απολύμανση PDF
#addPageNumbers
-addPageNumbers.title=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03B1\u03C1\u03B9\u03B8\u03BC\u03CE\u03BD \u03C3\u03B5 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B5\u03C2
-addPageNumbers.header=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03B1\u03C1\u03B9\u03B8\u03BC\u03CE\u03BD \u03C3\u03B5 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B5\u03C2
-addPageNumbers.selectText.1=\u0395\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE PDF \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5:
-addPageNumbers.selectText.2=\u039C\u03AD\u03B3\u03B5\u03B8\u03BF\u03C2 \u03C0\u03B5\u03C1\u03B9\u03B8\u03C9\u03C1\u03AF\u03BF\u03C5
-addPageNumbers.selectText.3=\u0398\u03AD\u03C3\u03B7
-addPageNumbers.selectText.4=\u0391\u03C1\u03B9\u03B8\u03BC\u03CC\u03C2 \u03C0\u03BF\u03C5 \u03BE\u03B5\u03BA\u03B9\u03BD\u03AC \u03B7 \u03B1\u03C1\u03AF\u03B8\u03BC\u03B7\u03C3\u03B7
-addPageNumbers.selectText.5=\u03A3\u03B5\u03BB\u03AF\u03B4\u03B5\u03C2 \u03C3\u03B5 \u03B1\u03C1\u03B9\u03B8\u03BC\u03CC
-addPageNumbers.selectText.6=\u03A0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03C3\u03BC\u03AD\u03BD\u03BF \u039A\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF
-addPageNumbers.customTextDesc=\u03A0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03C3\u03BC\u03AD\u03BD\u03BF \u039A\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF
-addPageNumbers.numberPagesDesc=\u03A0\u03BF\u03B9\u03AD\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B5\u03C2 \u03BD\u03B1 \u03B1\u03C1\u03B9\u03B8\u03BC\u03B7\u03B8\u03BF\u03CD\u03BD, \u03C0\u03C1\u03BF\u03B5\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE 'all' (\u03CC\u03BB\u03B5\u03C2), \u03B5\u03C0\u03AF\u03C3\u03B7\u03C2 \u03B4\u03AD\u03C7\u03B5\u03C4\u03B1\u03B9 1-5 \u03AE 2,5,9 \u03BA.\u03BB.\u03C0
-addPageNumbers.customNumberDesc=\u03A0\u03C1\u03BF\u03B5\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE \u03C3\u03B5 {n}, \u03B4\u03AD\u03C7\u03B5\u03C4\u03B1\u03B9 \u03B5\u03C0\u03AF\u03C3\u03B7\u03C2 "\u03A3\u03B5\u03BB\u03AF\u03B4\u03B1 {n} \u03B1\u03C0\u03CC {total}", "Text-{n}", "{filename}-{n}
-addPageNumbers.submit=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03B1\u03C1\u03B9\u03B8\u03BC\u03CE\u03BD \u03C3\u03B5 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B5\u03C2
+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=Ποιές σελίδες να αριθμηθούν, προεπιλογή 'all' (όλες), επίσης δέχεται 1-5 ή 2,5,9 κ.λ.π
+addPageNumbers.customNumberDesc=Προεπιλογή σε {n}, δέχεται επίσης "Σελίδα {n} από {total}", "Text-{n}", "{filename}-{n}
+addPageNumbers.submit=Προσθήκη αριθμών σε σελίδες
#auto-rename
-auto-rename.title=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B7 \u03BC\u03B5\u03C4\u03BF\u03BD\u03BF\u03BC\u03B1\u03C3\u03AF\u03B1
-auto-rename.header=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B7 \u03BC\u03B5\u03C4\u03BF\u03BD\u03BF\u03BC\u03B1\u03C3\u03AF\u03B1 PDF
-auto-rename.submit=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B7 \u03BC\u03B5\u03C4\u03BF\u03BD\u03BF\u03BC\u03B1\u03C3\u03AF\u03B1
+auto-rename.title=Αυτόματη μετονομασία
+auto-rename.header=Αυτόματη μετονομασία PDF
+auto-rename.submit=Αυτόματη μετονομασία
#adjustContrast
-adjustContrast.title=\u03A0\u03C1\u03BF\u03C3\u03C0\u03B1\u03C1\u03BC\u03BF\u03B3\u03AE \u03C4\u03B7\u03C2 \u0391\u03BD\u03C4\u03AF\u03B8\u03B5\u03C3\u03B7\u03C2
-adjustContrast.header=\u03A0\u03C1\u03BF\u03C3\u03C0\u03B1\u03C1\u03BC\u03BF\u03B3\u03AE \u03C4\u03B7\u03C2 \u0391\u03BD\u03C4\u03AF\u03B8\u03B5\u03C3\u03B7\u03C2
-adjustContrast.contrast=\u0391\u03BD\u03C4\u03AF\u03B8\u03B5\u03C3\u03B7:
-adjustContrast.brightness=\u03A6\u03C9\u03C4\u03B5\u03B9\u03BD\u03CC\u03C4\u03B7\u03C4\u03B1:
-adjustContrast.saturation=\u039A\u03BF\u03C1\u03B5\u03C3\u03BC\u03CC\u03C2:
-adjustContrast.download=\u039B\u03AE\u03C8\u03B7
+adjustContrast.title=Προσπαρμογή της Αντίθεσης
+adjustContrast.header=Προσπαρμογή της Αντίθεσης
+adjustContrast.contrast=Αντίθεση:
+adjustContrast.brightness=Φωτεινότητα:
+adjustContrast.saturation=Κορεσμός:
+adjustContrast.download=Λήψη
#crop
-crop.title=\u039A\u03BF\u03C0\u03AE
-crop.header=\u039A\u03BF\u03C0\u03AE \u0395\u03B9\u03BA\u03CC\u03BD\u03B1\u03C2
-crop.submit=\u03A5\u03C0\u03BF\u03B2\u03BF\u03BB\u03AE
+crop.title=Κοπή
+crop.header=Κοπή Εικόνας
+crop.submit=Υποβολή
#autoSplitPDF
-autoSplitPDF.title=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B7 \u03B4\u03B9\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 PDF
-autoSplitPDF.header=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B7 \u03B4\u03B9\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 PDF
-autoSplitPDF.description=\u0395\u03BA\u03C4\u03C5\u03C0\u03CE\u03C3\u03C4\u03B5, \u03B5\u03B9\u03C3\u03AC\u03B3\u03B5\u03C4\u03B5, \u03C3\u03B1\u03C1\u03CE\u03C3\u03C4\u03B5, \u03B1\u03BD\u03B5\u03B2\u03AC\u03C3\u03C4\u03B5 \u03BA\u03B1\u03B9 \u03B1\u03C6\u03AE\u03C3\u03C4\u03B5 \u03BC\u03B1\u03C2 \u03BD\u03B1 \u03B4\u03B9\u03B1\u03C7\u03C9\u03C1\u03AF\u03C3\u03BF\u03C5\u03BC\u03B5 \u03B1\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B1 \u03C4\u03B1 \u03AD\u03B3\u03B3\u03C1\u03B1\u03C6\u03AC \u03C3\u03B1\u03C2. \u0394\u03B5\u03BD \u03B1\u03C0\u03B1\u03B9\u03C4\u03B5\u03AF\u03C4\u03B1\u03B9 \u03C7\u03B5\u03B9\u03C1\u03BF\u03BA\u03AF\u03BD\u03B7\u03C4\u03B7 \u03C4\u03B1\u03BE\u03B9\u03BD\u03CC\u03BC\u03B7\u03C3\u03B7.
-autoSplitPDF.selectText.1=\u0395\u03BA\u03C4\u03C5\u03C0\u03CE\u03C3\u03C4\u03B5 \u03BC\u03B5\u03C1\u03B9\u03BA\u03AC \u03C6\u03CD\u03BB\u03BB\u03B1 \u03B4\u03B9\u03B1\u03C7\u03C9\u03C1\u03B9\u03C3\u03BC\u03BF\u03CD \u03B1\u03C0\u03CC \u03BA\u03AC\u03C4\u03C9 (\u03C4\u03BF \u03B1\u03C3\u03C0\u03C1\u03CC\u03BC\u03B1\u03C5\u03C1\u03BF \u03B5\u03AF\u03BD\u03B1\u03B9 \u03BC\u03B9\u03B1 \u03C7\u03B1\u03C1\u03AC).
-autoSplitPDF.selectText.2=\u03A3\u03B1\u03C1\u03CE\u03C3\u03C4\u03B5 \u03CC\u03BB\u03B1 \u03C4\u03B1 \u03AD\u03B3\u03B3\u03C1\u03B1\u03C6\u03AC \u03C3\u03B1\u03C2 \u03C4\u03B1\u03C5\u03C4\u03CC\u03C7\u03C1\u03BF\u03BD\u03B1, \u03BC\u03B5 \u03C4\u03BF \u03BD\u03B1 \u03B5\u03B9\u03C3\u03AC\u03B3\u03B5\u03C4\u03B5 \u03C4\u03BF \u03B4\u03B9\u03B1\u03C7\u03C9\u03C1\u03B9\u03C3\u03C4\u03B9\u03BA\u03CC \u03C6\u03CD\u03BB\u03BB\u03BF \u03BC\u03B5\u03C4\u03B1\u03BE\u03CD \u03C4\u03BF\u03C5\u03C2.
-autoSplitPDF.selectText.3=\u0391\u03BD\u03B5\u03B2\u03AC\u03C3\u03C4\u03B5 \u03AD\u03BD\u03B1 \u03BC\u03B5\u03B3\u03AC\u03BB\u03BF \u03C3\u03B1\u03C1\u03C9\u03BC\u03AD\u03BD\u03BF PDF \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF \u03BA\u03B1\u03B9 \u03B1\u03C6\u03AE\u03C3\u03C4\u03B5 \u03C4\u03BF Stirling PDF \u03BD\u03B1 \u03C7\u03B5\u03B9\u03C1\u03B9\u03C3\u03C4\u03B5\u03AF \u03C4\u03B1 \u03C5\u03C0\u03CC\u03BB\u03BF\u03B9\u03C0\u03B1
-autoSplitPDF.selectText.4=\u039F\u03B9 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B5\u03C2 \u03B4\u03B9\u03B1\u03C7\u03C9\u03C1\u03B9\u03C3\u03BC\u03BF\u03CD \u03B5\u03BD\u03C4\u03BF\u03C0\u03AF\u03B6\u03BF\u03BD\u03C4\u03B1\u03B9 \u03BA\u03B1\u03B9 \u03B1\u03C6\u03B1\u03B9\u03C1\u03BF\u03CD\u03BD\u03C4\u03B1\u03B9 \u03B1\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B1, \u03B4\u03B9\u03B1\u03C3\u03C6\u03B1\u03BB\u03AF\u03B6\u03BF\u03BD\u03C4\u03B1\u03C2 \u03AD\u03BD\u03B1 \u03C0\u03C1\u03BF\u03C3\u03B5\u03B3\u03BC\u03AD\u03BD\u03BF \u03C4\u03B5\u03BB\u03B9\u03BA\u03CC \u03AD\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF.
-autoSplitPDF.formPrompt=\u03A5\u03C0\u03BF\u03B2\u03BF\u03BB\u03AE PDF \u03C0\u03BF\u03C5 \u03C0\u03B5\u03C1\u03B9\u03AD\u03C7\u03B5\u03B9 \u03B4\u03B9\u03B1\u03B9\u03C1\u03AD\u03C4\u03B5\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD Stirling-PDF:
-autoSplitPDF.duplexMode=\u039B\u03B5\u03B9\u03C4\u03BF\u03C5\u03C1\u03B3\u03AF\u03B1 \u03B4\u03B9\u03C0\u03BB\u03AE\u03C2 \u03CC\u03C8\u03B7\u03C2 (\u03A3\u03AC\u03C1\u03C9\u03C3\u03B7 \u03BC\u03C0\u03C1\u03BF\u03C3\u03C4\u03AC \u03BA\u03B1\u03B9 \u03C0\u03AF\u03C3\u03C9)
-autoSplitPDF.dividerDownload1=\u039B\u03AE\u03C8\u03B7 'Auto Splitter Divider (minimal).pdf'
-autoSplitPDF.dividerDownload2=\u039B\u03AE\u03C8\u03B7 'Auto Splitter Divider (with instructions).pdf'
-autoSplitPDF.submit=\u03A5\u03C0\u03BF\u03B2\u03BF\u03BB\u03AE
+autoSplitPDF.title=Αυτόματη διαίρεση PDF
+autoSplitPDF.header=Αυτόματη διαίρεση PDF
+autoSplitPDF.description=Εκτυπώστε, εισάγετε, σαρώστε, ανεβάστε και αφήστε μας να διαχωρίσουμε αυτόματα τα έγγραφά σας. Δεν απαιτείται χειροκίνητη ταξινόμηση.
+autoSplitPDF.selectText.1=Εκτυπώστε μερικά φύλλα διαχωρισμού από κάτω (το ασπρόμαυρο είναι μια χαρά).
+autoSplitPDF.selectText.2=Σαρώστε όλα τα έγγραφά σας ταυτόχρονα, με το να εισάγετε το διαχωριστικό φύλλο μεταξύ τους.
+autoSplitPDF.selectText.3=Ανεβάστε ένα μεγάλο σαρωμένο PDF αρχείο και αφήστε το Stirling PDF να χειριστεί τα υπόλοιπα
+autoSplitPDF.selectText.4=Οι σελίδες διαχωρισμού εντοπίζονται και αφαιρούνται αυτόματα, διασφαλίζοντας ένα προσεγμένο τελικό έγγραφο.
+autoSplitPDF.formPrompt=Υποβολή PDF που περιέχει διαιρέτες σελίδων Stirling-PDF:
+autoSplitPDF.duplexMode=Λειτουργία διπλής όψης (Σάρωση μπροστά και πίσω)
+autoSplitPDF.dividerDownload1=Λήψη 'Auto Splitter Divider (minimal).pdf'
+autoSplitPDF.dividerDownload2=Λήψη 'Auto Splitter Divider (with instructions).pdf'
+autoSplitPDF.submit=Υποβολή
#pipeline
@@ -567,406 +606,459 @@ pipeline.title=Pipeline
#pageLayout
-pageLayout.title=\u0394\u03B9\u03AC\u03C4\u03B1\u03BE\u03B7 \u03C0\u03BF\u03BB\u03BB\u03CE\u03BD \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD
-pageLayout.header=\u0394\u03B9\u03AC\u03C4\u03B1\u03BE\u03B7 \u03C0\u03BF\u03BB\u03BB\u03CE\u03BD \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD
-pageLayout.pagesPerSheet=\u03A3\u03B5\u03BB\u03AF\u03B4\u03B5\u03C2 \u03B1\u03BD\u03AC \u03C6\u03CD\u03BB\u03BB\u03BF:
-pageLayout.addBorder=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03C0\u03B5\u03C1\u03B9\u03B3\u03C1\u03B1\u03BC\u03BC\u03AC\u03C4\u03C9\u03BD
-pageLayout.submit=\u03A5\u03C0\u03BF\u03B2\u03BF\u03BB\u03AE
+pageLayout.title=Διάταξη πολλών σελίδων
+pageLayout.header=Διάταξη πολλών σελίδων
+pageLayout.pagesPerSheet=Σελίδες ανά φύλλο:
+pageLayout.addBorder=Προσθήκη περιγραμμάτων
+pageLayout.submit=Υποβολή
#scalePages
-scalePages.title=\u03A0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03B3\u03AE \u03BA\u03BB\u03AF\u03BC\u03B1\u03BA\u03B1\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2
-scalePages.header=\u03A0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03B3\u03AE \u03BA\u03BB\u03AF\u03BC\u03B1\u03BA\u03B1\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2
-scalePages.pageSize=\u039C\u03AD\u03B3\u03B5\u03B8\u03BF\u03C2 \u03BC\u03B9\u03B1\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2 \u03C4\u03BF\u03C5 \u03B5\u03B3\u03B3\u03C1\u03AC\u03C6\u03BF\u03C5.
-scalePages.scaleFactor=\u0395\u03C0\u03AF\u03C0\u03B5\u03B4\u03BF \u03B6\u03BF\u03C5\u03BC (\u03C0\u03B5\u03C1\u03B9\u03BA\u03BF\u03C0\u03AE) \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2.
-scalePages.submit=\u03A5\u03C0\u03BF\u03B2\u03BF\u03BB\u03AE
+scalePages.title=Προσαρμογή κλίμακας σελίδας
+scalePages.header=Προσαρμογή κλίμακας σελίδας
+scalePages.pageSize=Μέγεθος μιας σελίδας του εγγράφου.
+scalePages.scaleFactor=Επίπεδο ζουμ (περικοπή) σελίδας.
+scalePages.submit=Υποβολή
#certSign
-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
-certSign.reason=\u0391\u03B9\u03C4\u03AF\u03B1
-certSign.location=\u03A4\u03BF\u03C0\u03BF\u03B8\u03B5\u03C3\u03AF\u03B1
-certSign.name=\u038C\u03BD\u03BF\u03BC\u03B1
-certSign.submit=\u03A5\u03C0\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE PDF
+certSign.title=Υπογραφή Πιστοποιητικού
+certSign.header=Υπογράψτε ένα αρχείο PDF με το πιστοποιητικό σας (Εργασία σε εξέλιξη)
+certSign.selectPDF=Επιλογή αρχείου PDF για υπογραφή:
+certSign.jksNote=Σημείωση: Εάν ο τύπος πιστοποιητικού σας δεν αναφέρεται παρακάτω, μετατρέψτε το σε αρχείο Java Keystore (.jks) χρησιμοποιώντας το εργαλείο γραμμής εντολών keytool. Στη συνέχεια, επιλέξτε την επιλογή αρχείου .jks παρακάτω.
+certSign.selectKey=Επιλέξτε το αρχείο του ιδιωτικού κλειδιού σας (μορφή PKCS#8, μπορεί να είναι .pem ή .der):
+certSign.selectCert=Επιλέξτε το αρχείο πιστοποιητικού σας (μορφή X.509, μπορεί να είναι .pem ή .der):
+certSign.selectP12=Επιλέξτε το αρχείο PKCS#12 Keystore (.p12 ή .pfx) (Προαιρετικό, εάν παρέχεται, θα πρέπει να περιέχει το ιδιωτικό κλειδί και το πιστοποιητικό σας):
+certSign.selectJKS=Επιλέξτε το αρχείο Java Keystore (.jks ή .keystore):
+certSign.certType=Τύπος Πιστοποιητικού
+certSign.password=Εισαγάγετε τον κωδικό του Keystore ή του Ιδιωτικού Κλειδιού (εάν υπάρχει):
+certSign.showSig=Εμφάνιση Υπογραφής
+certSign.reason=Αιτία
+certSign.location=Τοποθεσία
+certSign.name=Όνομα
+certSign.submit=Υπογραφή PDF
#removeBlanks
-removeBlanks.title=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u039A\u03B5\u03BD\u03CE\u03BD
-removeBlanks.header=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u039A\u03B5\u03BD\u03CE\u03BD \u03A3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD
-removeBlanks.threshold=\u038C\u03C1\u03B9\u03BF \u03BB\u03B5\u03C5\u03BA\u03CC\u03C4\u03B7\u03C4\u03B1\u03C2 pixel:
-removeBlanks.thresholdDesc=\u038C\u03C1\u03B9\u03BF \u03B3\u03B9\u03B1 \u03C4\u03BF\u03BD \u03C0\u03C1\u03BF\u03C3\u03B4\u03B9\u03BF\u03C1\u03B9\u03C3\u03BC\u03CC \u03C4\u03BF\u03C5 \u03C0\u03CC\u03C3\u03BF \u03BB\u03B5\u03C5\u03BA\u03CC \u03C0\u03C1\u03AD\u03C0\u03B5\u03B9 \u03BD\u03B1 \u03B5\u03AF\u03BD\u03B1\u03B9 \u03AD\u03BD\u03B1 \u03BB\u03B5\u03C5\u03BA\u03CC \u03B5\u03B9\u03BA\u03BF\u03BD\u03BF\u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03BF (pixel) \u03B3\u03B9\u03B1 \u03BD\u03B1 \u03C4\u03B1\u03BE\u03B9\u03BD\u03BF\u03BC\u03B7\u03B8\u03B5\u03AF \u03C9\u03C2 "\u039B\u03B5\u03C5\u03BA\u03CC". 0 = \u039C\u03B1\u03CD\u03C1\u03BF, 255 \u03BA\u03B1\u03B8\u03B1\u03C1\u03CC \u03BB\u03B5\u03C5\u03BA\u03CC.
-removeBlanks.whitePercent=\u03A0\u03BF\u03C3\u03BF\u03C3\u03C4\u03CC \u039B\u03B5\u03C5\u03BA\u03BF\u03CD (%):
-removeBlanks.whitePercentDesc=\u03A4\u03BF \u03C0\u03BF\u03C3\u03BF\u03C3\u03C4\u03CC \u03C4\u03B7\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2 \u03C0\u03BF\u03C5 \u03C0\u03C1\u03AD\u03C0\u03B5\u03B9 \u03BD\u03B1 \u03B5\u03AF\u03BD\u03B1\u03B9 "\u03BB\u03B5\u03C5\u03BA\u03AC" pixel \u03B3\u03B9\u03B1 \u03BD\u03B1 \u03B1\u03C6\u03B1\u03B9\u03C1\u03B5\u03B8\u03B5\u03AF
-removeBlanks.submit=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u039A\u03B5\u03BD\u03CE\u03BD
+removeBlanks.title=Αφαίρεση Κενών
+removeBlanks.header=Αφαίρεση Κενών Σελίδων
+removeBlanks.threshold=Όριο λευκότητας pixel:
+removeBlanks.thresholdDesc=Όριο για τον προσδιορισμό του πόσο λευκό πρέπει να είναι ένα λευκό εικονοστοιχείο (pixel) για να ταξινομηθεί ως "Λευκό". 0 = Μαύρο, 255 καθαρό λευκό.
+removeBlanks.whitePercent=Ποσοστό Λευκού (%):
+removeBlanks.whitePercentDesc=Το ποσοστό της σελίδας που πρέπει να είναι "λευκά" pixel για να αφαιρεθεί
+removeBlanks.submit=Αφαίρεση Κενών
#removeAnnotations
-removeAnnotations.title=Remove Annotations
-removeAnnotations.header=Remove Annotations
-removeAnnotations.submit=Remove
+removeAnnotations.title=Κατάργηση σχολιασμών
+removeAnnotations.header=Κατάργηση σχολιασμών
+removeAnnotations.submit=Κατάργηση
#compare
-compare.title=\u03A3\u03CD\u03B3\u03BA\u03C1\u03B9\u03C3\u03B7
-compare.header=\u03A3\u03CD\u03B3\u03BA\u03C1\u03B9\u03C3\u03B7 PDFs
-compare.document.1=\u0388\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF 1
-compare.document.2=\u0388\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF 2
-compare.submit=\u03A3\u03CD\u03B3\u03BA\u03C1\u03B9\u03C3\u03B7
+compare.title=Σύγκριση
+compare.header=Σύγκριση PDFs
+compare.document.1=Έγγραφο 1
+compare.document.2=Έγγραφο 2
+compare.submit=Σύγκριση
+#BookToPDF
+BookToPDF.title=Books και Comics σε PDF
+BookToPDF.header=Book σε PDF
+BookToPDF.credit=Χρησιμοποιεί Caliber
+BookToPDF.submit=Μετατροπή
+
+#PDFToBook
+PDFToBook.title=PDF σε Book
+PDFToBook.header=PDF σε Book
+PDFToBook.selectText.1=Μορφή
+PDFToBook.credit=Χρησιμοποιεί Caliber
+PDFToBook.submit=Μετατροπή
#sign
-sign.title=\u03A5\u03C0\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE
-sign.header=\u03A5\u03C0\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE PDFs
-sign.upload=\u0391\u03BD\u03AD\u03B2\u03B1\u03C3\u03BC\u03B1 \u0395\u03B9\u03BA\u03CC\u03BD\u03B1\u03C2
-sign.draw=\u03A3\u03C7\u03B5\u03B4\u03AF\u03B1\u03C3\u03B7 \u03C5\u03C0\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE\u03C2
-sign.text=\u0395\u03B9\u03C3\u03B1\u03B3\u03C9\u03B3\u03AE \u03BA\u03B5\u03B9\u03BC\u03AD\u03BD\u03BF\u03C5
-sign.clear=\u039A\u03B1\u03B8\u03AC\u03C1\u03B9\u03C3\u03BC\u03B1
-sign.add=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7
+sign.title=Υπογραφή
+sign.header=Υπογραφή PDFs
+sign.upload=Ανέβασμα Εικόνας
+sign.draw=Σχεδίαση υπογραφής
+sign.text=Εισαγωγή κειμένου
+sign.clear=Καθάρισμα
+sign.add=Προσθήκη
#repair
-repair.title=\u0395\u03C0\u03B9\u03B4\u03B9\u03CC\u03C1\u03B8\u03C9\u03C3\u03B7
-repair.header=\u0395\u03C0\u03B9\u03B4\u03B9\u03CC\u03C1\u03B8\u03C9\u03C3\u03B7 PDFs
-repair.submit=\u0395\u03C0\u03B9\u03B4\u03B9\u03CC\u03C1\u03B8\u03C9\u03C3\u03B7
+repair.title=Επιδιόρθωση
+repair.header=Επιδιόρθωση PDFs
+repair.submit=Επιδιόρθωση
#flatten
flatten.title=Flatten
flatten.header=Flatten PDFs
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Flatten
#ScannerImageSplit
-ScannerImageSplit.selectText.1=\u038C\u03C1\u03B9\u03BF \u03B3\u03C9\u03BD\u03AF\u03B1\u03C2:
-ScannerImageSplit.selectText.2=\u039F\u03C1\u03AF\u03B6\u03B5\u03B9 \u03C4\u03B7\u03BD \u03B5\u03BB\u03AC\u03C7\u03B9\u03C3\u03C4\u03B7 \u03B1\u03C0\u03CC\u03BB\u03C5\u03C4\u03B7 \u03B3\u03C9\u03BD\u03AF\u03B1 \u03C0\u03BF\u03C5 \u03B1\u03C0\u03B1\u03B9\u03C4\u03B5\u03AF\u03C4\u03B1\u03B9 \u03B3\u03B9\u03B1 \u03C4\u03B7\u03BD \u03C0\u03B5\u03C1\u03B9\u03C3\u03C4\u03C1\u03BF\u03C6\u03AE \u03C4\u03B7\u03C2 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B1\u03C2 (\u03C0\u03C1\u03BF\u03B5\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE: 10).
-ScannerImageSplit.selectText.3=\u0391\u03BD\u03B5\u03BA\u03C4\u03B9\u03BA\u03CC\u03C4\u03B7\u03C4\u03B1 (Tolerance):
-ScannerImageSplit.selectText.4=\u039A\u03B1\u03B8\u03BF\u03C1\u03AF\u03B6\u03B5\u03B9 \u03C4\u03BF \u03B5\u03CD\u03C1\u03BF\u03C2 \u03C4\u03B7\u03C2 \u03C7\u03C1\u03C9\u03BC\u03B1\u03C4\u03B9\u03BA\u03AE\u03C2 \u03B4\u03B9\u03B1\u03BA\u03CD\u03BC\u03B1\u03BD\u03C3\u03B7\u03C2 \u03B3\u03CD\u03C1\u03C9 \u03B1\u03C0\u03CC \u03C4\u03BF \u03B5\u03BA\u03C4\u03B9\u03BC\u03CE\u03BC\u03B5\u03BD\u03BF \u03C7\u03C1\u03CE\u03BC\u03B1 \u03C6\u03CC\u03BD\u03C4\u03BF\u03C5 (\u03C0\u03C1\u03BF\u03B5\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE: 30).
-ScannerImageSplit.selectText.5=\u0395\u03BB\u03AC\u03C7\u03B9\u03C3\u03C4\u03B7 \u03A0\u03B5\u03C1\u03B9\u03BF\u03C7\u03AE:
-ScannerImageSplit.selectText.6=\u039F\u03C1\u03AF\u03B6\u03B5\u03B9 \u03C4\u03BF \u03B5\u03BB\u03AC\u03C7\u03B9\u03C3\u03C4\u03BF \u03CC\u03C1\u03B9\u03BF \u03B5\u03C0\u03B9\u03C6\u03AC\u03BD\u03B5\u03B9\u03B1\u03C2 \u03B3\u03B9\u03B1 \u03BC\u03B9\u03B1 \u03C6\u03C9\u03C4\u03BF\u03B3\u03C1\u03B1\u03C6\u03AF\u03B1 (\u03C0\u03C1\u03BF\u03B5\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE: 10000).
-ScannerImageSplit.selectText.7=\u0395\u03BB\u03AC\u03C7\u03B9\u03C3\u03C4\u03B7 \u03B5\u03C0\u03B9\u03C6\u03AC\u03BD\u03B5\u03B9\u03B1 \u03C0\u03B5\u03C1\u03B9\u03B3\u03C1\u03AC\u03BC\u03BC\u03B1\u03C4\u03BF\u03C2:
-ScannerImageSplit.selectText.8=\u03A1\u03C5\u03B8\u03BC\u03AF\u03B6\u03B5\u03B9 \u03C4\u03BF \u03B5\u03BB\u03AC\u03C7\u03B9\u03C3\u03C4\u03BF \u03CC\u03C1\u03B9\u03BF \u03C0\u03B5\u03C1\u03B9\u03B3\u03C1\u03AC\u03BC\u03BC\u03B1\u03C4\u03BF\u03C2 \u03B3\u03B9\u03B1 \u03BC\u03B9\u03B1 \u03C6\u03C9\u03C4\u03BF\u03B3\u03C1\u03B1\u03C6\u03AF\u03B1
-ScannerImageSplit.selectText.9=\u039C\u03AD\u03B3\u03B5\u03B8\u03BF\u03C2 \u03C0\u03B5\u03C1\u03B9\u03B3\u03C1\u03AC\u03BC\u03BC\u03B1\u03C4\u03BF\u03C2:
-ScannerImageSplit.selectText.10=\u039F\u03C1\u03AF\u03B6\u03B5\u03B9 \u03C4\u03BF \u03BC\u03AD\u03B3\u03B5\u03B8\u03BF\u03C2 \u03C4\u03BF\u03C5 \u03C0\u03B5\u03C1\u03B9\u03B3\u03C1\u03AC\u03BC\u03BC\u03B1\u03C4\u03BF\u03C2 \u03C0\u03BF\u03C5 \u03C0\u03C1\u03BF\u03C3\u03C4\u03AF\u03B8\u03B5\u03C4\u03B1\u03B9 \u03BA\u03B1\u03B9 \u03B1\u03C6\u03B1\u03B9\u03C1\u03B5\u03AF\u03C4\u03B1\u03B9 \u03B3\u03B9\u03B1 \u03BD\u03B1 \u03B1\u03C0\u03BF\u03C4\u03C1\u03AD\u03C0\u03BF\u03BD\u03C4\u03B1\u03B9 \u03BB\u03B5\u03C5\u03BA\u03AC \u03C0\u03B5\u03C1\u03B9\u03B3\u03C1\u03AC\u03BC\u03BC\u03B1\u03C4\u03B1 \u03C3\u03C4\u03B7\u03BD \u03AD\u03BE\u03BF\u03B4\u03BF (\u03C0\u03C1\u03BF\u03B5\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE: 1).
+ScannerImageSplit.selectText.1=Όριο γωνίας:
+ScannerImageSplit.selectText.2=Ορίζει την ελάχιστη απόλυτη γωνία που απαιτείται για την περιστροφή της εικόνας (προεπιλογή: 10).
+ScannerImageSplit.selectText.3=Ανεκτικότητα (Tolerance):
+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=\u039F\u03C0\u03C4\u03B9\u03BA\u03AE \u03B1\u03BD\u03B1\u03B3\u03BD\u03CE\u03C1\u03B9\u03C3\u03B7 \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03C9\u03BD (OCR) / \u03A3\u03B1\u03C1\u03CE\u03C3\u03B5\u03B9\u03C2 Cleanup
-ocr.header=\u03A3\u03B1\u03C1\u03CE\u03C3\u03B5\u03B9\u03C2 Cleanup / OCR (Optical Character Recognition - \u039F\u03C0\u03C4\u03B9\u03BA\u03AE \u03B1\u03BD\u03B1\u03B3\u03BD\u03CE\u03C1\u03B9\u03C3\u03B7 \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03C9\u03BD)
-ocr.selectText.1=\u0395\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 \u03B3\u03BB\u03CE\u03C3\u03C3\u03B5\u03C2 \u03C0\u03BF\u03C5 \u03C0\u03C1\u03CC\u03BA\u03B5\u03B9\u03C4\u03B1\u03B9 \u03BD\u03B1 \u03B5\u03BD\u03C4\u03BF\u03C0\u03B9\u03C3\u03C4\u03BF\u03CD\u03BD \u03C3\u03C4\u03BF PDF (\u039F\u03B9 \u03C0\u03BF\u03C5 \u03B1\u03BD\u03B1\u03C6\u03AD\u03C1\u03BF\u03BD\u03C4\u03B1\u03B9 \u03B5\u03AF\u03BD\u03B1\u03B9 \u03B1\u03C5\u03C4\u03AD\u03C2 \u03C0\u03BF\u03C5 \u03B1\u03BD\u03B9\u03C7\u03BD\u03B5\u03CD\u03BF\u03BD\u03C4\u03B1\u03B9 \u03B1\u03C5\u03C4\u03AE\u03BD \u03C4\u03B7 \u03C3\u03C4\u03B9\u03B3\u03BC\u03AE):
-ocr.selectText.2=\u0394\u03B7\u03BC\u03B9\u03BF\u03C5\u03C1\u03B3\u03AE\u03C3\u03C4\u03B5 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF \u03BA\u03B5\u03B9\u03BC\u03AD\u03BD\u03BF\u03C5 \u03C0\u03BF\u03C5 \u03C0\u03B5\u03C1\u03B9\u03AD\u03C7\u03B5\u03B9 \u03BA\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF OCR \u03BC\u03B1\u03B6\u03AF \u03BC\u03B5 \u03C4\u03BF PDF \u03C0\u03BF\u03C5 \u03AD\u03C7\u03B5\u03B9 \u03C5\u03C0\u03BF\u03B2\u03BB\u03B7\u03B8\u03B5\u03AF \u03C3\u03B5 OCR
-ocr.selectText.3=\u039F\u03B9 \u03C3\u03C9\u03C3\u03C4\u03AD\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B5\u03C2 \u03C3\u03B1\u03C1\u03CE\u03B8\u03B7\u03BA\u03B1\u03BD \u03BC\u03B5 \u03BB\u03BF\u03BE\u03AE \u03B3\u03C9\u03BD\u03AF\u03B1 \u03C0\u03B5\u03C1\u03B9\u03C3\u03C4\u03C1\u03AD\u03C6\u03BF\u03BD\u03C4\u03AC\u03C2 \u03C4\u03B5\u03C2 \u03C3\u03C4\u03B7 \u03B8\u03AD\u03C3\u03B7 \u03C4\u03BF\u03C5\u03C2
-ocr.selectText.4=C\u039A\u03B1\u03B8\u03B1\u03C1\u03AF\u03C3\u03C4\u03B5 \u03C4\u03B7 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1, \u03CE\u03C3\u03C4\u03B5 \u03BD\u03B1 \u03B5\u03AF\u03BD\u03B1\u03B9 \u03BB\u03B9\u03B3\u03CC\u03C4\u03B5\u03C1\u03BF \u03C0\u03B9\u03B8\u03B1\u03BD\u03CC \u03C4\u03BF OCR \u03BD\u03B1 \u03B2\u03C1\u03B5\u03B9 \u03BA\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF \u03C3\u03C4\u03BF \u03B8\u03CC\u03C1\u03C5\u03B2\u03BF \u03C6\u03CC\u03BD\u03C4\u03BF\u03C5 (background noise). (\u039A\u03B1\u03BC\u03AF\u03B1 \u03B1\u03BB\u03BB\u03B1\u03B3\u03AE \u03C3\u03C4\u03BF \u03B5\u03BE\u03B1\u03B3\u03CC\u03BC\u03B5\u03BD\u03BF)
-ocr.selectText.5=\u039A\u03B1\u03B8\u03B1\u03C1\u03AF\u03C3\u03C4\u03B5 \u03C4\u03B7 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1, \u03CE\u03C3\u03C4\u03B5 \u03BD\u03B1 \u03B5\u03AF\u03BD\u03B1\u03B9 \u03BB\u03B9\u03B3\u03CC\u03C4\u03B5\u03C1\u03BF \u03C0\u03B9\u03B8\u03B1\u03BD\u03CC \u03C4\u03BF OCR \u03BD\u03B1 \u03B2\u03C1\u03B5\u03B9 \u03BA\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF \u03C3\u03C4\u03BF \u03B8\u03CC\u03C1\u03C5\u03B2\u03BF \u03C6\u03CC\u03BD\u03C4\u03BF\u03C5, \u03B4\u03B9\u03B1\u03C4\u03B7\u03C1\u03B5\u03AF \u03C4\u03B7\u03BD \u03B5\u03BA\u03BA\u03B1\u03B8\u03AC\u03C1\u03B9\u03C3\u03B7 \u03C3\u03C4\u03BF \u03C0\u03B1\u03C1\u03B1\u03B3\u03CC\u03BC\u03B5\u03BD\u03BF.
-ocr.selectText.6=\u0391\u03B3\u03BD\u03BF\u03B5\u03AF \u03C4\u03B9\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B5\u03C2 \u03C0\u03BF\u03C5 \u03AD\u03C7\u03BF\u03C5\u03BD \u03B4\u03B9\u03B1\u03B4\u03C1\u03B1\u03C3\u03C4\u03B9\u03BA\u03CC \u03BA\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF, \u03BC\u03CC\u03BD\u03BF \u03C4\u03B9\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B5\u03C2 OCR \u03C0\u03BF\u03C5 \u03B5\u03AF\u03BD\u03B1\u03B9 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B5\u03C2
-ocr.selectText.7=\u0395\u03C0\u03B9\u03B2\u03BF\u03BB\u03AE OCR, \u03B8\u03B1 \u03C0\u03C1\u03B1\u03B3\u03BC\u03B1\u03C4\u03BF\u03C0\u03BF\u03B9\u03AE\u03C3\u03B5\u03B9 \u039F\u03C0\u03C4\u03B9\u03BA\u03AE \u03B1\u03BD\u03B1\u03B3\u03BD\u03CE\u03C1\u03B9\u03C3\u03B7 \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03C9\u03BD \u03C3\u03B5 \u03BA\u03AC\u03B8\u03B5 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1 \u03B1\u03C6\u03B1\u03B9\u03C1\u03CE\u03BD\u03C4\u03B1\u03C2 \u03CC\u03BB\u03BF \u03C4\u03B1 \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03B1 \u03C4\u03BF\u03C5 \u03B1\u03C1\u03C7\u03B9\u03BA\u03BF\u03CD \u03BA\u03B5\u03AF\u03BC\u03AD\u03BD\u03BF\u03C5
-ocr.selectText.8=\u039A\u03B1\u03BD\u03BF\u03BD\u03B9\u03BA\u03CC (\u0398\u03B1 \u03C0\u03B1\u03C1\u03AC\u03BE\u03B5\u03B9 \u03C3\u03C6\u03AC\u03BB\u03BC\u03B1 \u03B1\u03BD \u03C4\u03BF PDF \u03C0\u03B5\u03C1\u03B9\u03AD\u03C7\u03B5\u03B9 \u03BA\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF)
-ocr.selectText.9=\u0395\u03C0\u03B9\u03C0\u03C1\u03CC\u03C3\u03B8\u03B5\u03C4\u03B5\u03C2 \u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03B9\u03C2
-ocr.selectText.10=\u039B\u03B5\u03B9\u03C4\u03BF\u03C5\u03C1\u03B3\u03AF\u03B1 OCR
-ocr.selectText.11=\u039A\u03B1\u03C4\u03AC\u03C1\u03B3\u03B7\u03C3\u03B7 \u03B5\u03B9\u03BA\u03CC\u03BD\u03C9\u03BD \u03BC\u03B5\u03C4\u03AC \u03C4\u03BF OCR (\u039A\u03B1\u03C4\u03B1\u03C1\u03B3\u03B5\u03AF \u039F\u039B\u0395\u03A3 \u03C4\u03B9\u03C2 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B5\u03C2, \u03B5\u03AF\u03BD\u03B1\u03B9 \u03C7\u03C1\u03AE\u03C3\u03B9\u03BC\u03BF \u03BC\u03CC\u03BD\u03BF \u03B1\u03BD \u03B1\u03C0\u03BF\u03C4\u03B5\u03BB\u03B5\u03AF \u03BC\u03AD\u03C1\u03BF\u03C2 \u03C4\u03BF\u03C5 \u03B2\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2 \u03BC\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE\u03C2)
-ocr.selectText.12=\u03A4\u03CD\u03C0\u03BF\u03C2 \u03B1\u03C0\u03CC\u03B4\u03BF\u03C3\u03B7\u03C2 (\u0393\u03B9\u03B1 \u03C0\u03C1\u03BF\u03C7\u03C9\u03C1\u03B7\u03BC\u03AD\u03BD\u03BF\u03C5\u03C2)
-ocr.help=\u0394\u03B9\u03B1\u03B2\u03AC\u03C3\u03C4\u03B5 \u03B1\u03C5\u03C4\u03AE\u03BD \u03C4\u03B7\u03BD \u03C4\u03B5\u03BA\u03BC\u03B7\u03C1\u03AF\u03C9\u03C3\u03B7 \u03C3\u03C7\u03B5\u03C4\u03B9\u03BA\u03AC \u03BC\u03B5 \u03C4\u03BF\u03BD \u03C4\u03C1\u03CC\u03C0\u03BF \u03C7\u03C1\u03AE\u03C3\u03B7\u03C2 \u03B1\u03C5\u03C4\u03AE\u03C2 \u03B3\u03B9\u03B1 \u03AC\u03BB\u03BB\u03B5\u03C2 \u03B3\u03BB\u03CE\u03C3\u03C3\u03B5\u03C2 \u03AE/\u03BA\u03B1\u03B9 \u03BC\u03B7 \u03C7\u03C1\u03AE\u03C3\u03B7\u03C2 \u03C3\u03B5 docker
-ocr.credit=\u0391\u03C5\u03C4\u03AE \u03B7 \u03C5\u03C0\u03B7\u03C1\u03B5\u03C3\u03AF\u03B1 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF OCRmyPDF \u03BA\u03B1\u03B9 Tesseract \u03B3\u03B9\u03B1 OCR.
-ocr.submit=\u0395\u03C0\u03B5\u03BE\u03B5\u03C1\u03B3\u03B1\u03C3\u03AF\u03B1 PDF \u03BC\u03B5 OCR
+ocr.title=Οπτική αναγνώριση χαρακτήρων (OCR) / Σαρώσεις Cleanup
+ocr.header=Σαρώσεις Cleanup / OCR (Optical Character Recognition - Οπτική αναγνώριση χαρακτήρων)
+ocr.selectText.1=Επιλέξτε γλώσσες που πρόκειται να εντοπιστούν στο PDF (Οι που αναφέρονται είναι αυτές που ανιχνεύονται αυτήν τη στιγμή):
+ocr.selectText.2=Δημιουργήστε αρχείο κειμένου που περιέχει κείμενο OCR μαζί με το PDF που έχει υποβληθεί σε OCR
+ocr.selectText.3=Οι σωστές σελίδες σαρώθηκαν με λοξή γωνία περιστρέφοντάς τες στη θέση τους
+ocr.selectText.4=CΚαθαρίστε τη σελίδα, ώστε να είναι λιγότερο πιθανό το OCR να βρει κείμενο στο θόρυβο φόντου (background noise). (Καμία αλλαγή στο εξαγόμενο)
+ocr.selectText.5=Καθαρίστε τη σελίδα, ώστε να είναι λιγότερο πιθανό το OCR να βρει κείμενο στο θόρυβο φόντου, διατηρεί την εκκαθάριση στο παραγόμενο.
+ocr.selectText.6=Αγνοεί τις σελίδες που έχουν διαδραστικό κείμενο, μόνο τις σελίδες OCR που είναι εικόνες
+ocr.selectText.7=Επιβολή 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=Επεξεργασία PDF με OCR
#extractImages
-extractImages.title=\u0395\u03BE\u03B1\u03B3\u03C9\u03B3\u03AE \u0395\u03B9\u03BA\u03CC\u03BD\u03C9\u03BD
-extractImages.header=\u0395\u03BE\u03B1\u03B3\u03C9\u03B3\u03AE \u0395\u03B9\u03BA\u03CC\u03BD\u03C9\u03BD
-extractImages.selectText=\u0395\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 \u03BC\u03BF\u03C1\u03C6\u03AE \u03B5\u03B9\u03BA\u03CC\u03BD\u03B1\u03C2 \u03B3\u03B9\u03B1 \u03BD\u03B1 \u03BC\u03B5\u03C4\u03B1\u03C4\u03C1\u03AD\u03C8\u03B5\u03C4\u03B5 \u03C4\u03B9\u03C2 \u03B5\u03BE\u03B1\u03B3\u03CC\u03BC\u03B5\u03BD\u03B5\u03C2 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B5\u03C2
-extractImages.submit=\u0395\u03BE\u03B1\u03B3\u03C9\u03B3\u03AE
+extractImages.title=Εξαγωγή Εικόνων
+extractImages.header=Εξαγωγή Εικόνων
+extractImages.selectText=Επιλέξτε μορφή εικόνας για να μετατρέψετε τις εξαγόμενες εικόνες
+extractImages.submit=Εξαγωγή
#File to PDF
-fileToPDF.title=\u0391\u03C1\u03C7\u03B5\u03AF\u03BF \u03C3\u03B5 PDF
-fileToPDF.header=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03BF\u03C0\u03BF\u03B9\u03BF\u03C5\u03B4\u03AE\u03C0\u03BF\u03C4\u03B5 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5 \u03C3\u03B5 PDF
-fileToPDF.credit=\u0391\u03C5\u03C4\u03AE \u03B7 \u03C5\u03C0\u03B7\u03C1\u03B5\u03C3\u03AF\u03B1 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF LibreOffice \u03BA\u03B1\u03B9 Unoconv \u03B3\u03B9\u03B1 \u03C4\u03B7\u03BD \u03BC\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C4\u03C9\u03BD \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD.
-fileToPDF.supportedFileTypes=\u039F\u03B9 \u03C5\u03C0\u03BF\u03C3\u03C4\u03B7\u03C1\u03B9\u03B6\u03CC\u03BC\u03B5\u03BD\u03BF\u03B9 \u03C4\u03CD\u03C0\u03BF\u03B9 \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD \u03B8\u03B1 \u03C0\u03C1\u03AD\u03C0\u03B5\u03B9 \u03BD\u03B1 \u03C0\u03B5\u03C1\u03B9\u03BB\u03B1\u03BC\u03B2\u03AC\u03BD\u03BF\u03C5\u03BD \u03C4\u03B1 \u03C0\u03B1\u03C1\u03B1\u03BA\u03AC\u03C4\u03C9, \u03C9\u03C3\u03C4\u03CC\u03C3\u03BF, \u03B3\u03B9\u03B1 \u03BC\u03B9\u03B1 \u03C0\u03BB\u03AE\u03C1\u03B7 \u03B5\u03BD\u03B7\u03BC\u03B5\u03C1\u03C9\u03BC\u03AD\u03BD\u03B7 \u03BB\u03AF\u03C3\u03C4\u03B1 \u03BC\u03B5 \u03C4\u03B9\u03C2 \u03C5\u03C0\u03BF\u03C3\u03C4\u03B7\u03C1\u03B9\u03B6\u03CC\u03BC\u03B5\u03BD\u03B5\u03C2 \u03BC\u03BF\u03C1\u03C6\u03AD\u03C2, \u03B1\u03BD\u03B1\u03C4\u03C1\u03AD\u03BE\u03C4\u03B5 \u03C3\u03C4\u03B7\u03BD \u03C4\u03B5\u03BA\u03BC\u03B7\u03C1\u03AF\u03C9\u03C3\u03B7 \u03C4\u03BF\u03C5 LibreOffice
-fileToPDF.submit=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C3\u03B5 PDF
+fileToPDF.title=Αρχείο σε PDF
+fileToPDF.header=Μετατροπή οποιουδήποτε αρχείου σε PDF
+fileToPDF.credit=Αυτή η υπηρεσία χρησιμοποιεί LibreOffice και Unoconv για την μετατροπή των αρχείων.
+fileToPDF.supportedFileTypes=Οι υποστηριζόμενοι τύποι αρχείων θα πρέπει να περιλαμβάνουν τα παρακάτω, ωστόσο, για μια πλήρη ενημερωμένη λίστα με τις υποστηριζόμενες μορφές, ανατρέξτε στην τεκμηρίωση του LibreOffice
+fileToPDF.submit=Μετατροπή σε PDF
#compress
-compress.title=\u03A3\u03C5\u03BC\u03C0\u03AF\u03B5\u03C3\u03B7
-compress.header=\u03A3\u03C5\u03BC\u03C0\u03AF\u03B5\u03C3\u03B7 PDF
-compress.credit=\u0391\u03C5\u03C4\u03AE \u03B7 \u03C5\u03C0\u03B7\u03C1\u03B5\u03C3\u03AF\u03B1 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF Ghostscript \u03B3\u03B9\u03B1 PDF \u03A3\u03C5\u03BC\u03C0\u03AF\u03B5\u03C3\u03B7/\u0392\u03B5\u03BB\u03C4\u03B9\u03C3\u03C4\u03BF\u03C0\u03BF\u03AF\u03B7\u03C3\u03B7.
-compress.selectText.1=\u03A7\u03B5\u03B9\u03C1\u03BF\u03BA\u03AF\u03BD\u03B7\u03C4\u03B7 \u039B\u03B5\u03B9\u03C4\u03BF\u03C5\u03C1\u03B3\u03AF\u03B1 - \u0391\u03C0\u03CC 1 \u03AD\u03C9\u03C2 4
-compress.selectText.2=\u0395\u03C0\u03AF\u03C0\u03B5\u03B4\u03BF \u0392\u03B5\u03BB\u03C4\u03B9\u03C3\u03C4\u03BF\u03C0\u03BF\u03AF\u03B7\u03C3\u03B7\u03C2:
-compress.selectText.3=4 (\u03A0\u03BF\u03BB\u03CD \u03BA\u03B1\u03BA\u03CC \u03B3\u03B9\u03B1 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B5\u03C2 \u03BA\u03B5\u03B9\u03BC\u03AD\u03BD\u03BF\u03C5)
-compress.selectText.4=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B7 \u039B\u03B5\u03B9\u03C4\u03BF\u03C5\u03C1\u03B3\u03AF\u03B1 - Auto mode - \u03A0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03CC\u03B6\u03B5\u03B9 \u03B1\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B1 \u03C4\u03B7\u03BD \u03C0\u03BF\u03B9\u03CC\u03C4\u03B7\u03C4\u03B1 \u03B3\u03B9\u03B1 \u03BB\u03AE\u03C8\u03B7 PDF \u03C3\u03C4\u03BF \u03B1\u03BA\u03C1\u03B9\u03B2\u03AD\u03C2 \u03BC\u03AD\u03B3\u03B5\u03B8\u03BF\u03C2
-compress.selectText.5=\u0391\u03BD\u03B1\u03BC\u03B5\u03BD\u03CC\u03BC\u03B5\u03BD\u03BF \u039C\u03AD\u03B3\u03B5\u03B8\u03BF\u03C2 PDF (\u03C0.\u03C7 25MB, 10.8MB, 25KB)
-compress.submit=\u03A3\u03C5\u03BC\u03C0\u03AF\u03B5\u03C3\u03B7
+compress.title=Συμπίεση
+compress.header=Συμπίεση PDF
+compress.credit=Αυτή η υπηρεσία χρησιμοποιεί Ghostscript για PDF Συμπίεση/Βελτιστοποίηση.
+compress.selectText.1=Χειροκίνητη Λειτουργία - Από 1 έως 4
+compress.selectText.2=Επίπεδο Βελτιστοποίησης:
+compress.selectText.3=4 (Πολύ κακό για εικόνες κειμένου)
+compress.selectText.4=Αυτόματη Λειτουργία - Auto mode - Προσαρμόζει αυτόματα την ποιότητα για λήψη PDF στο ακριβές μέγεθος
+compress.selectText.5=Αναμενόμενο Μέγεθος PDF (π.χ 25MB, 10.8MB, 25KB)
+compress.submit=Συμπίεση
#Add image
-addImage.title=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u0395\u03B9\u03BA\u03CC\u03BD\u03B1\u03C2
-addImage.header=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u0395\u03B9\u03BA\u03CC\u03BD\u03B1\u03C2 \u03C3\u03B5 PDF
-addImage.everyPage=\u039A\u03AC\u03B8\u03B5 \u03A3\u03B5\u03BB\u03AF\u03B4\u03B1?
-addImage.upload=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u0395\u03B9\u03BA\u03CC\u03BD\u03B1\u03C2
-addImage.submit=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u0395\u03B9\u03BA\u03CC\u03BD\u03B1\u03C2
+addImage.title=Προσθήκη Εικόνας
+addImage.header=Προσθήκη Εικόνας σε PDF
+addImage.everyPage=Κάθε Σελίδα;
+addImage.upload=Προσθήκη Εικόνας
+addImage.submit=Προσθήκη Εικόνας
#merge
-merge.title=\u03A3\u03C5\u03B3\u03C7\u03CE\u03BD\u03B5\u03C5\u03C3\u03B7
-merge.header=\u03A3\u03C5\u03B3\u03C7\u03CE\u03BD\u03B5\u03C5\u03C3\u03B7 \u03C0\u03BF\u03BB\u03BB\u03B1\u03C0\u03BB\u03CE\u03BD PDFs (2+)
-merge.sortByName=\u03A4\u03B1\u03BE\u03B9\u03BD\u03CC\u03BC\u03B7\u03C3\u03B7 \u03BC\u03B5 \u03B2\u03AC\u03C3\u03B7 \u03C4\u03BF \u038C\u03BD\u03BF\u03BC\u03B1
-merge.sortByDate=\u03A4\u03B1\u03BE\u03B9\u03BD\u03CC\u03BC\u03B7\u03C3\u03B7 \u03BC\u03B5 \u03B2\u03AC\u03C3\u03B7 \u03C4\u03B7\u03BD \u0397\u03BC\u03B5\u03C1\u03BF\u03BC\u03B7\u03BD\u03AF\u03B1
-merge.submit=\u03A3\u03C5\u03B3\u03C7\u03CE\u03BD\u03B5\u03C5\u03C3\u03B7
+merge.title=Συγχώνευση
+merge.header=Συγχώνευση πολλαπλών PDFs (2+)
+merge.sortByName=Ταξινόμηση με βάση το Όνομα
+merge.sortByDate=Ταξινόμηση με βάση την Ημερομηνία
+merge.submit=Συγχώνευση
#pdfOrganiser
-pdfOrganiser.title=\u0394\u03B9\u03BF\u03C1\u03B3\u03B1\u03BD\u03C9\u03C4\u03AE\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2
-pdfOrganiser.header=\u0394\u03B9\u03BF\u03C1\u03B3\u03B1\u03BD\u03C9\u03C4\u03AE\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2 PDF
-pdfOrganiser.submit=\u0391\u03BD\u03B1\u03B4\u03B9\u03AC\u03C4\u03B1\u03BE\u03B7 \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD
+pdfOrganiser.title=Διοργανωτής σελίδας
+pdfOrganiser.header=Διοργανωτής σελίδας PDF
+pdfOrganiser.submit=Αναδιάταξη σελίδων
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Προσαρμοσμένη Σειρά Σελίδας
+pdfOrganiser.mode.2=Αντίστροφη Σειρά
+pdfOrganiser.mode.3=Ταξινόμηση Διπλής Όψης (Duplex Sort)
+pdfOrganiser.mode.4=Ταξινόμηση Φυλλαδίου (Booklet Sort)
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Διαίρεση Μονού-Ζυγού
+pdfOrganiser.mode.7=Αφαίρεση Πρώτου
+pdfOrganiser.mode.8=Αφαίρεση Τελευταίου
+pdfOrganiser.mode.9=Αφαίρεση Πρώτου και Τελευταίου
+pdfOrganiser.placeholder=(π.χ. 1,3,2 ή 4-8,2,10-12 ή 2n-1)
#multiTool
-multiTool.title=PDF \u03A0\u03BF\u03BB\u03C5\u03B5\u03C1\u03B3\u03B1\u03BB\u03B5\u03AF\u03BF
-multiTool.header=PDF \u03A0\u03BF\u03BB\u03C5\u03B5\u03C1\u03B3\u03B1\u03BB\u03B5\u03AF\u03BF
+multiTool.title=PDF Πολυεργαλείο
+multiTool.header=PDF Πολυεργαλείο
+multiTool.uploadPrompts=Ανεβάστε το PDF
#view pdf
-viewPdf.title=View PDF
-viewPdf.header=View PDF
+viewPdf.title=Προβολή PDF
+viewPdf.header=Προβολή PDF
#pageRemover
-pageRemover.title=\u0391\u03C6\u03B1\u03B9\u03C1\u03B5\u03C4\u03AE\u03C2 \u03A3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD
-pageRemover.header=\u0391\u03C6\u03B1\u03B9\u03C1\u03B5\u03C4\u03AE\u03C2 \u03A3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD PDF
-pageRemover.pagesToDelete=\u03A3\u03B5\u03BB\u03AF\u03B4\u03B5\u03C2 \u03C0\u03C1\u03BF\u03C2 \u03B4\u03B9\u03B1\u03B3\u03C1\u03B1\u03C6\u03AE (\u0395\u03B9\u03C3\u03B1\u03B3\u03AC\u03B3\u03B5\u03C4\u03B5 \u03BC\u03B9\u03B1 \u03BB\u03AF\u03C3\u03C4\u03B1 \u03BC\u03B5 \u03B1\u03C1\u03B9\u03B8\u03BC\u03BF\u03CD\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD \u03B4\u03B9\u03B1\u03C7\u03C9\u03C1\u03B9\u03C3\u03BC\u03AD\u03BD\u03C9\u03BD \u03BC\u03B5 \u03BA\u03CC\u03BC\u03BC\u03B1\u03C4\u03B1):
-pageRemover.submit=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u03A3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD
+pageRemover.title=Αφαιρετής Σελίδων
+pageRemover.header=Αφαιρετής Σελίδων PDF
+pageRemover.pagesToDelete=Σελίδες προς διαγραφή (Εισαγάγετε μια λίστα με αριθμούς σελίδων διαχωρισμένων με κόμματα):
+pageRemover.submit=Αφαίρεση Σελίδων
+pageRemover.placeholder=(π.χ. 1,2,6 ή 1-10,15-30)
#rotate
-rotate.title=\u03A0\u03B5\u03C1\u03B9\u03C3\u03C4\u03C1\u03BF\u03C6\u03AE PDF
-rotate.header=\u03A0\u03B5\u03C1\u03B9\u03C3\u03C4\u03C1\u03BF\u03C6\u03AE PDF
-rotate.selectAngle=Select rotation angle (in multiples of 90 degrees):
-rotate.submit=Rotate
+rotate.title=Περιστροφή PDF
+rotate.header=Περιστροφή PDF
+rotate.selectAngle=Επιλέξτε γωνία περιστροφής (σε πολλαπλάσια των 90 μοιρών):
+rotate.submit=Περιστροφή
+
+
+#split-pdfs
+split.title=Διαίρεση PDF
+split.header=Διαίρεση PDF
+split.desc.1=Οι αριθμοί που επιλέγετε είναι ο αριθμός σελίδας στον οποίο θέλετε να κάνετε διαχωρισμό
+split.desc.2=Ως εκ τούτου, η επιλογή 1,3,7-9 θα χωρίσει ένα έγγραφο 10 σελίδων σε 6 ξεχωριστά αρχεία PDF με:
+split.desc.3=Έγγραφο #1: Σελίδα 1
+split.desc.4=Έγγραφο #2: Σελίδα 2 και 3
+split.desc.5=Έγγραφο #3: Σελίδα 4, 5, 6 και 7
+split.desc.6=Έγγραφο #4: Σελίδα 8
+split.desc.7=Έγγραφο #5: Σελίδα 9
+split.desc.8=Έγγραφο #6: Σελίδα 10
+split.splitPages=Εισαγάγετε σελίδες για διαχωρισμό:
+split.submit=Διαίρεση
#merge
-split.title=\u0394\u03B9\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 PDF
-split.header=\u0394\u03B9\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 PDF
-split.desc.1=\u039F\u03B9 \u03B1\u03C1\u03B9\u03B8\u03BC\u03BF\u03AF \u03C0\u03BF\u03C5 \u03B5\u03C0\u03B9\u03BB\u03AD\u03B3\u03B5\u03C4\u03B5 \u03B5\u03AF\u03BD\u03B1\u03B9 \u03BF \u03B1\u03C1\u03B9\u03B8\u03BC\u03CC\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2 \u03C3\u03C4\u03BF\u03BD \u03BF\u03C0\u03BF\u03AF\u03BF \u03B8\u03AD\u03BB\u03B5\u03C4\u03B5 \u03BD\u03B1 \u03BA\u03AC\u03BD\u03B5\u03C4\u03B5 \u03B4\u03B9\u03B1\u03C7\u03C9\u03C1\u03B9\u03C3\u03BC\u03CC
-split.desc.2=\u03A9\u03C2 \u03B5\u03BA \u03C4\u03BF\u03CD\u03C4\u03BF\u03C5, \u03B7 \u03B5\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE 1,3,7-8 \u03B8\u03B1 \u03C7\u03C9\u03C1\u03AF\u03C3\u03B5\u03B9 \u03AD\u03BD\u03B1 \u03AD\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF 10 \u03C3\u03B5\u03BB\u03AF\u03B4\u03C9\u03BD \u03C3\u03B5 6 \u03BE\u03B5\u03C7\u03C9\u03C1\u03B9\u03C3\u03C4\u03AC \u03B1\u03C1\u03C7\u03B5\u03AF\u03B1 PDF \u03BC\u03B5:
-split.desc.3=\u0388\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF #1: \u03A3\u03B5\u03BB\u03AF\u03B4\u03B1 1
-split.desc.4=\u0388\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF #2: \u03A3\u03B5\u03BB\u03AF\u03B4\u03B1 2 \u03BA\u03B1\u03B9 3
-split.desc.5=\u0388\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF #3: \u03A3\u03B5\u03BB\u03AF\u03B4\u03B1 4, 5 \u03BA\u03C3\u03B9 6
-split.desc.6=\u0388\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF #4: \u03A3\u03B5\u03BB\u03AF\u03B4\u03B1 7
-split.desc.7=\u0388\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF #5: \u03A3\u03B5\u03BB\u03AF\u03B4\u03B1 8
-split.desc.8=\u0388\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF #6: \u03A3\u03B5\u03BB\u03AF\u03B4\u03B1 9 \u03BA\u03B1\u03B9 10
-split.splitPages=\u0395\u03B9\u03C3\u03B1\u03B3\u03AC\u03B3\u03B5\u03C4\u03B5 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B5\u03C2 \u03B3\u03B9\u03B1 \u03B4\u03B9\u03B1\u03C7\u03C9\u03C1\u03B9\u03C3\u03BC\u03CC:
-split.submit=\u0394\u03B9\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7
-
-
-#merge
-imageToPDF.title=\u0395\u03B9\u03BA\u03CC\u03BD\u03B1 \u03C3\u03B5 PDF
-imageToPDF.header=\u0395\u03B9\u03BA\u03CC\u03BD\u03B1 \u03C3\u03B5 PDF
-imageToPDF.submit=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE
-imageToPDF.selectLabel=\u0395\u03C0\u03B9\u03BB\u03BF\u03B3\u03AD\u03C2 \u03C0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03B3\u03AE\u03C2 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B1\u03C2
-imageToPDF.fillPage=\u0393\u03AD\u03BC\u03B9\u03C3\u03BC\u03B1 \u03A3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2
-imageToPDF.fitDocumentToImage=\u03A0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03B3\u03AE \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2 \u03C3\u03B5 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B1
-imageToPDF.maintainAspectRatio=\u0394\u03B9\u03B1\u03C4\u03AE\u03C1\u03B7\u03C3\u03B7 \u03B1\u03BD\u03B1\u03BB\u03BF\u03B3\u03B9\u03CE\u03BD \u03B4\u03B9\u03B1\u03C3\u03C4\u03AC\u03C3\u03B5\u03C9\u03BD
-imageToPDF.selectText.2=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B7 \u03C0\u03B5\u03C1\u03B9\u03C3\u03C4\u03C1\u03BF\u03C6\u03AE PDF
-imageToPDF.selectText.3=\u039B\u03BF\u03B3\u03B9\u03BA\u03AE \u03C0\u03BF\u03BB\u03BB\u03CE\u03BD \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD (\u0395\u03BD\u03B5\u03C1\u03B3\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF\u03C4\u03B1\u03B9 \u03BC\u03CC\u03BD\u03BF \u03B5\u03AC\u03BD \u03B5\u03C1\u03B3\u03AC\u03B6\u03B5\u03C3\u03C4\u03B5 \u03BC\u03B5 \u03C0\u03BF\u03BB\u03BB\u03AD\u03C2 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B5\u03C2)
-imageToPDF.selectText.4=\u03A3\u03C5\u03B3\u03C7\u03CE\u03BD\u03B5\u03C5\u03C3\u03B7 \u03C3\u03B5 \u03AD\u03BD\u03B1 PDF
-imageToPDF.selectText.5=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C3\u03B5 \u03BE\u03B5\u03C7\u03C9\u03C1\u03B9\u03C3\u03C4\u03AC \u03B1\u03C1\u03C7\u03B5\u03AF\u03B1 PDF
+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 \u03C3\u03B5 \u0395\u03B9\u03BA\u03CC\u03BD\u03B1
-pdfToImage.header=PDF \u03C3\u03B5 \u0395\u03B9\u03BA\u03CC\u03BD\u03B1
-pdfToImage.selectText=\u039C\u03BF\u03C1\u03C6\u03BF\u03C0\u03BF\u03AF\u03B7\u03C3\u03B7 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B1\u03C2
-pdfToImage.singleOrMultiple=\u03A4\u03CD\u03C0\u03BF\u03C2 \u03B1\u03C0\u03BF\u03C4\u03B5\u03BB\u03AD\u03C3\u03BC\u03B1\u03C4\u03BF\u03C2 \u03B1\u03C0\u03CC \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1 \u03C3\u03B5 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B1
-pdfToImage.single=\u0395\u03BD\u03B9\u03B1\u03AF\u03B1 \u03BC\u03B5\u03B3\u03AC\u03BB\u03B7 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B1 \u03C0\u03BF\u03C5 \u03C3\u03C5\u03BD\u03B4\u03C5\u03AC\u03B6\u03B5\u03B9 \u03CC\u03BB\u03B5\u03C2 \u03C4\u03B9\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B5\u03C2
-pdfToImage.multi=\u03A0\u03BF\u03BB\u03BB\u03B1\u03C0\u03BB\u03AD\u03C2 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B5\u03C2, \u03BC\u03AF\u03B1 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B1 \u03B1\u03BD\u03AC \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1
-pdfToImage.colorType=\u03A4\u03CD\u03C0\u03BF\u03C2 \u03A7\u03C1\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2
-pdfToImage.color=\u03A7\u03C1\u03CE\u03BC\u03B1
-pdfToImage.grey=\u039A\u03BB\u03AF\u03BC\u03B1\u03BA\u03B1 \u03C4\u03BF\u03C5 \u03B3\u03BA\u03C1\u03B9
-pdfToImage.blackwhite=\u0391\u03C3\u03C0\u03C1\u03CC\u03BC\u03B1\u03C5\u03C1\u03BF (\u039C\u03C0\u03BF\u03C1\u03B5\u03AF \u03BD\u03B1 \u03C7\u03B1\u03B8\u03BF\u03CD\u03BD \u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03B1!)
-pdfToImage.submit=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE
+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=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u039A\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD
-addPassword.header=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u039A\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD (\u039A\u03C1\u03C5\u03C0\u03C4\u03BF\u03B3\u03C1\u03AC\u03C6\u03B7\u03C3\u03B7)
-addPassword.selectText.1=\u0395\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 PDF \u03B3\u03B9\u03B1 \u03BA\u03C1\u03C5\u03C0\u03C4\u03BF\u03B3\u03C1\u03AC\u03C6\u03B7\u03C3\u03B7
-addPassword.selectText.2=\u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03A7\u03C1\u03AE\u03C3\u03C4\u03B7
-addPassword.selectText.3=\u039C\u03AE\u03BA\u03BF\u03C2 \u039A\u03BB\u03B5\u03B9\u03B4\u03B9\u03BF\u03CD \u039A\u03C1\u03C5\u03C0\u03C4\u03BF\u03B3\u03C1\u03AC\u03C6\u03B7\u03C3\u03B7\u03C2
-addPassword.selectText.4=\u039F\u03B9 \u03C5\u03C8\u03B7\u03BB\u03CC\u03C4\u03B5\u03C1\u03B5\u03C2 \u03C4\u03B9\u03BC\u03AD\u03C2 \u03B5\u03AF\u03BD\u03B1\u03B9 \u03B9\u03C3\u03C7\u03C5\u03C1\u03CC\u03C4\u03B5\u03C1\u03B5\u03C2, \u03B1\u03BB\u03BB\u03AC \u03BF\u03B9 \u03C7\u03B1\u03BC\u03B7\u03BB\u03CC\u03C4\u03B5\u03C1\u03B5\u03C2 \u03C4\u03B9\u03BC\u03AD\u03C2 \u03AD\u03C7\u03BF\u03C5\u03BD \u03BA\u03B1\u03BB\u03CD\u03C4\u03B5\u03C1\u03B7 \u03C3\u03C5\u03BC\u03B2\u03B1\u03C4\u03CC\u03C4\u03B7\u03C4\u03B1.
-addPassword.selectText.5=\u0394\u03B9\u03BA\u03B1\u03B9\u03CE\u03BC\u03B1\u03C4\u03B1 \u03B3\u03B9\u03B1 \u03C1\u03CD\u03B8\u03BC\u03B9\u03C3\u03B7 (\u03A3\u03C5\u03BD\u03B9\u03C3\u03C4\u03AC\u03C4\u03B1\u03B9 \u03BD\u03B1 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF\u03C4\u03B1\u03B9 \u03BC\u03B1\u03B6\u03AF \u03BC\u03B5 \u03C4\u03BF\u03BD \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 \u03BA\u03B1\u03C4\u03CC\u03C7\u03BF\u03C5 (Owner password)
-addPassword.selectText.6=\u0391\u03C0\u03BF\u03C4\u03C1\u03BF\u03C0\u03AE \u03C3\u03C5\u03BD\u03B1\u03C1\u03BC\u03BF\u03BB\u03CC\u03B3\u03B7\u03C3\u03B7\u03C2 \u03B5\u03B3\u03B3\u03C1\u03AC\u03C6\u03BF\u03C5
-addPassword.selectText.7=\u0391\u03C0\u03BF\u03C4\u03C1\u03BF\u03C0\u03AE \u03B5\u03BE\u03B1\u03B3\u03C9\u03B3\u03AE\u03C2 \u03C0\u03B5\u03C1\u03B9\u03B5\u03C7\u03BF\u03BC\u03AD\u03BD\u03BF\u03C5
-addPassword.selectText.8=\u0391\u03C0\u03BF\u03C4\u03C1\u03BF\u03C0\u03AE \u03B5\u03BE\u03B1\u03B3\u03C9\u03B3\u03AE\u03C2 \u03B3\u03B9\u03B1 \u03C0\u03C1\u03BF\u03C3\u03B2\u03B1\u03C3\u03B9\u03BC\u03CC\u03C4\u03B7\u03C4\u03B1
-addPassword.selectText.9=\u0391\u03C0\u03BF\u03C4\u03C1\u03BF\u03C0\u03AE \u03C3\u03C5\u03BC\u03C0\u03BB\u03AE\u03C1\u03C9\u03C3\u03B7\u03C2 \u03C6\u03CC\u03C1\u03BC\u03B1\u03C2
-addPassword.selectText.10=\u0391\u03C0\u03BF\u03C4\u03C1\u03BF\u03C0\u03AE \u03C4\u03C1\u03BF\u03C0\u03BF\u03C0\u03BF\u03AF\u03B7\u03C3\u03B7\u03C2
-addPassword.selectText.11=\u0391\u03C0\u03BF\u03C4\u03C1\u03BF\u03C0\u03AE \u03C4\u03C1\u03BF\u03C0\u03BF\u03C0\u03BF\u03AF\u03B7\u03C3\u03B7\u03C2 annotation
-addPassword.selectText.12=\u0391\u03C0\u03BF\u03C4\u03C1\u03BF\u03C0\u03AE \u03B5\u03BA\u03C4\u03CD\u03C0\u03C9\u03C3\u03B7\u03C2
-addPassword.selectText.13=\u0391\u03C0\u03BF\u03C4\u03C1\u03BF\u03C0\u03AE \u03B5\u03BA\u03C4\u03CD\u03C0\u03C9\u03C3\u03B7\u03C2 \u03C3\u03B5 \u03B4\u03B9\u03B1\u03C6\u03BF\u03C1\u03B5\u03C4\u03B9\u03BA\u03BF\u03CD\u03C2 \u03C4\u03CD\u03C0\u03BF\u03C5\u03C2 \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD
-addPassword.selectText.14=\u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 \u03BA\u03B1\u03C4\u03CC\u03C7\u03BF\u03C5
-addPassword.selectText.15=\u03A0\u03B5\u03C1\u03B9\u03BF\u03C1\u03AF\u03B6\u03B5\u03B9 \u03CC,\u03C4\u03B9 \u03BC\u03C0\u03BF\u03C1\u03B5\u03AF \u03BD\u03B1 \u03B3\u03AF\u03BD\u03B5\u03B9 \u03BC\u03B5 \u03C4\u03BF \u03AD\u03B3\u03B3\u03C1\u03B1\u03C6\u03BF \u03BC\u03B5\u03C4\u03AC \u03C4\u03BF \u03AC\u03BD\u03BF\u03B9\u03B3\u03BC\u03B1 (\u0394\u03B5\u03BD \u03C5\u03C0\u03BF\u03C3\u03C4\u03B7\u03C1\u03AF\u03B6\u03B5\u03C4\u03B1\u03B9 \u03B1\u03C0\u03CC \u03CC\u03BB\u03BF\u03C5\u03C2 \u03C4\u03BF\u03C5\u03C2 \u03B1\u03BD\u03B1\u03B3\u03BD\u03CE\u03C3\u03C4\u03B5\u03C2 PDF)
-addPassword.selectText.16=\u03A0\u03B5\u03C1\u03B9\u03BF\u03C1\u03AF\u03B6\u03B5\u03B9 \u03C4\u03BF \u03AC\u03BD\u03BF\u03B9\u03B3\u03BC\u03B1 \u03C4\u03BF\u03C5 \u03AF\u03B4\u03B9\u03BF\u03C5 \u03C4\u03BF\u03C5 \u03B5\u03B3\u03B3\u03C1\u03AC\u03C6\u03BF\u03C5
-addPassword.submit=\u039A\u03C1\u03C5\u03C0\u03C4\u03BF\u03B3\u03C1\u03AC\u03C6\u03B7\u03C3\u03B7
+addPassword.title=Προσθήκη Κωδικού
+addPassword.header=Προσθήκη Κωδικού (Κρυπτογράφηση)
+addPassword.selectText.1=Επιλέξτε PDF για κρυπτογράφηση
+addPassword.selectText.2=Κωδικός Χρήστη
+addPassword.selectText.3=Μήκος Κλειδιού Κρυπτογράφησης
+addPassword.selectText.4=Οι υψηλότερες τιμές είναι ισχυρότερες, αλλά οι χαμηλότερες τιμές έχουν καλύτερη συμβατότητα.
+addPassword.selectText.5=Δικαιώματα για ρύθμιση (Συνιστάται να χρησιμοποιείται μαζί με τον κωδικό πρόσβασης κατόχου (Owner password)
+addPassword.selectText.6=Αποτροπή συναρμολόγησης εγγράφου
+addPassword.selectText.7=Αποτροπή εξαγωγής περιεχομένου
+addPassword.selectText.8=Αποτροπή εξαγωγής για προσβασιμότητα
+addPassword.selectText.9=Αποτροπή συμπλήρωσης φόρμας
+addPassword.selectText.10=Αποτροπή τροποποίησης
+addPassword.selectText.11=Αποτροπή τροποποίησης annotation
+addPassword.selectText.12=Αποτροπή εκτύπωσης
+addPassword.selectText.13=Αποτροπή εκτύπωσης σε διαφορετικούς τύπους αρχείων
+addPassword.selectText.14=Κωδικός πρόσβασης κατόχου
+addPassword.selectText.15=Περιορίζει ό,τι μπορεί να γίνει με το έγγραφο μετά το άνοιγμα (Δεν υποστηρίζεται από όλους τους αναγνώστες PDF)
+addPassword.selectText.16=Περιορίζει το άνοιγμα του ίδιου του εγγράφου
+addPassword.submit=Κρυπτογράφηση
#watermark
-watermark.title=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03A5\u03B4\u03B1\u03C4\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2
-watermark.header=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03A5\u03B4\u03B1\u03C4\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2
-watermark.selectText.1=\u0395\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 PDF \u03B3\u03B9\u03B1 \u03C4\u03B7\u03BD \u03C0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03C4\u03BF\u03C5 \u03C5\u03B4\u03B1\u03C4\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2:
-watermark.selectText.2=\u039A\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF \u03A5\u03B4\u03B1\u03C4\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2:
-watermark.selectText.3=\u039C\u03AD\u03B3\u03B5\u03B8\u03BF\u03C2 \u039A\u03B5\u03B9\u03BC\u03AD\u03BD\u03BF\u03C5:
-watermark.selectText.4=\u03A0\u03B5\u03C1\u03B9\u03C3\u03C4\u03C1\u03BF\u03C6\u03AE (0-360):
-watermark.selectText.5=widthSpacer (\u039A\u03B5\u03BD\u03CC \u03BC\u03B5\u03C4\u03B1\u03BE\u03CD \u03BA\u03AC\u03B8\u03B5 \u03C5\u03B4\u03B1\u03C4\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2 \u03BF\u03C1\u03B9\u03B6\u03CC\u03BD\u03C4\u03B9\u03B1):
-watermark.selectText.6=heightSpacer (\u039A\u03B5\u03BD\u03CC \u03BC\u03B5\u03C4\u03B1\u03BE\u03CD \u03BA\u03AC\u03B8\u03B5 \u03C5\u03B4\u03B1\u03C4\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2 \u03BA\u03AC\u03B8\u03B5\u03C4\u03B1):
-watermark.selectText.7=\u0391\u03B4\u03B9\u03B1\u03C6\u03AC\u03BD\u03B5\u03B9\u03B1 (Opacity) (0% - 100%):
-watermark.selectText.8=\u03A4\u03CD\u03C0\u03BF\u03C2 \u03A5\u03B4\u03B1\u03C4\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2:
-watermark.selectText.9=\u0395\u03B9\u03BA\u03CC\u03BD\u03B1 \u03A5\u03B4\u03B1\u03C4\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2:
-watermark.submit=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03A5\u03B4\u03B1\u03C4\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2
+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=Αδιαφάνεια (Opacity) (0% - 100%):
+watermark.selectText.8=Τύπος Υδατογραφήματος:
+watermark.selectText.9=Εικόνα Υδατογραφήματος:
+watermark.submit=Προσθήκη Υδατογραφήματος
+watermark.type.1=Κείμενο
+watermark.type.2=Εικόνα
#Change permissions
-permissions.title=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE \u0394\u03B9\u03BA\u03B1\u03B9\u03C9\u03BC\u03AC\u03C4\u03C9\u03BD
-permissions.header=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE \u0394\u03B9\u03BA\u03B1\u03B9\u03C9\u03BC\u03AC\u03C4\u03C9\u03BD
-permissions.warning=\u03A0\u03C1\u03BF\u03B5\u03B9\u03B4\u03BF\u03C0\u03BF\u03AF\u03B7\u03C3\u03B7 \u03CC\u03C4\u03B9 \u03B1\u03C5\u03C4\u03AC \u03C4\u03B1 \u03B4\u03B9\u03BA\u03B1\u03B9\u03CE\u03BC\u03B1\u03C4\u03B1 \u03B4\u03B5\u03BD \u03B1\u03BB\u03BB\u03AC\u03B6\u03BF\u03C5\u03BD, \u03C3\u03C5\u03BD\u03B9\u03C3\u03C4\u03AC\u03C4\u03B1\u03B9 \u03BD\u03B1 \u03C4\u03B1 \u03BF\u03C1\u03AF\u03C3\u03B5\u03C4\u03B5 \u03BC\u03B5 \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 \u03BC\u03AD\u03C3\u03C9 \u03C4\u03B7\u03C2 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2 \u03C0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7\u03C2 \u03BA\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2
-permissions.selectText.1=\u0395\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 PDF \u03B3\u03B9\u03B1 \u03BD\u03B1 \u03B1\u03BB\u03BB\u03AC\u03BE\u03B5\u03C4\u03B5 \u03C4\u03B1 \u03B4\u03B9\u03BA\u03B1\u03B9\u03CE\u03BC\u03B1\u03C4\u03B1
-permissions.selectText.2=\u0394\u03B9\u03BA\u03B1\u03B9\u03CE\u03BC\u03B1\u03C4\u03B1 \u03B3\u03B9\u03B1 \u03C1\u03CD\u03B8\u03BC\u03B9\u03C3\u03B7
-permissions.selectText.3=\u0391\u03C0\u03BF\u03C4\u03C1\u03BF\u03C0\u03AE \u03C3\u03C5\u03BD\u03B1\u03C1\u03BC\u03BF\u03BB\u03CC\u03B3\u03B7\u03C3\u03B7\u03C2 \u03B5\u03B3\u03B3\u03C1\u03AC\u03C6\u03BF\u03C5
-permissions.selectText.4=\u0391\u03C0\u03BF\u03C4\u03C1\u03BF\u03C0\u03AE \u03B5\u03BE\u03B1\u03B3\u03C9\u03B3\u03AE\u03C2 \u03C0\u03B5\u03C1\u03B9\u03B5\u03C7\u03BF\u03BC\u03AD\u03BD\u03BF\u03C5
-permissions.selectText.5=\u0391\u03C0\u03BF\u03C4\u03C1\u03BF\u03C0\u03AE \u03B5\u03BE\u03B1\u03B3\u03C9\u03B3\u03AE\u03C2 \u03B3\u03B9\u03B1 \u03C0\u03C1\u03BF\u03C3\u03B2\u03B1\u03C3\u03B9\u03BC\u03CC\u03C4\u03B7\u03C4\u03B1
-permissions.selectText.6=\u0391\u03C0\u03BF\u03C4\u03C1\u03BF\u03C0\u03AE \u03C3\u03C5\u03BC\u03C0\u03BB\u03AE\u03C1\u03C9\u03C3\u03B7\u03C2 \u03C6\u03CC\u03C1\u03BC\u03B1\u03C2
-permissions.selectText.7=\u0391\u03C0\u03BF\u03C4\u03C1\u03BF\u03C0\u03AE \u03C4\u03C1\u03BF\u03C0\u03BF\u03C0\u03BF\u03AF\u03B7\u03C3\u03B7\u03C2
-permissions.selectText.8=\u0391\u03C0\u03BF\u03C4\u03C1\u03BF\u03C0\u03AE \u03C4\u03C1\u03BF\u03C0\u03BF\u03C0\u03BF\u03AF\u03B7\u03C3\u03B7\u03C2 annotation
-permissions.selectText.9=\u0391\u03C0\u03BF\u03C4\u03C1\u03BF\u03C0\u03AE \u03B5\u03BA\u03C4\u03CD\u03C0\u03C9\u03C3\u03B7\u03C2
-permissions.selectText.10=\u0391\u03C0\u03BF\u03C4\u03C1\u03BF\u03C0\u03AE \u03B5\u03BA\u03C4\u03CD\u03C0\u03C9\u03C3\u03B7\u03C2 \u03C3\u03B5 \u03B4\u03B9\u03B1\u03C6\u03BF\u03C1\u03B5\u03C4\u03B9\u03BA\u03BF\u03CD\u03C2 \u03C4\u03CD\u03C0\u03BF\u03C5\u03C2 \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD
-permissions.submit=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE
+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=Αποτροπή τροποποίησης annotation
+permissions.selectText.9=Αποτροπή εκτύπωσης
+permissions.selectText.10=Αποτροπή εκτύπωσης σε διαφορετικούς τύπους αρχείων
+permissions.submit=Αλλαγή
#remove password
-removePassword.title=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u039A\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD
-removePassword.header=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7 \u039A\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD (\u0391\u03C0\u03BF\u03BA\u03C1\u03C5\u03C0\u03C4\u03BF\u03B3\u03C1\u03AC\u03C6\u03B7\u03C3\u03B7)
-removePassword.selectText.1=\u0395\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 PDF \u03B3\u03B9\u03B1 \u03B1\u03C0\u03BF\u03BA\u03C1\u03C5\u03C0\u03C4\u03BF\u03B3\u03C1\u03AC\u03C6\u03B7\u03C3\u03B7
-removePassword.selectText.2=\u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2
-removePassword.submit=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7
+removePassword.title=Αφαίρεση Κωδικού
+removePassword.header=Αφαίρεση Κωδικού (Αποκρυπτογράφηση)
+removePassword.selectText.1=Επιλέξτε PDF για αποκρυπτογράφηση
+removePassword.selectText.2=Κωδικός
+removePassword.submit=Αφαίρεση
#changeMetadata
-changeMetadata.title=\u03A4\u03AF\u03C4\u03BB\u03BF\u03C2:
-changeMetadata.header=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE \u039C\u03B5\u03C4\u03B1\u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03C9\u03BD
-changeMetadata.selectText.1=\u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03BF\u03CD\u03BC\u03B5 \u03B5\u03C0\u03B5\u03BE\u03B5\u03C1\u03B3\u03B1\u03C3\u03C4\u03B5\u03AF\u03C4\u03B5 \u03C4\u03B9\u03C2 \u03BC\u03B5\u03C4\u03B1\u03B2\u03BB\u03B7\u03C4\u03AD\u03C2 \u03C0\u03BF\u03C5 \u03B8\u03AD\u03BB\u03B5\u03C4\u03B5 \u03BD\u03B1 \u03B1\u03BB\u03BB\u03AC\u03BE\u03B5\u03C4\u03B5
-changeMetadata.selectText.2=\u0394\u03B9\u03B1\u03B3\u03C1\u03B1\u03C6\u03AE \u03CC\u03BB\u03C9\u03BD \u03C4\u03C9\u03BD \u03BC\u03B5\u03C4\u03B1\u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03C9\u03BD
-changeMetadata.selectText.3=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03C0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03C3\u03BC\u03AD\u03BD\u03C9\u03BD \u03BC\u03B5\u03C4\u03B1\u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03C9\u03BD:
-changeMetadata.author=\u03A3\u03C5\u03BD\u03C4\u03AC\u03BA\u03C4\u03B7\u03C2:
-changeMetadata.creationDate=\u0397\u03BC\u03B5\u03C1\u03BF\u03BC\u03B7\u03BD\u03AF\u03B1 \u0394\u03B7\u03BC\u03B9\u03BF\u03C5\u03C1\u03B3\u03AF\u03B1\u03C2 (yyyy/MM/dd HH:mm:ss):
-changeMetadata.creator=\u0394\u03B7\u03BC\u03B9\u03BF\u03C5\u03C1\u03B3\u03CC\u03C2:
-changeMetadata.keywords=\u039B\u03AD\u03BE\u03B5\u03B9\u03C2-\u03BA\u03BB\u03B5\u03B9\u03B4\u03B9\u03AC:
-changeMetadata.modDate=\u0397\u03BC\u03B5\u03C1\u03BF\u03BC\u03B7\u03BD\u03AF\u03B1 \u03A4\u03C1\u03BF\u03C0\u03BF\u03C0\u03BF\u03AF\u03B7\u03C3\u03B7\u03C2 (yyyy/MM/dd HH:mm:ss):
-changeMetadata.producer=\u03A0\u03B1\u03C1\u03B1\u03B3\u03C9\u03B3\u03CC\u03C2:
-changeMetadata.subject=\u0398\u03AD\u03BC\u03B1:
+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.trapped=Trapped:
-changeMetadata.selectText.4=\u0386\u03BB\u03BB\u03B1 \u03BC\u03B5\u03C4\u03B1\u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03B1:
-changeMetadata.selectText.5=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03B5\u03B3\u03B3\u03C1\u03B1\u03C6\u03AE\u03C2 \u03C0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03C3\u03BC\u03AD\u03BD\u03C9\u03BD \u03BC\u03B5\u03C4\u03B1\u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03C9\u03BD
-changeMetadata.submit=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE
+changeMetadata.selectText.4=Άλλα μεταδεδομένα:
+changeMetadata.selectText.5=Προσθήκη εγγραφής προσαρμοσμένων μεταδεδομένων
+changeMetadata.submit=Αλλαγή
#pdfToPDFA
-pdfToPDFA.title=PDF \u03C3\u03B5 PDF/A
-pdfToPDFA.header=PDF \u03C3\u03B5 PDF/A
-pdfToPDFA.credit=\u0391\u03C5\u03C4\u03AE \u03B7 \u03C5\u03C0\u03B7\u03C1\u03B5\u03C3\u03AF\u03B1 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF OCRmyPDF \u03B3\u03B9\u03B1 PDF/A \u03BC\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE
-pdfToPDFA.submit=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE
+pdfToPDFA.title=PDF σε PDF/A
+pdfToPDFA.header=PDF σε PDF/A
+pdfToPDFA.credit=Αυτή η υπηρεσία χρησιμοποιεί OCRmyPDF για PDF/A μετατροπή
+pdfToPDFA.submit=Μετατροπή
+pdfToPDFA.tip=Προς το παρόν δεν λειτουργεί για πολλαπλές εισόδους ταυτόχρονα
+pdfToPDFA.outputFormat=Output format
#PDFToWord
-PDFToWord.title=PDF \u03C3\u03B5 Word
-PDFToWord.header=PDF \u03C3\u03B5 Word
-PDFToWord.selectText.1=\u03A4\u03CD\u03C0\u03BF\u03C2 \u0391\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5 \u0395\u03BE\u03B1\u03B3\u03CC\u03BC\u03B5\u03BD\u03BF\u03C5
-PDFToWord.credit=\u0391\u03C5\u03C4\u03AE \u03B7 \u03C5\u03C0\u03B7\u03C1\u03B5\u03C3\u03AF\u03B1 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF LibreOffice \u03B3\u03B9\u03B1 \u03C4\u03B7 \u03BC\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C4\u03C9\u03BD \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD.
-PDFToWord.submit=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE
+PDFToWord.title=PDF σε Word
+PDFToWord.header=PDF σε Word
+PDFToWord.selectText.1=Τύπος Αρχείου Εξαγόμενου
+PDFToWord.credit=Αυτή η υπηρεσία χρησιμοποιεί LibreOffice για τη μετατροπή των αρχείων.
+PDFToWord.submit=Μετατροπή
#PDFToPresentation
-PDFToPresentation.title=PDF \u03C3\u03B5 Powerpoint
-PDFToPresentation.header=PDF \u03C3\u03B5 Powerpoint
-PDFToPresentation.selectText.1=\u03A4\u03CD\u03C0\u03BF\u03C2 \u0391\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5 \u0395\u03BE\u03B1\u03B3\u03CC\u03BC\u03B5\u03BD\u03BF\u03C5
-PDFToPresentation.credit=\u0391\u03C5\u03C4\u03AE \u03B7 \u03C5\u03C0\u03B7\u03C1\u03B5\u03C3\u03AF\u03B1 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF LibreOffice \u03B3\u03B9\u03B1 \u03C4\u03B7 \u03BC\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C4\u03C9\u03BD \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD.
-PDFToPresentation.submit=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE
+PDFToPresentation.title=PDF σε Powerpoint
+PDFToPresentation.header=PDF σε Powerpoint
+PDFToPresentation.selectText.1=Τύπος Αρχείου Εξαγόμενου
+PDFToPresentation.credit=Αυτή η υπηρεσία χρησιμοποιεί LibreOffice για τη μετατροπή των αρχείων.
+PDFToPresentation.submit=Μετατροπή
#PDFToText
-PDFToText.title=PDF \u03C3\u03B5 RTF (\u039A\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF)
-PDFToText.header=PDF \u03C3\u03B5 RTF (\u039A\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF)
-PDFToText.selectText.1=\u03A4\u03CD\u03C0\u03BF\u03C2 \u0391\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5 \u0395\u03BE\u03B1\u03B3\u03CC\u03BC\u03B5\u03BD\u03BF\u03C5
-PDFToText.credit=\u0391\u03C5\u03C4\u03AE \u03B7 \u03C5\u03C0\u03B7\u03C1\u03B5\u03C3\u03AF\u03B1 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF LibreOffice \u03B3\u03B9\u03B1 \u03C4\u03B7 \u03BC\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C4\u03C9\u03BD \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD.
-PDFToText.submit=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE
+PDFToText.title=PDF σε RTF (Κείμενο)
+PDFToText.header=PDF σε RTF (Κείμενο)
+PDFToText.selectText.1=Τύπος Αρχείου Εξαγόμενου
+PDFToText.credit=Αυτή η υπηρεσία χρησιμοποιεί LibreOffice για τη μετατροπή των αρχείων.
+PDFToText.submit=Μετατροπή
#PDFToHTML
-PDFToHTML.title=PDF \u03C3\u03B5 HTML
-PDFToHTML.header=PDF \u03C3\u03B5 HTML
-PDFToHTML.credit=\u0391\u03C5\u03C4\u03AE \u03B7 \u03C5\u03C0\u03B7\u03C1\u03B5\u03C3\u03AF\u03B1 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF LibreOffice \u03B3\u03B9\u03B1 \u03C4\u03B7 \u03BC\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C4\u03C9\u03BD \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD.
-PDFToHTML.submit=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE
+PDFToHTML.title=PDF σε HTML
+PDFToHTML.header=PDF σε HTML
+PDFToHTML.credit=Αυτή η υπηρεσία χρησιμοποιεί pdftohtml για τη μετατροπή των αρχείων.
+PDFToHTML.submit=Μετατροπή
#PDFToXML
-PDFToXML.title=PDF \u03C3\u03B5 XML
-PDFToXML.header=PDF \u03C3\u03B5 XML
-PDFToXML.credit=\u0391\u03C5\u03C4\u03AE \u03B7 \u03C5\u03C0\u03B7\u03C1\u03B5\u03C3\u03AF\u03B1 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF LibreOffice \u03B3\u03B9\u03B1 \u03C4\u03B7 \u03BC\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C4\u03C9\u03BD \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD.
-PDFToXML.submit=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE
+PDFToXML.title=PDF σε XML
+PDFToXML.header=PDF σε XML
+PDFToXML.credit=Αυτή η υπηρεσία χρησιμοποιεί LibreOffice για τη μετατροπή των αρχείων.
+PDFToXML.submit=Μετατροπή
#PDFToCSV
-PDFToCSV.title=PDF ?? CSV
-PDFToCSV.header=PDF ?? CSV
-PDFToCSV.prompt=Choose page to extract table
-PDFToCSV.submit=?????????
+PDFToCSV.title=PDF σε CSV
+PDFToCSV.header=PDF σε CSV
+PDFToCSV.prompt=Επιλέξτε σελίδα για εξαγωγή πίνακα
+PDFToCSV.submit=Εξαξωγή
#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
+split-by-size-or-count.title=Διαχωρίστε το PDF Κατά Μέγεθος ή Μέτρηση
+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=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.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=Foreground
overlay-pdfs.position.background=Background
-overlay-pdfs.submit=Submit
+overlay-pdfs.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
+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
+split-by-sections.merge=Συγχώνευση σε ένα PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
-licenses.nav=Licenses
-licenses.title=3rd Party Licenses
-licenses.header=3rd Party Licenses
+licenses.nav=Άδειες
+licenses.title=3rd Party Άδειες
+licenses.header=3rd Party Άδειες
licenses.module=Module
-licenses.version=Version
-licenses.license=License
+licenses.version=Εκδοχή
+licenses.license=Άδεια
+# error
+error.sorry=Συγγνώμη για το ζήτημα!
+error.needHelp=Χρειάζεστε βοήθεια / Βρήκατε πρόβλημα;
+error.contactTip=Εάν εξακολουθείτε να αντιμετωπίζετε προβλήματα, μη διστάσετε να επικοινωνήσετε μαζί μας για βοήθεια. Μπορείτε να υποβάλετε ένα ticket στη σελίδα μας στο GitHub ή να επικοινωνήσετε μαζί μας μέσω του Discord:
+error.404.head=404 - Η σελίδα δεν βρέθηκε | Oops, we tripped in the code!
+error.404.1=Δεν μπορούμε να βρούμε τη σελίδα που ψάχνετε.
+error.404.2=Κάτι πήγε στραβά
+error.github=Υποβάλετε ένα ticket στο GitHub
+error.showStack=Εμφάνιση Stack Trace
+error.copyStack=Αντιγραφή Stack Trace
+error.githubSubmit=GitHub - Υποβάλετε ένα ticket
+error.discordSubmit=Discord - Υποβάλετε ένα Support post
+
diff --git a/src/main/resources/messages_en_GB.properties b/src/main/resources/messages_en_GB.properties
index 1dd5262d..6189f56b 100644
--- a/src/main/resources/messages_en_GB.properties
+++ b/src/main/resources/messages_en_GB.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr = left to right, rtl = right to left)
@@ -17,9 +17,11 @@ true=True
false=False
unknown=Unknown
save=Save
+saveToBrowser=Save to Browser
close=Close
filesSelected=files selected
noFavourites=No favourites added
+downloadComplete=Download Complete
bored=Bored Waiting?
alphabet=Alphabet
downloadPdf=Download PDF
@@ -52,16 +54,34 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
+invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
+deleteCurrentUserMessage=Cannot delete currently logged in user.
+deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
+downgradeCurrentUserMessage=Cannot downgrade current user's role
+downgradeCurrentUserLongMessage=Cannot downgrade current user's role. Hence, current user will not be shown.
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
+pipeline.header=Pipeline Menu (Beta)
pipeline.uploadButton=Upload Custom
pipeline.configureButton=Configure
pipeline.defaultOption=Custom
pipeline.submitButton=Submit
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
######################
# Pipeline Options #
@@ -94,6 +114,7 @@ navbar.settings=Settings
#############
settings.title=Settings
settings.update=Update available
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=App Version:
settings.downloadOption.title=Choose download option (For single file non zip downloads):
settings.downloadOption.1=Open in same window
@@ -102,12 +123,13 @@ settings.downloadOption.3=Download file
settings.zipThreshold=Zip files when the number of downloaded files exceeds
settings.signOut=Sign Out
settings.accountSettings=Account Settings
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=Change Credentials
changeCreds.header=Update Your Account Details
-changeCreds.changeUserAndPassword=You are using default login credentials. Please enter a new password (and username if wanted)
+changeCreds.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=New Username
changeCreds.oldPassword=Current Password
changeCreds.newPassword=New Password
@@ -142,14 +164,18 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
adminUserSettings.actions=Actions
adminUserSettings.apiUser=Limited API User
+adminUserSettings.extraApiUser=Additional 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.internalApiUser=Internal API User
+adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User
+adminUserSettings.changeUserRole=Change User's Role
#############
# HOME-PAGE #
@@ -392,6 +418,15 @@ home.AddStampRequest.desc=Add text or add image stamps at set locations
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle,epub,mobi,azw3,docx,rtf,txt,html,lit,fb2,pdb,lrf
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle,epub,mobi,azw3,docx,rtf,txt,html,lit,fb2,pdb,lrf
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Sign in
+login.header=Sign in
login.signin=Sign in
login.rememberme=Remember me
login.invalid=Invalid username or password.
login.locked=Your account has been locked.
login.signinTitle=Please sign in
+login.ssoSignIn=Login via Single Sign-on
+login.oauth2AutoCreateDisabled=OAUTH2 Auto-Create User Disabled
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Convert To Single Page
pageExtracter.title=Extract Pages
pageExtracter.header=Extract Pages
pageExtracter.submit=Extract
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -623,6 +662,18 @@ compare.document.1=Document 1
compare.document.2=Document 2
compare.submit=Compare
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
#sign
sign.title=Sign
@@ -642,7 +693,8 @@ repair.submit=Repair
#flatten
flatten.title=Flatten
-flatten.header=Flatten PDFs
+flatten.header=Flatten PDF
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Flatten
@@ -726,11 +778,23 @@ merge.submit=Merge
pdfOrganiser.title=Page Organiser
pdfOrganiser.header=PDF Page Organiser
pdfOrganiser.submit=Rearrange Pages
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=PDF Multi Tool
multiTool.header=PDF Multi Tool
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
viewPdf.title=View PDF
@@ -741,6 +805,7 @@ pageRemover.title=Page Remover
pageRemover.header=PDF Page remover
pageRemover.pagesToDelete=Pages to delete (Enter a comma-separated list of page numbers) :
pageRemover.submit=Delete Pages
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Select rotation angle (in multiples of 90 degrees):
rotate.submit=Rotate
-#merge
+#split-pdfs
split.title=Split PDF
split.header=Split PDF
split.desc.1=The numbers you select are the page number you wish to do a split on
-split.desc.2=As such selecting 1,3,7-8 would split a 10 page document into 6 separate PDFS with:
+split.desc.2=As such selecting 1,3,7-9 would split a 10 page document into 6 separate PDFS with:
split.desc.3=Document #1: Page 1
split.desc.4=Document #2: Page 2 and 3
-split.desc.5=Document #3: Page 4, 5 and 6
-split.desc.6=Document #4: Page 7
-split.desc.7=Document #5: Page 8
-split.desc.8=Document #6: Page 9 and 10
+split.desc.5=Document #3: Page 4, 5, 6 and 7
+split.desc.6=Document #4: Page 8
+split.desc.7=Document #5: Page 9
+split.desc.8=Document #6: Page 10
split.splitPages=Enter pages to split on:
split.submit=Split
@@ -828,6 +893,8 @@ watermark.selectText.7=Opacity (0% - 100%):
watermark.selectText.8=Watermark Type:
watermark.selectText.9=Watermark Image:
watermark.submit=Add Watermark
+watermark.type.1=Text
+watermark.type.2=Image
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF To PDF/A
pdfToPDFA.header=PDF To PDF/A
pdfToPDFA.credit=This service uses OCRmyPDF for PDF/A conversion
pdfToPDFA.submit=Convert
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Convert
#PDFToHTML
PDFToHTML.title=PDF to HTML
PDFToHTML.header=PDF to HTML
-PDFToHTML.credit=This service uses LibreOffice for file conversion.
+PDFToHTML.credit=This service uses pdftohtml for file conversion.
PDFToHTML.submit=Convert
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Choose page to extract table
PDFToCSV.submit=Extract
#split-by-size-or-count
+split-by-size-or-count.title=Split PDF 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
@@ -959,6 +1029,15 @@ 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
+split-by-sections.merge=Merge Into One PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Version
licenses.license=License
+# error
+error.sorry=Sorry for the issue!
+error.needHelp=Need help / Found an issue?
+error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
+error.404.head=404 - Page Not Found | Oops, we tripped in the code!
+error.404.1=We can't seem to find the page you're looking for.
+error.404.2=Something went wrong
+error.github=Submit a ticket on GitHub
+error.showStack=Show Stack Trace
+error.copyStack=Copy Stack Trace
+error.githubSubmit=GitHub - Submit a ticket
+error.discordSubmit=Discord - Submit Support post
+
diff --git a/src/main/resources/messages_en_US.properties b/src/main/resources/messages_en_US.properties
index 120ace75..2ecaa2e8 100644
--- a/src/main/resources/messages_en_US.properties
+++ b/src/main/resources/messages_en_US.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -17,9 +17,11 @@ true=True
false=False
unknown=Unknown
save=Save
+saveToBrowser=Save to Browser
close=Close
filesSelected=files selected
noFavourites=No favorites added
+downloadComplete=Download Complete
bored=Bored Waiting?
alphabet=Alphabet
downloadPdf=Download PDF
@@ -52,16 +54,34 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
+invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
+deleteCurrentUserMessage=Cannot delete currently logged in user.
+deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
+downgradeCurrentUserMessage=Cannot downgrade current user's role
+downgradeCurrentUserLongMessage=Cannot downgrade current user's role. Hence, current user will not be shown.
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
+pipeline.header=Pipeline Menu (Beta)
pipeline.uploadButton=Upload Custom
pipeline.configureButton=Configure
pipeline.defaultOption=Custom
pipeline.submitButton=Submit
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
######################
# Pipeline Options #
@@ -94,6 +114,7 @@ navbar.settings=Settings
#############
settings.title=Settings
settings.update=Update available
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=App Version:
settings.downloadOption.title=Choose download option (For single file non zip downloads):
settings.downloadOption.1=Open in same window
@@ -102,12 +123,13 @@ settings.downloadOption.3=Download file
settings.zipThreshold=Zip files when the number of downloaded files exceeds
settings.signOut=Sign Out
settings.accountSettings=Account Settings
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=Change Credentials
changeCreds.header=Update Your Account Details
-changeCreds.changeUserAndPassword=You are using default login credentials. Please enter a new password (and username if wanted)
+changeCreds.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=New Username
changeCreds.oldPassword=Current Password
changeCreds.newPassword=New Password
@@ -142,14 +164,18 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
adminUserSettings.actions=Actions
adminUserSettings.apiUser=Limited API User
+adminUserSettings.extraApiUser=Additional 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.internalApiUser=Internal API User
+adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User
+adminUserSettings.changeUserRole=Change User's Role
#############
# HOME-PAGE #
@@ -392,6 +418,15 @@ home.AddStampRequest.desc=Add text or add image stamps at set locations
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Sign in
+login.header=Sign in
login.signin=Sign in
login.rememberme=Remember me
login.invalid=Invalid username or password.
login.locked=Your account has been locked.
login.signinTitle=Please sign in
+login.ssoSignIn=Login via Single Sign-on
+login.oauth2AutoCreateDisabled=OAUTH2 Auto-Create User Disabled
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Convert To Single Page
pageExtracter.title=Extract Pages
pageExtracter.header=Extract Pages
pageExtracter.submit=Extract
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -623,6 +662,18 @@ compare.document.1=Document 1
compare.document.2=Document 2
compare.submit=Compare
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
#sign
sign.title=Sign
@@ -643,6 +694,7 @@ repair.submit=Repair
#flatten
flatten.title=Flatten
flatten.header=Flatten PDFs
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Flatten
@@ -726,11 +778,23 @@ merge.submit=Merge
pdfOrganiser.title=Page Organizer
pdfOrganiser.header=PDF Page Organizer
pdfOrganiser.submit=Rearrange Pages
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=PDF Multi Tool
multiTool.header=PDF Multi Tool
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
viewPdf.title=View PDF
@@ -741,6 +805,7 @@ pageRemover.title=Page Remover
pageRemover.header=PDF Page remover
pageRemover.pagesToDelete=Pages to delete (Enter a comma-separated list of page numbers) :
pageRemover.submit=Delete Pages
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Select rotation angle (in multiples of 90 degrees):
rotate.submit=Rotate
-#merge
+#split-pdfs
split.title=Split PDF
split.header=Split PDF
split.desc.1=The numbers you select are the page number you wish to do a split on
-split.desc.2=As such selecting 1,3,7-8 would split a 10 page document into 6 separate PDFS with:
+split.desc.2=As such selecting 1,3,7-9 would split a 10 page document into 6 separate PDFS with:
split.desc.3=Document #1: Page 1
split.desc.4=Document #2: Page 2 and 3
-split.desc.5=Document #3: Page 4, 5 and 6
-split.desc.6=Document #4: Page 7
-split.desc.7=Document #5: Page 8
-split.desc.8=Document #6: Page 9 and 10
+split.desc.5=Document #3: Page 4, 5, 6, 7
+split.desc.6=Document #4: Page 8
+split.desc.7=Document #5: Page 9
+split.desc.8=Document #6: Page 10
split.splitPages=Enter pages to split on:
split.submit=Split
@@ -828,6 +893,8 @@ watermark.selectText.7=Opacity (0% - 100%):
watermark.selectText.8=Watermark Type:
watermark.selectText.9=Watermark Image:
watermark.submit=Add Watermark
+watermark.type.1=Text
+watermark.type.2=Image
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF To PDF/A
pdfToPDFA.header=PDF To PDF/A
pdfToPDFA.credit=This service uses OCRmyPDF for PDF/A conversion
pdfToPDFA.submit=Convert
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Convert
#PDFToHTML
PDFToHTML.title=PDF to HTML
PDFToHTML.header=PDF to HTML
-PDFToHTML.credit=This service uses LibreOffice for file conversion.
+PDFToHTML.credit=This service uses pdftohtml for file conversion.
PDFToHTML.submit=Convert
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Choose page to extract table
PDFToCSV.submit=Extract
#split-by-size-or-count
+split-by-size-or-count.title=Split PDF 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
@@ -959,6 +1029,15 @@ 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
+split-by-sections.merge=Merge Into One PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Version
licenses.license=License
+# error
+error.sorry=Sorry for the issue!
+error.needHelp=Need help / Found an issue?
+error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
+error.404.head=404 - Page Not Found | Oops, we tripped in the code!
+error.404.1=We can't seem to find the page you're looking for.
+error.404.2=Something went wrong
+error.github=Submit a ticket on GitHub
+error.showStack=Show Stack Trace
+error.copyStack=Copy Stack Trace
+error.githubSubmit=GitHub - Submit a ticket
+error.discordSubmit=Discord - Submit Support post
+
diff --git a/src/main/resources/messages_es_ES.properties b/src/main/resources/messages_es_ES.properties
index 43061780..275bf1d1 100644
--- a/src/main/resources/messages_es_ES.properties
+++ b/src/main/resources/messages_es_ES.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -11,15 +11,17 @@ imgPrompt=Seleccionar Imagen(es)
genericSubmit=Enviar
processTimeWarning=Advertencia: este proceso puede tardar hasta un minuto dependiendo del tamaño del archivo
pageOrderPrompt=Orden de páginas (Introduzca una lista de números de página separados por coma):
-pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
+pageSelectionPrompt=Selección de página personalizada (Intruduzca una lista de números de página separados por comas 1,5,6 o funciones como 2n+1) :
goToPage=Ir a
true=Verdadero
false=Falso
unknown=Desconocido
save=Guardar
+saveToBrowser=Guardar en el Navegador
close=Cerrar
filesSelected=archivos seleccionados
noFavourites=No se agregaron favoritos
+downloadComplete=Descarga finalizada
bored=¿Cansado de esperar?
alphabet=Alfabeto
downloadPdf=Descargar PDF
@@ -52,27 +54,45 @@ notAuthenticatedMessage=Usuario no autentificado.
userNotFoundMessage=Usuario no encontrado.
incorrectPasswordMessage=La contraseña actual no es correcta.
usernameExistsMessage=El nuevo nombre de usuario está en uso.
+invalidUsernameMessage=Nombre de usuario no válido, El nombre de ususario debe contener únicamente números y caracteres alfabéticos.
+deleteCurrentUserMessage=No puede eliminar el usuario que tiene la sesión actualmente en uso.
+deleteUsernameExistsMessage=El usuario no existe y no puede eliminarse.
+downgradeCurrentUserMessage=No se puede degradar el rol del usuario actual
+downgradeCurrentUserLongMessage=No se puede degradar el rol del usuario actual. Por lo tanto, el usuario actual no se mostrará.
+error=Error
+oops=Ups!
+help=Help
+goHomepage=Ir a la página principal
+joinDiscord=Únase a nuestro servidor Discord
+seeDockerHub=Ver Docker Hub
+visitGithub=Visitar Repositorio de Github
+donate=Donar
+color=Color
+sponsor=Patrocinador
+
###############
# Pipeline #
###############
-pipeline.header=Menu Pipeline (Alfa)
+pipeline.header=Menú de canalización (Alfa)
pipeline.uploadButton=Cargar personalización
pipeline.configureButton=Configurar
pipeline.defaultOption=Personalizar
pipeline.submitButton=Enviar
+pipeline.help=Ayuda de Canalización
+pipeline.scanHelp=Ayuda de escaneado de carpetas
######################
# Pipeline Options #
######################
-pipelineOptions.header=Configuración Pipeline
-pipelineOptions.pipelineNameLabel=Nombre del Pipeline
-pipelineOptions.saveSettings=Guardar configuración de la oiperación
-pipelineOptions.pipelineNamePrompt=Introduzca aquí el nombre del pipeline
+pipelineOptions.header=Configuración de la canalización
+pipelineOptions.pipelineNameLabel=Nombre de la canalización
+pipelineOptions.saveSettings=Guardar configuración de la canalización
+pipelineOptions.pipelineNamePrompt=Introduzca aquí el nombre de la canalización
pipelineOptions.selectOperation=Seleccione la operación
pipelineOptions.addOperationButton=Añadir operación
-pipelineOptions.pipelineHeader=Pipeline:
+pipelineOptions.pipelineHeader=Canalización:
pipelineOptions.saveButton=Descargar
pipelineOptions.validateButton=Validar
@@ -94,6 +114,7 @@ navbar.settings=Configuración
#############
settings.title=Configuración
settings.update=Actualización disponible
+settings.updateAvailable={0} es la versión instalada. Hay disponible una versión nueva ({1}).
settings.appVersion=Versión de la aplicación:
settings.downloadOption.title=Elegir la opción de descarga (para descargas de un solo archivo sin ZIP):
settings.downloadOption.1=Abrir en la misma ventana
@@ -102,12 +123,13 @@ settings.downloadOption.3=Descargar el archivo
settings.zipThreshold=Archivos ZIP cuando excede el número de archivos descargados
settings.signOut=Desconectar
settings.accountSettings=Configuración de la cuenta
-
-
+settings.bored.help=Habilita el juego del huevo de pascua
+settings.cacheInputs.name=Guardar entradas del formulario
+settings.cacheInputs.help=Habilitar guardar entradas previamente utilizadas para futuras acciones
changeCreds.title=Cambiar Credenciales
changeCreds.header=Actualice los detalles de su cuenta
-changeCreds.changeUserAndPassword=Está usando las credenciales por defecto. Por favor, introduzca una nueva contraseña (y usuario si lo desea)
+changeCreds.changePassword=Está usando las credenciales de inicio de sesión por defecto. Por favor, introduzca una contraseña nueva
changeCreds.newUsername=Nuevo usuario
changeCreds.oldPassword=Contraseña actual
changeCreds.newPassword=Nueva contraseña
@@ -142,14 +164,18 @@ adminUserSettings.header=Configuración de control de usuario administrador
adminUserSettings.admin=Administrador
adminUserSettings.user=Usuario
adminUserSettings.addUser=Añadir Nuevo Usuario
+adminUserSettings.usernameInfo=El nombrede usuario debe contener únicamente letras y números, no espacios ni caracteres especiales.
adminUserSettings.roles=Roles
adminUserSettings.role=Rol
adminUserSettings.actions=Acciones
adminUserSettings.apiUser=Usuario limitado de API
+adminUserSettings.extraApiUser=Otro usuario limitado de API
adminUserSettings.webOnlyUser=Usuario solo web
-adminUserSettings.demoUser=Demo User (No custom settings)
+adminUserSettings.demoUser=Usuario Demo (Sin ajustes personalizados)
+adminUserSettings.internalApiUser=Usuario interno de API
adminUserSettings.forceChange=Forzar usuario a cambiar usuario/contraseña en el acceso
adminUserSettings.submit=Guardar Usuario
+adminUserSettings.changeUserRole=Cambiar rol de usuario
#############
# HOME-PAGE #
@@ -224,7 +250,7 @@ compressPdfs.tags=aplastar,pequeño,diminuto
home.changeMetadata.title=Cambiar metadatos
home.changeMetadata.desc=Cambiar/Eliminar/Añadir metadatos al documento PDF
-changeMetadata.tags==Título,autor,fecha,creación,hora,editorial,productor,estadísticas
+changeMetadata.tags=título,autor,fecha,creación,hora,editorial,productor,estadísticas
home.fileToPDF.title=Convertir archivo a PDF
home.fileToPDF.desc=Convertir casi cualquier archivo a PDF (DOCX, PNG, XLS, PPT, TXT y más)
@@ -367,7 +393,7 @@ showJS.tags=JS
home.autoRedact.title=Auto Redactar
home.autoRedact.desc=Redactar automáticamente (ocultar) texto en un PDF según el texto introducido
-autoRedact.tags=Redact,Hide,black out,black,marker,hidden
+autoRedact.tags=Redactar,Ocultar,ocultar,negro,subrayador,oculto
home.tableExtraxt.title=PDF a CSV
home.tableExtraxt.desc=Extraer Tablas de un PDF convirtiéndolas a CSV
@@ -387,9 +413,18 @@ home.split-by-sections.title=Dividir PDF por Secciones
home.split-by-sections.desc=Dividir cada página de un PDF en secciones verticales y horizontales más pequeñas
split-by-sections.tags=Dividir sección, Dividir, Personalizar
-home.AddStampRequest.title=Add Stamp to PDF
-home.AddStampRequest.desc=Add text or add image stamps at set locations
-AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.AddStampRequest.title=Añadir Sello a PDF
+home.AddStampRequest.desc=Añadir texto o sello de imagen en ubicaciones específicas
+AddStampRequest.tags=Sello, Añadir imagen, centrar imagen, Marca de agua, PDF, Incrustar, Personalizar
+
+
+home.PDFToBook.title=PDF a Libro
+home.PDFToBook.desc=Convierte PDF a formatos de Libro/Cómic usando Calibre
+PDFToBook.tags=Libro,Cómic,Calibre,Convertir,Manga,Amazon,Kindle
+
+home.BookToPDF.title=Libro a PDF
+home.BookToPDF.desc=Convierte formatos de Libro/Cómic a PDF usando Calibre
+BookToPDF.tags=Libro,Cómic,Calibre,Convertir,manga,Amazon,Kindle
###########################
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Iniciar sesión
+login.header=Iniciar sesión
login.signin=Iniciar sesión
login.rememberme=Recordarme
login.invalid=Nombre de usuario o contraseña erróneos.
login.locked=Su cuenta se ha bloqueado.
login.signinTitle=Por favor, inicie sesión
+login.ssoSignIn=Iniciar sesión a través del inicio de sesión único
+login.oauth2AutoCreateDisabled=Usuario DE creación automática de OAUTH2 DESACTIVADO
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Convertir a página única
pageExtracter.title=Extraer Páginas
pageExtracter.header=Extraer Páginas
pageExtracter.submit=Extraer
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -563,7 +602,7 @@ autoSplitPDF.submit=Entregar
#pipeline
-pipeline.title=Pipeline
+pipeline.title=Canalización
#pageLayout
@@ -623,6 +662,18 @@ compare.document.1=Documento 1
compare.document.2=Documento 2
compare.submit=Comparar
+#BookToPDF
+BookToPDF.title=Libros y Cómics a PDF
+BookToPDF.header=Libro a PDF
+BookToPDF.credit=Usa Calibre
+BookToPDF.submit=Convertir
+
+#PDFToBook
+PDFToBook.title=PDF a Libro
+PDFToBook.header=PDF a Libro
+PDFToBook.selectText.1=Formato
+PDFToBook.credit=Utiliza Calibre
+PDFToBook.submit=Convertir
#sign
sign.title=Firmar
@@ -643,6 +694,7 @@ repair.submit=Reparar
#flatten
flatten.title=Aplanar
flatten.header=Acoplar archivos PDF
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Aplanar
@@ -726,11 +778,23 @@ merge.submit=Unir
pdfOrganiser.title=Organizador de páginas
pdfOrganiser.header=Organizador de páginas PDF
pdfOrganiser.submit=Organizar páginas
+pdfOrganiser.mode=Modo
+pdfOrganiser.mode.1=Orden de páginas personalizado
+pdfOrganiser.mode.2=Orden inverso
+pdfOrganiser.mode.3=Ordenar dúplex
+pdfOrganiser.mode.4=Ordenar folleto
+pdfOrganiser.mode.5=Orden de folleto de encuadernado lateral
+pdfOrganiser.mode.6=División par-impar
+pdfOrganiser.mode.7=Quitar primera
+pdfOrganiser.mode.8=Quitar última
+pdfOrganiser.mode.9=Quitar primera y última
+pdfOrganiser.placeholder=(por ej., 1,3,2 o 4-8,2,10-12 o 2n-1)
#multiTool
multiTool.title=Multi-herramienta PDF
multiTool.header=Multi-herramienta PDF
+multiTool.uploadPrompts=Por favor, cargue PDF
#view pdf
viewPdf.title=Ver PDF
@@ -741,6 +805,7 @@ pageRemover.title=Eliminador de páginas
pageRemover.header=Eliminador de páginas PDF
pageRemover.pagesToDelete=Páginas a eliminar (introducir una lista de números de página separados por coma):
pageRemover.submit=Eliminar Páginas
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Seleccionar ángulo de rotación (en múltiplos de 90 grados)
rotate.submit=Rotar
-#merge
+#split-pdfs
split.title=Dividir PDF
split.header=Dividir PDF
split.desc.1=Los números que seleccione son el número de página en el que desea hacer una división
-split.desc.2=Como tal, seleccionar 1,3,7-8 dividiría un documento de 10 páginas en 6 archivos PDF separados con:
+split.desc.2=Como tal, seleccionar 1,3,7-9 dividiría un documento de 10 páginas en 6 archivos PDF separados con:
split.desc.3=Documento #1: Página 1
split.desc.4=Documento #2: Páginas 2 y 3
-split.desc.5=Documento #3: Páginas 4, 5 y 6
-split.desc.6=Documento #4: Página 7
-split.desc.7=Documento #5: Página 8
-split.desc.8=Documento #6: Páginas 9 y 10
+split.desc.5=Documento #3: Páginas 4, 5, 6 y 7
+split.desc.6=Documento #4: Página 8
+split.desc.7=Documento #5: Página 9
+split.desc.8=Documento #6: Páginas 10
split.splitPages=Introducir las páginas para dividir:
split.submit=Dividir
@@ -828,6 +893,8 @@ watermark.selectText.7=Opacidad (0% - 100%):
watermark.selectText.8=Tipo de marca de agua:
watermark.selectText.9=Imagen de marca de agua:
watermark.submit=Añadir marca de agua
+watermark.type.1=Texto
+watermark.type.2=Imagen
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF a PDF/A
pdfToPDFA.header=PDF a PDF/A
pdfToPDFA.credit=Este servicio usa OCRmyPDF para la conversión a PDF/A
pdfToPDFA.submit=Convertir
+pdfToPDFA.tip=Actualmente no funciona para múltiples entrada a la vez
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Convertir
#PDFToHTML
PDFToHTML.title=PDF a HTML
PDFToHTML.header=PDF a HTML
-PDFToHTML.credit=Este servicio utiliza LibreOffice para la conversión de archivos
+PDFToHTML.credit=Este servicio utiliza pdftohtml para la conversión de archivos
PDFToHTML.submit=Convertir
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Elija una página para extraer la tabla
PDFToCSV.submit=Extraer
#split-by-size-or-count
+split-by-size-or-count.title=Split PDF by Size or Count
split-by-size-or-count.header=Dividir PDF por tamaño o número
split-by-size-or-count.type.label=Seleccionar tipo de división
split-by-size-or-count.type.size=Por tamaño
@@ -959,6 +1029,15 @@ 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
+split-by-sections.merge=Unir en Un PDF
+
+
+#printFile
+printFile.title=Imprimir archivo
+printFile.header=Imprimir archivo en la impresora
+printFile.selectText.1=Seleccionar archivo para imprimir
+printFile.selectText.2=Introducir nombre de la impresora
+printFile.submit=Imprimir
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Versión
licenses.license=Licencia
+# error
+error.sorry=¡Perdón por el fallo!
+error.needHelp=Necesita ayuda / Encontró un fallo?
+error.contactTip=Si sigue experimentando errores, no dude en contactarnos para solicitar soporte. Puede enviarnos un ticket en la página de GitHub o contactarnos mediante Discord:
+error.404.head=404 - Página no encontrada | Ups, tropezamos con el código!
+error.404.1=Parece que no podemos encontrar la página que está buscando.
+error.404.2=Algo salió mal
+error.github=Envíe un ticket en GitHub
+error.showStack=Mostrar seguimiento de pila
+error.copyStack=Mostrar seguimiento de pila
+error.githubSubmit=GitHub - Enviar un ticket
+error.discordSubmit=Discord - Enviar mensaje de soporte
+
diff --git a/src/main/resources/messages_eu_ES.properties b/src/main/resources/messages_eu_ES.properties
index 21767b94..c9337e03 100644
--- a/src/main/resources/messages_eu_ES.properties
+++ b/src/main/resources/messages_eu_ES.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -17,9 +17,11 @@ true=Egiazkoa
false=Faltsua
unknown=Ezezaguna
save=Gorde
+saveToBrowser=Save to Browser
close=Itxi
filesSelected=Hautatutako fitxategiak
noFavourites=Ez dira gogokoak gehitu
+downloadComplete=Download Complete
bored=Itxaroten aspertuta?
alphabet=Alfabetoa
downloadPdf=PDFa deskargatu
@@ -52,16 +54,34 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
+invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
+deleteCurrentUserMessage=Cannot delete currently logged in user.
+deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
+downgradeCurrentUserMessage=Ezin da uneko erabiltzailearen rola jaitsi
+downgradeCurrentUserLongMessage=Ezin da uneko erabiltzailearen rola jaitsi. Beraz, oraingo erabiltzailea ez da erakutsiko.
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
+pipeline.header=Pipeline Menu (Beta)
pipeline.uploadButton=Upload Custom
pipeline.configureButton=Configure
pipeline.defaultOption=Custom
pipeline.submitButton=Submit
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
######################
# Pipeline Options #
@@ -94,6 +114,7 @@ navbar.settings=Ezarpenak
#############
settings.title=Ezarpenak
settings.update=Eguneratze eskuragarria
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=Aplikazioaren bertsioa:
settings.downloadOption.title=Hautatu deskargatzeko aukera (fitxategi bakarra deskargatzeko ZIP gabe):
settings.downloadOption.1=Ireki leiho berean
@@ -102,12 +123,13 @@ settings.downloadOption.3=Deskargatu fitxategia
settings.zipThreshold=ZIP fitxategiak deskargatutako fitxategi kopurua gainditzen denean
settings.signOut=Saioa itxi
settings.accountSettings=Kontuaren ezarpenak
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=Change Credentials
changeCreds.header=Update Your Account Details
-changeCreds.changeUserAndPassword=You are using default login credentials. Please enter a new password (and username if wanted)
+changeCreds.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=New Username
changeCreds.oldPassword=Current Password
changeCreds.newPassword=New Password
@@ -142,14 +164,18 @@ adminUserSettings.header=Admin Erabiltzailearen Ezarpenen Kontrolak
adminUserSettings.admin=Admin
adminUserSettings.user=Erabiltzaile
adminUserSettings.addUser=Erabiltzaile berria
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.roles=Rolak
adminUserSettings.role=Rol
adminUserSettings.actions=Ekintzak
adminUserSettings.apiUser=APIren erabiltzaile mugatua
+adminUserSettings.extraApiUser=Additional Limited API User
adminUserSettings.webOnlyUser=Web-erabiltzailea bakarrik
adminUserSettings.demoUser=Demo User (No custom settings)
-adminUserSettings.forceChange=Force user to change username/password on login
+adminUserSettings.internalApiUser=Internal API User
+adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Gorde Erabiltzailea
+adminUserSettings.changeUserRole=Erabiltzailearen rola aldatu
#############
# HOME-PAGE #
@@ -392,6 +418,15 @@ home.AddStampRequest.desc=Add text or add image stamps at set locations
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Saioa hasi
+login.header=Saioa hasi
login.signin=Saioa hasi
login.rememberme=Oroitu nazazu
login.invalid=Okerreko erabiltzaile izena edo pasahitza.
login.locked=Zure kontua blokeatu egin da.
login.signinTitle=Mesedez, hasi saioa
+login.ssoSignIn=Hasi saioa Saioa hasteko modu bakarraren bidez
+login.oauth2AutoCreateDisabled=OAUTH2 Sortu automatikoki erabiltzailea desgaituta dago
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Orrialde bakarrera bihurtu
pageExtracter.title=Atera orriak
pageExtracter.header=Atera orriak
pageExtracter.submit=Atera
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -623,6 +662,18 @@ compare.document.1=1. dokumentua
compare.document.2=2. dokumentua
compare.submit=Konparatu
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
#sign
sign.title=Sinatu
@@ -643,6 +694,7 @@ repair.submit=Konpondu
#flatten
flatten.title=Lautu
flatten.header=Akoplatu PDF fitxategiak
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Lautu
@@ -726,11 +778,23 @@ merge.submit=Elkartu
pdfOrganiser.title=Orrialdeen antolatzailea
pdfOrganiser.header=PDF orrialdeen antolatzailea
pdfOrganiser.submit=Antolatu orrialdeak
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=PDF erabilera anitzeko tresna
multiTool.header=PDF erabilera anitzeko tresna
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
viewPdf.title=View PDF
@@ -741,6 +805,7 @@ pageRemover.title=Orrialdeen ezabatzailea
pageRemover.header=PDF orrialdeen ezabatzailea
pageRemover.pagesToDelete=Ezabatu beharreko orrialdeak (sartu komaz bereizitako orrialde-zenbakien zerrenda):
pageRemover.submit=Ezabatu orrialdeak
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Hautatu errotazio-angelua (90 graduko multiploetan):
rotate.submit=Biratu
-#merge
+#split-pdfs
split.title=Zatitu PDFa
split.header=Zatitu PDFa
split.desc.1=Hautatzen dituzun zenbakiak zatiketa egin nahi duzun orrialde-zenbakiak dira
-split.desc.2=Beraz, 1,3,7-8 hautatzean 10 orrialdeko dokumentua zatituko luke 6 PDF fitxategi bereizituetan
+split.desc.2=Beraz, 1,3,7-9 hautatzean 10 orrialdeko dokumentua zatituko luke 6 PDF fitxategi bereizituetan
split.desc.3=#1 Dokumentua: 1. orrialdea
split.desc.4=#2 Dokumentua: 2. eta 3. orrialdeak
-split.desc.5=#3 Dokumentua: 4., 5. eta 6. orrialdeak
-split.desc.6=#4 Dokumentua: 7. orrialdea
-split.desc.7=#5 Dokumentua: 8. orrialdea
-split.desc.8=#6 Dokumentua: 9. eta 10. orrialdeak
+split.desc.5=#3 Dokumentua: 4., 5., 6. eta 7. orrialdeak
+split.desc.6=#4 Dokumentua: 8. orrialdea
+split.desc.7=#5 Dokumentua: 9. orrialdea
+split.desc.8=#6 Dokumentua: 10. orrialdeak
split.splitPages=Sartu orrialdeak zatitzeko:
split.submit=Zatitu
@@ -828,6 +893,8 @@ watermark.selectText.7=Opakutasuna (0% - 100%):
watermark.selectText.8=Watermark Type:
watermark.selectText.9=Watermark Image:
watermark.submit=Gehitu ur-marka
+watermark.type.1=Text
+watermark.type.2=Image
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDFa PDF/A bihurtu
pdfToPDFA.header=PDFa PDF/A bihurtu
pdfToPDFA.credit=Zerbitzu honek OCRmyPDF erabiltzen du PDFak PDF/A bihurtzeko
pdfToPDFA.submit=Bihurtu
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Bihurtu
#PDFToHTML
PDFToHTML.title=PDFa HTML bihurtu
PDFToHTML.header=PDFa HTML bihurtu
-PDFToHTML.credit=Zerbitzu honek LibreOffice erabiltzen du fitxategiak bihurtzeko
+PDFToHTML.credit=Zerbitzu honek pdftohtml erabiltzen du fitxategiak bihurtzeko
PDFToHTML.submit=Bihurtu
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Choose page to extract table
PDFToCSV.submit=Extracto
#split-by-size-or-count
+split-by-size-or-count.title=Split PDF 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
@@ -959,6 +1029,15 @@ 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
+split-by-sections.merge=Merge Into One PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Version
licenses.license=License
+# error
+error.sorry=Sorry for the issue!
+error.needHelp=Need help / Found an issue?
+error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
+error.404.head=404 - Page Not Found | Oops, we tripped in the code!
+error.404.1=We can't seem to find the page you're looking for.
+error.404.2=Something went wrong
+error.github=Submit a ticket on GitHub
+error.showStack=Show Stack Trace
+error.copyStack=Copy Stack Trace
+error.githubSubmit=GitHub - Submit a ticket
+error.discordSubmit=Discord - Submit Support post
+
diff --git a/src/main/resources/messages_fr_FR.properties b/src/main/resources/messages_fr_FR.properties
index 7bda2156..06068ffc 100644
--- a/src/main/resources/messages_fr_FR.properties
+++ b/src/main/resources/messages_fr_FR.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -9,18 +9,20 @@ multiPdfPrompt=Sélectionnez les PDF
multiPdfDropPrompt=Sélectionnez (ou glissez-déposez) tous les PDF dont vous avez besoin
imgPrompt=Choisir une image
genericSubmit=Envoyer
-processTimeWarning=Attention, ce processus peut prendre jusqu\u2019à une minute en fonction de la taille du fichier.
-pageOrderPrompt=Ordre des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1)\u00a0:
-pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
+processTimeWarning=Attention, ce processus peut prendre jusqu’à une minute en fonction de la taille du fichier.
+pageOrderPrompt=Ordre des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1) :
+pageSelectionPrompt=Sélection des pages (entrez une liste de numéros de page séparés par des virgules ou des fonctions telles que 2n+1) :
goToPage=Aller
true=Vrai
false=Faux
unknown=Inconnu
save=Enregistrer
+saveToBrowser=Save to Browser
close=Fermer
filesSelected=fichiers sélectionnés
noFavourites=Aucun favori ajouté
-bored=Ennuyé d\u2019attendre\u00a0?
+downloadComplete=Téléchargement terminé
+bored=Ennuyé d’attendre ?
alphabet=Alphabet
downloadPdf=Télécharger le PDF
text=Texte
@@ -31,9 +33,9 @@ sizes.small=Petit
sizes.medium=Moyen
sizes.large=Grand
sizes.x-large=Très grand
-error.pdfPassword=Le document PDF est protégé par un mot de passe et le mot de passe n\u2019a pas été fourni ou était incorrect
+error.pdfPassword=Le document PDF est protégé par un mot de passe et le mot de passe n’a pas été fourni ou était incorrect
delete=Supprimer
-username=Nom d\u2019utilisateur
+username=Nom d’utilisateur
password=Mot de passe
welcome=Bienvenue
property=Propriété
@@ -42,39 +44,57 @@ white=Blanc
red=Rouge
green=Vert
blue=Bleu
-custom=Personnalisé\u2026
-WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
-poweredBy=Powered by
-yes=Yes
-no=No
-changedCredsMessage=Les identifiants ont été mis à jour\u00a0!
+custom=Personnalisé…
+WorkInProgess=En cours de développement, merci de nous remonter les problèmes que vous pourriez constater!
+poweredBy=Propulsé par
+yes=Oui
+no=Non
+changedCredsMessage=Les identifiants ont été mis à jour !
notAuthenticatedMessage=Utilisateur non authentifié.
userNotFoundMessage=Utilisateur non trouvé.
incorrectPasswordMessage=Le mot de passe actuel est incorrect.
-usernameExistsMessage=Le nouveau nom d\u2019utilisateur existe déjà.
+usernameExistsMessage=Le nouveau nom d’utilisateur existe déjà.
+invalidUsernameMessage=Nom d’utilisateur invalide, le nom d’utilisateur ne peut contenir que des chiffres et des lettres.
+deleteCurrentUserMessage=Impossible de supprimer l’utilisateur actuellement connecté.
+deleteUsernameExistsMessage=Le nom d’utilisateur n’existe pas et ne peut pas être supprimé.
+downgradeCurrentUserMessage=Impossible de rétrograder le rôle de l'utilisateur actuel
+downgradeCurrentUserLongMessage=Impossible de rétrograder le rôle de l'utilisateur actuel. Par conséquent, l'utilisateur actuel ne sera pas affiché.
+error=Erreur
+oops=Oups !
+help=Aide
+goHomepage=Aller à la page d’accueil
+joinDiscord=Rejoignez notre serveur Discord
+seeDockerHub=Consulter le Docker Hub
+visitGithub=Visiter le dépôt Github
+donate=Faire un don
+color=Couleur
+sponsor=Sponsor
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
-pipeline.uploadButton=Upload Custom
-pipeline.configureButton=Configure
-pipeline.defaultOption=Custom
-pipeline.submitButton=Submit
+pipeline.header=Menu Pipeline (Alpha)
+pipeline.uploadButton=Charger une personnalisation
+pipeline.configureButton=Configurer
+pipeline.defaultOption=Personnaliser
+pipeline.submitButton=Soumettre
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
######################
# 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.header=Configuration du pipeline
+pipelineOptions.pipelineNameLabel=Nom du pipeline
+pipelineOptions.saveSettings=Sauvegarder la configuration
+pipelineOptions.pipelineNamePrompt=Entrez ici le nom du pipeline
+pipelineOptions.selectOperation=Sélectionner une opération
+pipelineOptions.addOperationButton=Ajouter une opération
pipelineOptions.pipelineHeader=Pipeline:
-pipelineOptions.saveButton=Download
-pipelineOptions.validateButton=Validate
+pipelineOptions.saveButton=Télécharger
+pipelineOptions.validateButton=Valider
@@ -94,21 +114,23 @@ navbar.settings=Paramètres
#############
settings.title=Paramètres
settings.update=Mise à jour disponible
-settings.appVersion=Version de l\u2019application\u00a0:
-settings.downloadOption.title=Choisissez l\u2019option de téléchargement (pour les téléchargements à fichier unique non ZIP)\u00a0:
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
+settings.appVersion=Version de l’application :
+settings.downloadOption.title=Choisissez l’option de téléchargement (pour les téléchargements à fichier unique non ZIP) :
settings.downloadOption.1=Ouvrir dans la même fenêtre
settings.downloadOption.2=Ouvrir dans une nouvelle fenêtre
settings.downloadOption.3=Télécharger le fichier
settings.zipThreshold=Compresser les fichiers en ZIP lorsque le nombre de fichiers téléchargés dépasse
settings.signOut=Déconnexion
settings.accountSettings=Paramètres du compte
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=Modifiez vos identifiants
changeCreds.header=Mettez à jour vos identifiants de connexion
-changeCreds.changeUserAndPassword=Vous utilisez les identifiants de connexion par défaut. Veuillez entrer un nouveau mot de passe (et nom d\u2019utilisateur si vous le souhaitez)
-changeCreds.newUsername=Nouveau nom d\u2019utilisateur
+changeCreds.changePassword=Vous utilisez les identifiants de connexion par défaut. Veuillez saisir un nouveau mot de passe
+changeCreds.newUsername=Nouveau nom d’utilisateur
changeCreds.oldPassword=Mot de passe actuel
changeCreds.newPassword=Nouveau mot de passe
changeCreds.confirmNewPassword=Confirmer le nouveau mot de passe
@@ -118,10 +140,10 @@ changeCreds.submit=Soumettre les modifications
account.title=Paramètres du compte
account.accountSettings=Paramètres du compte
-account.adminSettings=Paramètres d\u2019administration \u2013 Voir et ajouter des utilisateurs
+account.adminSettings=Paramètres d’administration – Voir et ajouter des utilisateurs
account.userControlSettings=Contrôle des paramètres des utilisateurs
-account.changeUsername=Modifier le nom d\u2019utilisateur
-account.newUsername=Nouveau nom d\u2019utilisateur
+account.changeUsername=Modifier le nom d’utilisateur
+account.newUsername=Nouveau nom d’utilisateur
account.password=Mot de passe de confirmation
account.oldPassword=Ancien mot de passe
account.newPassword=Nouveau mot de passe
@@ -133,8 +155,8 @@ account.syncTitle=Synchroniser les paramètres du navigateur avec le compte
account.settingsCompare=Comparaison des paramètres
account.property=Propriété
account.webBrowserSettings=Paramètres du navigateur
-account.syncToBrowser=Synchroniser\u00a0: Compte → Navigateur
-account.syncToAccount=Synchroniser\u00a0: Compte ← Navigateur
+account.syncToBrowser=Synchroniser : Compte → Navigateur
+account.syncToAccount=Synchroniser : Compte ← Navigateur
adminUserSettings.title=Administration des paramètres des utilisateurs
@@ -142,14 +164,18 @@ adminUserSettings.header=Administration des paramètres des utilisateurs
adminUserSettings.admin=Administateur
adminUserSettings.user=Utilisateur
adminUserSettings.addUser=Ajouter un utilisateur
+adminUserSettings.usernameInfo=Le nom d’utilisateur ne doit contenir que des lettres et des chiffres, sans espaces ni caractères spéciaux.
adminUserSettings.roles=Rôles
adminUserSettings.role=Rôle
adminUserSettings.actions=Actions
adminUserSettings.apiUser=Utilisateur API limité
+adminUserSettings.extraApiUser=Utilisateur limité supplémentaire de l’API
adminUserSettings.webOnlyUser=Utilisateur Web uniquement
-adminUserSettings.demoUser=Demo User (No custom settings)
-adminUserSettings.forceChange=Forcer l\u2019utilisateur à changer son nom d\u2019utilisateur/mot de passe lors de la connexion
+adminUserSettings.demoUser=Demo User (Paramètres par défaut)
+adminUserSettings.internalApiUser=Internal API User
+adminUserSettings.forceChange=Forcer l’utilisateur à changer son nom d’utilisateur/mot de passe lors de la connexion
adminUserSettings.submit=Ajouter
+adminUserSettings.changeUserRole=Changer le rôle de l'utilisateur
#############
# HOME-PAGE #
@@ -159,7 +185,7 @@ home.searchBar=Rechercher des fonctionnalités...
home.viewPdf.title=Visionner le PDF
-home.viewPdf.desc=Visionner, annoter, ajouter du texte ou des images
+home.viewPdf.desc=Visionner, annoter, ajouter du texte ou des images.
viewPdf.tags=visualiser,lire,annoter,texte,image
home.multiTool.title=Outil multifonction PDF
@@ -168,7 +194,7 @@ multiTool.tags=outil multifonction,opération multifonction,interface utilisateu
home.merge.title=Fusionner
home.merge.desc=Fusionnez facilement plusieurs PDF en un seul.
-merge.tags=fusionner,opérations sur les pages,backeend,server side,merge
+merge.tags=fusionner,opérations sur les pages,backend,server side,merge
home.split.title=Diviser
home.split.desc=Divisez un PDF en plusieurs documents.
@@ -188,7 +214,7 @@ home.pdfToImage.desc=Convertissez un PDF en image (PNG, JPEG, GIF).
pdfToImage.tags=conversion,img,jpg,image,photo
home.pdfOrganiser.title=Organiser
-home.pdfOrganiser.desc=Supprimez ou réorganisez les pages dans n\u2019importe quel ordre.
+home.pdfOrganiser.desc=Supprimez ou réorganisez les pages dans n’importe quel ordre.
pdfOrganiser.tags=organiser,recto-verso,duplex,even,odd,sort,move
@@ -198,7 +224,7 @@ addImage.tags=img,jpg,image,photo
home.watermark.title=Ajouter un filigrane
home.watermark.desc=Ajoutez un filigrane personnalisé à votre PDF.
-watermark.tags=texte,filigrane,label,propriété,droit d\u2019auteur,marque déposée,img,jpg,image,photo,copyright,trademark
+watermark.tags=texte,filigrane,label,propriété,droit d’auteur,marque déposée,img,jpg,image,photo,copyright,trademark
home.permissions.title=Modifier les permissions
home.permissions.desc=Modifiez les permissions de votre PDF.
@@ -227,16 +253,16 @@ home.changeMetadata.desc=Modifiez, supprimez ou ajoutez des métadonnées à un
changeMetadata.tags=métadonnées,titre,auteur,date,création,heure,éditeur,statistiques,title,author,date,creation,time,publisher,producer,stats,metadata
home.fileToPDF.title=Fichier en PDF
-home.fileToPDF.desc=Convertissez presque n\u2019importe quel fichiers en PDF (DOCX, PNG, XLS, PPT, TXT et plus).
+home.fileToPDF.desc=Convertissez presque n’importe quel fichiers en PDF (DOCX, PNG, XLS, PPT, TXT et plus).
fileToPDF.tags=convertion,transformation,format,document,image,slide,texte,conversion,office,docs,word,excel,powerpoint
home.ocr.title=OCR / Nettoyage des numérisations
-home.ocr.desc=Utilisez l\u2019OCR pour analyser et détecter le texte des images d\u2019un PDF et le rajouter en temps que tel.
+home.ocr.desc=Utilisez l’OCR pour analyser et détecter le texte des images d’un PDF et le rajouter en temps que tel.
ocr.tags=ocr,reconnaissance,texte,image,numérisation,scan,read,identify,detection,editable
home.extractImages.title=Extraire les images
-home.extractImages.desc=Extrayez toutes les images d\u2019un PDF et enregistrez-les dans un ZIP.
+home.extractImages.desc=Extrayez toutes les images d’un PDF et enregistrez-les dans un ZIP.
extractImages.tags=image,photo,save,archive,zip,capture,grab
home.pdfToPDFA.title=PDF en PDF/A
@@ -265,7 +291,7 @@ home.PDFToXML.desc=Convertissez un PDF au format XML.
PDFToXML.tags=xml,extraction de données,contenu structuré,interopérabilité,data-extraction,structured-content,interop,transformation,convert
home.ScannerImageSplit.title=Diviser les photos numérisées
-home.ScannerImageSplit.desc=Divisez plusieurs photos à partir d\u2019une photo ou d\u2019un PDF.
+home.ScannerImageSplit.desc=Divisez plusieurs photos à partir d’une photo ou d’un PDF.
ScannerImageSplit.tags=diviser,détecter automatiquement,numériser,separate,auto-detect,scans,multi-photo,organize
home.sign.title=Signer
@@ -273,7 +299,7 @@ home.sign.desc=Ajoutez une signature au PDF avec un dessin, du texte ou une imag
sign.tags=signer,authorize,initials,drawn-signature,text-sign,image-signature
home.flatten.title=Rendre inerte
-home.flatten.desc=Supprimez tous les éléments et formulaires interactifs d\u2019un PDF.
+home.flatten.desc=Supprimez tous les éléments et formulaires interactifs d’un PDF.
flatten.tags=inerte,static,deactivate,non-interactive,streamline
home.repair.title=Réparer
@@ -281,12 +307,12 @@ home.repair.desc=Essayez de réparer un PDF corrompu ou cassé.
repair.tags=réparer,restaurer,corriger,récupérer,fix,restore,correction,recover
home.removeBlanks.title=Supprimer les pages vierges
-home.removeBlanks.desc=Détectez et supprimez les pages vierges d\u2019un PDF.
+home.removeBlanks.desc=Détectez et supprimez les pages vierges d’un PDF.
removeBlanks.tags=pages vierges,supprimer,nettoyer,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.removeAnnotations.title=Supprimer les annotations
+home.removeAnnotations.desc=Supprimer tous les commentaires/annotations d’un PDF.
+removeAnnotations.tags=commentaires,supprimer,annotations,highlight,notes,markup,remove
home.compare.title=Comparer
home.compare.desc=Comparez et visualisez les différences entre deux PDF.
@@ -297,11 +323,11 @@ home.certSign.desc=Signez un PDF avec un certificat ou une clé (PEM/P12).
certSign.tags=signer,chiffrer,certificat,authenticate,PEM,P12,official,encrypt
home.pageLayout.title=Fusionner des pages
-home.pageLayout.desc=Fusionnez plusieurs pages d\u2019un PDF en une seule.
+home.pageLayout.desc=Fusionnez plusieurs pages d’un PDF en une seule.
pageLayout.tags=fusionner,merge,composite,single-view,organize
-home.scalePages.title=Ajuster l\u2019échelle ou la taille
-home.scalePages.desc=Modifiez la taille ou l\u2019échelle d\u2019une page et/ou de son contenu.
+home.scalePages.title=Ajuster l’échelle ou la taille
+home.scalePages.desc=Modifiez la taille ou l’échelle d’une page et/ou de son contenu.
scalePages.tags=ajuster,redimensionner,resize,modify,dimension,adapt
home.pipeline.title=Pipeline (avancé)
@@ -317,11 +343,11 @@ home.auto-rename.desc=Renommez automatiquement un fichier PDF en fonction de son
auto-rename.tags=renommer,détection automatique,réétiqueter,auto-detect,header-based,organize,relabel
home.adjust-contrast.title=Ajuster les couleurs
-home.adjust-contrast.desc=Ajustez le contraste, la saturation et la luminosité d\u2019un PDF.
+home.adjust-contrast.desc=Ajustez le contraste, la saturation et la luminosité d’un PDF.
adjust-contrast.tags=ajuster,couleurs,amélioration,color-correction,tune,modify,enhance
home.crop.title=Redimensionner
-home.crop.desc=Redimmensionnez un PDF pour réduire sa taille (en conservant le texte\u00a0!).
+home.crop.desc=Redimmensionnez un PDF pour réduire sa taille (en conservant le texte !).
crop.tags=redimensionner,trim,shrink,edit,shape
home.autoSplitPDF.title=Séparer automatiquement les pages
@@ -333,16 +359,16 @@ home.sanitizePdf.desc=Supprimez les scripts et autres éléments des PDF.
sanitizePdf.tags=assainir,sécurisé,clean,secure,safe,remove-threats
home.URLToPDF.title=URL en PDF
-home.URLToPDF.desc=Convertissez n\u2019importe quelle URL http(s) en PDF.
+home.URLToPDF.desc=Convertissez n’importe quelle URL http(s) en PDF.
URLToPDF.tags=pdf,contenu Web,save-page,web-to-doc,archive
home.HTMLToPDF.title=HTML en PDF
-home.HTMLToPDF.desc=Convertissez n\u2019importe quel fichier HTML ou ZIP en PDF.
+home.HTMLToPDF.desc=Convertissez n’importe quel fichier HTML ou ZIP en PDF.
HTMLToPDF.tags=html,markup,contenu Web,transformation,convert
home.MarkdownToPDF.title=Markdown en PDF
-home.MarkdownToPDF.desc=Convertissez n\u2019importe quel fichier Markdown en PDF.
+home.MarkdownToPDF.desc=Convertissez n’importe quel fichier Markdown en PDF.
MarkdownToPDF.tags=markdown,markup,contenu Web,transformation,convert
@@ -366,11 +392,11 @@ home.showJS.desc=Recherche et affiche tout JavaScript injecté dans un PDF.
showJS.tags=JS
home.autoRedact.title=Caviarder automatiquement
-home.autoRedact.desc=Caviardez automatiquement les informations sensibles d\u2019un PDF.
+home.autoRedact.desc=Caviardez automatiquement les informations sensibles d’un PDF.
autoRedact.tags=caviarder,redact,auto
home.tableExtraxt.title=PDF en CSV
-home.tableExtraxt.desc=Extrait les tableaux d\u2019un PDF et les transforme en CSV
+home.tableExtraxt.desc=Extrait les tableaux d’un PDF et les transforme en CSV.
tableExtraxt.tags=CSV,Table Extraction,extract,convert
@@ -380,16 +406,25 @@ autoSizeSplitPDF.tags=pdf,split,document,organization
home.overlay-pdfs.title=Incrustation de PDF
-home.overlay-pdfs.desc=Incrustation d\u2019un PDF sur un autre PDF
-overlay-pdfs.tags=Overlay
+home.overlay-pdfs.desc=Incrustation d’un PDF sur un autre PDF.
+overlay-pdfs.tags=Overlay,incrustation
-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
+home.split-by-sections.title=Séparer un PDF en sections
+home.split-by-sections.desc=Diviser chaque page d’un PDF en sections horizontales/verticales plus petites.
+split-by-sections.tags=Sections,Diviser,Section Split, Divide, Customize
-home.AddStampRequest.title=Add Stamp to PDF
-home.AddStampRequest.desc=Add text or add image stamps at set locations
-AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.AddStampRequest.title=Ajouter un tampon sur un PDF
+home.AddStampRequest.desc=Ajouter un texte ou l’image d’un tampon à un emplacement défini.
+AddStampRequest.tags=Tampon,Ajouter,Stamp,Add image,center image,Watermark,PDF,Embed,Customize
+
+
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
###########################
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Connexion
+login.header=Connexion
login.signin=Connexion
login.rememberme=Se souvenir de moi
-login.invalid=Nom d\u2019utilisateur ou mot de passe invalide.
+login.invalid=Nom d’utilisateur ou mot de passe invalide.
login.locked=Votre compte a été verrouillé.
login.signinTitle=Veuillez vous connecter
+login.ssoSignIn=Se connecter via l'authentification unique
+login.oauth2AutoCreateDisabled=OAUTH2 Création automatique d'utilisateur désactivée
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Convertir en une seule page
pageExtracter.title=Extraire des pages
pageExtracter.header=Extraire des pages
pageExtracter.submit=Extraire
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -467,37 +506,37 @@ HTMLToPDF.header=HTML en PDF
HTMLToPDF.help=Accepte les fichiers HTML et les ZIP contenant du HTML, du CSS, des images, etc. (requis).
HTMLToPDF.submit=Convertir
HTMLToPDF.credit=Utilise WeasyPrint.
-HTMLToPDF.zoom=Zoom level for displaying the website.
-HTMLToPDF.pageWidth=Width of the page in centimeters. (Blank to default)
-HTMLToPDF.pageHeight=Height of the page in centimeters. (Blank to default)
-HTMLToPDF.marginTop=Top margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginBottom=Bottom margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginLeft=Left margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginRight=Right margin of the page in millimeters. (Blank to default)
-HTMLToPDF.printBackground=Render the background of websites.
-HTMLToPDF.defaultHeader=Enable Default Header (Name and page number)
-HTMLToPDF.cssMediaType=Change the CSS media type of the page.
-HTMLToPDF.none=None
-HTMLToPDF.print=Print
-HTMLToPDF.screen=Screen
+HTMLToPDF.zoom=Niveau de zoom pour l’affichage du site web.
+HTMLToPDF.pageWidth=Largeur de la page en centimètres. (Vide par défaut)
+HTMLToPDF.pageHeight=Hauteur de la page en centimètres. (Vide par défaut)
+HTMLToPDF.marginTop=Marge supérieure de la page en millimètres. (Vide par défaut)
+HTMLToPDF.marginBottom=Marge inférieure de la page en millimètres. (Vide par défaut)
+HTMLToPDF.marginLeft=Marge gauche de la page en millimètres. (Vide par défaut)
+HTMLToPDF.marginRight=Marge droite de la page en millimètres. (Vide par défaut)
+HTMLToPDF.printBackground=Restituer l’image de fond des sites web.
+HTMLToPDF.defaultHeader=Activer l’entête par défaut (Nom et numéro de page)
+HTMLToPDF.cssMediaType=Modifier le type de média CSS de la page.
+HTMLToPDF.none=Aucun
+HTMLToPDF.print=Imprimer
+HTMLToPDF.screen=Écran
#AddStampRequest
-AddStampRequest.header=Stamp PDF
-AddStampRequest.title=Stamp PDF
-AddStampRequest.stampType=Stamp Type
-AddStampRequest.stampText=Stamp Text
-AddStampRequest.stampImage=Stamp Image
+AddStampRequest.header=Tampon PDF
+AddStampRequest.title=Tampon PDF
+AddStampRequest.stampType=Type de tampon
+AddStampRequest.stampText=Tampon texte
+AddStampRequest.stampImage=Tampon image
AddStampRequest.alphabet=Alphabet
-AddStampRequest.fontSize=Font/Image Size
+AddStampRequest.fontSize=Taille de fonte/image
AddStampRequest.rotation=Rotation
-AddStampRequest.opacity=Opacity
+AddStampRequest.opacity=Opacité
AddStampRequest.position=Position
-AddStampRequest.overrideX=Override X Coordinate
-AddStampRequest.overrideY=Override Y Coordinate
-AddStampRequest.customMargin=Custom Margin
-AddStampRequest.customColor=Custom Text Color
-AddStampRequest.submit=Submit
+AddStampRequest.overrideX=Définir coordonnées X
+AddStampRequest.overrideY=Définir coordonnées Y
+AddStampRequest.customMargin=Marge personnalisée
+AddStampRequest.customColor=Couleur de texte personnalisée
+AddStampRequest.submit=Soumettre
#sanitizePDF
@@ -553,9 +592,9 @@ autoSplitPDF.header=Séparer automatiquement les pages
autoSplitPDF.description=Imprimez, insérez, numérisez, téléchargez et laissez-nous séparer automatiquement vos documents. Aucun travail de tri manuel nécessaire.
autoSplitPDF.selectText.1=Imprimez des feuilles de séparation ci-dessous (le mode noir et blanc convient).
autoSplitPDF.selectText.2=Numérisez tous vos documents en une seule fois en insérant les feuilles intercalaires entre eux.
-autoSplitPDF.selectText.3=Téléchargez le fichier PDF numérisé et laissez Stirling PDF s\u2019occuper du reste.
+autoSplitPDF.selectText.3=Téléchargez le fichier PDF numérisé et laissez Stirling PDF s’occuper du reste.
autoSplitPDF.selectText.4=Les feuilles de séparation sont automatiquement détectées et supprimées, garantissant un document final soigné.
-autoSplitPDF.formPrompt=PDF contenant des feuilles de séparation de Stirling PDF\u00a0:
+autoSplitPDF.formPrompt=PDF contenant des feuilles de séparation de Stirling PDF :
autoSplitPDF.duplexMode=Mode recto-verso
autoSplitPDF.dividerDownload1=Auto Splitter Divider (minimal).pdf
autoSplitPDF.dividerDownload2=Auto Splitter Divider (with instructions).pdf
@@ -575,10 +614,10 @@ pageLayout.submit=Fusionner
#scalePages
-scalePages.title=Ajuster la taille ou l\u2019échelle
-scalePages.header=Ajuster la taille ou l\u2019échelle
-scalePages.pageSize=Taille d\u2019une page du document
-scalePages.scaleFactor=Niveau de zoom (recadrage) d\u2019une page
+scalePages.title=Ajuster la taille ou l’échelle
+scalePages.header=Ajuster la taille ou l’échelle
+scalePages.pageSize=Taille d’une page du document
+scalePages.scaleFactor=Niveau de zoom (recadrage) d’une page
scalePages.submit=Ajuster
@@ -586,11 +625,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.jksNote=Note: Si votre type de certificat n’est pas listé ci-dessous, merci de le convertir en fichier Java Keystore (.jks) en utilisant l’outil en ligne de commande keytool. Puis choisissez l’option Fichier .jks ci-dessous.
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.selectP12=Fichier keystore de clés PKCS#12 (.p12 ou .pfx) (facultatif, s’il n’est fourni, il doit contenir votre clé privée et votre certificat)
+certSign.selectJKS=Sélectionner votre fichier 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
@@ -604,16 +643,16 @@ certSign.submit=Signer
removeBlanks.title=Supprimer les pages vierges
removeBlanks.header=Supprimer les pages vierges
removeBlanks.threshold=Seuil de blancheur des pixels
-removeBlanks.thresholdDesc=Seuil pour déterminer à quel point un pixel blanc doit être blanc pour être classé comme «\u00a0blanc\u00a0» (0 = noir, 255 = blanc pur).
+removeBlanks.thresholdDesc=Seuil pour déterminer à quel point un pixel blanc doit être blanc pour être classé comme « blanc » (0 = noir, 255 = blanc pur).
removeBlanks.whitePercent=Pourcentage de blanc
removeBlanks.whitePercentDesc=Pourcentage de la page qui doit contenir des pixels « blancs » à supprimer.
removeBlanks.submit=Supprimer les pages vierges
#removeAnnotations
-removeAnnotations.title=Remove Annotations
-removeAnnotations.header=Remove Annotations
-removeAnnotations.submit=Remove
+removeAnnotations.title=Supprimer les annotations
+removeAnnotations.header=Supprimer les annotations
+removeAnnotations.submit=Supprimer
#compare
@@ -623,6 +662,18 @@ compare.document.1=Document 1
compare.document.2=Document 2
compare.submit=Comparer
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
#sign
sign.title=Signer
@@ -643,20 +694,21 @@ repair.submit=Réparer
#flatten
flatten.title=Rendre inerte
flatten.header=Rendre inerte
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Rendre inerte
#ScannerImageSplit
ScannerImageSplit.selectText.1=Seuil de rotation
-ScannerImageSplit.selectText.2=Définit l\u2019angle absolu minimum requis pour la rotation de l\u2019image (par défaut\u00a0: 10).
+ScannerImageSplit.selectText.2=Définit l’angle absolu minimum requis pour la rotation de l’image (par défaut : 10).
ScannerImageSplit.selectText.3=Tolérance
-ScannerImageSplit.selectText.4=Détermine la plage de variation de couleur autour de la couleur d\u2019arrière-plan estimée (par défaut\u00a0: 20).
+ScannerImageSplit.selectText.4=Détermine la plage de variation de couleur autour de la couleur d’arrière-plan estimée (par défaut : 20).
ScannerImageSplit.selectText.5=Surface minimale
-ScannerImageSplit.selectText.6=Définit la surface minimale pour une photo (par défaut\u00a0: 8\u202f000).
+ScannerImageSplit.selectText.6=Définit la surface minimale pour une photo (par défaut : 8 000).
ScannerImageSplit.selectText.7=Surface de contour minimale
-ScannerImageSplit.selectText.8=Définit la surface de contour minimale pour une photo (par défaut\u00a0: 500).
+ScannerImageSplit.selectText.8=Définit la surface de contour minimale pour une photo (par défaut : 500).
ScannerImageSplit.selectText.9=Taille de la bordure
-ScannerImageSplit.selectText.10=Définit la taille de la bordure ajoutée et supprimée pour éviter les bordures blanches dans la sortie (par défaut\u00a0: 1).
+ScannerImageSplit.selectText.10=Définit la taille de la bordure ajoutée et supprimée pour éviter les bordures blanches dans la sortie (par défaut : 1).
#OCR
@@ -665,24 +717,24 @@ ocr.header=OCR (Reconnaissance optique de caractères) / Nettoyage des numérisa
ocr.selectText.1=Langues à détecter dans le PDF (celles listées sont celles actuellement détectées)
ocr.selectText.2=Produire un fichier texte contenant le texte détecté à côté du PDF
ocr.selectText.3=Corriger les pages qui ont été numérisées à un angle oblique en les remettant en place
-ocr.selectText.4=Nettoyer la page afin qu\u2019il soit moins probable que l\u2019OCR trouve du texte dans le bruit de fond, sans modifier la sortie
-ocr.selectText.5=Nettoyer la page afin qu\u2019il soit moins probable que l\u2019OCR trouve du texte dans le bruit de fond, en modifiant la sortie
-ocr.selectText.6=Ignorer les pages contenant du texte interactif, n\u2019analyser que les pages qui sont des images
-ocr.selectText.7=Forcer l\u2019OCR, analyser chaque page et supprimer tous les éléments de texte d\u2019origine
+ocr.selectText.4=Nettoyer la page afin qu’il soit moins probable que l’OCR trouve du texte dans le bruit de fond, sans modifier la sortie
+ocr.selectText.5=Nettoyer la page afin qu’il soit moins probable que l’OCR trouve du texte dans le bruit de fond, en modifiant la sortie
+ocr.selectText.6=Ignorer les pages contenant du texte interactif, n’analyser que les pages qui sont des images
+ocr.selectText.7=Forcer l’OCR, analyser chaque page et supprimer tous les éléments de texte d’origine
ocr.selectText.8=Normal (génère une erreur si le PDF contient du texte)
ocr.selectText.9=Paramètres additionnels
ocr.selectText.10=Mode OCR
-ocr.selectText.11=Supprimer les images après l\u2019OCR (Supprime TOUTES les images, utile uniquement si elles font partie de l\u2019étape de conversion)
+ocr.selectText.11=Supprimer les images après l’OCR (Supprime TOUTES les images, utile uniquement si elles font partie de l’étape de conversion)
ocr.selectText.12=Type de rendu (avancé)
-ocr.help=Veuillez lire cette documentation pour savoir comment utiliser l\u2019OCR pour d\u2019autres langues ou une utilisation hors Docker\u00a0:
-ocr.credit=Ce service utilise OCRmyPDF et Tesseract pour l\u2019OCR.
+ocr.help=Veuillez lire cette documentation pour savoir comment utiliser l’OCR pour d’autres langues ou une utilisation hors Docker :
+ocr.credit=Ce service utilise OCRmyPDF et Tesseract pour l’OCR.
ocr.submit=Traiter
#extractImages
extractImages.title=Extraire les images
extractImages.header=Extraire les images
-extractImages.selectText=Format d\u2019image dans lequel convertir les images extraites
+extractImages.selectText=Format d’image dans lequel convertir les images extraites
extractImages.submit=Extraire
@@ -695,21 +747,21 @@ fileToPDF.submit=Convertir
#compress
-compress.title=Compresser
-compress.header=Compresser
-compress.credit=Ce service utilise Ghostscript pour la compression et l\u2019optimisation des PDF.
-compress.selectText.1=Mode manuel \u2013 de 1 à 4
-compress.selectText.2=Niveau d\u2019optimisation
+compress.title=Compresser un PDF
+compress.header=Compresser un PDF (lorsque c’est possible!)
+compress.credit=Ce service utilise Ghostscript pour la compression et l’optimisation des PDF.
+compress.selectText.1=Mode manuel – de 1 à 4
+compress.selectText.2=Niveau d’optimisation
compress.selectText.3=4 (terrible pour les images textuelles)
-compress.selectText.4=Mode automatique \u2013 ajuste automatiquement la qualité pour obtenir le PDF à la taille exacte
-compress.selectText.5=Taille PDF attendue (par exemple, 25\u202fMo, 10,8\u202fMo, 25\u202fKo)
+compress.selectText.4=Mode automatique – ajuste automatiquement la qualité pour obtenir le PDF à la taille exacte
+compress.selectText.5=Taille PDF attendue (par exemple, 25 MB, 10,8 MB, 25 KB)
compress.submit=Compresser
#Add image
addImage.title=Ajouter une image
addImage.header=Ajouter une image
-addImage.everyPage=Toutes les pages\u00a0?
+addImage.everyPage=Toutes les pages ?
addImage.upload=Télécharger une image
addImage.submit=Ajouter une image
@@ -726,41 +778,54 @@ merge.submit=Fusionner
pdfOrganiser.title=Organiser
pdfOrganiser.header=Organiser les pages
pdfOrganiser.submit=Organiser
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=Outil multifonction PDF
multiTool.header=Outil multifonction PDF
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
-viewPdf.title=View PDF
-viewPdf.header=View PDF
+viewPdf.title=Visualiser un PDF
+viewPdf.header=Visualiser un PDF
#pageRemover
pageRemover.title=Supprimer des pages
pageRemover.header=Supprimer des pages
-pageRemover.pagesToDelete=Pages à supprimer (entrez une liste de numéros de pages séparés par des virgules)\u00a0:
+pageRemover.pagesToDelete=Pages à supprimer (entrez une liste de numéros de pages séparés par des virgules) :
pageRemover.submit=Supprimer les pages
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
rotate.title=Pivoter
rotate.header=Pivoter
-rotate.selectAngle=Angle de rotation (par multiples de 90\u202fdegrés)
+rotate.selectAngle=Angle de rotation (par multiples de 90 degrés)
rotate.submit=Pivoter
-#merge
+#split-pdfs
split.title=Diviser
split.header=Diviser
split.desc.1=Les numéros que vous sélectionnez sont le numéro de page sur lequel vous souhaitez faire une division
-split.desc.2=Ainsi, la sélection de 1,3,7-8 diviserait un document de 10 pages en 6 PDF distincts avec\u00a0:
+split.desc.2=Ainsi, la sélection de 1,3,7-9 diviserait un document de 10 pages en 6 PDF distincts avec :
split.desc.3=Document #1: Page 1
split.desc.4=Document #2: Page 2 et 3
-split.desc.5=Document #3: Page 4, 5 et 6
-split.desc.6=Document #4: Page 7
-split.desc.7=Document #5: Page 8
-split.desc.8=Document #6: Page 9 et 10
+split.desc.5=Document #3: Page 4, 5, 6 et 7
+split.desc.6=Document #4: Page 8
+split.desc.7=Document #5: Page 9
+split.desc.8=Document #6: Page 10
split.splitPages=Pages sur lesquelles diviser
split.submit=Diviser
@@ -769,9 +834,9 @@ split.submit=Diviser
imageToPDF.title=Image en PDF
imageToPDF.header=Image en PDF
imageToPDF.submit=Convertir
-imageToPDF.selectLabel=Options d\u2019ajustement de l\u2019image
+imageToPDF.selectLabel=Options d’ajustement de l’image
imageToPDF.fillPage=Remplir la page
-imageToPDF.fitDocumentToImage=Ajuster la page à l\u2019image
+imageToPDF.fitDocumentToImage=Ajuster la page à l’image
imageToPDF.maintainAspectRatio=Maintenir les proportions
imageToPDF.selectText.2=Rotation automatique du PDF
imageToPDF.selectText.3=Logique multi-fichiers (uniquement activée si vous travaillez avec plusieurs images)
@@ -782,14 +847,14 @@ imageToPDF.selectText.5=Convertir en PDF séparés
#pdfToImage
pdfToImage.title=Image en PDF
pdfToImage.header=Image en PDF
-pdfToImage.selectText=Format d\u2019image
+pdfToImage.selectText=Format d’image
pdfToImage.singleOrMultiple=Type de résultat
pdfToImage.single=Une seule grande image
pdfToImage.multi=Plusieurs images
-pdfToImage.colorType=Type d\u2019impression
+pdfToImage.colorType=Type d’impression
pdfToImage.color=Couleur
pdfToImage.grey=Niveaux de gris
-pdfToImage.blackwhite=Noir et blanc (peut engendre une perde de données\u00a0!)
+pdfToImage.blackwhite=Noir et blanc (peut engendrer une perte de données !)
pdfToImage.submit=Convertir
@@ -797,21 +862,21 @@ pdfToImage.submit=Convertir
addPassword.title=Ajouter un mot de passe
addPassword.header=Ajouter un mot de passe
addPassword.selectText.1=PDF à chiffrer
-addPassword.selectText.2=Mot de passe de l\u2019utilisateur
+addPassword.selectText.2=Mot de passe de l’utilisateur
addPassword.selectText.3=Longueur de la clé de chiffrement
addPassword.selectText.4=Les valeurs plus élevées sont plus fortes, mais les valeurs plus faibles ont une meilleure compatibilité.
addPassword.selectText.5=Autorisations à définir (utilisation recommandée avec le mot de passe du propriétaire)
-addPassword.selectText.6=Empêcher l\u2019assemblage du document
-addPassword.selectText.7=Empêcher l\u2019extraction de contenu
-addPassword.selectText.8=Empêcher l\u2019extraction pour l\u2019accessibilité
+addPassword.selectText.6=Empêcher l’assemblage du document
+addPassword.selectText.7=Empêcher l’extraction de contenu
+addPassword.selectText.8=Empêcher l’extraction pour l’accessibilité
addPassword.selectText.9=Empêcher de remplir les formulaires
addPassword.selectText.10=Empêcher la modification
addPassword.selectText.11=Empêcher la modification des annotations
-addPassword.selectText.12=Empêcher l\u2019impression
-addPassword.selectText.13=Empêcher l\u2019impression des différents formats
+addPassword.selectText.12=Empêcher l’impression
+addPassword.selectText.13=Empêcher l’impression des différents formats
addPassword.selectText.14=Mot de passe du propriétaire
-addPassword.selectText.15=Restreint ce qui peut être fait avec le document une fois qu\u2019il est ouvert (non pris en charge par tous les lecteurs).
-addPassword.selectText.16=Restreint l\u2019ouverture du document lui-même.
+addPassword.selectText.15=Restreint ce qui peut être fait avec le document une fois qu’il est ouvert (non pris en charge par tous les lecteurs).
+addPassword.selectText.16=Restreint l’ouverture du document lui-même.
addPassword.submit=Chiffrer
@@ -828,6 +893,8 @@ watermark.selectText.7=Opacité (de 0% à 100%)
watermark.selectText.8=Type de filigrane
watermark.selectText.9=Image du filigrane
watermark.submit=Ajouter un filigrane
+watermark.type.1=Text
+watermark.type.2=Image
#Change permissions
@@ -836,14 +903,14 @@ permissions.header=Modifier les permissions
permissions.warning=Attention, pour que ces permissions soient immuables il est recommandé de les paramétrer avec un mot de passe via la page Ajouter un mot de passe.
permissions.selectText.1=Sélectionnez le PDF
permissions.selectText.2=Permissions à définir
-permissions.selectText.3=Empêcher l\u2019assemblage du document
-permissions.selectText.4=Empêcher l\u2019extraction de contenu
-permissions.selectText.5=Empêcher l\u2019extraction pour l\u2019accessibilité
+permissions.selectText.3=Empêcher l’assemblage du document
+permissions.selectText.4=Empêcher l’extraction de contenu
+permissions.selectText.5=Empêcher l’extraction pour l’accessibilité
permissions.selectText.6=Empêcher de remplir les formulaires
permissions.selectText.7=Empêcher la modification
permissions.selectText.8=Empêcher la modification des annotations
-permissions.selectText.9=Empêcher l\u2019impression
-permissions.selectText.10=Empêcher l\u2019impression des différents formats
+permissions.selectText.9=Empêcher l’impression
+permissions.selectText.10=Empêcher l’impression des différents formats
permissions.submit=Modifier
@@ -868,7 +935,7 @@ changeMetadata.keywords=Mots clés
changeMetadata.modDate=Date de modification (yyyy/MM/dd HH:mm:ss)
changeMetadata.producer=Producteur
changeMetadata.subject=Sujet
-changeMetadata.trapped=Défoncé (technique d’impression)
+changeMetadata.trapped=Recouvrement (technique d’impression)
changeMetadata.selectText.4=Autres métadonnées
changeMetadata.selectText.5=Ajouter une entrée de métadonnées personnalisée
changeMetadata.submit=Modifier
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF en PDF/A
pdfToPDFA.header=PDF en PDF/A
pdfToPDFA.credit=Ce service utilise OCRmyPDF pour la conversion en PDF/A.
pdfToPDFA.submit=Convertir
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Convertir
#PDFToHTML
PDFToHTML.title=PDF en HTML
PDFToHTML.header=PDF en HTML
-PDFToHTML.credit=Ce service utilise LibreOffice pour la conversion de fichiers.
+PDFToHTML.credit=Ce service utilise pdftohtml pour la conversion de fichiers.
PDFToHTML.submit=Convertir
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Choisir la page pour en extraire le tableau
PDFToCSV.submit=Extrait
#split-by-size-or-count
+split-by-size-or-count.title=Séparer le PDF par taille ou par nombre
split-by-size-or-count.header=Séparer le PDF par taille ou par nombre
split-by-size-or-count.type.label=Sélectionner le type de division
split-by-size-or-count.type.size=Par taille
@@ -936,19 +1006,19 @@ split-by-size-or-count.submit=Séparer
#overlay-pdfs
-overlay-pdfs.header=Overlay PDF Files
+overlay-pdfs.header=Incrustation de PDF
overlay-pdfs.baseFile.label=Sélectionner le fichier PDF de base
overlay-pdfs.overlayFiles.label=Sélectionner les fichiers PDF à superposer
-overlay-pdfs.mode.label=Select Overlay Mode
-overlay-pdfs.mode.sequential=Sequential Overlay
-overlay-pdfs.mode.interleaved=Interleaved Overlay
+overlay-pdfs.mode.label=Sélectionner le mode d’incrustation
+overlay-pdfs.mode.sequential=Superposition séquentielle
+overlay-pdfs.mode.interleaved=Superposition entrelacée
overlay-pdfs.mode.fixedRepeat=Superposition à répétition fixe
overlay-pdfs.counts.label=Nombre de superpositions (pour le mode de répétition fixe)
-overlay-pdfs.counts.placeholder=Enter comma-separated counts (e.g., 2,3,1)
-overlay-pdfs.position.label=Select Overlay Position
+overlay-pdfs.counts.placeholder=Compteurs (séparés par des virgules, exemple : 2,3,1)
+overlay-pdfs.position.label=Définir la position de l’incrustation
overlay-pdfs.position.foreground=Premier plan
overlay-pdfs.position.background=Arrière-plan
-overlay-pdfs.submit=Submit
+overlay-pdfs.submit=Soumettre
#split-by-sections
@@ -959,14 +1029,36 @@ 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
+split-by-sections.merge=Fusionner en un seul PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
-licenses.nav=Licenses
-licenses.title=3rd Party Licenses
-licenses.header=3rd Party Licenses
+licenses.nav=Licences
+licenses.title=Licences tierces
+licenses.header=Licences tierces
licenses.module=Module
licenses.version=Version
-licenses.license=License
+licenses.license=Licence
+# error
+error.sorry=Désolé pour ce problème !
+error.needHelp=Besoin d’aide / Vous avez trouvé un problème ?
+error.contactTip=Si vous avez encore des problèmes, n’hésitez pas à nous contacter pour obtenir de l’aide. Vous pouvez soumettre un ticket sur notre page GitHub ou nous contacter via Discord :
+error.404.head=404 - Page non trouvée | oups on s’est foiré !
+error.404.1=Nous ne parvenons pas à trouver la page que vous recherchez.
+error.404.2=Quelque chose n’a pas fonctionné
+error.github=Créer un ticket sur GitHub
+error.showStack=Afficher la Stack Trace
+error.copyStack=Copier la Stack Trace
+error.githubSubmit=GitHub - Créer un ticket
+error.discordSubmit=Discord - Poster un message de demande d’assistance
+
diff --git a/src/main/resources/messages_hi_IN.properties b/src/main/resources/messages_hi_IN.properties
index b17af690..9bcddca1 100644
--- a/src/main/resources/messages_hi_IN.properties
+++ b/src/main/resources/messages_hi_IN.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -17,9 +17,11 @@ true=सही
false=गलत
unknown=अज्ञात
save=सहेजें
+saveToBrowser=Save to Browser
close=बंद करें
filesSelected=फ़ाइलें चयनित हैं
noFavourites=कोई पसंदीदा जोड़ा नहीं गया है
+downloadComplete=Download Complete
bored=बोर हो रहे हैं?
alphabet=वर्णमाला
downloadPdf=पीडीएफ़ डाउनलोड करें
@@ -52,16 +54,34 @@ notAuthenticatedMessage=उपयोगकर्ता प्रमाणित
userNotFoundMessage=उपयोगकर्ता नहीं मिला।
incorrectPasswordMessage=वर्तमान पासवर्ड गलत है।
usernameExistsMessage=नया उपयोगकर्ता नाम पहले से मौजूद है।
+invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
+deleteCurrentUserMessage=Cannot delete currently logged in user.
+deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
+downgradeCurrentUserMessage=मौजूदा यूज़र की भूमिका को डाउनग्रेड नहीं किया जा सकता
+downgradeCurrentUserLongMessage=मौजूदा यूज़र की भूमिका को डाउनग्रेड नहीं किया जा सकता। इसलिए, वर्तमान उपयोगकर्ता को नहीं दिखाया जाएगा।
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
+pipeline.header=Pipeline Menu (Beta)
pipeline.uploadButton=Upload Custom
pipeline.configureButton=Configure
pipeline.defaultOption=Custom
pipeline.submitButton=Submit
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
######################
# Pipeline Options #
@@ -94,6 +114,7 @@ navbar.settings=सेटिंग्स
#############
settings.title=सेटिंग्स
settings.update=अपडेट उपलब्ध है
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=ऐप संस्करण:
settings.downloadOption.title=डाउनलोड विकल्प चुनें (एकल फ़ाइल गैर-ज़िप डाउनलोड के लिए):
settings.downloadOption.1=एक ही विंडो में खोलें
@@ -102,12 +123,13 @@ settings.downloadOption.3=फ़ाइल डाउनलोड करें
settings.zipThreshold=जब डाउनलोड की गई फ़ाइलों की संख्या सीमा से अधिक हो
settings.signOut=साइन आउट
settings.accountSettings=खाता सेटिंग्स
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=क्रेडेंशियल बदलें
changeCreds.header=अपना खाता विवरण अपडेट करें
-changeCreds.changeUserAndPassword=आप डिफ़ॉल्ट लॉगिन क्रेडेंशियल का उपयोग कर रहे हैं। कृपया एक नया पासवर्ड दर्ज करें (और यदि चाहें तो उपयोगकर्ता नाम)
+changeCreds.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=नया उपयोगकर्ता नाम
changeCreds.oldPassword=वर्तमान पासवर्ड
changeCreds.newPassword=नया पासवर्ड
@@ -142,14 +164,18 @@ adminUserSettings.header=व्यवस्थापक उपयोगकर्
adminUserSettings.admin=व्यवस्थापक
adminUserSettings.user=उपयोगकर्ता
adminUserSettings.addUser=नया उपयोगकर्ता जोड़ें
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.roles=रोल्स
adminUserSettings.role=रोल
adminUserSettings.actions=क्रियाएँ
adminUserSettings.apiUser=सीमित API उपयोगकर्ता
+adminUserSettings.extraApiUser=Additional Limited API User
adminUserSettings.webOnlyUser=केवल वेब उपयोगकर्ता
adminUserSettings.demoUser=Demo User (No custom settings)
+adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=उपयोगकर्ता को लॉगिन पर उपयोगकर्ता नाम/पासवर्ड बदलने के लिए मजबूर करें
adminUserSettings.submit=उपयोगकर्ता को सहेजें
+adminUserSettings.changeUserRole=यूज़र की भूमिका बदलें
#############
# HOME-PAGE #
@@ -392,6 +418,15 @@ home.AddStampRequest.desc=Add text or add image stamps at set locations
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=साइन इन करें
+login.header=साइन इन करें
login.signin=साइन इन करें
login.rememberme=मुझे याद रखें
login.invalid=अमान्य उपयोगकर्ता नाम या पासवर्ड।
login.locked=आपका खाता लॉक कर दिया गया है।
login.signinTitle=कृपया साइन इन करें
+login.ssoSignIn=सिंगल साइन - ऑन के ज़रिए लॉग इन करें
+login.oauth2AutoCreateDisabled=OAUTH2 ऑटो - क्रिएट यूज़र अक्षम किया गया
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=एकल पृष्ठ में परिवर्त
pageExtracter.title=पृष्ठों को निकालें
pageExtracter.header=पृष्ठों को निकालें
pageExtracter.submit=निकालें
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -623,6 +662,18 @@ compare.document.1=दस्तावेज़ 1
compare.document.2=दस्तावेज़ 2
compare.submit=तुलना करें
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
#sign
sign.title=हस्ताक्षर
@@ -643,6 +694,7 @@ repair.submit=मरम्मत
#flatten
flatten.title=समतल करें
flatten.header=पीडीएफ़ समतल करें
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=समतल करें
@@ -726,11 +778,23 @@ merge.submit=मर्ज करें
pdfOrganiser.title=पेज व्यवस्थापक
pdfOrganiser.header=PDF पेज व्यवस्थापक
pdfOrganiser.submit=पृष्ठों को पुनः व्यवस्थित करें
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=पीडीएफ मल्टी टूल
multiTool.header=पीडीएफ मल्टी टूल
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
viewPdf.title=पीडीएफ देखें
@@ -741,6 +805,7 @@ pageRemover.title=पेज हटाने वाला
pageRemover.header=पीडीएफ पेज हटाने वाला
pageRemover.pagesToDelete=हटाने के पेज (पृष्ठ संख्याओं की व्यवस्था के लिए एक कॉमा से अलग संख्याओं की सूची दर्ज करें):
pageRemover.submit=पेज हटाएं
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=चुनें घुमाने का कोण (90 ड
rotate.submit=घुमाएं
-#merge
+#split-pdfs
split.title=पीडीएफ को विभाजित करें
split.header=पीडीएफ को विभाजित करें
split.desc.1=जिन नंबरों को आप चुनते हैं, वे पृष्ठ संख्या होती हैं जिन पर आप विभाजन करना चाहते हैं।
-split.desc.2=इसलिए, 1,3,7-8 का चयन करना एक 10 पृष्ठों के दस्तावेज़ को 6 अलग-अलग पीडीएफ में विभाजित करेगा जैसे:
+split.desc.2=इसलिए, 1,3,7-9 का चयन करना एक 10 पृष्ठों के दस्तावेज़ को 6 अलग-अलग पीडीएफ में विभाजित करेगा जैसे:
split.desc.3=दस्तावेज़ #1: पृष्ठ 1
split.desc.4=दस्तावेज़ #2: पृष्ठ 2 और 3
-split.desc.5=दस्तावेज़ #3: पृष्ठ 4, 5 और 6
+split.desc.5=दस्तावेज़ #3: पृष्ठ 4, 5, 6 और 7
split.desc.6=दस्तावेज़ #4: पृष्ठ 7
split.desc.7=दस्तावेज़ #5: पृष्ठ 8
-split.desc.8=दस्तावेज़ #6: पृष्ठ 9 और 10
+split.desc.8=दस्तावेज़ #6: पृष्ठ 10
split.splitPages=विभाजन करने के लिए पृष्ठ दर्ज करें:
split.submit=विभाजित करें
@@ -828,6 +893,8 @@ watermark.selectText.7=अपारदर्शिता (0% - 100%):
watermark.selectText.8=वॉटरमार्क प्रकार:
watermark.selectText.9=वॉटरमार्क छवि:
watermark.submit=वॉटरमार्क जोड़ें
+watermark.type.1=Text
+watermark.type.2=Image
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF से PDF/A में
pdfToPDFA.header=PDF से PDF/A में
pdfToPDFA.credit=इस सेवा में PDF/A परिवर्तन के लिए OCRmyPDF का उपयोग किया जाता है।
pdfToPDFA.submit=परिवर्तित करें
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=परिवर्तित करें
#PDFToHTML
PDFToHTML.title=PDF से HTML
PDFToHTML.header=PDF से HTML
-PDFToHTML.credit=यह सेवा फ़ाइल परिवर्तन के लिए LibreOffice का उपयोग करती है।
+PDFToHTML.credit=यह सेवा फ़ाइल परिवर्तन के लिए pdftohtml का उपयोग करती है।
PDFToHTML.submit=परिवर्तित करें
@@ -925,6 +994,7 @@ PDFToCSV.prompt=टेबल निकालने के लिए पृष्
PDFToCSV.submit=निकालें
#split-by-size-or-count
+split-by-size-or-count.title=आकार या गणना द्वारा PDF को विभाजित करें
split-by-size-or-count.header=आकार या गणना द्वारा PDF को विभाजित करें
split-by-size-or-count.type.label=स्प्लिट प्रकार चुनें
split-by-size-or-count.type.size=आकार द्वारा
@@ -959,6 +1029,15 @@ split-by-sections.vertical.label=लंबवत विभाजन
split-by-sections.horizontal.placeholder=क्षैतिज विभाजन की संख्या दर्ज करें
split-by-sections.vertical.placeholder=लंबवत विभाजन की संख्या दर्ज करें
split-by-sections.submit=PDF को विभाजित करें
+split-by-sections.merge=Merge Into One PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Version
licenses.license=License
+# error
+error.sorry=Sorry for the issue!
+error.needHelp=Need help / Found an issue?
+error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
+error.404.head=404 - Page Not Found | Oops, we tripped in the code!
+error.404.1=We can't seem to find the page you're looking for.
+error.404.2=Something went wrong
+error.github=Submit a ticket on GitHub
+error.showStack=Show Stack Trace
+error.copyStack=Copy Stack Trace
+error.githubSubmit=GitHub - Submit a ticket
+error.discordSubmit=Discord - Submit Support post
+
diff --git a/src/main/resources/messages_hu_HU.properties b/src/main/resources/messages_hu_HU.properties
index 0fab7e30..625e8b23 100644
--- a/src/main/resources/messages_hu_HU.properties
+++ b/src/main/resources/messages_hu_HU.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -17,9 +17,11 @@ true=Igaz
false=Hamis
unknown=Ismeretlen
save=Mentés
+saveToBrowser=Save to Browser
close=Bezárás
filesSelected=kiválasztott fájlok
noFavourites=Nincs hozzáadva kedvenc
+downloadComplete=Download Complete
bored=Unatkozol?
alphabet=Ábécé
downloadPdf=PDF letöltése
@@ -52,16 +54,34 @@ notAuthenticatedMessage=Felhasználó nincs hitelesítve.
userNotFoundMessage=A felhasználó nem található.
incorrectPasswordMessage=A jelenlegi jelszó helytelen.
usernameExistsMessage=Az új felhasználónév már létezik.
+invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
+deleteCurrentUserMessage=Cannot delete currently logged in user.
+deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
+downgradeCurrentUserMessage=A jelenlegi felhasználó szerepkörét nem lehet visszaminősíteni
+downgradeCurrentUserLongMessage=Az aktuális felhasználó szerepkörét nem lehet visszaminősíteni. Ezért az aktuális felhasználó nem jelenik meg.
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
+pipeline.header=Pipeline Menu (Beta)
pipeline.uploadButton=Upload Custom
pipeline.configureButton=Configure
pipeline.defaultOption=Custom
pipeline.submitButton=Submit
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
######################
# Pipeline Options #
@@ -94,6 +114,7 @@ navbar.settings=Beállítások
#############
settings.title=Beállítások
settings.update=Frisítés elérhető
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=App Verzió:
settings.downloadOption.title=Válassza ki a letöltési lehetőséget (Egyetlen fájl esetén a nem tömörített letöltésekhez):
settings.downloadOption.1=Nyissa meg ugyanabban az ablakban
@@ -102,12 +123,13 @@ settings.downloadOption.3=Töltse le a fájlt
settings.zipThreshold=Fájlok tömörítése, ha a letöltött fájlok száma meghaladja
settings.signOut=Kijelentkezés
settings.accountSettings=Fiókbeállítások
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=Hitelesítés megváltoztatása
changeCreds.header=Frissítse fiókadatait
-changeCreds.changeUserAndPassword=Alapértelmezett bejelentkezési adatokat használ. Adjon meg egy új jelszót (és felhasználónevet, ha szeretné)
+changeCreds.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=Új felhasználónév
changeCreds.oldPassword=Jelenlegi jelszó
changeCreds.newPassword=Új jelszó
@@ -142,14 +164,18 @@ adminUserSettings.header=Adminisztrátori Felhasználói Vezérlési Beállítá
adminUserSettings.admin=Adminisztrátor
adminUserSettings.user=Felhasználó
adminUserSettings.addUser=Új felhasználó hozzáadása
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.roles=Szerepek
adminUserSettings.role=Szerep
adminUserSettings.actions=Műveletek
adminUserSettings.apiUser=Korlátozott API-felhasználó
+adminUserSettings.extraApiUser=Additional Limited API User
adminUserSettings.webOnlyUser=Csak webes felhasználó
adminUserSettings.demoUser=Demo User (No custom settings)
+adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Kényszerítse a felhasználót a felhasználónév/jelszó megváltoztatására bejelentkezéskor
adminUserSettings.submit=Felhasználó mentése
+adminUserSettings.changeUserRole=Felhasználó szerepkörének módosítása
#############
# HOME-PAGE #
@@ -392,6 +418,15 @@ home.AddStampRequest.desc=Add text or add image stamps at set locations
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Bejelentkezés
+login.header=Bejelentkezés
login.signin=Bejelentkezés
login.rememberme=Emlékezz rám
login.invalid=Érvénytelen felhasználónév vagy jelszó!
login.locked=A fiókja zárolva lett!
login.signinTitle=Kérjük, jelentkezzen be!
+login.ssoSignIn=Bejelentkezés egyszeri bejelentkezéssel
+login.oauth2AutoCreateDisabled=OAUTH2 Felhasználó automatikus létrehozása letiltva
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Átalakítás egyetlen oldallá
pageExtracter.title=Oldalak kinyerése
pageExtracter.header=Oldalak kinyerése
pageExtracter.submit=Kinyerés
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -623,6 +662,18 @@ compare.document.1=Dokumentum 1
compare.document.2=Dokumentum 2
compare.submit=Összehasonlítás
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
#sign
sign.title=Aláírás
@@ -643,6 +694,7 @@ repair.submit=Javítás
#flatten
flatten.title=Kiegyenlítés
flatten.header=PDF-ek kiegyenlítése
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Kiegyenlítés
@@ -726,11 +778,23 @@ merge.submit=Összevonás
pdfOrganiser.title=Oldalszervező
pdfOrganiser.header=PDF Oldalszervező
pdfOrganiser.submit=Oldalak átrendezése
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=PDF többfunkciós eszköz
multiTool.header=PDF többfunkciós eszköz
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
viewPdf.title=PDF megtekintése
@@ -741,6 +805,7 @@ pageRemover.title=Oldaltörlő
pageRemover.header=PDF oldaltörlő
pageRemover.pagesToDelete=Törlendő oldalak (adja meg az oldalszámok vesszővel elválasztott listáját):
pageRemover.submit=Oldalak törlése
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Válassza ki a forgatási szöget (90 fok egész számú töb
rotate.submit=Forgatás
-#merge
+#split-pdfs
split.title=PDF szétválasztás
split.header=PDF szétválasztás
split.desc.1=A kiválasztott számok a szétválasztani kívánt oldalszámok
-split.desc.2=Például az 1,3,7-8 kiválasztása egy 10 oldalas dokumentumot 6 különálló PDF-fé szétválaszt
+split.desc.2=Például az 1,3,7-9 kiválasztása egy 10 oldalas dokumentumot 6 különálló PDF-fé szétválaszt
split.desc.3=Dokumentum #1: Oldal 1
split.desc.4=Dokumentum #2: Oldal 2 és 3
-split.desc.5=Dokumentum #3: Oldal 4, 5 és 6
-split.desc.6=Dokumentum #4: Oldal 7
-split.desc.7=Dokumentum #5: Oldal 8
-split.desc.8=Dokumentum #6: Oldal 9 és 10
+split.desc.5=Dokumentum #3: Oldal 4, 5, 6 és 7
+split.desc.6=Dokumentum #4: Oldal 8
+split.desc.7=Dokumentum #5: Oldal 9
+split.desc.8=Dokumentum #6: Oldal 10
split.splitPages=Adja meg az oldalakat, amelyekre szét akarja választani:
split.submit=Szétválasztás
@@ -828,6 +893,8 @@ watermark.selectText.7=Átlátszóság (0% - 100%):
watermark.selectText.8=Vízjel típusa:
watermark.selectText.9=Vízjel képe:
watermark.submit=Vízjel hozzáadása
+watermark.type.1=Text
+watermark.type.2=Image
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF >> PDF/A
pdfToPDFA.header=PDF >> PDF/A
pdfToPDFA.credit=Ez a szolgáltatás az OCRmyPDF-t használja a PDF/A konverzióhoz
pdfToPDFA.submit=Konvertálás
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Konvertálás
#PDFToHTML
PDFToHTML.title=PDF >> HTML
PDFToHTML.header=PDF >> HTML
-PDFToHTML.credit=Ez a szolgáltatás a LibreOffice-t használja a fájlkonverzióhoz.
+PDFToHTML.credit=Ez a szolgáltatás a pdftohtml-t használja a fájlkonverzióhoz.
PDFToHTML.submit=Konvertálás
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Válassza ki az oldalt a táblázat kinyeréséhez
PDFToCSV.submit=Kinyerés
#split-by-size-or-count
+split-by-size-or-count.title=PDF felosztása méret vagy oldalszám alapján
split-by-size-or-count.header=PDF felosztása méret vagy oldalszám alapján
split-by-size-or-count.type.label=Válassza ki a felosztás típusát
split-by-size-or-count.type.size=Méret alapján
@@ -959,6 +1029,15 @@ 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
+split-by-sections.merge=Merge Into One PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Version
licenses.license=License
+# error
+error.sorry=Sorry for the issue!
+error.needHelp=Need help / Found an issue?
+error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
+error.404.head=404 - Page Not Found | Oops, we tripped in the code!
+error.404.1=We can't seem to find the page you're looking for.
+error.404.2=Something went wrong
+error.github=Submit a ticket on GitHub
+error.showStack=Show Stack Trace
+error.copyStack=Copy Stack Trace
+error.githubSubmit=GitHub - Submit a ticket
+error.discordSubmit=Discord - Submit Support post
+
diff --git a/src/main/resources/messages_id_ID.properties b/src/main/resources/messages_id_ID.properties
index 4bbe247b..fd5c3e31 100644
--- a/src/main/resources/messages_id_ID.properties
+++ b/src/main/resources/messages_id_ID.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl=right to left)
@@ -17,9 +17,11 @@ true=Benar
false=Salah
unknown=Tidak diketahui
save=Simpan
+saveToBrowser=Save to Browser
close=Tutup
filesSelected=berkas dipilih
noFavourites=Tidak ada favorit yang ditambahkan
+downloadComplete=Download Complete
bored=Bosan Menunggu?
alphabet=Abjad
downloadPdf=Unduh PDF
@@ -52,16 +54,34 @@ notAuthenticatedMessage=Pengguna tidak ter-autentikasi.
userNotFoundMessage=Pengguna tidak ditemukan.
incorrectPasswordMessage=Kata sandi saat ini salah.
usernameExistsMessage=Nama pengguna baru sudah ada.
+invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
+deleteCurrentUserMessage=Cannot delete currently logged in user.
+deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
+downgradeCurrentUserMessage=Tidak dapat menurunkan peran pengguna saat ini
+downgradeCurrentUserLongMessage=Tidak dapat menurunkan peran pengguna saat ini. Oleh karena itu, pengguna saat ini tidak akan ditampilkan.
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
+pipeline.header=Pipeline Menu (Beta)
pipeline.uploadButton=Upload Custom
pipeline.configureButton=Configure
pipeline.defaultOption=Custom
pipeline.submitButton=Submit
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
######################
# Pipeline Options #
@@ -94,6 +114,7 @@ navbar.settings=Pengaturan
#############
settings.title=Pengaturan
settings.update=Pembaruan tersedia
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=Versi Aplikasi:
settings.downloadOption.title=Pilih opsi unduhan (Untuk unduhan berkas tunggal non zip):
settings.downloadOption.1=Buka di jendela yang sama
@@ -102,12 +123,13 @@ settings.downloadOption.3=Unduh berkas
settings.zipThreshold=Berkas zip ketika jumlah berkas yang diunduh melebihi
settings.signOut=Keluar
settings.accountSettings=Pengaturan Akun
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=Ubah Kredensial
changeCreds.header=Perbarui Detail Akun Anda
-changeCreds.changeUserAndPassword=Anda menggunakan kredensial masuk default. Masukkan kata sandi baru (dan nama pengguna jika diinginkan)
+changeCreds.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=Nama Pengguna Baru
changeCreds.oldPassword=Kata Sandi Saat Ini
changeCreds.newPassword=Kata Sandi Baru
@@ -142,14 +164,18 @@ adminUserSettings.header=Pengaturan Kontrol Admin
adminUserSettings.admin=Admin
adminUserSettings.user=Pengguna
adminUserSettings.addUser=Tambahkan Pengguna Baru
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.roles=Peran
adminUserSettings.role=Peran
adminUserSettings.actions=Tindakan
adminUserSettings.apiUser=Pengguna API Terbatas
+adminUserSettings.extraApiUser=Additional Limited API User
adminUserSettings.webOnlyUser=Pengguna Khusus Web
adminUserSettings.demoUser=Demo User (No custom settings)
+adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Memaksa pengguna untuk mengubah nama pengguna/kata sandi saat masuk
adminUserSettings.submit=Simpan Pengguna
+adminUserSettings.changeUserRole=Ubah Peran Pengguna
#############
# HOME-PAGE #
@@ -392,6 +418,15 @@ home.AddStampRequest.desc=Add text or add image stamps at set locations
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Masuk
+login.header=Masuk
login.signin=Masuk
login.rememberme=Ingat saya
login.invalid=Nama pengguna atau kata sandi tidak valid.
login.locked=Akun Anda telah dikunci.
login.signinTitle=Silakan masuk
+login.ssoSignIn=Masuk melalui Single Sign - on
+login.oauth2AutoCreateDisabled=OAUTH2 Buat Otomatis Pengguna Dinonaktifkan
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Konversi ke Halaman Tunggal
pageExtracter.title=Ekstrak Halaman
pageExtracter.header=Ekstrak Halaman
pageExtracter.submit=Ekstrak
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -623,6 +662,18 @@ compare.document.1=Dokumen 1
compare.document.2=Dokumen 2
compare.submit=Bandingkan
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
#sign
sign.title=Tanda
@@ -643,6 +694,7 @@ repair.submit=Perbaiki
#flatten
flatten.title=Ratakan
flatten.header=Ratakan PDF
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Ratakan
@@ -726,11 +778,23 @@ merge.submit=Gabungkan
pdfOrganiser.title=Pengaturan Halaman
pdfOrganiser.header=Pengaturan Halaman PDF
pdfOrganiser.submit=Susun ulang halaman
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=Alat Multi PDF
multiTool.header=Alat Multi PDF
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
viewPdf.title=Lihat PDF
@@ -741,6 +805,7 @@ pageRemover.title=Penghapus Halaman
pageRemover.header=Penghapus Halaman PDF
pageRemover.pagesToDelete=Halaman yang akan dihapus (Masukkan daftar nomor halaman yang dipisahkan dengan koma) :
pageRemover.submit=Hapus Halaman
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Pilih sudut rotasi (dalam kelipatan 90 derajat):
rotate.submit=Rotasi
-#merge
+#split-pdfs
split.title=Membagi PDF
split.header=Membagi PDF
split.desc.1=Angka yang Anda pilih adalah nomor halaman yang ingin Anda pisahkan
-split.desc.2=Dengan demikian, memilih 1,3,7-8 akan membagi dokumen 10 halaman menjadi 6 PDF terpisah:
+split.desc.2=Dengan demikian, memilih 1,3,7-9 akan membagi dokumen 10 halaman menjadi 6 PDF terpisah:
split.desc.3=Dokumen #1: Halaman 1
split.desc.4=Dokumen #2: Halaman 2 dan 3
-split.desc.5=Dokumen #3: Halaman 4, 5 dan 6
-split.desc.6=Dokumen #4: Halaman 7
-split.desc.7=Dokumen #5: Halaman 8
-split.desc.8=Dokumen #6: Halaman 9 dan 10
+split.desc.5=Dokumen #3: Halaman 4, 5, 6 dan 7
+split.desc.6=Dokumen #4: Halaman 8
+split.desc.7=Dokumen #5: Halaman 9
+split.desc.8=Dokumen #6: Halaman 10
split.splitPages=Masukkan halaman yang akan dipisah:
split.submit=Pisahkan
@@ -828,6 +893,8 @@ watermark.selectText.7=Opacity (0% - 100%):
watermark.selectText.8=Tipe Watermark:
watermark.selectText.9=Gambar Watermark:
watermark.submit=Tambahkan Watermark
+watermark.type.1=Text
+watermark.type.2=Image
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF Ke PDF/A
pdfToPDFA.header=PDF ke PDF/A
pdfToPDFA.credit=Layanan ini menggunakan OCRmyPDF untuk konversi PDF/A.
pdfToPDFA.submit=Konversi
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Konversi
#PDFToHTML
PDFToHTML.title=PDF Ke HTML
PDFToHTML.header=PDF ke HTML
-PDFToHTML.credit=Layanan ini menggunakan LibreOffice untuk konversi berkas.
+PDFToHTML.credit=Layanan ini menggunakan pdftohtml untuk konversi berkas.
PDFToHTML.submit=Konversi
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Pilih halaman untuk mengambil tabel
PDFToCSV.submit=Ektraksi
#split-by-size-or-count
+split-by-size-or-count.title=Pisahkan PDF berdasarkan ukuran atau jumlah
split-by-size-or-count.header=Pisahkan PDF berdasarkan ukuran atau jumlah
split-by-size-or-count.type.label=Pilih Tipe Split
split-by-size-or-count.type.size=Berdasarkan Ukuran
@@ -959,6 +1029,15 @@ 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
+split-by-sections.merge=Merge Into One PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Version
licenses.license=License
+# error
+error.sorry=Sorry for the issue!
+error.needHelp=Need help / Found an issue?
+error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
+error.404.head=404 - Page Not Found | Oops, we tripped in the code!
+error.404.1=We can't seem to find the page you're looking for.
+error.404.2=Something went wrong
+error.github=Submit a ticket on GitHub
+error.showStack=Show Stack Trace
+error.copyStack=Copy Stack Trace
+error.githubSubmit=GitHub - Submit a ticket
+error.discordSubmit=Discord - Submit Support post
+
diff --git a/src/main/resources/messages_it_IT.properties b/src/main/resources/messages_it_IT.properties
index 70793c70..e22addfe 100644
--- a/src/main/resources/messages_it_IT.properties
+++ b/src/main/resources/messages_it_IT.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -11,15 +11,17 @@ imgPrompt=Scegli immagine/i
genericSubmit=Invia
processTimeWarning=Nota: Questo processo potrebbe richiedere fino a un minuto in base alla dimensione dei file
pageOrderPrompt=Ordine delle pagine (inserisci una lista di numeri separati da virgola):
-pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
+pageSelectionPrompt=Selezione pagina personalizzata (inserisci un elenco separato da virgole di numeri di pagina 1,5,6 o funzioni come 2n+1) :
goToPage=Vai
true=Vero
false=Falso
unknown=Sconosciuto
save=Salva
+saveToBrowser=Salva nel browser
close=Chiudi
filesSelected=file selezionati
noFavourites=Nessun preferito
+downloadComplete=Download completo
bored=Stanco di aspettare?
alphabet=Alfabeto
downloadPdf=Scarica PDF
@@ -52,16 +54,34 @@ notAuthenticatedMessage=Utente non autenticato.
userNotFoundMessage=Utente non trovato.
incorrectPasswordMessage=La password attuale non è corretta.
usernameExistsMessage=Il nuovo nome utente esiste già.
+invalidUsernameMessage=Nome utente non valido, il nome utente deve contenere solo caratteri alfabetici e numeri.
+deleteCurrentUserMessage=Impossibile eliminare l'utente attualmente connesso.
+deleteUsernameExistsMessage=Il nome utente non esiste e non può essere eliminato.
+downgradeCurrentUserMessage=Impossibile declassare il ruolo dell'utente corrente
+downgradeCurrentUserLongMessage=Impossibile declassare il ruolo dell'utente corrente. Pertanto, l'utente corrente non verrà visualizzato.
+error=Errore
+oops=Oops!
+help=Aiuto
+goHomepage=Vai alla Homepage
+joinDiscord=Unisciti al nostro server Discord
+seeDockerHub=Vedi DockerHub
+visitGithub=Visita il repository Github
+donate=Donazione
+color=Colore
+sponsor=Sponsor
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
+pipeline.header=Menù pipeline (Beta)
pipeline.uploadButton=Caricamento personalizzato
pipeline.configureButton=Configura
pipeline.defaultOption=Personalizzato
pipeline.submitButton=Invia
+pipeline.help=Aiuto sulla pipeline
+pipeline.scanHelp=Aiuto per la scansione delle cartelle
######################
# Pipeline Options #
@@ -94,6 +114,7 @@ navbar.settings=Impostazioni
#############
settings.title=Impostazioni
settings.update=Aggiornamento disponibile
+settings.updateAvailable={0} è la versione attualmente installata. Una nuova versione ({1}) è disponibile.
settings.appVersion=Versione App:
settings.downloadOption.title=Scegli opzione di download (Per file singoli non compressi):
settings.downloadOption.1=Apri in questa finestra
@@ -102,16 +123,17 @@ settings.downloadOption.3=Scarica file
settings.zipThreshold=Comprimi file in .zip quando il numero di download supera
settings.signOut=Logout
settings.accountSettings=Impostazioni Account
-
-
+settings.bored.help=Abilita easter egg game
+settings.cacheInputs.name=Salva gli input del modulo
+settings.cacheInputs.help=Abilitare per memorizzare gli input utilizzati in precedenza per esecuzioni future
changeCreds.title=Cambia credenziali
changeCreds.header=Aggiorna i dettagli del tuo account
-changeCreds.changeUserAndPassword=Stai utilizzando le credenziali di accesso predefinite. Inserisci una nuova password (e un nome utente se lo desideri)
+changeCreds.changePassword=Stai utilizzando le credenziali di accesso predefinite. Inserisci una nuova password
changeCreds.newUsername=Nuovo nome utente
changeCreds.oldPassword=Password attuale
changeCreds.newPassword=Nuova Password
-changeCreds.confirmNewPassword=Conferma Nuova Password
+changeCreds.confirmNewPassword=Conferma nuova Password
changeCreds.submit=Invia modifiche
@@ -142,14 +164,18 @@ adminUserSettings.header=Impostazioni di controllo utente amministratore
adminUserSettings.admin=Amministratore
adminUserSettings.user=Utente
adminUserSettings.addUser=Aggiungi un nuovo Utente
+adminUserSettings.usernameInfo=Il nome utente deve contenere solo lettere e numeri, senza spazi o caratteri speciali.
adminUserSettings.roles=Ruoli
adminUserSettings.role=Ruolo
adminUserSettings.actions=Azioni
adminUserSettings.apiUser=Utente API limitato
+adminUserSettings.extraApiUser=API utente limitato aggiuntivo
adminUserSettings.webOnlyUser=Utente solo Web
adminUserSettings.demoUser=Utente demo (nessuna impostazione personalizzata)
+adminUserSettings.internalApiUser=API utente interna
adminUserSettings.forceChange=Forza l'utente a cambiare nome username/password all'accesso
adminUserSettings.submit=Salva utente
+adminUserSettings.changeUserRole=Cambia il ruolo dell'utente
#############
# HOME-PAGE #
@@ -168,7 +194,7 @@ multiTool.tags=Strumento multiplo,operazione multipla,interfaccia utente,trascin
home.merge.title=Unisci
home.merge.desc=Unisci facilmente più PDF in uno.
-merge.tags=unione, operazioni sulla pagina, back end, lato server
+merge.tags=unione,operazioni sulla pagina,back-end,lato server
home.split.title=Dividi
home.split.desc=Dividi un singolo PDF in più documenti.
@@ -237,7 +263,7 @@ ocr.tags=riconoscimento,testo,immagine,scansione,lettura,identificazione,rilevam
home.extractImages.title=Estrai immagini
home.extractImages.desc=Estrai tutte le immagini da un PDF e salvale come zip.
-extractImages.tags=immagine,photo,save,archive,zip,capture,grab
+extractImages.tags=immagine,foto,salva,archivio,zip,catturare,prendere
home.pdfToPDFA.title=Converti in PDF/A
home.pdfToPDFA.desc=Converti un PDF nel formato PDF/A per archiviazione a lungo termine.
@@ -367,7 +393,7 @@ showJS.tags=JS
home.autoRedact.title=Redazione automatica
home.autoRedact.desc=Redige automaticamente (oscura) il testo in un PDF in base al testo immesso
-autoRedact.tags=Redact,Hide,black out,black,marker,hidden
+autoRedact.tags=Redigere,nascondere,oscurare,nero,pennarello,nascosto
home.tableExtraxt.title=Da PDF a CSV
home.tableExtraxt.desc=Estrae tabelle da un PDF convertendolo in CSV
@@ -385,11 +411,20 @@ overlay-pdfs.tags=Svrapponi
home.split-by-sections.title=Dividi PDF per sezioni
home.split-by-sections.desc=Dividi ciascuna pagina di un PDF in sezioni orizzontali e verticali più piccole
-split-by-sections.tags=Dividi sezione, dividi, personalizza
+split-by-sections.tags=Dividi sezione,dividi,personalizza
home.AddStampRequest.title=Aggiungi timbro al PDF
home.AddStampRequest.desc=Aggiungi testo o aggiungi timbri immagine nelle posizioni prestabilite
-AddStampRequest.tags=Timbro, Aggiungi immagine, Centra immagine, Filigrana, PDF, Incorpora, Personalizza
+AddStampRequest.tags=Timbro,Aggiungi immagine,Centra immagine,Filigrana,PDF,Incorpora,Personalizza
+
+
+home.PDFToBook.title=PDF in libro
+home.PDFToBook.desc=Converte PDF in formati libro/fumetto utilizzando Calibre
+PDFToBook.tags=Libro,fumetto,calibre,conversione,manga,amazon,kindle
+
+home.BookToPDF.title=Libro in PDF
+home.BookToPDF.desc=Converte i formati di libri/fumetti in PDF utilizzando Calibre
+BookToPDF.tags=Libro,fumetto,calibre,conversione,manga,amazon,kindle
###########################
@@ -399,11 +434,14 @@ AddStampRequest.tags=Timbro, Aggiungi immagine, Centra immagine, Filigrana, PDF,
###########################
#login
login.title=Accedi
+login.header=Accedi
login.signin=Accedi
login.rememberme=Ricordami
login.invalid=Nome utente o password errati.
login.locked=Il tuo account è stato bloccato.
login.signinTitle=Per favore accedi
+login.ssoSignIn=Accedi tramite Single Sign-on
+login.oauth2AutoCreateDisabled=Creazione automatica utente OAUTH2 DISABILITATA
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Converti in pagina singola
pageExtracter.title=Estrai pagine
pageExtracter.header=Estrai pagine
pageExtracter.submit=Estrai
+pageExtracter.placeholder=(es. 1,2,8 o 4,7,12-16 o 2n-1)
#getPdfInfo
@@ -612,7 +651,7 @@ removeBlanks.submit=Rimuovi
#removeAnnotations
removeAnnotations.title=Rimuovi Annotazioni
-removeAnnotations.header=Remuovi Annotazioni
+removeAnnotations.header=Rimuovi Annotazioni
removeAnnotations.submit=Rimuovi
@@ -623,6 +662,18 @@ compare.document.1=Documento 1
compare.document.2=Documento 2
compare.submit=Compara
+#BookToPDF
+BookToPDF.title=Libri e fumetti in PDF
+BookToPDF.header=Libro in PDF
+BookToPDF.credit=Utilizza Calibre
+BookToPDF.submit=Converti
+
+#PDFToBook
+PDFToBook.title=PDF in libro
+PDFToBook.header=PDF in libro
+PDFToBook.selectText.1=Formato
+PDFToBook.credit=Utilizzo Calibre
+PDFToBook.submit=Converti
#sign
sign.title=Firma
@@ -641,8 +692,9 @@ repair.submit=Ripara
#flatten
-flatten.title=Appiattisci
+flatten.title=Appiattire
flatten.header=Appiattisci PDF
+flatten.flattenOnlyForms=Appiattisci solo i moduli
flatten.submit=Appiattisci
@@ -726,11 +778,23 @@ merge.submit=Unisci
pdfOrganiser.title=Organizza pagine
pdfOrganiser.header=Organizza le pagine di un PDF
pdfOrganiser.submit=Riordina pagine
+pdfOrganiser.mode=Modalità
+pdfOrganiser.mode.1=Ordine delle pagine personalizzato
+pdfOrganiser.mode.2=Ordine inverso
+pdfOrganiser.mode.3=Ordinamento fronte-retro
+pdfOrganiser.mode.4=Ordinamento a libretto
+pdfOrganiser.mode.5=Ordinamento libretto con cucitura laterale
+pdfOrganiser.mode.6=Divisione pari-dispari
+pdfOrganiser.mode.7=Rimuovi prima
+pdfOrganiser.mode.8=Rimuovi ultima
+pdfOrganiser.mode.9=Rimuovi la prima e l'ultima
+pdfOrganiser.placeholder=(ad es. 1,3,2 o 4-8,2,10-12 o 2n-1)
#multiTool
multiTool.title=Multifunzione PDF
multiTool.header=Multifunzione PDF
+multiTool.uploadPrompts=Caricare il PDF
#view pdf
viewPdf.title=Visualizza PDF
@@ -741,6 +805,7 @@ pageRemover.title=Rimuovi pagine
pageRemover.header=Rimuovi pagine da un PDF
pageRemover.pagesToDelete=Pagine da eliminare (inserisci una lista di numeri separati da virgola):
pageRemover.submit=Rimuovi pagine
+pageRemover.placeholder=(es. 1,2,6 o 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Scegli angolo di rotazione (in multipli di 90 gradi):
rotate.submit=Ruota
-#merge
+#split-pdfs
split.title=Dividi PDF
split.header=Dividi PDF
split.desc.1=I numeri che scegli sono le pagine a cui desideri dividere il documento
-split.desc.2=Per esempio inserendo 1,3,7-8 separeresti un documento di 10 pagine in 6 diversi PDF con:
+split.desc.2=Per esempio inserendo 1,3,7-9 separeresti un documento di 10 pagine in 6 diversi PDF con:
split.desc.3=Documento #1: Pagina 1
split.desc.4=Documento #2: Pagine 2 e 3
-split.desc.5=Documento #3: Pagine 4, 5 e 6
-split.desc.6=Documento #4: Pagina 7
-split.desc.7=Documento #5: Pagina 8
-split.desc.8=Documento #6: Pagine 9 e 10
+split.desc.5=Documento #3: Pagine 4, 5, 6 e 7
+split.desc.6=Documento #4: Pagina 8
+split.desc.7=Documento #5: Pagina 9
+split.desc.8=Documento #6: Pagine 10
split.splitPages=Inserisci pagine a cui dividere:
split.submit=Dividi
@@ -828,6 +893,8 @@ watermark.selectText.7=Opacità (0% - 100%):
watermark.selectText.8=Tipo di filigrana:
watermark.selectText.9=Immagine filigrana:
watermark.submit=Aggiungi Filigrana
+watermark.type.1=Testo
+watermark.type.2=Immagine
#Change permissions
@@ -868,10 +935,10 @@ changeMetadata.keywords=Parole chiave:
changeMetadata.modDate=Data di modifica (yyyy/MM/dd HH:mm:ss):
changeMetadata.producer=Produttore:
changeMetadata.subject=Oggetto:
-changeMetadata.trapped=Trapped:
+changeMetadata.trapped=Recuperato:
changeMetadata.selectText.4=Altre proprietà:
changeMetadata.selectText.5=Aggiungi proprietà personalizzata:
-changeMetadata.submit=Cambia Proprietà
+changeMetadata.submit=Cambia proprietà
#pdfToPDFA
@@ -879,6 +946,8 @@ pdfToPDFA.title=Da PDF a PDF/A
pdfToPDFA.header=Da PDF a PDF/A
pdfToPDFA.credit=Questo servizio utilizza OCRmyPDF per la conversione in PDF/A.
pdfToPDFA.submit=Converti
+pdfToPDFA.tip=Attualmente non funziona per più input contemporaneamente
+pdfToPDFA.outputFormat=Formato di output
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Converti
#PDFToHTML
PDFToHTML.title=Da PDF a HTML
PDFToHTML.header=Da PDF a HTML
-PDFToHTML.credit=Questo servizio utilizza LibreOffice per la conversione.
+PDFToHTML.credit=Questo servizio utilizza pdftohtml per la conversione.
PDFToHTML.submit=Converti
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Scegli la pagina per estrarre la tabella
PDFToCSV.submit=Estrai
#split-by-size-or-count
+split-by-size-or-count.title=Dividi il PDF per dimensione o numero
split-by-size-or-count.header=Dividi il PDF per dimensione o numero
split-by-size-or-count.type.label=Seleziona il tipo di divisione
split-by-size-or-count.type.size=Per dimensione
@@ -959,6 +1029,15 @@ 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
+split-by-sections.merge=Unisci in un unico PDF
+
+
+#printFile
+printFile.title=Stampa file
+printFile.header=Stampa file su stampante
+printFile.selectText.1=Seleziona file da stampare
+printFile.selectText.2=Inserire il nome della stampante
+printFile.submit=Stampare
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Versione
licenses.license=Licenza
+# error
+error.sorry=Ci scusiamo per il problema!
+error.needHelp=Hai bisogno di aiuto / trovato un problema?
+error.contactTip=Se i problemi persistono, non esitare a contattarci per chiedere aiuto. Puoi inviare un ticket sulla nostra pagina GitHub o contattarci tramite Discord:
+error.404.head=404 - Pagina non trovata | Spiacenti, siamo inciampati nel codice!
+error.404.1=Non riusciamo a trovare la pagina che stai cercando.
+error.404.2=Qualcosa è andato storto
+error.github=Invia un ticket su GitHub
+error.showStack=Mostra traccia dello stack
+error.copyStack=Copia traccia dello stack
+error.githubSubmit=GitHub: invia un ticket
+error.discordSubmit=Discord: invia post di supporto
+
diff --git a/src/main/resources/messages_ja_JP.properties b/src/main/resources/messages_ja_JP.properties
index fb794c81..9f981333 100644
--- a/src/main/resources/messages_ja_JP.properties
+++ b/src/main/resources/messages_ja_JP.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -11,17 +11,19 @@ imgPrompt=画像を選択
genericSubmit=送信
processTimeWarning=警告:この処理はファイルサイズによって1分程度かかることがあります
pageOrderPrompt=ページ順序 (ページ番号をカンマ区切り又は2n+1のような関数で入力):
-pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
+pageSelectionPrompt=カスタムページ選択(ページ番号1、5、6または2n + 1などの関数のコンマ区切りリストを入力します):
goToPage=移動
-true=True
-false=False
+true=真
+false=偽
unknown=不明
save=保存
+saveToBrowser=ブラウザへ保存
close=閉じる
filesSelected=選択されたファイル
noFavourites=お気に入りはありません
+downloadComplete=ダウンロード完了
bored=待ち時間が退屈
-alphabet=\u30A2\u30EB\u30D5\u30A1\u30D9\u30C3\u30C8
+alphabet=アルファベット
downloadPdf=PDFをダウンロード
text=テキスト
font=フォント
@@ -43,25 +45,43 @@ red=赤
green=緑
blue=青
custom=カスタム...
-WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
+WorkInProgess=作業中です。動作しないまたはバグがある可能性があります。問題があれば報告してください!
poweredBy=Powered by
-yes=Yes
-no=No
+yes=はい
+no=いいえ
changedCredsMessage=資格情報が変更されました!
notAuthenticatedMessage=ユーザーが認証されていません。
userNotFoundMessage=ユーザーが見つかりません。
incorrectPasswordMessage=現在のパスワードが正しくありません。
usernameExistsMessage=新しいユーザー名はすでに存在します。
+invalidUsernameMessage=ユーザー名が無効です。ユーザー名にはアルファベットと数字のみを使用してください。
+deleteCurrentUserMessage=現在ログインしているユーザーは削除できません。
+deleteUsernameExistsMessage=そのユーザー名は存在しないため削除できません。
+downgradeCurrentUserMessage=現在のユーザーの役割をダウングレードできません
+downgradeCurrentUserLongMessage=現在のユーザーの役割をダウングレードできません。したがって、現在のユーザーは表示されません。
+error=エラー
+oops=おっと!
+help=ヘルプ
+goHomepage=ホームページへ移動
+joinDiscord=Discordサーバーに参加する
+seeDockerHub=Docker Hubを見る
+visitGithub=Githubリポジトリを訪問する
+donate=寄付する
+color=色
+sponsor=スポンサー
+
###############
# Pipeline #
###############
pipeline.header=パイプラインメニュー (Alpha)
-pipeline.uploadButton=Upload Custom
+pipeline.uploadButton=カスタムのアップロード
pipeline.configureButton=設定
pipeline.defaultOption=カスタム
pipeline.submitButton=送信
+pipeline.help=パイプラインのヘルプ
+pipeline.scanHelp=フォルダ スキャンのヘルプ
######################
# Pipeline Options #
@@ -70,7 +90,7 @@ pipelineOptions.header=パイプライン設定
pipelineOptions.pipelineNameLabel=パイプライン名
pipelineOptions.saveSettings=動作設定の保存
pipelineOptions.pipelineNamePrompt=ここにパイプライン名を入力
-pipelineOptions.selectOperation=Select Operation
+pipelineOptions.selectOperation=動作の選択
pipelineOptions.addOperationButton=動作の追加
pipelineOptions.pipelineHeader=パイプライン:
pipelineOptions.saveButton=ダウンロード
@@ -94,6 +114,7 @@ navbar.settings=設定
#############
settings.title=設定
settings.update=利用可能なアップデート
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=Appバージョン:
settings.downloadOption.title=ダウンロードオプション (zip以外の単一ファイル):
settings.downloadOption.1=同じウィンドウで開く
@@ -102,12 +123,13 @@ settings.downloadOption.3=ファイルをダウンロード
settings.zipThreshold=このファイル数を超えたときにファイルを圧縮する
settings.signOut=サインアウト
settings.accountSettings=アカウント設定
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=資格情報の変更
changeCreds.header=アカウントの詳細を更新する
-changeCreds.changeUserAndPassword=デフォルトのログイン認証情報を使用しています。新しいパスワード (必要に応じてユーザー名も) を入力してください
+changeCreds.changePassword=デフォルトのログイン認証情報を使用しています。新しいパスワードを入力してください
changeCreds.newUsername=新しいユーザー名
changeCreds.oldPassword=現在のパスワード
changeCreds.newPassword=新しいパスワード
@@ -142,14 +164,18 @@ adminUserSettings.header=管理者ユーザー制御設定
adminUserSettings.admin=管理者
adminUserSettings.user=ユーザー
adminUserSettings.addUser=新しいユーザを追加
+adminUserSettings.usernameInfo=ユーザー名には文字と数字のみが使用でき、スペースや特殊文字は使用できません。
adminUserSettings.roles=役割
adminUserSettings.role=役割
adminUserSettings.actions=アクション
adminUserSettings.apiUser=限定されたAPIユーザー
+adminUserSettings.extraApiUser=追加の制限付きAPIユーザー
adminUserSettings.webOnlyUser=ウェブ専用ユーザー
-adminUserSettings.demoUser=Demo User (No custom settings)
+adminUserSettings.demoUser=デモユーザー (カスタム設定なし)
+adminUserSettings.internalApiUser=内部APIユーザー
adminUserSettings.forceChange=ログイン時にユーザー名/パスワードを強制的に変更する
adminUserSettings.submit=ユーザーの保存
+adminUserSettings.changeUserRole=ユーザーの役割を変更する
#############
# HOME-PAGE #
@@ -158,7 +184,7 @@ home.desc=PDFのあらゆるニーズに対応するローカルホスティン
home.searchBar=機能検索...
-home.viewPdf.title=View PDF
+home.viewPdf.title=PDFを表示
home.viewPdf.desc=表示、注釈、テキストや画像の追加
viewPdf.tags=view,read,annotate,text,image
@@ -387,11 +413,20 @@ home.split-by-sections.title=PDFをセクションで分割
home.split-by-sections.desc=PDFの各ページを縦横に分割します。
split-by-sections.tags=Section Split, Divide, Customize
-home.AddStampRequest.title=Add Stamp to PDF
-home.AddStampRequest.desc=Add text or add image stamps at set locations
+home.AddStampRequest.title=PDFにスタンプを追加
+home.AddStampRequest.desc=設定した位置にテキストや画像のスタンプを追加できます
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDFを書籍に変換
+home.PDFToBook.desc=calibreを使用してPDFを書籍/コミック形式に変換します
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=PDFを書籍に変換
+home.BookToPDF.desc=calibreを使用してPDFを書籍/コミック形式に変換します
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=サインイン
+login.header=サインイン
login.signin=サインイン
login.rememberme=サインイン状態を記憶する
login.invalid=ユーザー名かパスワードが無効です。
login.locked=あなたのアカウントはロックされています。
login.signinTitle=サインインしてください
+login.ssoSignIn=シングルサインオンでログイン
+login.oauth2AutoCreateDisabled=OAuth 2自動作成ユーザーが無効
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=単一ページに変換
pageExtracter.title=ページの抽出
pageExtracter.header=ページの抽出
pageExtracter.submit=抽出
+pageExtracter.placeholder=(例:1,2,8、4,7,12-16、2n-1)
#getPdfInfo
@@ -467,37 +506,37 @@ HTMLToPDF.header=HTMLをPDFに変換
HTMLToPDF.help=HTMLファイルと必要なhtml/css/画像などを含むZIPを受け入れます
HTMLToPDF.submit=変換
HTMLToPDF.credit=WeasyPrintを使用
-HTMLToPDF.zoom=Zoom level for displaying the website.
-HTMLToPDF.pageWidth=Width of the page in centimeters. (Blank to default)
-HTMLToPDF.pageHeight=Height of the page in centimeters. (Blank to default)
-HTMLToPDF.marginTop=Top margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginBottom=Bottom margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginLeft=Left margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginRight=Right margin of the page in millimeters. (Blank to default)
-HTMLToPDF.printBackground=Render the background of websites.
-HTMLToPDF.defaultHeader=Enable Default Header (Name and page number)
-HTMLToPDF.cssMediaType=Change the CSS media type of the page.
-HTMLToPDF.none=None
-HTMLToPDF.print=Print
-HTMLToPDF.screen=Screen
+HTMLToPDF.zoom=Webサイトを表示するためのズームレベル。
+HTMLToPDF.pageWidth=ページ幅 (cm)。 (デフォルトでは空白)
+HTMLToPDF.pageHeight=ページ高さ (cm)。 (デフォルトでは空白)
+HTMLToPDF.marginTop=ページ上の余白 (mm)。 (デフォルトでは空白)
+HTMLToPDF.marginBottom=ページ下の余白 (mm)。 (デフォルトでは空白)
+HTMLToPDF.marginLeft=ページ左の余白 (mm)。 (デフォルトでは空白)
+HTMLToPDF.marginRight=ページ右の余白 (mm)。 (デフォルトでは空白)
+HTMLToPDF.printBackground=Webサイトの背景をレンダリングします。
+HTMLToPDF.defaultHeader=デフォルトのヘッダー (名前とページ番号) を有効にする
+HTMLToPDF.cssMediaType=ページのCSSメディアタイプを変更します。
+HTMLToPDF.none=なし
+HTMLToPDF.print=印刷
+HTMLToPDF.screen=画面
#AddStampRequest
-AddStampRequest.header=Stamp PDF
-AddStampRequest.title=Stamp PDF
-AddStampRequest.stampType=Stamp Type
-AddStampRequest.stampText=Stamp Text
-AddStampRequest.stampImage=Stamp Image
-AddStampRequest.alphabet=Alphabet
-AddStampRequest.fontSize=Font/Image Size
-AddStampRequest.rotation=Rotation
-AddStampRequest.opacity=Opacity
-AddStampRequest.position=Position
-AddStampRequest.overrideX=Override X Coordinate
-AddStampRequest.overrideY=Override Y Coordinate
-AddStampRequest.customMargin=Custom Margin
-AddStampRequest.customColor=Custom Text Color
-AddStampRequest.submit=Submit
+AddStampRequest.header=PDFにスタンプを押す
+AddStampRequest.title=PDFにスタンプを押す
+AddStampRequest.stampType=スタンプの種類
+AddStampRequest.stampText=スタンプする文章
+AddStampRequest.stampImage=スタンプする画像
+AddStampRequest.alphabet=文字
+AddStampRequest.fontSize=フォント/画像 サイズ
+AddStampRequest.rotation=回転
+AddStampRequest.opacity=不透明度
+AddStampRequest.position=位置
+AddStampRequest.overrideX=X座標のオーバーライド
+AddStampRequest.overrideY=Y座標のオーバーライド
+AddStampRequest.customMargin=余白のカスタム
+AddStampRequest.customColor=文字色のカスタム
+AddStampRequest.submit=送信
#sanitizePDF
@@ -522,7 +561,7 @@ addPageNumbers.selectText.5=番号をつけるページ
addPageNumbers.selectText.6=カスタムテキスト
addPageNumbers.customTextDesc=カスタムテキスト
addPageNumbers.numberPagesDesc=番号をつけるページ、デフォルトは'all'、 1-5 や 2,5,9 など
-addPageNumbers.customNumberDesc=デフォルトは{n}、'{n} / {total} ページ'、'テキスト-{n}'、'{filename}-{n}など
+addPageNumbers.customNumberDesc=デフォルトは{n}、'{n} / {total} ページ'、'テキスト-{n}'、'{filename}-{n}など'
addPageNumbers.submit=ページ番号の追加
@@ -570,7 +609,7 @@ pipeline.title=パイプライン
pageLayout.title=マルチページレイアウト
pageLayout.header=マルチページレイアウト
pageLayout.pagesPerSheet=1枚あたりのページ数:
-pageLayout.addBorder=Add Borders
+pageLayout.addBorder=境界線を追加
pageLayout.submit=送信
@@ -586,11 +625,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.jksNote=注: 証明書のタイプが以下にリストされていない場合は、keytoolコマンドラインツールを使用して証明書をJavaキーストア(.jks)ファイルに変換してください。次に以下の.jksファイル オプションを選択します。
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.selectJKS=Javaキーストアファイルを選択 (.jks or .keystore):
certSign.certType=証明書の種類
certSign.password=キーストアまたは秘密キーのパスワードを入力 (ある場合) :
certSign.showSig=署名を表示
@@ -613,7 +652,7 @@ removeBlanks.submit=空白ページの削除
#removeAnnotations
removeAnnotations.title=注釈の削除
removeAnnotations.header=注釈の削除
-removeAnnotations.submit=Remove
+removeAnnotations.submit=削除
#compare
@@ -623,6 +662,18 @@ compare.document.1=ドキュメント 1
compare.document.2=ドキュメント 2
compare.submit=比較
+#BookToPDF
+BookToPDF.title=書籍やコミックをPDFに変換
+BookToPDF.header=書籍をPDFに変換
+BookToPDF.credit=calibreを使用
+BookToPDF.submit=変換
+
+#PDFToBook
+PDFToBook.title=書籍をPDFに変換
+PDFToBook.header=書籍をPDFに変換
+PDFToBook.selectText.1=フォーマット
+PDFToBook.credit=calibreを使用
+PDFToBook.submit=変換
#sign
sign.title=署名
@@ -643,6 +694,7 @@ repair.submit=修復
#flatten
flatten.title=平坦化
flatten.header=PDFを平坦化する
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=平坦化
@@ -726,21 +778,34 @@ merge.submit=結合
pdfOrganiser.title=整理
pdfOrganiser.header=PDFページの整理
pdfOrganiser.submit=ページの整理
+pdfOrganiser.mode=モード
+pdfOrganiser.mode.1=カスタムページ順序
+pdfOrganiser.mode.2=逆順
+pdfOrganiser.mode.3=デュプレックスソート
+pdfOrganiser.mode.4=小冊子ソート
+pdfOrganiser.mode.5=サイドステッチ小冊子ソート
+pdfOrganiser.mode.6=奇数-偶数分割
+pdfOrganiser.mode.7=最初に削除
+pdfOrganiser.mode.8=最後を削除
+pdfOrganiser.mode.9=最初と最後を削除
+pdfOrganiser.placeholder=(例:1,3,2または4-8,2,10-12または2n-1)
#multiTool
multiTool.title=PDFマルチツール
multiTool.header=PDFマルチツール
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
-viewPdf.title=View PDF
-viewPdf.header=View PDF
+viewPdf.title=PDFを表示
+viewPdf.header=PDFを表示
#pageRemover
pageRemover.title=ページ削除
pageRemover.header=PDFページ削除
pageRemover.pagesToDelete=削除するページ (ページ番号のカンマ区切りリストを入力してください):
pageRemover.submit=ページ削除
+pageRemover.placeholder=(例:1,2,6または1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=回転角度を選択 (90度の倍数):
rotate.submit=回転
-#merge
+#split-pdfs
split.title=PDFの分割
split.header=PDFの分割
split.desc.1=選択する番号は分割するページ番号です。
-split.desc.2=したがって、1,3,7-8を選択すると、10ページのドキュメントが以下のように6つのPDFに分割されることになります。
+split.desc.2=したがって、1,3,7-9を選択すると、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.desc.5=ドキュメント #3: ページ 4, 5, 6, 7
+split.desc.6=ドキュメント #4: ページ 8
+split.desc.7=ドキュメント #5: ページ 9
+split.desc.8=ドキュメント #6: ページ 10
split.splitPages=分割するページ番号を入力:
split.submit=分割
@@ -825,9 +890,11 @@ watermark.selectText.4=回転 (0-360):
watermark.selectText.5=幅スペース (各透かし間の水平方向のスペース):
watermark.selectText.6=高さスペース (各透かし間の垂直方向のスペース):
watermark.selectText.7=不透明度 (0% - 100%):
-watermark.selectText.8=Watermark Type:
-watermark.selectText.9=Watermark Image:
+watermark.selectText.8=透かしの種類:
+watermark.selectText.9=透かしの画像:
watermark.submit=透かしを追加
+watermark.type.1=テキスト
+watermark.type.2=画像
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDFをPDF/Aに変換
pdfToPDFA.header=PDFをPDF/Aに変換
pdfToPDFA.credit=本サービスはPDF/Aの変換にOCRmyPDFを使用しています。
pdfToPDFA.submit=変換
+pdfToPDFA.tip=現在、一度に複数の入力に対して機能しません
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=変換
#PDFToHTML
PDFToHTML.title=PDFをHTMLに変換
PDFToHTML.header=PDFをHTMLに変換
-PDFToHTML.credit=本サービスはファイル変換にLibreOfficeを使用しています。
+PDFToHTML.credit=本サービスはファイル変換にpdftohtmlを使用しています。
PDFToHTML.submit=変換
@@ -925,6 +994,7 @@ PDFToCSV.prompt=表を抽出するページを選択
PDFToCSV.submit=変換
#split-by-size-or-count
+split-by-size-or-count.title=サイズまたは数で分割
split-by-size-or-count.header=サイズまたは数で分割
split-by-size-or-count.type.label=分割タイプの選択
split-by-size-or-count.type.size=サイズ
@@ -959,6 +1029,15 @@ split-by-sections.vertical.label=垂直方向
split-by-sections.horizontal.placeholder=水平方向の分割数を選択
split-by-sections.vertical.placeholder=垂直方向の分割数を選択
split-by-sections.submit=分割
+split-by-sections.merge=1 つの PDF に結合するかどうか
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
@@ -969,3 +1048,17 @@ licenses.module=モジュール
licenses.version=バージョン
licenses.license=ライセンス
+
+# error
+error.sorry=問題が発生したことをお詫び申し上げます!
+error.needHelp=助けが必要/問題が見つかりましたか?
+error.contactTip=まだ問題が解決していない場合は、お手数ですが、GitHubページでチケットを提出するか、Discordで私たちに連絡してください:
+error.404.head=404 - ページが見つかりません | おっと、コードでつまずきました!
+error.404.1=あなたが探しているページが見つかりません。
+error.404.2=何か問題が発生しました
+error.github=GitHubでチケットを提出
+error.showStack=スタックトレースを表示
+error.copyStack=スタックトレースをコピー
+error.githubSubmit=GitHub - チケットを提出
+error.discordSubmit=Discord - サポート投稿を提出
+
diff --git a/src/main/resources/messages_ko_KR.properties b/src/main/resources/messages_ko_KR.properties
index a016e6b3..da011ec6 100644
--- a/src/main/resources/messages_ko_KR.properties
+++ b/src/main/resources/messages_ko_KR.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -11,70 +11,90 @@ imgPrompt=이미지 선택
genericSubmit=확인
processTimeWarning=경고: 파일 크기에 따라 1분 정도 소요될 수 있습니다
pageOrderPrompt=페이지 순서(쉼표로 구분된 페이지 번호 목록 입력):
-pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
+pageSelectionPrompt=사용자 지정 페이지 선택(페이지 번호 1,5,6 또는 2n+1과 같은 기능을 쉼표로 구분하여 목록 입력):
goToPage=이동
true=참
false=거짓
unknown=알 수 없음
save=저장
+saveToBrowser=브라우저에 저장
close=닫기
filesSelected=개 파일 선택됨
noFavourites=즐겨찾기 없음
+downloadComplete=다운로드 완료
bored=기다리는 게 지루하신가요?
-alphabet=\uC54C\uD30C\uBCB3
+alphabet=알파벳
downloadPdf=PDF 다운로드
text=텍스트
font=폰트
selectFillter=-- 선택 --
pageNum=페이지 번호
-sizes.small=Small
-sizes.medium=Medium
-sizes.large=Large
-sizes.x-large=X-Large
+sizes.small=작은 크기
+sizes.medium=중간 사이즈
+sizes.large=큰 사이즈
+sizes.x-large=초대형 사이즈
error.pdfPassword=이 PDF는 비밀번호로 보호되어 있으며, 비밀번호를 입력하지 않았거나, 입력된 비밀번호가 올바르지 않습니다.
delete=삭제
username=사용자명
password=비밀번호
welcome=환영합니다.
-property=Property
-black=Black
-white=White
-red=Red
-green=Green
-blue=Blue
-custom=Custom...
-WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
+property=재산
+black=검정
+white=하얀
+red=빨강
+green=녹색
+blue=파랑
+custom=관습...
+WorkInProgess=작업 진행 중, 작동하지 않거나 버그가 있을 수 있음, 문제가 있으면 보고하십시오!
poweredBy=Powered by
-yes=Yes
-no=No
+yes=예
+no=아니요
changedCredsMessage=계정 정보 변경 성공!
-notAuthenticatedMessage=User not authenticated.
+notAuthenticatedMessage=사용자가 인증되지 않았습니다.
userNotFoundMessage=사용자를 찾을 수 없습니다.
incorrectPasswordMessage=현재 비밀번호가 틀립니다.
usernameExistsMessage=새 사용자명이 이미 존재합니다.
+invalidUsernameMessage=사용자 이름이 잘못되었습니다. 사용자 이름에는 알파벳 문자와 숫자만 포함되어야 합니다.
+deleteCurrentUserMessage=현재 로그인한 사용자를 삭제할 수 없습니다.
+deleteUsernameExistsMessage=사용자 이름이 존재하지 않으며 삭제할 수 없습니다.
+downgradeCurrentUserMessage=현재 사용자의 역할을 다운그레이드할 수 없습니다
+downgradeCurrentUserLongMessage=현재 사용자의 역할을 다운그레이드할 수 없습니다. 따라서 현재 사용자는 표시되지 않습니다.
+error=오류
+oops=어머나!
+help=도움말
+goHomepage=홈페이지로 이동
+joinDiscord=Discord 서버에 참여하기
+seeDockerHub=Docker Hub에서 확인하기
+visitGithub=GitHub 저장소 방문하기
+donate=기부하기
+color=색상
+sponsor=스폰서
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
-pipeline.uploadButton=Upload Custom
-pipeline.configureButton=Configure
-pipeline.defaultOption=Custom
-pipeline.submitButton=Submit
+pipeline.header=파이프라인 메뉴 (Beta)
+pipeline.uploadButton=사용자 지정 업로드
+pipeline.configureButton=구성
+pipeline.defaultOption=관습
+pipeline.submitButton=전송
+pipeline.help=파이프라인 도움말
+pipeline.scanHelp=폴더 스캔 도움말
######################
# 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
+pipelineOptions.header=파이프라인 구성
+pipelineOptions.pipelineNameLabel=파이프라인 이름
+pipelineOptions.saveSettings=작업 설정 저장
+pipelineOptions.pipelineNamePrompt=여기에 파이프라인 이름을 입력합니다.
+pipelineOptions.selectOperation=작업 선택
+pipelineOptions.addOperationButton=작업 추가
+pipelineOptions.pipelineHeader=파이프라인:
+pipelineOptions.saveButton=다운로드
+pipelineOptions.validateButton=확인
@@ -94,6 +114,7 @@ navbar.settings=설정
#############
settings.title=설정
settings.update=업데이트 가능
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=앱 버전:
settings.downloadOption.title=다운로드 옵션 선택 (zip 파일이 아닌 단일 파일 다운로드 시):
settings.downloadOption.1=현재 창에서 열기
@@ -102,12 +123,13 @@ settings.downloadOption.3=다운로드
settings.zipThreshold=다운로드한 파일 수가 초과된 경우 파일 압축하기
settings.signOut=로그아웃
settings.accountSettings=계정 설정
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=계정 정보 변경
changeCreds.header=계정 정보 업데이트
-changeCreds.changeUserAndPassword=기본 제공된 로그인 정보를 사용하고 있습니다. 새 비밀번호를 입력합니다. (필요하다면 사용자명을 변경할 수 있습니다.)
+changeCreds.changePassword=기본 로그인 자격 증명을 사용하고 있습니다. 새 비밀번호를 입력해 주세요.
changeCreds.newUsername=새 사용자명
changeCreds.oldPassword=현재 비밀번호
changeCreds.newPassword=새 비밀번호
@@ -119,20 +141,20 @@ changeCreds.submit=변경
account.title=계정 설정
account.accountSettings=계정 설정
account.adminSettings=관리자 설정 - 사용자 추가 및 확인
-account.userControlSettings=User Control Settings
+account.userControlSettings=사용자 컨트롤 설정
account.changeUsername=사용자명 변경
account.newUsername=새 사용자 이름
-account.password=Confirmation Password
+account.password=확인 비밀번호
account.oldPassword=이전 비밀번호
account.newPassword=새 비밀번호
account.changePassword=비밀번호 변경
account.confirmNewPassword=새 비밀번호 확인
account.signOut=로그아웃
account.yourApiKey=API 키
-account.syncTitle=Sync browser settings with Account
-account.settingsCompare=Settings Comparison:
-account.property=Property
-account.webBrowserSettings=Web Browser Setting
+account.syncTitle=브라우저 설정을 계정과 동기화
+account.settingsCompare=설정 비교:
+account.property=재산
+account.webBrowserSettings=웹 브라우저 설정
account.syncToBrowser=계정 -> 브라우저로 동기화
account.syncToAccount=브라우저 -> 계정으로 동기화
@@ -142,14 +164,18 @@ adminUserSettings.header=사용자 관리
adminUserSettings.admin=관리자
adminUserSettings.user=사용자
adminUserSettings.addUser=새 사용자 추가
+adminUserSettings.usernameInfo=사용자 이름은 문자와 숫자만 포함해야 하며 공백이나 특수 문자는 포함할 수 없습니다.
adminUserSettings.roles=역할
adminUserSettings.role=역할
adminUserSettings.actions=동작
adminUserSettings.apiUser=제한된 API 사용
+adminUserSettings.extraApiUser=제한된 API 사용자 추가
adminUserSettings.webOnlyUser=웹 사용만 허용
-adminUserSettings.demoUser=Demo User (No custom settings)
+adminUserSettings.demoUser=데모 사용자(사용자 지정 설정 없음)
+adminUserSettings.internalApiUser=내부 API 사용자
adminUserSettings.forceChange=다음 로그인 때 사용자명과 비밀번호를 변경하도록 강제
adminUserSettings.submit=사용자 저장
+adminUserSettings.changeUserRole=사용자의 역할 변경
#############
# HOME-PAGE #
@@ -179,11 +205,11 @@ home.rotate.desc=PDF 페이지를 회전합니다.
rotate.tags=server side
-home.imageToPdf.title=Image to PDF
+home.imageToPdf.title=이미지를 PDF로
home.imageToPdf.desc=이미지(PNG, JPEG, GIF)를 PDF 문서로 변환합니다.
imageToPdf.tags=conversion,img,jpg,picture,photo
-home.pdfToImage.title=PDF to Image
+home.pdfToImage.title=PDF를 이미지로
home.pdfToImage.desc=PDF 문서을 이미지(PNG, JPEG, GIF)로 변환합니다.
pdfToImage.tags=conversion,img,jpg,picture,photo
@@ -239,15 +265,15 @@ home.extractImages.title=이미지 추출
home.extractImages.desc=PDF에서 모든 이미지를 추출하여 zip으로 저장합니다.
extractImages.tags=picture,photo,save,archive,zip,capture,grab
-home.pdfToPDFA.title=PDF to PDF/A
+home.pdfToPDFA.title=PDF를 PDF/A로 변환
home.pdfToPDFA.desc=장기 보관을 위해 PDF 문서를 PDF/A 문서로 변환합니다.
pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
-home.PDFToWord.title=PDF to Word
+home.PDFToWord.title=PDF를 Word로
home.PDFToWord.desc=PDF 문서를 Word 형식으로 변환합니다. (DOC, DOCX, ODT)
PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
-home.PDFToPresentation.title=PDF to Presentation
+home.PDFToPresentation.title=PDF를 프리젠테이션으로
home.PDFToPresentation.desc=PDF 문서를 프리젠테이션 형식으로 변환합니다. (PPT, PPTX, ODP)
PDFToPresentation.tags=slides,show,office,microsoft
@@ -255,12 +281,12 @@ home.PDFToText.title=PDF to 텍스트/RTF
home.PDFToText.desc=PDF 문서를 텍스트 또는 RTF 형식으로 변환합니다.
PDFToText.tags=richformat,richtextformat,rich text format
-home.PDFToHTML.title=PDF to HTML
+home.PDFToHTML.title=PDF를 HTML로
home.PDFToHTML.desc=PDF 문서를 HTML 형식으로 변환합니다.
PDFToHTML.tags=web content,browser friendly
-home.PDFToXML.title=PDF to XML
+home.PDFToXML.title=PDF를 XML로 변환
home.PDFToXML.desc=PDF 문서를 XML 형식으로 변환합니다.
PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
@@ -284,8 +310,8 @@ home.removeBlanks.title=빈 페이지 제거
home.removeBlanks.desc=PDF 문서에서 빈 페이지를 감지하고 제거합니다.
removeBlanks.tags=cleanup,streamline,non-content,organize
-home.removeAnnotations.title=Remove Annotations
-home.removeAnnotations.desc=Removes all comments/annotations from a PDF
+home.removeAnnotations.title=주석 제거
+home.removeAnnotations.desc=PDF에서 모든 주석/주석을 제거합니다.
removeAnnotations.tags=comments,highlight,notes,markup,remove
home.compare.title=비교
@@ -332,16 +358,16 @@ home.sanitizePdf.title=정제
home.sanitizePdf.desc=PDF 문서에서 스크립트와 같은 요소들을 제거합니다.
sanitizePdf.tags=clean,secure,safe,remove-threats
-home.URLToPDF.title=URL/Website To PDF
+home.URLToPDF.title=URL/웹사이트를 PDF로
home.URLToPDF.desc=http(s) 웹사이트를 PDF 문서로 변환합니다.
URLToPDF.tags=web-capture,save-page,web-to-doc,archive
-home.HTMLToPDF.title=HTML to PDF
+home.HTMLToPDF.title=HTML에서 PDF로
home.HTMLToPDF.desc=HTML 파일, 또는 ZIP 파일을 PDF로 변환합니다.
HTMLToPDF.tags=markup,web-content,transformation,convert
-home.MarkdownToPDF.title=Markdown to PDF
+home.MarkdownToPDF.title=Markdown에서 PDF로
home.MarkdownToPDF.desc=마크다운 파일을 PDF 문서로 변환합니다.
MarkdownToPDF.tags=markup,web-content,transformation,convert
@@ -369,29 +395,38 @@ home.autoRedact.title=자동 검열
home.autoRedact.desc=PDF 문서에서 입력된 텍스트들을 자동으로 검열(모자이크)합니다.
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
-home.tableExtraxt.title=PDF to CSV
-home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
+home.tableExtraxt.title=PDF에서 CSV로
+home.tableExtraxt.desc=PDF에서 표를 추출하여 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
+home.autoSizeSplitPDF.title=크기/개수로 자동 분할
+home.autoSizeSplitPDF.desc=단일 PDF를 크기, 페이지 수 또는 문서 수에 따라 여러 문서로 분할
autoSizeSplitPDF.tags=pdf,split,document,organization
-home.overlay-pdfs.title=Overlay PDFs
-home.overlay-pdfs.desc=Overlays PDFs on-top of another PDF
+home.overlay-pdfs.title=PDF 오버레이
+home.overlay-pdfs.desc=PDF를 다른 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
+home.split-by-sections.title=섹션별로 PDF 분할
+home.split-by-sections.desc=PDF의 각 페이지를 더 작은 가로와 세로 구역으로 나눕니다
split-by-sections.tags=Section Split, Divide, Customize
-home.AddStampRequest.title=Add Stamp to PDF
-home.AddStampRequest.desc=Add text or add image stamps at set locations
+home.AddStampRequest.title=PDF에 스탬프 추가
+home.AddStampRequest.desc=설정된 위치에 텍스트 추가 또는 이미지 스탬프 추가
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF를 책으로
+home.PDFToBook.desc=구경을 사용하여 PDF를 책/만화 형식으로 변환
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=책을 PDF로
+home.BookToPDF.desc=구경을 사용하여 책/만화 형식을 PDF로 변환
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=로그인
+login.header=로그인
login.signin=로그인
login.rememberme=로그인 유지
login.invalid=사용자 이름이나 비밀번호가 틀립니다.
login.locked=계정이 잠겼습니다.
login.signinTitle=로그인해 주세요.
+login.ssoSignIn=싱글사인온을 통한 로그인
+login.oauth2AutoCreateDisabled=OAUTH2 사용자 자동 생성 비활성화됨
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=단일 페이지로 통합
pageExtracter.title=페이지 추출
pageExtracter.header=페이지 추출
pageExtracter.submit=추출
+pageExtracter.placeholder=(예: 1,2,8 또는 4,7,12-16 또는 2n-1)
#getPdfInfo
@@ -446,7 +485,7 @@ getPdfInfo.downloadJson=JSON으로 다운로드
#markdown-to-pdf
-MarkdownToPDF.title=Markdown To PDF
+MarkdownToPDF.title=Markdown에서 PDF로
MarkdownToPDF.header=Markdown 문서를 PDF 문서로 변환
MarkdownToPDF.submit=변환
MarkdownToPDF.help=변환중
@@ -455,49 +494,49 @@ MarkdownToPDF.credit=이 기능은 WeasyPrint를 사용합니다.
#url-to-pdf
-URLToPDF.title=URL To PDF
+URLToPDF.title=URL을 PDF로
URLToPDF.header=URL을 PDF 문서로 변환
URLToPDF.submit=변환
URLToPDF.credit=이 기능은 WeasyPrint를 사용합니다.
#html-to-pdf
-HTMLToPDF.title=HTML To PDF
+HTMLToPDF.title=HTML을 PDF로
HTMLToPDF.header=HTML 파일을 PDF 문서로 변환
HTMLToPDF.help=HTML 파일, 또는 html/css/이미지 등을 포함한 ZIP 파일을 받습니다.
HTMLToPDF.submit=변환
HTMLToPDF.credit=이 기능은 WeasyPrint를 사용합니다.
-HTMLToPDF.zoom=Zoom level for displaying the website.
-HTMLToPDF.pageWidth=Width of the page in centimeters. (Blank to default)
-HTMLToPDF.pageHeight=Height of the page in centimeters. (Blank to default)
-HTMLToPDF.marginTop=Top margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginBottom=Bottom margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginLeft=Left margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginRight=Right margin of the page in millimeters. (Blank to default)
-HTMLToPDF.printBackground=Render the background of websites.
-HTMLToPDF.defaultHeader=Enable Default Header (Name and page number)
-HTMLToPDF.cssMediaType=Change the CSS media type of the page.
-HTMLToPDF.none=None
-HTMLToPDF.print=Print
-HTMLToPDF.screen=Screen
+HTMLToPDF.zoom=웹 사이트를 표시하기 위한 확대/축소 수준입니다.
+HTMLToPDF.pageWidth=센티미터 단위의 페이지 너비입니다. (기본값은 비어 있음)
+HTMLToPDF.pageHeight=페이지 높이(센티미터)입니다. (기본값은 비어 있음)
+HTMLToPDF.marginTop=페이지의 위쪽 여백(밀리미터)입니다. (기본값은 비어 있음)
+HTMLToPDF.marginBottom=페이지의 아래쪽 여백(밀리미터)입니다. (기본값은 비어 있음)
+HTMLToPDF.marginLeft=페이지의 왼쪽 여백(밀리미터)입니다. (기본값은 비어 있음)
+HTMLToPDF.marginRight=페이지의 오른쪽 여백(밀리미터)입니다. (기본값은 비어 있음)
+HTMLToPDF.printBackground=웹 사이트의 배경을 렌더링합니다.
+HTMLToPDF.defaultHeader=기본 헤더 활성화(이름 및 페이지 번호)
+HTMLToPDF.cssMediaType=페이지의 CSS 미디어 유형을 변경합니다.
+HTMLToPDF.none=없음
+HTMLToPDF.print=인쇄하다
+HTMLToPDF.screen=화면
#AddStampRequest
-AddStampRequest.header=Stamp PDF
-AddStampRequest.title=Stamp PDF
-AddStampRequest.stampType=Stamp Type
-AddStampRequest.stampText=Stamp Text
-AddStampRequest.stampImage=Stamp Image
-AddStampRequest.alphabet=Alphabet
-AddStampRequest.fontSize=Font/Image Size
-AddStampRequest.rotation=Rotation
-AddStampRequest.opacity=Opacity
-AddStampRequest.position=Position
-AddStampRequest.overrideX=Override X Coordinate
-AddStampRequest.overrideY=Override Y Coordinate
-AddStampRequest.customMargin=Custom Margin
-AddStampRequest.customColor=Custom Text Color
-AddStampRequest.submit=Submit
+AddStampRequest.header=스탬프 PDF
+AddStampRequest.title=스탬프 PDF
+AddStampRequest.stampType=스탬프 유형
+AddStampRequest.stampText=스탬프 텍스트
+AddStampRequest.stampImage=스탬프 이미지
+AddStampRequest.alphabet=알파벳
+AddStampRequest.fontSize=글꼴/이미지 크기
+AddStampRequest.rotation=회전
+AddStampRequest.opacity=불투명도
+AddStampRequest.position=위치
+AddStampRequest.overrideX=X 좌표 재정의
+AddStampRequest.overrideY=Y 좌표 재정의
+AddStampRequest.customMargin=맞춤 마진
+AddStampRequest.customColor=사용자 정의 텍스트 색상
+AddStampRequest.submit=전송
#sanitizePDF
@@ -586,11 +625,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.jksNote=참고: 인증서 유형이 아래에 나열되지 않은 경우 keytool 명령줄 도구를 사용하여 Java 키 저장소(.jks) 파일로 변환하십시오. 그런 다음 아래의 .jks 파일 옵션을 선택합니다.
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.selectJKS=Java 키 저장소 파일(.jks 또는 .keystore)을 선택합니다.
certSign.certType=인증서 유형
certSign.password=키 저장소 또는 개인 키 비밀번호를 입력합니다 (있는 경우):
certSign.showSig=서명 보기
@@ -611,9 +650,9 @@ removeBlanks.submit=빈 페이지 제거
#removeAnnotations
-removeAnnotations.title=Remove Annotations
-removeAnnotations.header=Remove Annotations
-removeAnnotations.submit=Remove
+removeAnnotations.title=주석 제거
+removeAnnotations.header=주석 제거
+removeAnnotations.submit=제거하다
#compare
@@ -623,6 +662,18 @@ compare.document.1=문서 1
compare.document.2=문서 2
compare.submit=비교
+#BookToPDF
+BookToPDF.title=책과 만화를 PDF로
+BookToPDF.header=책을 PDF로
+BookToPDF.credit=이 서비스는 파일 변환을 위해 Calibre 사용합니다.
+BookToPDF.submit=변환
+
+#PDFToBook
+PDFToBook.title=PDF를 책으로
+PDFToBook.header=PDF를 책으로
+PDFToBook.selectText.1=판
+PDFToBook.credit=이 서비스는 파일 변환을 위해 Calibre 사용합니다.
+PDFToBook.submit=변환
#sign
sign.title=서명
@@ -643,6 +694,7 @@ repair.submit=복구
#flatten
flatten.title=평탄화
flatten.header=PDF 문서의 레이어 평탄화
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=평탄화
@@ -717,8 +769,8 @@ addImage.submit=이미지 추가
#merge
merge.title=병합
merge.header=여러 개의 PDF 병합 (2개 이상)
-merge.sortByName=Sort by name
-merge.sortByDate=Sort by date
+merge.sortByName=이름순 정렬
+merge.sortByDate=날짜순 정렬
merge.submit=병합
@@ -726,11 +778,23 @@ merge.submit=병합
pdfOrganiser.title=페이지 정렬
pdfOrganiser.header=PDF 페이지 정렬
pdfOrganiser.submit=페이지 재정렬
+pdfOrganiser.mode=모드
+pdfOrganiser.mode.1=사용자 지정 페이지 순서
+pdfOrganiser.mode.2=역순
+pdfOrganiser.mode.3=양면 정렬(Duplex Sort)
+pdfOrganiser.mode.4=소책자 정렬
+pdfOrganiser.mode.5=사이드 스티치 소책자 정렬
+pdfOrganiser.mode.6=홀수-짝수 분할
+pdfOrganiser.mode.7=첫 번째 항목 삭제
+pdfOrganiser.mode.8=마지막 항목 제거
+pdfOrganiser.mode.9=첫 번째와 마지막 제거
+pdfOrganiser.placeholder=(예: 1,3,2 또는 4-8,2,10-12 또는 2n-1)
#multiTool
multiTool.title=PDF 멀티툴
multiTool.header=PDF 멀티툴
+multiTool.uploadPrompts=PDF를 업로드하십시오
#view pdf
viewPdf.title=PDF 뷰어
@@ -741,6 +805,7 @@ pageRemover.title=페이지 제거
pageRemover.header=PDF 페이지 제거
pageRemover.pagesToDelete=제거할 페이지 (쉼표로 구분된 페이지 번호 입력):
pageRemover.submit=페이지 제거
+pageRemover.placeholder=(예: 1,2,6 또는 1-10,15-30)
#rotate
@@ -750,23 +815,23 @@ rotate.selectAngle=회전 각도 선택 (90도의 배수로):
rotate.submit=회전
-#merge
+#split-pdfs
split.title=PDF 분할
split.header=PDF 분할
split.desc.1=입력한 번호는 분할할 페이지의 번호입니다.
-split.desc.2=예를 들어, 1,3,7-8을 입력하면 10페이지 문서를 아래와 같이 6개의 별도의 PDF 문서로 분할하게 됩니다.
+split.desc.2=예를 들어, 1,3,7-9을 입력하면 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.desc.5=문서 #3: 페이지 4, 5, 6, 7
+split.desc.6=문서 #4: 페이지 8
+split.desc.7=문서 #5: 페이지 9
+split.desc.8=문서 #6: 페이지 10
split.splitPages=분할할 페이지 입력:
split.submit=분할
#merge
-imageToPDF.title=Image to PDF
+imageToPDF.title=이미지를 PDF로
imageToPDF.header=이미지를 PDF로 변환
imageToPDF.submit=변환
imageToPDF.selectLabel=이미지 맞춤 방법
@@ -780,7 +845,7 @@ imageToPDF.selectText.5=별도의 PDF로 변환
#pdfToImage
-pdfToImage.title=PDF to Image
+pdfToImage.title=PDF를 이미지로
pdfToImage.header=PDF 문서를 이미지로 변환
pdfToImage.selectText=이미지 형식
pdfToImage.singleOrMultiple=이미지 결과 유형
@@ -828,6 +893,8 @@ watermark.selectText.7=투명도 (0% - 100%):
watermark.selectText.8=워터마크 유형:
watermark.selectText.9=워터마크 이미지:
watermark.submit=워터마크 추가
+watermark.type.1=텍스트
+watermark.type.2=이미지
#Change permissions
@@ -875,14 +942,16 @@ changeMetadata.submit=변경
#pdfToPDFA
-pdfToPDFA.title=PDF To PDF/A
+pdfToPDFA.title=PDF를 PDF/A로
pdfToPDFA.header=PDF 문서를 PDF/A로 변환
pdfToPDFA.credit=이 서비스는 PDF/A 변환을 위해 OCRmyPDF 문서를 사용합니다.
pdfToPDFA.submit=변환
+pdfToPDFA.tip=현재 한 번에 여러 입력에 대해 작동하지 않습니다.
+pdfToPDFA.outputFormat=Output format
#PDFToWord
-PDFToWord.title=PDF to Word
+PDFToWord.title=PDF를 Word로
PDFToWord.header=PDF 문서를 Word 문서로 변환
PDFToWord.selectText.1=출력 파일 형식
PDFToWord.credit=이 서비스는 파일 변환을 위해 LibreOffice를 사용합니다.
@@ -890,7 +959,7 @@ PDFToWord.submit=변환
#PDFToPresentation
-PDFToPresentation.title=PDF to Presentation
+PDFToPresentation.title=PDF를 프리젠테이션으로
PDFToPresentation.header=PDF 문서를 프레젠테이션으로 변환
PDFToPresentation.selectText.1=출력 파일 형식
PDFToPresentation.credit=이 서비스는 파일 변환을 위해 LibreOffice를 사용합니다.
@@ -898,7 +967,7 @@ PDFToPresentation.submit=변환
#PDFToText
-PDFToText.title=PDF to RTF
+PDFToText.title=PDF에서 RTF로
PDFToText.header=PDF 문서를 RTF(서식 있는 텍스트 문서)로 변환
PDFToText.selectText.1=출력 파일 형식
PDFToText.credit=이 서비스는 파일 변환을 위해 LibreOffice를 사용합니다.
@@ -906,67 +975,90 @@ PDFToText.submit=변환
#PDFToHTML
-PDFToHTML.title=PDF to HTML
+PDFToHTML.title=PDF를 HTML로
PDFToHTML.header=PDF 문서를 HTML로 변환
-PDFToHTML.credit=이 서비스는 파일 변환을 위해 LibreOffice를 사용합니다.
+PDFToHTML.credit=이 서비스는 파일 변환을 위해 pdftohtml를 사용합니다.
PDFToHTML.submit=변환
#PDFToXML
-PDFToXML.title=PDF to XML
+PDFToXML.title=PDF를 XML로 변환
PDFToXML.header=PDF 문서를 XML로 변환
PDFToXML.credit=이 서비스는 파일 변환을 위해 LibreOffice를 사용합니다.
PDFToXML.submit=변환
#PDFToCSV
-PDFToCSV.title=PDF? CSV?
-PDFToCSV.header=PDF? CSV?
-PDFToCSV.prompt=Choose page to extract table
-PDFToCSV.submit=??
+PDFToCSV.title=PDF에서 CSV로
+PDFToCSV.header=PDF에서 CSV로
+PDFToCSV.prompt=테이블을 추출할 페이지 선택
+PDFToCSV.submit=추출물
#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
+split-by-size-or-count.title=크기 또는 개수로 PDF 분할
+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=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
+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=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
+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 분할
+split-by-sections.merge=하나의 PDF로 병합
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
-licenses.nav=Licenses
-licenses.title=3rd Party Licenses
-licenses.header=3rd Party Licenses
-licenses.module=Module
-licenses.version=Version
-licenses.license=License
+licenses.nav=라이센스
+licenses.title=제3자 라이선스
+licenses.header=제3자 라이선스
+licenses.module=모듈
+licenses.version=버전
+licenses.license=라이센스
+# error
+error.sorry=문제를 끼친 점 죄송합니다!
+error.needHelp=도움이 필요하신가요 / 문제가 있으신가요?
+error.contactTip=여전히 문제가 해결되지 않는다면 망설이지 마시고 도움을 요청하십시오. GitHub 페이지에서 티켓을 제출하거나 Discord를 통해 우리에게 연락하실 수 있습니다:
+error.404.head=404 - 페이지를 찾을 수 없습니다 | 이런, 코드에 걸려 넘어졌어요!
+error.404.1=원하시는 페이지를 찾을 수가 없네요.
+error.404.2=문제가 발생했습니다
+error.github=GitHub에서 티켓 제출
+error.showStack=스택 추적 보기
+error.copyStack=스택 추적 복사
+error.githubSubmit=GitHub - 티켓 제출
+error.discordSubmit=Discord - 문의 게시
+
diff --git a/src/main/resources/messages_nl_NL.properties b/src/main/resources/messages_nl_NL.properties
index fed34234..cbbf7b43 100644
--- a/src/main/resources/messages_nl_NL.properties
+++ b/src/main/resources/messages_nl_NL.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -17,9 +17,11 @@ true=Waar
false=Onwaar
unknown=Onbekend
save=Opslaan
+saveToBrowser=Save to Browser
close=Sluiten
filesSelected=Bestanden geselecteerd
noFavourites=Geen favorieten toegevoegd
+downloadComplete=Download Complete
bored=Verveeld met wachten?
alphabet=Alfabet
downloadPdf=Download PDF
@@ -52,6 +54,22 @@ notAuthenticatedMessage=Gebruiker niet ingelogd.
userNotFoundMessage=Gebruiker niet gevonden.
incorrectPasswordMessage=Huidige wachtwoord is onjuist.
usernameExistsMessage=Nieuwe gebruikersnaam bestaat al.
+invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
+deleteCurrentUserMessage=Cannot delete currently logged in user.
+deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
+downgradeCurrentUserMessage=Kan de rol van de huidige gebruiker niet downgraden
+downgradeCurrentUserLongMessage=Kan de rol van de huidige gebruiker niet downgraden. Huidige gebruiker wordt dus niet weergegeven.
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
###############
@@ -62,6 +80,8 @@ pipeline.uploadButton=Aangepast uploaden
pipeline.configureButton=Configureren
pipeline.defaultOption=Aangepast
pipeline.submitButton=Opslaan
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
######################
# Pipeline Options #
@@ -94,6 +114,7 @@ navbar.settings=Instellingen
#############
settings.title=Instellingen
settings.update=Update beschikbaar
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=App versie:
settings.downloadOption.title=Kies download optie (Voor enkelvoudige bestanddownloads zonder zip):
settings.downloadOption.1=Open in hetzelfde venster
@@ -102,12 +123,13 @@ settings.downloadOption.3=Download bestand
settings.zipThreshold=Bestanden zippen wanneer het aantal gedownloade bestanden meer is dan
settings.signOut=Uitloggen
settings.accountSettings=Account instellingen
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=Inloggegevens wijzigen
changeCreds.header=Werk je accountgegevens bij
-changeCreds.changeUserAndPassword=Je gebruikt de standaard inloggegevens. Voer een nieuw wachtwoord in (en eventueel een gebruikersnaam)
+changeCreds.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=Nieuwe gebruikersnaam
changeCreds.oldPassword=Huidige wachtwoord
changeCreds.newPassword=Nieuw wachtwoord
@@ -142,14 +164,18 @@ adminUserSettings.header=Beheer gebruikers
adminUserSettings.admin=Beheerder
adminUserSettings.user=Gebruiker
adminUserSettings.addUser=Voeg nieuwe gebruiker toe
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.roles=Rollen
adminUserSettings.role=Rol
adminUserSettings.actions=Acties
adminUserSettings.apiUser=Beperkte API gebruiker
+adminUserSettings.extraApiUser=Additional Limited API User
adminUserSettings.webOnlyUser=Alleen web gebruiker
adminUserSettings.demoUser=Demogebruiker (geen aangepaste instellingen)
+adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Forceer gebruiker om gebruikersnaam/wachtwoord te wijzigen bij inloggen
adminUserSettings.submit=Gebruiker opslaan
+adminUserSettings.changeUserRole=De rol van de gebruiker wijzigen
#############
# HOME-PAGE #
@@ -392,6 +418,15 @@ home.AddStampRequest.desc=Voeg tekst of afbeeldingsstempels toe op vaste locatie
AddStampRequest.tags=Stempel, Afbeelding toevoegen, afbeelding centreren, watermerk, PDF, Insluiten, Aanpassen
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stempel, Afbeelding toevoegen, afbeelding centreren, waterm
###########################
#login
login.title=Inloggen
+login.header=Inloggen
login.signin=Inloggen
login.rememberme=Onthoud mij
login.invalid=Ongeldige gebruikersnaam of wachtwoord.
login.locked=Je account is geblokkeerd.
login.signinTitle=Gelieve in te loggen
+login.ssoSignIn=Inloggen via Single Sign-on
+login.oauth2AutoCreateDisabled=OAUTH2 Automatisch aanmaken gebruiker uitgeschakeld
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Converteren naar enkele pagina
pageExtracter.title=Pagina's extraheren
pageExtracter.header=Pagina's extraheren
pageExtracter.submit=Extraheren
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -623,6 +662,18 @@ compare.document.1=Document 1
compare.document.2=Document 2
compare.submit=Vergelijken
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
#sign
sign.title=Ondertekenen
@@ -643,6 +694,7 @@ repair.submit=Repareren
#flatten
flatten.title=Afvlakken
flatten.header=PDF's afvlakken
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Afvlakken
@@ -726,11 +778,23 @@ merge.submit=Samenvoegen
pdfOrganiser.title=Pagina organisator
pdfOrganiser.header=PDF pagina organisator
pdfOrganiser.submit=Pagina's herschikken
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=PDF Multitool
multiTool.header=PDF Multitool
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
viewPdf.title=PDF bekijken
@@ -741,6 +805,7 @@ pageRemover.title=Pagina verwijderaar
pageRemover.header=PDF pagina verwijderaar
pageRemover.pagesToDelete=Te verwijderen pagina's (Voer een door komma's gescheiden lijst met paginanummers in):
pageRemover.submit=Pagina's verwijderen
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Selecteer rotatiehoek (in veelvouden van 90 graden):
rotate.submit=Roteren
-#merge
+#split-pdfs
split.title=PDF splitsen
split.header=PDF splitsen
split.desc.1=De nummers die je kiest zijn de paginanummers waarop je een splitsing wilt uitvoeren
-split.desc.2=Als zodanig selecteren van 1,3,7-8 zou een 10 pagina's tellend document splitsen in 6 aparte PDF's met:
+split.desc.2=Als zodanig selecteren van 1,3,7-9 zou een 10 pagina's tellend document splitsen in 6 aparte PDF's met:
split.desc.3=Document #1: Pagina 1
split.desc.4=Document #2: Pagina 2 en 3
-split.desc.5=Document #3: Pagina 4, 5 en 6
-split.desc.6=Document #4: Pagina 7
-split.desc.7=Document #5: Pagina 8
-split.desc.8=Document #6: Pagina 9 en 10
+split.desc.5=Document #3: Pagina 4, 5, 6 en 7
+split.desc.6=Document #4: Pagina 8
+split.desc.7=Document #5: Pagina 9
+split.desc.8=Document #6: Pagina 10
split.splitPages=Voer pagina's in om op te splitsen:
split.submit=Splitsen
@@ -828,6 +893,8 @@ watermark.selectText.7=Transparantie (0% - 100%):
watermark.selectText.8=Type watermerk:
watermark.selectText.9=Watermerk afbeelding:
watermark.submit=Watermerk toevoegen
+watermark.type.1=Text
+watermark.type.2=Image
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF naar PDF/A
pdfToPDFA.header=PDF naar PDF/A
pdfToPDFA.credit=Deze service gebruikt OCRmyPDF voor PDF/A-conversie
pdfToPDFA.submit=Converteren
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Converteren
#PDFToHTML
PDFToHTML.title=PDF naar HTML
PDFToHTML.header=PDF naar HTML
-PDFToHTML.credit=Deze service gebruikt LibreOffice voor bestandsconversie.
+PDFToHTML.credit=Deze service gebruikt pdftohtml voor bestandsconversie.
PDFToHTML.submit=Converteren
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Kies pagina om tabel te extraheren
PDFToCSV.submit=Extraheren
#split-by-size-or-count
+split-by-size-or-count.title=PDF splitsen op grootte of aantal
split-by-size-or-count.header=PDF splitsen op grootte of aantal
split-by-size-or-count.type.label=Selecteer splits type
split-by-size-or-count.type.size=Op grootte
@@ -959,6 +1029,15 @@ split-by-sections.vertical.label=Verticale secties
split-by-sections.horizontal.placeholder=Voer het aantal horizontale secties in
split-by-sections.vertical.placeholder=Voer het aantal verticale secties in
split-by-sections.submit=PDF splitsen
+split-by-sections.merge=Merge Into One PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Versie
licenses.license=Licentie
+# error
+error.sorry=Sorry for the issue!
+error.needHelp=Need help / Found an issue?
+error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
+error.404.head=404 - Page Not Found | Oops, we tripped in the code!
+error.404.1=We can't seem to find the page you're looking for.
+error.404.2=Something went wrong
+error.github=Submit a ticket on GitHub
+error.showStack=Show Stack Trace
+error.copyStack=Copy Stack Trace
+error.githubSubmit=GitHub - Submit a ticket
+error.discordSubmit=Discord - Submit Support post
+
diff --git a/src/main/resources/messages_pl_PL.properties b/src/main/resources/messages_pl_PL.properties
index c385a13f..757647ee 100644
--- a/src/main/resources/messages_pl_PL.properties
+++ b/src/main/resources/messages_pl_PL.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -17,9 +17,11 @@ true=Tak
false=Nie
unknown=Nieznany
save=Zapisz
+saveToBrowser=Save to Browser
close=Zamknij
filesSelected=wybrane pliki
noFavourites=Nie dodano ulubionych
+downloadComplete=Download Complete
bored=Znudzony czekaniem?
alphabet=Alfabet
downloadPdf=Pobierz PDF
@@ -52,16 +54,34 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
+invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
+deleteCurrentUserMessage=Cannot delete currently logged in user.
+deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
+downgradeCurrentUserMessage=Nie można obniżyć roli bieżącego użytkownika
+downgradeCurrentUserLongMessage=Nie można obniżyć roli bieżącego użytkownika. W związku z tym bieżący użytkownik nie zostanie wyświetlony.
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
+pipeline.header=Pipeline Menu (Beta)
pipeline.uploadButton=Upload Custom
pipeline.configureButton=Configure
pipeline.defaultOption=Custom
pipeline.submitButton=Submit
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
######################
# Pipeline Options #
@@ -94,6 +114,7 @@ navbar.settings=Ustawienia
#############
settings.title=Ustawienia
settings.update=Dostępna aktualizacja
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=Wersia aplikacji:
settings.downloadOption.title=Wybierz opcję pobierania (w przypadku pobierania pojedynczych plików innych niż ZIP):
settings.downloadOption.1=Otwórz w tym samym oknie
@@ -102,12 +123,13 @@ settings.downloadOption.3=Pobierz plik
settings.zipThreshold=Spakuj pliki, gdy liczba pobranych plików przekroczy
settings.signOut=Sign Out
settings.accountSettings=Account Settings
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=Change Credentials
changeCreds.header=Update Your Account Details
-changeCreds.changeUserAndPassword=You are using default login credentials. Please enter a new password (and username if wanted)
+changeCreds.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=New Username
changeCreds.oldPassword=Current Password
changeCreds.newPassword=New Password
@@ -142,14 +164,18 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
adminUserSettings.actions=Actions
adminUserSettings.apiUser=Limited API User
+adminUserSettings.extraApiUser=Additional 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.internalApiUser=Internal API User
+adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User
+adminUserSettings.changeUserRole=Zmień rolę użytkownika
#############
# HOME-PAGE #
@@ -392,6 +418,15 @@ home.AddStampRequest.desc=Add text or add image stamps at set locations
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Sign in
+login.header=Sign in
login.signin=Sign in
login.rememberme=Remember me
login.invalid=Invalid username or password.
login.locked=Your account has been locked.
login.signinTitle=Please sign in
+login.ssoSignIn=Zaloguj się za pomocą logowania jednokrotnego
+login.oauth2AutoCreateDisabled=Wyłączono automatyczne tworzenie użytkownika OAUTH2
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Convert To Single Page
pageExtracter.title=Extract Pages
pageExtracter.header=Extract Pages
pageExtracter.submit=Extract
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -623,6 +662,18 @@ compare.document.1=Dokument 1
compare.document.2=Dokument 2
compare.submit=Porównaj
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
#sign
sign.title=Podpis
@@ -643,6 +694,7 @@ repair.submit=Napraw
#flatten
flatten.title=Spłaszcz
flatten.header=Spłaszcz dokument(y) PDF
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Spłaszcz
@@ -726,11 +778,23 @@ merge.submit=Połącz
pdfOrganiser.title=Kolejność stron
pdfOrganiser.header=Kolejność stron PDF
pdfOrganiser.submit=Zmień kolejność stron
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=Multi narzędzie PDF
multiTool.header=Multi narzędzie PDF
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
viewPdf.title=View PDF
@@ -741,6 +805,7 @@ pageRemover.title=Narzędzie do usuwania stron
pageRemover.header=Narzędzie do usuwania stron w dokumentach PDF
pageRemover.pagesToDelete=Strony do usunięcia (wprowadź listę numerów stron oddzielonych przecinkami):
pageRemover.submit=Usuń strony
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Wybierz kąt obrotu (domyślnie 90 stopni):
rotate.submit=Obróć
-#merge
+#split-pdfs
split.title=Podziel dokument PDF
split.header=Podziel dokument PDF
split.desc.1=Wybrane numery to numery stron, na których chcesz dokonać podziału
-split.desc.2=Np. taki wybór 1,3,7-8 podzieliłby 10-stronicowy dokument na 6 oddzielnych plików PDF z:
+split.desc.2=Np. taki wybór 1,3,7-9 podzieliłby 10-stronicowy dokument na 6 oddzielnych plików PDF z:
split.desc.3=Dokument #1: Strona 1
split.desc.4=Dokument #2: Strona 2 i 3
-split.desc.5=Dokument #3: Strona 4, 5 i 6
-split.desc.6=Dokument #4: Strona 7
-split.desc.7=Dokument #5: Strona 8
-split.desc.8=Dokument #6: Strona 9 i 10
+split.desc.5=Dokument #3: Strona 4, 5, 6 i 7
+split.desc.6=Dokument #4: Strona 8
+split.desc.7=Dokument #5: Strona 9
+split.desc.8=Dokument #6: Strona 10
split.splitPages=Wprowadź strony do podziału na:
split.submit=Podziel
@@ -828,6 +893,8 @@ watermark.selectText.7=Nieprzezroczystość (0% - 100%):
watermark.selectText.8=Watermark Type:
watermark.selectText.9=Watermark Image:
watermark.submit=Dodaj znak wodny
+watermark.type.1=Text
+watermark.type.2=Image
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF na PDF/A
pdfToPDFA.header=PDF na PDF/A
pdfToPDFA.credit=Ta usługa używa OCRmyPDF do konwersji PDF/A
pdfToPDFA.submit=Konwertuj
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Konwertuj
#PDFToHTML
PDFToHTML.title=PDF na HTML
PDFToHTML.header=PDF na HTML
-PDFToHTML.credit=Ta usługa używa LibreOffice do konwersji plików.
+PDFToHTML.credit=Ta usługa używa pdftohtml do konwersji plików.
PDFToHTML.submit=Konwertuj
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Choose page to extract table
PDFToCSV.submit=Wyci?g
#split-by-size-or-count
+split-by-size-or-count.title=Split PDF 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
@@ -959,6 +1029,15 @@ 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
+split-by-sections.merge=Merge Into One PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Version
licenses.license=License
+# error
+error.sorry=Sorry for the issue!
+error.needHelp=Need help / Found an issue?
+error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
+error.404.head=404 - Page Not Found | Oops, we tripped in the code!
+error.404.1=We can't seem to find the page you're looking for.
+error.404.2=Something went wrong
+error.github=Submit a ticket on GitHub
+error.showStack=Show Stack Trace
+error.copyStack=Copy Stack Trace
+error.githubSubmit=GitHub - Submit a ticket
+error.discordSubmit=Discord - Submit Support post
+
diff --git a/src/main/resources/messages_pt_BR.properties b/src/main/resources/messages_pt_BR.properties
index 778f1df5..97ac151e 100644
--- a/src/main/resources/messages_pt_BR.properties
+++ b/src/main/resources/messages_pt_BR.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -17,9 +17,11 @@ true=Verdadeiro
false=Falso
unknown=Desconhecido
save=Salvar
+saveToBrowser=Save to Browser
close=Fechar
filesSelected=arquivos selecionados
noFavourites=Nenhum favorito adicionado
+downloadComplete=Download Complete
bored=Entediado esperando?
alphabet=Alfabeto
downloadPdf=baixar PDF
@@ -52,16 +54,34 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
+invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
+deleteCurrentUserMessage=Cannot delete currently logged in user.
+deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
+downgradeCurrentUserMessage=Não é possível fazer downgrade da função do usuário atual
+downgradeCurrentUserLongMessage=Não é possível fazer downgrade da função do usuário atual. Portanto, o usuário atual não será mostrado.
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
+pipeline.header=Pipeline Menu (Beta)
pipeline.uploadButton=Upload Custom
pipeline.configureButton=Configure
pipeline.defaultOption=Custom
pipeline.submitButton=Submit
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
######################
# Pipeline Options #
@@ -94,6 +114,7 @@ navbar.settings=Configurações
#############
settings.title=Configurações
settings.update=Atualização disponível
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=Versão do aplicativo:
settings.downloadOption.title=Escolha a opção de download (para downloads não compactados de arquivo único):
settings.downloadOption.1=Abrir na mesma janela
@@ -102,12 +123,13 @@ settings.downloadOption.3=⇬ Fazer download do arquivo
settings.zipThreshold=Compactar arquivos quando o número de arquivos baixados exceder
settings.signOut=Sign Out
settings.accountSettings=Account Settings
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=Change Credentials
changeCreds.header=Update Your Account Details
-changeCreds.changeUserAndPassword=You are using default login credentials. Please enter a new password (and username if wanted)
+changeCreds.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=New Username
changeCreds.oldPassword=Current Password
changeCreds.newPassword=New Password
@@ -142,14 +164,18 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
adminUserSettings.actions=Actions
adminUserSettings.apiUser=Limited API User
+adminUserSettings.extraApiUser=Additional 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.internalApiUser=Internal API User
+adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User
+adminUserSettings.changeUserRole=Alterar Função de Usuário
#############
# HOME-PAGE #
@@ -392,6 +418,15 @@ home.AddStampRequest.desc=Add text or add image stamps at set locations
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Sign in
+login.header=Sign in
login.signin=Sign in
login.rememberme=Remember me
login.invalid=Invalid username or password.
login.locked=Your account has been locked.
login.signinTitle=Please sign in
+login.ssoSignIn=Iniciar sessão através de início de sessão único
+login.oauth2AutoCreateDisabled=OAUTH2 Auto-Criar Usuário Desativado
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Converter para Página Única
pageExtracter.title=Extrair Páginas
pageExtracter.header=Extrair Páginas
pageExtracter.submit=Extrair
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -623,6 +662,18 @@ compare.document.1=Documento 1
compare.document.2=Documento 2
compare.submit=Comparar
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
#sign
sign.title=Assinar
@@ -643,6 +694,7 @@ repair.submit=Reparar
#flatten
flatten.title=Achatar
flatten.header=Achatar PDFs
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Achatar
@@ -726,11 +778,23 @@ merge.submit=Mesclar
pdfOrganiser.title=Organizador de Páginas
pdfOrganiser.header=Organizador de Páginas PDF
pdfOrganiser.submit=Reorganizar Páginas
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=Multiferramenta de PDF
multiTool.header=Multiferramenta de PDF
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
viewPdf.title=View PDF
@@ -741,6 +805,7 @@ pageRemover.title=Remover Página
pageRemover.header=Remover Páginas do PDF
pageRemover.pagesToDelete=Páginas a serem excluídas (insira uma lista separada por vírgulas de números de página):
pageRemover.submit=Excluir Páginas
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Selecione o ângulo de rotação (múltiplos de 90 graus):
rotate.submit=Girar
-#merge
+#split-pdfs
split.title=Dividir PDF
split.header=Dividir PDF
split.desc.1=Os números selecionados correspondem às páginas onde você deseja fazer a divisão.
-split.desc.2=Por exemplo, selecionar 1,3,7-8 dividirá um documento de 10 páginas em 6 PDFs separados da seguinte forma:
+split.desc.2=Por exemplo, selecionar 1,3,7-9 dividirá um documento de 10 páginas em 6 PDFs separados da seguinte forma:
split.desc.3=Documento Nº1: Página 1
split.desc.4=Documento Nº2: Páginas 2 e 3
-split.desc.5=Documento Nº3: Páginas 4, 5 e 6
-split.desc.6=Documento Nº4: Página 7
-split.desc.7=Documento Nº5: Página 8
-split.desc.8=Documento Nº6: Páginas 9 e 10
+split.desc.5=Documento Nº3: Páginas 4, 5, 6 e 7
+split.desc.6=Documento Nº4: Página 8
+split.desc.7=Documento Nº5: Página 9
+split.desc.8=Documento Nº6: Páginas 10
split.splitPages=Digite as páginas para a divisão:
split.submit=Dividir
@@ -828,6 +893,8 @@ watermark.selectText.7=Opacidade (0% - 100%)
watermark.selectText.8=Tipo de Marca d'Água
watermark.selectText.9=Imagem da Marca d'Água
watermark.submit=Adicionar Marca d'Água
+watermark.type.1=Text
+watermark.type.2=Image
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF para PDF/A
pdfToPDFA.header=PDF para PDF/A
pdfToPDFA.credit=Este serviço usa OCRmyPDF para Conversão de PDF/A
pdfToPDFA.submit=Converter
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Converter
#PDFToHTML
PDFToHTML.title=PDF para HTML
PDFToHTML.header=PDF para HTML
-PDFToHTML.credit=Este serviço usa o LibreOffice para Conversão de Arquivos.
+PDFToHTML.credit=Este serviço usa o pdftohtml para Conversão de Arquivos.
PDFToHTML.submit=Converter
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Choose page to extract table
PDFToCSV.submit=Eztenna
#split-by-size-or-count
+split-by-size-or-count.title=Split PDF 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
@@ -959,6 +1029,15 @@ 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
+split-by-sections.merge=Merge Into One PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Version
licenses.license=License
+# error
+error.sorry=Sorry for the issue!
+error.needHelp=Need help / Found an issue?
+error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
+error.404.head=404 - Page Not Found | Oops, we tripped in the code!
+error.404.1=We can't seem to find the page you're looking for.
+error.404.2=Something went wrong
+error.github=Submit a ticket on GitHub
+error.showStack=Show Stack Trace
+error.copyStack=Copy Stack Trace
+error.githubSubmit=GitHub - Submit a ticket
+error.discordSubmit=Discord - Submit Support post
+
diff --git a/src/main/resources/messages_pt_PT.properties b/src/main/resources/messages_pt_PT.properties
new file mode 100644
index 00000000..fcde52ad
--- /dev/null
+++ b/src/main/resources/messages_pt_PT.properties
@@ -0,0 +1,1064 @@
+###########
+# Generic #
+###########
+# the direction that the language is written (ltr=left to right, rtl = right to left)
+language.direction=ltr
+
+pdfPrompt=Selecione PDF(s)
+multiPdfPrompt=Selecione PDFs (2+)
+multiPdfDropPrompt=Selecione (ou arraste e solte) todos os PDFs necessários
+imgPrompt=Selecione a(s) imagem(ns)
+genericSubmit=Enviar
+processTimeWarning=Aviso: esse processo pode levar até um minuto, dependendo do tamanho do ficheiro
+pageOrderPrompt=Ordem das páginas (digite uma lista separada por vírgulas de números de página):
+pageSelectionPrompt=Seleção de página personalizada (Insira uma lista separada por vírgulas de números de página 1,5,6 ou funções como 2n+1):
+goToPage=Ir
+true=Verdadeiro
+false=Falso
+unknown=Desconhecido
+save=Salvar
+saveToBrowser=Save to Browser
+close=Fechar
+filesSelected=Ficheiros Selecionados
+noFavourites=Nenhum favorito adicionado
+downloadComplete=Download Complete
+bored=Entediado esperando?
+alphabet=Alfabeto
+downloadPdf=Descarregar PDF
+text=Texto
+font=Fonte
+selectFillter=-- Selecione --
+pageNum=Número de página
+sizes.small=Pequeno
+sizes.medium=Médio
+sizes.large=Grande
+sizes.x-large=Muito grande
+error.pdfPassword=O documento PDF está protegido por senha e a senha não foi fornecida ou está incorreta
+delete=Apagar
+username=Utilizador
+password=Senha
+welcome=Bem-vindo
+property=Propriedade
+black=Preto
+white=Branco
+red=Vermelho
+green=Verde
+blue=Azul
+custom=Personalizar...
+WorkInProgess=Trabalho em progresso, pode não funcionar ou apresentar erros. Por favor, relate quaisquer problemas!
+poweredBy=Distribuído por
+yes=Sim
+no=Não
+changedCredsMessage=Dados alterados!
+notAuthenticatedMessage=Utilizador não autenticado.
+userNotFoundMessage=Utilizador inexistente.
+incorrectPasswordMessage=Senha incorreta.
+usernameExistsMessage=Esse utilizador já existe.
+invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
+deleteCurrentUserMessage=Cannot delete currently logged in user.
+deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
+downgradeCurrentUserMessage=Não é possível fazer downgrade da função do utilizador atual
+downgradeCurrentUserLongMessage=Não é possível fazer downgrade da função do utilizador atual. Portanto, o utilizador atual não será mostrado.
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
+
+
+###############
+# Pipeline #
+###############
+pipeline.header=Pipeline Menu (Beta)
+pipeline.uploadButton=Carregar personalizado
+pipeline.configureButton=Configurar
+pipeline.defaultOption=Personalizar
+pipeline.submitButton=Submeter
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
+
+######################
+# Pipeline Options #
+######################
+pipelineOptions.header=Pipeline Configuração
+pipelineOptions.pipelineNameLabel=Pipeline Nome
+pipelineOptions.saveSettings=Guardar configuração da operação
+pipelineOptions.pipelineNamePrompt=Introduza o nome da pipeline aqui
+pipelineOptions.selectOperation=Escolher acção
+pipelineOptions.addOperationButton=Adicionar acção
+pipelineOptions.pipelineHeader=Pipeline:
+pipelineOptions.saveButton=Descarregar
+pipelineOptions.validateButton=Validar
+
+
+
+
+#############
+# NAVBAR #
+#############
+navbar.convert=Converter
+navbar.security=Segurança
+navbar.other=Outro
+navbar.darkmode=Modo Escuro
+navbar.pageOps=Operações de página
+navbar.settings=Configurações
+
+#############
+# SETTINGS #
+#############
+settings.title=Configurações
+settings.update=Atualização disponível
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
+settings.appVersion=Versão da aplicação:
+settings.downloadOption.title=Escolha a opção de download (para downloads não compactados de ficheiro único):
+settings.downloadOption.1=Abrir na mesma janela
+settings.downloadOption.2=Abrir em nova janela
+settings.downloadOption.3=⇬ Fazer download do ficheiro
+settings.zipThreshold=Compactar ficheiros quando o número de ficheiros baixados exceder
+settings.signOut=Terminar Sessão
+settings.accountSettings=Configuração de Conta
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
+
+changeCreds.title=Alterar senha
+changeCreds.header=Alterar dados da sua conta
+changeCreds.changePassword=You are using default login credentials. Please enter a new password
+changeCreds.newUsername=Novo Utilizador
+changeCreds.oldPassword=Senha Atual
+changeCreds.newPassword=Nova Senha
+changeCreds.confirmNewPassword=Confirmar Nova Senha
+changeCreds.submit=Submeter Alterações
+
+
+
+account.title=Account Settings
+account.accountSettings=Account Settings
+account.adminSettings=Admin Settings - View and Add Users
+account.userControlSettings=User Control Settings
+account.changeUsername=Change Username
+account.newUsername=New Username
+account.password=Confirmation Password
+account.oldPassword=Old password
+account.newPassword=New Password
+account.changePassword=Change Password
+account.confirmNewPassword=Confirm New Password
+account.signOut=Sign Out
+account.yourApiKey=Your API Key
+account.syncTitle=Sync browser settings with Account
+account.settingsCompare=Settings Comparison:
+account.property=Property
+account.webBrowserSettings=Web Browser Setting
+account.syncToBrowser=Sync Account -> Browser
+account.syncToAccount=Sync Account <- Browser
+
+
+adminUserSettings.title=User Control Settings
+adminUserSettings.header=Admin User Control Settings
+adminUserSettings.admin=Admin
+adminUserSettings.user=User
+adminUserSettings.addUser=Add New User
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
+adminUserSettings.roles=Roles
+adminUserSettings.role=Role
+adminUserSettings.actions=Actions
+adminUserSettings.apiUser=Limited API User
+adminUserSettings.extraApiUser=Additional Limited API User
+adminUserSettings.webOnlyUser=Web Only User
+adminUserSettings.demoUser=Demo User (No custom settings)
+adminUserSettings.internalApiUser=Internal API User
+adminUserSettings.forceChange=Force user to change password on login
+adminUserSettings.submit=Save User
+adminUserSettings.changeUserRole=Alterar usuário
+
+#############
+# HOME-PAGE #
+#############
+home.desc=Seu melhor utilitário para suas necessidades de PDF.
+home.searchBar=Procurar ferramentas...
+
+
+home.viewPdf.title=Visualizar PDF
+home.viewPdf.desc=Visualizar, adicionar notas, texto ou imagens
+viewPdf.tags=visualizat,ler,notas,texto,imagens
+
+home.multiTool.title=Multiferramenta de PDF
+home.multiTool.desc=Juntar, girar, reorganizar e remover páginas
+multiTool.tags=Multi Ferramenta, Operação Múltipla, Interface do Usuário, Clique e Arraste, Front-end, Lado do Cliente
+
+home.merge.title=Juntar
+home.merge.desc=Juntar facilmente vários PDFs num só.
+merge.tags=juntar, Operações de Página, Lado do Servidor
+
+home.split.title=Dividir
+home.split.desc=Dividir PDFs em vários documentos
+split.tags=Operações de Página, dividir, Múltiplas Páginas, cortar, Lado do Servidor
+
+home.rotate.title=Girar
+home.rotate.desc=Girar facilmente seus PDFs.
+rotate.tags=Lado do Servidor
+
+
+home.imageToPdf.title=Imagem para PDF
+home.imageToPdf.desc=Converter uma imagem (PNG, JPEG, GIF) em PDF.
+imageToPdf.tags=conversão, img, jpg, imagem, foto
+
+home.pdfToImage.title=PDF para Imagem
+home.pdfToImage.desc=Converter um PDF em uma imagem. (PNG, JPG, GIF)
+pdfToImage.tags=conversão, img, jpg, imagem, foto
+
+home.pdfOrganiser.title=Organizar
+home.pdfOrganiser.desc=Remover/reorganizar as páginas em qualquer ordem.
+pdfOrganiser.tags=duplex, par, ímpar, ordenar, mover
+
+
+home.addImage.title=Adicionar Imagem
+home.addImage.desc=Adicionar uma imagem em um local definido no PDF (trabalho em andamento)
+addImage.tags=img, jpg, imagem, foto
+
+home.watermark.title=Adicionar Marca d'água
+home.watermark.desc=Adicionar uma marca d'água personalizada ao seu documento PDF.
+watermark.tags=Texto, repetindo, rótulo, próprio, direitos autorais, marca registrada, img, jpg, imagem, foto
+
+home.permissions.title=Alterar Permissões
+home.permissions.desc=Alterar as permissões do seu documento PDF.
+permissions.tags=leitura, escrita, edição, impressão
+
+
+home.removePages.title=Remover
+home.removePages.desc=Excluir as páginas indesejadas do seu documento PDF.
+removePages.tags=Remover páginas, excluir páginas
+
+home.addPassword.title=Adicionar Senha
+home.addPassword.desc=Proteger seu documento PDF com uma senha.
+addPassword.tags=seguro, segurança
+
+home.removePassword.title=Remover Senha
+home.removePassword.desc=Remover a proteção por senha do seu documento PDF.
+removePassword.tags=seguro, Descriptografar, segurança, remover senha
+
+home.compressPdfs.title=Comprimir
+home.compressPdfs.desc=Comprimir PDFs para reduzir o tamanho do ficheiro.
+compressPdfs.tags=compactar, pequeno, mínimo
+
+
+home.changeMetadata.title=Alterar Metadados
+home.changeMetadata.desc=Alterar/remover/adicionar metadados de um documento PDF.
+changeMetadata.tags=Título, autor, data, criação, hora, editor, produtor, estatísticas
+
+home.fileToPDF.title=Converter ficheiro para PDF
+home.fileToPDF.desc=Converter praticamente qualquer ficheiro em PDF (DOCX, PNG, XLS, PPT, TXT e mais)
+fileToPDF.tags=transformação, formato, documento, imagem, slide, texto, conversão, escritório, documentos, word, excel, powerpoint
+
+home.ocr.title=OCR / Limpeza de Digitalizações
+home.ocr.desc=Verifica e detecta texto não seleccionável de um PDF.
+ocr.tags=reconhecimento, texto, imagem, digitalização, leitura, identificação, detecção, editável
+
+
+home.extractImages.title=Extrair Imagens
+home.extractImages.desc=Extrair todas as imagens de um PDF e salvá-las em um ficheiro zip.
+extractImages.tags=imagem, foto, salvar, ficheiro, zip, captura, coleta
+
+home.pdfToPDFA.title=PDF para PDF/A
+home.pdfToPDFA.desc=Converter PDF para o formato PDF/A para armazenamento a longo prazo.
+pdfToPDFA.tags=ficheiro, longo prazo, padrão, conversão, armazenamento, preservação
+
+home.PDFToWord.title=PDF para Word
+home.PDFToWord.desc=Converter PDF para formatos Word (DOC, DOCX e ODT)
+PDFToWord.tags=doc, docx, odt, word, transformação, formato, conversão, escritório, microsoft, ficheiro doc
+
+home.PDFToPresentation.title=PDF para Powerpoint
+home.PDFToPresentation.desc=Converter PDF para formatos de apresentação (PPT, PPTX e ODP)
+PDFToPresentation.tags=slides, apresentação, escritório, microsoft
+
+home.PDFToText.title=PDF para Texto/RTF
+home.PDFToText.desc=Converter PDF em formato de texto ou RTF
+PDFToText.tags=formato rico, formato de texto enriquecido, formato de texto rico
+
+home.PDFToHTML.title=PDF para HTML
+home.PDFToHTML.desc=Converter PDF para o formato HTML
+PDFToHTML.tags=conteúdo web, compatível com navegador
+
+
+home.PDFToXML.title=PDF para XML
+home.PDFToXML.desc=Converter PDF para o formato XML
+PDFToXML.tags=extração-de-dados,conteúdo-estruturado,interoperabilidade,transformação,converter
+
+home.ScannerImageSplit.title=Detectar/Dividir Fotos Digitalizadas
+home.ScannerImageSplit.desc=Divide várias fotos de dentro de uma imagem/PDF digitalizado
+ScannerImageSplit.tags=separar,detecção-automática,digitalizações,foto-múltipla,organizar
+
+home.sign.title=Assinar
+home.sign.desc=Adicionar assinatura ao PDF por desenho, texto ou imagem
+sign.tags=autorizar,iniciais,assinatura-desenhada,assinatura-de-texto,assinatura-de-imagem
+
+home.flatten.title=Achatar
+home.flatten.desc=Remover todos os elementos e formulários interativos de um PDF
+flatten.tags=estático,desativar,não-interativo,otimizar
+
+home.repair.title=Reparar
+home.repair.desc=Tentar reparar um PDF corrompido/quebrado
+repair.tags=corrigir,restaurar,correção,recuperar
+
+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=Removee Notas
+home.removeAnnotations.desc=Remove todas as notas ou comentário de um 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
+
+home.certSign.title=Assinar com Certificado
+home.certSign.desc=Assinar um PDF com um Certificado/Chave (PEM/P12)
+certSign.tags=autenticar,PEM,P12,oficial,criptografar
+
+home.pageLayout.title=Layout de Múltiplas Páginas
+home.pageLayout.desc=Juntar várias páginas de um documento PDF em uma única página
+pageLayout.tags=juntar,composto,vista-única,organizar
+
+home.scalePages.title=Ajustar Tamanho/Escala de Página
+home.scalePages.desc=Alterar o tamanho/escala da página e/ou seu conteúdo.
+scalePages.tags=redimensionar,modificar,dimensão,adaptar
+
+home.pipeline.title=Pipeline (Avançado)
+home.pipeline.desc=Executar várias ações em PDFs definindo scripts de pipeline
+pipeline.tags=automatizar,sequência,scriptado,processo-em-lote
+
+home.add-page-numbers.title=Adicionar Números de Página
+home.add-page-numbers.desc=Adicionar números de página em todo o documento em um local definido
+add-page-numbers.tags=paginar,rotular,organizar,índice
+
+home.auto-rename.title=Renomear Automaticamente o ficheiro PDF
+home.auto-rename.desc=Renomeia automaticamente um ficheiro PDF com base no cabeçalho detectado
+auto-rename.tags=detecção-automática,baseado-em-cabeçalho,organizar,relabel
+
+home.adjust-contrast.title=Ajustar Cores/Contraste
+home.adjust-contrast.desc=Ajustar Contraste, Saturação e Brilho de um PDF
+adjust-contrast.tags=correção-de-cor,ajustar,modificar,realçar
+
+home.crop.title=Cortar PDF
+home.crop.desc=Cortar um PDF para reduzir o tamanho (mantém o texto!)
+crop.tags=aparar,encolher,editar,formato
+
+home.autoSplitPDF.title=Divisão Automática de Páginas
+home.autoSplitPDF.desc=Dividir automaticamente um PDF digitalizado com separador de páginas físicas QR Code
+autoSplitPDF.tags=baseado-em-QR,separar,segmento-de-digitalização,organizar
+
+home.sanitizePdf.title=Sanitizar
+home.sanitizePdf.desc=Remover scripts e outros elementos de ficheiros PDF
+sanitizePdf.tags=limpar,seguro,protegido,remover-ameaças
+
+home.URLToPDF.title=Converter Site para PDF
+home.URLToPDF.desc=Converte qualquer página da internet para um ficheiro PDF
+URLToPDF.tags=captura-de-web,salvar-página,web-para-doc,arquivar
+
+home.HTMLToPDF.title=HTML para PDF
+home.HTMLToPDF.desc=Converte qualquer ficheiro HTML ou zip para PDF
+HTMLToPDF.tags=marcação,conteúdo-web,transformação,converter
+
+
+home.MarkdownToPDF.title=Markdown para PDF
+home.MarkdownToPDF.desc=Converte qualquer ficheiro Markdown para PDF
+MarkdownToPDF.tags=marcação,conteúdo-web,transformação,converter
+
+
+home.getPdfInfo.title=Obter TODAS as Informações de um PDF
+home.getPdfInfo.desc=Obtém todas as informações possíveis de um PDF
+getPdfInfo.tags=informações,dados,estatísticas
+
+
+home.extractPage.title=Extrair Página(s)
+home.extractPage.desc=Extrai páginas selecionadas de um PDF
+extractPage.tags=extrair
+
+
+home.PdfToSinglePage.title=PDF para Página Única Grande
+home.PdfToSinglePage.desc=Combina todas as páginas de um PDF em uma única página grande
+PdfToSinglePage.tags=página única
+
+
+home.showJS.title=Mostrar Javascript
+home.showJS.desc=Procura e exibe qualquer JavaScript injetado em um PDF
+showJS.tags=JavaScript
+
+home.autoRedact.title=Edição automática
+home.autoRedact.desc=Edição automática (marca a preto) baseada numa expressão indicada de um PDF.
+autoRedact.tags=Redact,Hide,black out,black,marker,hidden
+
+home.tableExtraxt.title=PDF para CSV
+home.tableExtraxt.desc=Extrai tabelas de um PDF convertendo em um CSV
+tableExtraxt.tags=CSV,Tabelas Extracção,extracção,conversão
+
+
+home.autoSizeSplitPDF.title=Dividir automaticamente por Tamanho/Páginas
+home.autoSizeSplitPDF.desc=Divide um PDF em diversos documentos com base no tamanho ou número de páginas
+autoSizeSplitPDF.tags=pdf,dividir,documento,organização
+
+
+home.overlay-pdfs.title=Sobrepor PDFs
+home.overlay-pdfs.desc=Sobrepor um PDF em cima de outro PDF
+overlay-pdfs.tags=Sobrepor
+
+home.split-by-sections.title=Dividir PDF por Secções
+home.split-by-sections.desc=Divide cada páginas de um PDF em secções horizontais ou verticais mais pequenas
+split-by-sections.tags=Dividir secções, Dividir, Personalizar
+
+home.AddStampRequest.title=Adicionar carimbo em um PDF
+home.AddStampRequest.desc=Adicionar um carimbo de texto ou imagem
+AddStampRequest.tags=Carimbo, Adicionar imagem, imagem central, Marca d'água, PDF, Embebido, Personalizado
+
+
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
+###########################
+# #
+# WEB PAGES #
+# #
+###########################
+#login
+login.title=Aceder
+login.header=Aceder
+login.signin=Aceder
+login.rememberme=Lembrar dados
+login.invalid=Utilizador ou senha inválidos.
+login.locked=A sua conta foi bloqueada.
+login.signinTitle=Introduza os seus dados de acesso
+login.ssoSignIn=Iniciar sessão através de início de sessão único
+login.oauth2AutoCreateDisabled=OAUTH2 Criação Automática de Utilizador Desativada
+
+
+#auto-redact
+autoRedact.title=Edição Automática
+autoRedact.header=Edição Automática
+autoRedact.colorLabel=Cor
+autoRedact.textsToRedactLabel=Texto para editar (separado por linhas)
+autoRedact.textsToRedactPlaceholder=e.g. \nConfidencial \nTop-Secret
+autoRedact.useRegexLabel=Usar Regex
+autoRedact.wholeWordSearchLabel=Pesquisa de palavras inteiras
+autoRedact.customPaddingLabel=Preenchimento extra personalizado
+autoRedact.convertPDFToImageLabel=Converter PDF em imagem (usado para remover texto atrás de caixas)
+autoRedact.submitButton=Submeter
+
+
+#showJS
+showJS.title=Exibir JavaScript
+showJS.header=Exibir JavaScript
+showJS.downloadJS=Download do JavaScript
+showJS.submit=Exibir
+
+
+#pdfToSinglePage
+pdfToSinglePage.title=PDF para Página Única
+pdfToSinglePage.header=PDF para Página Única
+pdfToSinglePage.submit=Converter para Página Única
+
+
+#pageExtracter
+pageExtracter.title=Extrair Páginas
+pageExtracter.header=Extrair Páginas
+pageExtracter.submit=Extrair
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
+
+
+#getPdfInfo
+getPdfInfo.title=Obter Informações do PDF
+getPdfInfo.header=Obter Informações do PDF
+getPdfInfo.submit=Obter Informações
+getPdfInfo.downloadJson=Download JSON
+
+
+#markdown-to-pdf
+MarkdownToPDF.title=Markdown para PDF
+MarkdownToPDF.header=Markdown para PDF
+MarkdownToPDF.submit=Converter
+MarkdownToPDF.help=Trabalho em andamento
+MarkdownToPDF.credit=Usa o WeasyPrint
+
+
+
+#url-to-pdf
+URLToPDF.title=URL para PDF
+URLToPDF.header=URL para PDF
+URLToPDF.submit=Converter
+URLToPDF.credit=Usa o WeasyPrint
+
+
+#html-to-pdf
+HTMLToPDF.title=HTML para PDF
+HTMLToPDF.header=HTML para PDF
+HTMLToPDF.help=Aceita ficheiros HTML e ZIPs contendo html/css/imagens etc necessários
+HTMLToPDF.submit=Converter
+HTMLToPDF.credit=Usa o WeasyPrint
+HTMLToPDF.zoom=Nível de zoom para exibição do site.
+HTMLToPDF.pageWidth=Largura da página em centímetros. (Vazio para padrão)
+HTMLToPDF.pageHeight=Altura da página em centímetros. (BVazio para padrão)
+HTMLToPDF.marginTop=Margem superior da página em milímetros. (Vazio para padrão)
+HTMLToPDF.marginBottom=Margem inferior da página em milímetros. (Vazio para padrão)
+HTMLToPDF.marginLeft=Margem esquerda da página em milímetros. (Vazio para padrão)
+HTMLToPDF.marginRight=Margem direita da página em milímetros. (Vazio para padrão)
+HTMLToPDF.printBackground=Renderize o plano de fundo dos wesites.
+HTMLToPDF.defaultHeader=Habilitar cabeçalho padrão (Nome e número de página)
+HTMLToPDF.cssMediaType=Alterar o CSS da página.
+HTMLToPDF.none=Nenhum
+HTMLToPDF.print=Imprimir
+HTMLToPDF.screen=Ecrã
+
+
+#AddStampRequest
+AddStampRequest.header=Carimbo PDF
+AddStampRequest.title=Carimbo PDF
+AddStampRequest.stampType=Tipo do Carimbo
+AddStampRequest.stampText=Texto do Carimbo
+AddStampRequest.stampImage=Imagem do Carimbo
+AddStampRequest.alphabet=Alfabeto
+AddStampRequest.fontSize=Tamanho do(a) Tipo de Letra/Imagem
+AddStampRequest.rotation=Rotação
+AddStampRequest.opacity=Opacidade
+AddStampRequest.position=Posição
+AddStampRequest.overrideX=Substituir a Coordenada X
+AddStampRequest.overrideY=Substituir a Coordenada Y
+AddStampRequest.customMargin=Personalizar a Margem
+AddStampRequest.customColor=Personalizar a cor do texto
+AddStampRequest.submit=Submeter
+
+
+#sanitizePDF
+sanitizePDF.title=Sanitizar PDF
+sanitizePDF.header=Sanitizar um ficheiro PDF
+sanitizePDF.selectText.1=Remover acções de JavaScript
+sanitizePDF.selectText.2=Remover ficheiros embutidos
+sanitizePDF.selectText.3=Remover metadados
+sanitizePDF.selectText.4=Remover links
+sanitizePDF.selectText.5=Remover fontes
+sanitizePDF.submit=Sanitizar PDF
+
+
+#addPageNumbers
+addPageNumbers.title=Adicionar Números de Página
+addPageNumbers.header=Adicionar Números de Página
+addPageNumbers.selectText.1=Seleccionar ficheiro PDF:
+addPageNumbers.selectText.2=Tamanho da Margem
+addPageNumbers.selectText.3=Posição
+addPageNumbers.selectText.4=Número Inicial
+addPageNumbers.selectText.5=Páginas a Numerar
+addPageNumbers.selectText.6=Texto Personalizado
+addPageNumbers.customTextDesc=Texto personalizado
+addPageNumbers.numberPagesDesc=Quais as páginas a numerar. (padrão 'todas', ex: 1-5 ou 2,5,9 etc)
+addPageNumbers.customNumberDesc=O padrão é {n}, também aceita 'Pagina {n} de {total}', 'Texto-{n}', '{filename}-{n}
+addPageNumbers.submit=Adicionar Números de Página
+
+
+#auto-rename
+auto-rename.title=Renomear Automático
+auto-rename.header=Renomear Automático de PDF
+auto-rename.submit=Renomear Automático
+
+
+#adjustContrast
+adjustContrast.title=Ajustar Contraste
+adjustContrast.header=Ajustar Contraste
+adjustContrast.contrast=Contraste:
+adjustContrast.brightness=Brilho:
+adjustContrast.saturation=Saturação:
+adjustContrast.download=Download
+
+
+#crop
+crop.title=Cortar
+crop.header=Cortar Imagem
+crop.submit=Enviar
+
+
+#autoSplitPDF
+autoSplitPDF.title=Divisão Automática de PDF
+autoSplitPDF.header=Divisão Automática de PDF
+autoSplitPDF.description=Imprima, insira, digitalize, faça o upload e deixe que o sistema divida seus documentos automaticamente. Nenhuma classificação manual necessária.
+autoSplitPDF.selectText.1=Imprima algumas folhas divisórias abaixo.
+autoSplitPDF.selectText.2=Digitalize todos os seus documentos de uma vez, inserindo a folha divisória entre eles.
+autoSplitPDF.selectText.3=Faça o upload do único ficheiro PDF grande digitalizado e os sistema faz o restante trabalho.
+autoSplitPDF.selectText.4=As páginas divisórias são detectadas e removidas automaticamente, garantindo um documento final organizado.
+autoSplitPDF.formPrompt=Enviar PDF contendo folhas divisórias:
+autoSplitPDF.duplexMode=Modo Duplex (Digitalização frente e verso)
+autoSplitPDF.dividerDownload1=Download 'Folha Divisória Automática (mínima).pdf'
+autoSplitPDF.dividerDownload2=Download 'Folha Divisória Automática (com instruções).pdf'
+autoSplitPDF.submit=Enviar
+
+
+#pipeline
+pipeline.title=Pipeline
+
+
+#pageLayout
+pageLayout.title=Layout de Múltiplas Páginas
+pageLayout.header=Layout de Múltiplas Páginas
+pageLayout.pagesPerSheet=Páginas por folha:
+pageLayout.addBorder=Adicionar Contorno
+pageLayout.submit=Enviar
+
+
+#scalePages
+scalePages.title=Ajustar Tamanho/Escala da Página
+scalePages.header=Ajustar Tamanho/Escala da Página
+scalePages.pageSize=Tamanho de uma página do documento.
+scalePages.scaleFactor=Fator de zoom (corte) de uma página.
+scalePages.submit=Enviar
+
+
+#certSign
+certSign.title=Assinatura com Certificado
+certSign.header=Assine um PDF com o seu certificado (Em desenvolvimento)
+certSign.selectPDF=Selecione um ficheiro PDF para assinatura:
+certSign.jksNote=Nota: Se o seu tipo de certificado não estiver listado abaixo, converta-o em um arquivo Java Keystore (.jks) usando a ferramenta de linha de comando keytool. Em seguida, escolha a opção de arquivo .jks abaixo.
+certSign.selectKey=Selecione o seu ficheiro de chave privada (formato PKCS#8, pode ser .pem ou .der):
+certSign.selectCert=Selecione o seu ficheiro de certificado (formato X.509, pode ser .pem ou .der):
+certSign.selectP12=Selecione o seu ficheiro 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
+certSign.reason=Razão
+certSign.location=Localização
+certSign.name=Nome
+certSign.submit=Assinar PDF
+
+
+#removeBlanks
+removeBlanks.title=Remover Páginas em Branco
+removeBlanks.header=Remover Páginas em Branco
+removeBlanks.threshold=Limiar:
+removeBlanks.thresholdDesc=Limiar para determinar o quão branco um pixel branco deve ser
+removeBlanks.whitePercent=Porcentagem de Branco (%):
+removeBlanks.whitePercentDesc=Porcentagem da página que deve ser branca para ser removida
+removeBlanks.submit=Remover Páginas em Branco
+
+
+#removeAnnotations
+removeAnnotations.title=Remover Notas
+removeAnnotations.header=Remover Notas
+removeAnnotations.submit=Remover
+
+
+#compare
+compare.title=Comparar
+compare.header=Comparar PDFs
+compare.document.1=Documento 1
+compare.document.2=Documento 2
+compare.submit=Comparar
+
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
+
+#sign
+sign.title=Assinar
+sign.header=Assinar PDFs
+sign.upload=Enviar Imagem
+sign.draw=Desenhar Assinatura
+sign.text=Inserir Texto
+sign.clear=Limpar
+sign.add=Adicionar
+
+
+#repair
+repair.title=Reparar
+repair.header=Reparar PDFs
+repair.submit=Reparar
+
+
+#flatten
+flatten.title=Achatar
+flatten.header=Achatar PDFs
+flatten.flattenOnlyForms=Flatten only forms
+flatten.submit=Achatar
+
+
+#ScannerImageSplit
+ScannerImageSplit.selectText.1=Limite de Ângulo:
+ScannerImageSplit.selectText.2=Define o ângulo absoluto mínimo necessário para que a imagem seja girada (padrão: 10).
+ScannerImageSplit.selectText.3=Tolerância:
+ScannerImageSplit.selectText.4=Determina o intervalo de variação de cor em torno da cor de fundo estimada (padrão: 30).
+ScannerImageSplit.selectText.5=Área Mínima:
+ScannerImageSplit.selectText.6=Define o limite mínimo de área para uma foto (padrão: 10000).
+ScannerImageSplit.selectText.7=Área mínima de contorno:
+ScannerImageSplit.selectText.8=Define o limite mínimo da área de contorno para uma foto
+ScannerImageSplit.selectText.9=Tamanho do contorno:
+ScannerImageSplit.selectText.10=Define o tamanho do contorno adicionado e removido para evitar contornos brancos na saída (padrão: 1).
+
+
+#OCR
+ocr.title=OCR / Limpeza de Digitalização
+ocr.header=OCR / Limpeza de Digitalização (Reconhecimento Óptico de Caracteres)
+ocr.selectText.1=Selecione os idiomas a serem detectados no PDF (os listados são os atualmente detectados):
+ocr.selectText.2=Criar um ficheiro de texto contendo o texto OCR ao lado do PDF com OCR
+ocr.selectText.3=Páginas corretamente digitalizadas em um ângulo inclinado, gire-as de volta à posição original
+ocr.selectText.4=Limpar a página para reduzir a probabilidade de o OCR encontrar texto no ruído de fundo (sem alteração na saída)
+ocr.selectText.5=Limpar a página para reduzir a probabilidade de o OCR encontrar texto no ruído de fundo, mantendo a limpeza na saída.
+ocr.selectText.6=Ignorar páginas com texto interativo, processar apenas as páginas de OCR que são imagens
+ocr.selectText.7=Forçar OCR, executar OCR em todas as páginas, removendo todos os elementos de texto originais
+ocr.selectText.8=Normal (gerará um erro se o PDF já contiver texto)
+ocr.selectText.9=Configurações adicionais
+ocr.selectText.10=Modo OCR
+ocr.selectText.11=Remover imagens após o OCR (remove TODAS as imagens, útil apenas como parte do processo de conversão)
+ocr.selectText.12=Tipo de renderização (avançado)
+ocr.help=Por favor, leia a documentação sobre como usar isso para outros idiomas e/ou fora do ambiente Docker
+ocr.credit=Este serviço usa OCRmyPDF e Tesseract para OCR.
+ocr.submit=Processar PDF com OCR
+
+
+#extractImages
+extractImages.title=Extrair Imagens
+extractImages.header=Extrair Imagens
+extractImages.selectText=Selecione o formato de imagem para converter as imagens extraídas
+extractImages.submit=Extrair
+
+
+#File to PDF
+fileToPDF.title=Ficheiro para PDF
+fileToPDF.header=Converter Qualquer ficheiro para PDF
+fileToPDF.credit=Este serviço usa o LibreOffice e o Unoconv para conversão de ficheiros.
+fileToPDF.supportedFileTypes=Os tipos de ficheiro suportados devem incluir os listados abaixo. No entanto, para obter uma lista atualizada completa dos formatos suportados, consulte a documentação do LibreOffice.
+fileToPDF.submit=Converter para PDF
+
+
+#compress
+compress.title=Comprimir
+compress.header=Comprimir PDF
+compress.credit=Este serviço usa o Ghostscript para compressão/otimização de PDF.
+compress.selectText.1=Modo Manual - De 1 a 4
+compress.selectText.2=Nível de Otimização:
+compress.selectText.3=4 (Pior para imagens de texto)
+compress.selectText.4=Modo Automático - Ajusta automaticamente a qualidade para atingir o tamanho exato do PDF
+compress.selectText.5=Tamanho Esperado do PDF (por exemplo, 25 MB, 10,8 MB, 25 KB)
+compress.submit=Comprimir
+
+
+#Add image
+addImage.title=Adicionar Imagem
+addImage.header=Adicionar Imagem ao PDF
+addImage.everyPage=Para cada página?
+addImage.upload=Enviar Imagem
+addImage.submit=Adicionar Imagem
+
+
+#merge
+merge.title=Juntar
+merge.header=Juntar Vários PDFs (2+)
+merge.sortByName=Ordenar por nome
+merge.sortByDate=Ordenar por data
+merge.submit=Juntar
+
+
+#pdfOrganiser
+pdfOrganiser.title=Organizador de Páginas
+pdfOrganiser.header=Organizador de Páginas PDF
+pdfOrganiser.submit=Reorganizar Páginas
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
+
+
+#multiTool
+multiTool.title=Multiferramenta de PDF
+multiTool.header=Multiferramenta de PDF
+multiTool.uploadPrompts=Please Upload PDF
+
+#view pdf
+viewPdf.title=View PDF
+viewPdf.header=View PDF
+
+#pageRemover
+pageRemover.title=Remover Página
+pageRemover.header=Remover Páginas do PDF
+pageRemover.pagesToDelete=Páginas a serem excluídas (insira uma lista separada por vírgulas de números de página):
+pageRemover.submit=Excluir Páginas
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
+
+
+#rotate
+rotate.title=Girar PDF
+rotate.header=Girar PDF
+rotate.selectAngle=Seleccione o ângulo de rotação (múltiplos de 90 graus):
+rotate.submit=Girar
+
+
+#split-pdfs
+split.title=Dividir PDF
+split.header=Dividir PDF
+split.desc.1=Os números seleccionados correspondem às páginas onde você deseja fazer a divisão.
+split.desc.2=Por exemplo, seleccionar 1,3,7-9 dividirá um documento de 10 páginas em 6 PDFs separados da seguinte forma:
+split.desc.3=Documento Nº1: Página 1
+split.desc.4=Documento Nº2: Páginas 2 e 3
+split.desc.5=Documento Nº3: Páginas 4, 5, 6 e 7
+split.desc.6=Documento Nº4: Página 8
+split.desc.7=Documento Nº5: Página 9
+split.desc.8=Documento Nº6: Páginas 10
+split.splitPages=Digite as páginas para a divisão:
+split.submit=Dividir
+
+
+#merge
+imageToPDF.title=Imagem para PDF
+imageToPDF.header=Converter Imagem para PDF
+imageToPDF.submit=Converter
+imageToPDF.selectLabel=Opções de ajuste de imagem
+imageToPDF.fillPage=Preencher página
+imageToPDF.fitDocumentToImage=Ajustar página à imagem
+imageToPDF.maintainAspectRatio=Manter proporções
+imageToPDF.selectText.2=Girar Automaticamente
+imageToPDF.selectText.3=Lógica de Vários ficheiros (Ativada apenas ao trabalhar com várias imagens)
+imageToPDF.selectText.4=Juntar em um Único PDF
+imageToPDF.selectText.5=Converter em PDFs Separados
+
+
+#pdfToImage
+pdfToImage.title=PDF para Imagem
+pdfToImage.header=Converter PDF para Imagem
+pdfToImage.selectText=Formato de Imagem
+pdfToImage.singleOrMultiple=Tipo de Resultado de Imagem
+pdfToImage.single=Única Imagem Grande
+pdfToImage.multi=Múltiplas Imagens
+pdfToImage.colorType=Tipo de Cor
+pdfToImage.color=Colorida
+pdfToImage.grey=Escala de Cinza
+pdfToImage.blackwhite=Preto e Branco (pode resultar em perda de dados!)
+pdfToImage.submit=Converter
+
+
+#addPassword
+addPassword.title=Adicionar Senha
+addPassword.header=Adicionar Senha (Proteger)
+addPassword.selectText.1=Selecione o PDF para Proteger
+addPassword.selectText.2=Senha
+addPassword.selectText.3=Tamanho da Chave de Criptografia
+addPassword.selectText.4=Valores mais altos são mais seguros, mas valores mais baixos são mais compatíveis.
+addPassword.selectText.5=Permissões para Definir
+addPassword.selectText.6=Impedir Montagem do Documento
+addPassword.selectText.7=Impedir Extracção de Conteúdo
+addPassword.selectText.8=Impedir Extracção para Acessibilidade
+addPassword.selectText.9=Impedir Preenchimento de Formulário
+addPassword.selectText.10=Impedir Modificação
+addPassword.selectText.11=Impedir Modificação de Anotação
+addPassword.selectText.12=Impedir Impressão
+addPassword.selectText.13=Impedir Impressão de Formatos Diferentes
+addPassword.selectText.14=Senha do Proprietário
+addPassword.selectText.15=Restringe o que pode ser feito com o documento após a abertura (nem todos os leitores dão suporte a isso)
+addPassword.selectText.16=Restringe a abertura do próprio documento
+addPassword.submit=Proteger
+
+
+#watermark
+watermark.title=Adicionar Marca d'Água
+watermark.header=Adicionar Marca d'Água
+watermark.selectText.1=Seleccione o PDF para Adicionar a Marca d'Água
+watermark.selectText.2=Texto da Marca d'Água
+watermark.selectText.3=Tamanho da Fonte
+watermark.selectText.4=Rotação (0-360)
+watermark.selectText.5=Espaçamento Horizontal (widthSpacer)
+watermark.selectText.6=Espaçamento Vertical (heightSpacer)
+watermark.selectText.7=Opacidade (0% - 100%)
+watermark.selectText.8=Tipo de Marca d'Água
+watermark.selectText.9=Imagem da Marca d'Água
+watermark.submit=Adicionar Marca d'Água
+watermark.type.1=Text
+watermark.type.2=Image
+
+
+#Change permissions
+permissions.title=Alterar Permissões
+permissions.header=Alterar Permissões
+permissions.warning=Nota: Para tornar essas permissões inalteráveis, é recomendável defini-las com uma senha através da página "Adicionar Senha".
+permissions.selectText.1=Seleccione o PDF para Alterar as Permissões
+permissions.selectText.2=Permissões para Definir
+permissions.selectText.3=Impedir Montagem do Documento
+permissions.selectText.4=Impedir Extração de Conteúdo
+permissions.selectText.5=Impedir Extração para Acessibilidade
+permissions.selectText.6=Impedir Preenchimento de Formulário
+permissions.selectText.7=Impedir Modificações
+permissions.selectText.8=Impedir Modificação de Anotação
+permissions.selectText.9=Impedir Impressão
+permissions.selectText.10=Impedir Impressão de Formatos Diferentes
+permissions.submit=Alterar
+
+
+#remove password
+removePassword.title=Remover Senha
+removePassword.header=Remover Senha (Desproteger)
+removePassword.selectText.1=Selecione o PDF para Desproteger
+removePassword.selectText.2=Senha
+removePassword.submit=Remover
+
+
+#changeMetadata
+changeMetadata.title=Título:
+changeMetadata.header=Alterar Metadados
+changeMetadata.selectText.1=Edite as Variáveis que Deseja Alterar
+changeMetadata.selectText.2=Excluir Todos os Metadados
+changeMetadata.selectText.3=Mostrar Metadados Personalizados
+changeMetadata.author=Autor:
+changeMetadata.creationDate=Data de Criação (aaaa/MM/dd HH:mm:ss):
+changeMetadata.creator=Criador:
+changeMetadata.keywords=Palavras-chave:
+changeMetadata.modDate=Data de Modificação (aaaa/MM/dd HH:mm:ss):
+changeMetadata.producer=Produtor:
+changeMetadata.subject=Assunto:
+changeMetadata.trapped=Trapped:
+changeMetadata.selectText.4=Outros Metadados
+changeMetadata.selectText.5=Adicionar Entrada de Metadados Personalizados
+changeMetadata.submit=Mudar
+
+
+#pdfToPDFA
+pdfToPDFA.title=PDF para PDF/A
+pdfToPDFA.header=PDF para PDF/A
+pdfToPDFA.credit=Este serviço usa OCRmyPDF para Conversão de PDF/A
+pdfToPDFA.submit=Converter
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
+
+
+#PDFToWord
+PDFToWord.title=PDF para Word
+PDFToWord.header=PDF para Word
+PDFToWord.selectText.1=Formato do ficheiro de Saída
+PDFToWord.credit=Este serviço usa o LibreOffice para Conversão de ficheiros.
+PDFToWord.submit=Converter
+
+
+#PDFToPresentation
+PDFToPresentation.title=PDF para Apresentação
+PDFToPresentation.header=PDF para Apresentação
+PDFToPresentation.selectText.1=Formato do ficheiro de Saída
+PDFToPresentation.credit=Este serviço usa o LibreOffice para Conversão de ficheiros.
+PDFToPresentation.submit=Converter
+
+
+#PDFToText
+PDFToText.title=PDF para Texto/RTF
+PDFToText.header=PDF para Texto/RTF
+PDFToText.selectText.1=Formato do ficheiro de Saída
+PDFToText.credit=Este serviço usa o LibreOffice para Conversão de ficheiros.
+PDFToText.submit=Converter
+
+
+#PDFToHTML
+PDFToHTML.title=PDF para HTML
+PDFToHTML.header=PDF para HTML
+PDFToHTML.credit=Este serviço usa o pdftohtml para Conversão de ficheiros.
+PDFToHTML.submit=Converter
+
+
+#PDFToXML
+PDFToXML.title=PDF para XML
+PDFToXML.header=PDF para XML
+PDFToXML.credit=Este serviço usa o LibreOffice para Conversão de ficheiros.
+PDFToXML.submit=Converter
+
+#PDFToCSV
+PDFToCSV.title=PDF para CSV
+PDFToCSV.header=PDF para CSV
+PDFToCSV.prompt=Escolha a página para extrair a tabela
+PDFToCSV.submit=Eztenna
+
+#split-by-size-or-count
+split-by-size-or-count.title=Dividir o PDF por tamanho, número de páginas ou número de documentos
+split-by-size-or-count.header=Dividir o PDF por tamanho, número de páginas ou número de documentos
+split-by-size-or-count.type.label=Seleccione o tipo de divisão
+split-by-size-or-count.type.size=Por Tamanho
+split-by-size-or-count.type.pageCount=Por Número de Páginas
+split-by-size-or-count.type.docCount=Por Número de Documentos
+split-by-size-or-count.value.label=Introduzir valor
+split-by-size-or-count.value.placeholder=Introduzir tamanho (ex: 2MB or 3KB) or página (ex: 5)
+split-by-size-or-count.submit=Submeter
+
+
+#overlay-pdfs
+overlay-pdfs.header=Sobrepor arquivos PDF
+overlay-pdfs.baseFile.label=Selecione o arquivo PDF base
+overlay-pdfs.overlayFiles.label=Selecione o arquivo PDF para sobrepor
+overlay-pdfs.mode.label=Selecione o modo de sobreposição
+overlay-pdfs.mode.sequential=Sobreposição sequencial
+overlay-pdfs.mode.interleaved=Sobreposição intercalada
+overlay-pdfs.mode.fixedRepeat=Sobreposição de repetição fixa
+overlay-pdfs.counts.label=Contagens de sobreposição (para modo de repetição fixa)
+overlay-pdfs.counts.placeholder=Insira páginas separadas por vírgula (ex: 2,3,1)
+overlay-pdfs.position.label=Selecione a posição de sobreposição
+overlay-pdfs.position.foreground=Primeiro plano
+overlay-pdfs.position.background=Plano de fundo
+overlay-pdfs.submit=Submeter
+
+
+#split-by-sections
+split-by-sections.title=Dividir PDF por Secções
+split-by-sections.header=Divida o PDF em Secções
+split-by-sections.horizontal.label=Divisões Horizontais
+split-by-sections.vertical.label=Divisões Verticais
+split-by-sections.horizontal.placeholder=Introduza o número de divisões horizontais
+split-by-sections.vertical.placeholder=Introduza o número de divisões verticais
+split-by-sections.submit=Dividir PDF
+split-by-sections.merge=Merge Into One PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
+
+
+#licenses
+licenses.nav=Licenças
+licenses.title=Licenças de terceiros
+licenses.header=Licenças de terceiros
+licenses.module=Modulos
+licenses.version=Versão
+licenses.license=Licença
+
+
+# error
+error.sorry=Sorry for the issue!
+error.needHelp=Need help / Found an issue?
+error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
+error.404.head=404 - Page Not Found | Oops, we tripped in the code!
+error.404.1=We can't seem to find the page you're looking for.
+error.404.2=Something went wrong
+error.github=Submit a ticket on GitHub
+error.showStack=Show Stack Trace
+error.copyStack=Copy Stack Trace
+error.githubSubmit=GitHub - Submit a ticket
+error.discordSubmit=Discord - Submit Support post
+
diff --git a/src/main/resources/messages_ro_RO.properties b/src/main/resources/messages_ro_RO.properties
index 4e34c6e3..1f3daca5 100644
--- a/src/main/resources/messages_ro_RO.properties
+++ b/src/main/resources/messages_ro_RO.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -17,9 +17,11 @@ true=Adevărat
false=Fals
unknown=Necunoscut
save=Salvează
+saveToBrowser=Save to Browser
close=Închide
filesSelected=fișiere selectate
noFavourites=Niciun favorit adăugat
+downloadComplete=Download Complete
bored=Plictisit așteptând?
alphabet=Alfabet
downloadPdf=Descarcă PDF
@@ -52,16 +54,34 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
+invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
+deleteCurrentUserMessage=Cannot delete currently logged in user.
+deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
+downgradeCurrentUserMessage=Rolul utilizatorului curent nu poate fi retrogradat
+downgradeCurrentUserLongMessage=Rolul utilizatorului curent nu poate fi retrogradat. Prin urmare, utilizatorul curent nu va fi afișat.
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
+pipeline.header=Pipeline Menu (Beta)
pipeline.uploadButton=Upload Custom
pipeline.configureButton=Configure
pipeline.defaultOption=Custom
pipeline.submitButton=Submit
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
######################
# Pipeline Options #
@@ -94,6 +114,7 @@ navbar.settings=Setări
#############
settings.title=Setări
settings.update=Actualizare disponibilă
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=Versiune aplicație:
settings.downloadOption.title=Alege opțiunea de descărcare (pentru descărcarea unui singur fișier non-zip):
settings.downloadOption.1=Deschide în aceeași fereastră
@@ -102,12 +123,13 @@ settings.downloadOption.3=Descarcă fișierul
settings.zipThreshold=Împachetează fișierele când numărul de fișiere descărcate depășește
settings.signOut=Sign Out
settings.accountSettings=Account Settings
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=Change Credentials
changeCreds.header=Update Your Account Details
-changeCreds.changeUserAndPassword=You are using default login credentials. Please enter a new password (and username if wanted)
+changeCreds.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=New Username
changeCreds.oldPassword=Current Password
changeCreds.newPassword=New Password
@@ -142,14 +164,18 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
adminUserSettings.actions=Actions
adminUserSettings.apiUser=Limited API User
+adminUserSettings.extraApiUser=Additional 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.internalApiUser=Internal API User
+adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User
+adminUserSettings.changeUserRole=Schimbați rolul utilizatorului
#############
# HOME-PAGE #
@@ -392,6 +418,15 @@ home.AddStampRequest.desc=Add text or add image stamps at set locations
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Sign in
+login.header=Sign in
login.signin=Sign in
login.rememberme=Remember me
login.invalid=Invalid username or password.
login.locked=Your account has been locked.
login.signinTitle=Please sign in
+login.ssoSignIn=Conectare prin conectare unică
+login.oauth2AutoCreateDisabled=OAUTH2 Creare automată utilizator dezactivată
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Convert To Single Page
pageExtracter.title=Extract Pages
pageExtracter.header=Extract Pages
pageExtracter.submit=Extract
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -623,6 +662,18 @@ compare.document.1=Document 1
compare.document.2=Document 2
compare.submit=Compară
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
#sign
sign.title=Semnează
@@ -643,6 +694,7 @@ repair.submit=Repară
#flatten
flatten.title=Nivelare
flatten.header=Nivelează documente PDF
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Nivelează
@@ -726,11 +778,23 @@ merge.submit=Unire
pdfOrganiser.title=Organizator de pagini
pdfOrganiser.header=Organizator de pagini PDF
pdfOrganiser.submit=Rearanjați paginile
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=Instrument PDF multiplu
multiTool.header=Instrument PDF multiplu
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
viewPdf.title=View PDF
@@ -741,6 +805,7 @@ pageRemover.title=Înlăturare pagini
pageRemover.header=Înlăturare pagini din PDF
pageRemover.pagesToDelete=Pagini de șters (Introduceți o listă de numere de pagini separate prin virgulă):
pageRemover.submit=Ștergere pagini
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Selectați un unghi de rotație (în multiplicate de 90 de gr
rotate.submit=Rotește
-#merge
+#split-pdfs
split.title=Împarte PDF
split.header=Împarte PDF
split.desc.1=Numerele pe care le selectați reprezintă numărul paginii pe care doriți să o împărțiți
-split.desc.2=Prin urmare, selectând 1,3,7-8, un document cu 10 pagini va fi împărțit în 6 PDF-uri separate, astfel:
+split.desc.2=Prin urmare, selectând 1,3,7-9, un document cu 10 pagini va fi împărțit în 6 PDF-uri separate, astfel:
split.desc.3=Documentul #1: Pagina 1
split.desc.4=Documentul #2: Paginile 2 și 3
-split.desc.5=Documentul #3: Paginile 4, 5 și 6
-split.desc.6=Documentul #4: Pagina 7
-split.desc.7=Documentul #5: Pagina 8
-split.desc.8=Documentul #6: Paginile 9 și 10
+split.desc.5=Documentul #3: Paginile 4, 5, 6 și 7
+split.desc.6=Documentul #4: Pagina 8
+split.desc.7=Documentul #5: Pagina 9
+split.desc.8=Documentul #6: Pagina 10
split.splitPages=Introduceți paginile pe care să le împărțiți:
split.submit=Împarte
@@ -828,6 +893,8 @@ watermark.selectText.7=Opacitate (0% - 100%):
watermark.selectText.8=Watermark Type:
watermark.selectText.9=Watermark Image:
watermark.submit=Adăugați Filigran
+watermark.type.1=Text
+watermark.type.2=Image
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF către PDF/A
pdfToPDFA.header=PDF către PDF/A
pdfToPDFA.credit=Acest serviciu utilizează OCRmyPDF pentru conversia în PDF/A
pdfToPDFA.submit=Convert
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Convert
#PDFToHTML
PDFToHTML.title=PDF către HTML
PDFToHTML.header=PDF către HTML
-PDFToHTML.credit=Acest serviciu utilizează LibreOffice pentru conversia fișierului.
+PDFToHTML.credit=Acest serviciu utilizează pdftohtml pentru conversia fișierului.
PDFToHTML.submit=Convert
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Choose page to extract table
PDFToCSV.submit=Extrage
#split-by-size-or-count
+split-by-size-or-count.title=Split PDF 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
@@ -959,6 +1029,15 @@ 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
+split-by-sections.merge=Merge Into One PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Version
licenses.license=License
+# error
+error.sorry=Sorry for the issue!
+error.needHelp=Need help / Found an issue?
+error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
+error.404.head=404 - Page Not Found | Oops, we tripped in the code!
+error.404.1=We can't seem to find the page you're looking for.
+error.404.2=Something went wrong
+error.github=Submit a ticket on GitHub
+error.showStack=Show Stack Trace
+error.copyStack=Copy Stack Trace
+error.githubSubmit=GitHub - Submit a ticket
+error.discordSubmit=Discord - Submit Support post
+
diff --git a/src/main/resources/messages_ru_RU.properties b/src/main/resources/messages_ru_RU.properties
index d386167b..4517e100 100644
--- a/src/main/resources/messages_ru_RU.properties
+++ b/src/main/resources/messages_ru_RU.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -11,15 +11,17 @@ imgPrompt=Выберите картинку(и)
genericSubmit=Отправить
processTimeWarning=Внимание: Этот процесс может занять до минуты в зависимости от размера файла.
pageOrderPrompt=Порядок страниц (введите список номеров страниц через запятую):
-pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
+pageSelectionPrompt=Пользовательский выбор страницы (введите разделенный запятыми список номеров страниц 1,5,6 или функции типа 2n+1) :
goToPage=Вперед
true=Истина
false=Ложь
unknown=Неизвестно
save=Сохранить
+saveToBrowser=Сохранить в браузере
close=Закрыть
filesSelected=файлов выбрано
noFavourites=Нет избранного
+downloadComplete=Загрузка завершена
bored=Скучно ждать?
alphabet=Алфавит
downloadPdf=Скачать PDF
@@ -27,54 +29,72 @@ text=Текст
font=Шрифт
selectFillter=-- Выбрать --
pageNum=номер страницы
-sizes.small=Small
-sizes.medium=Medium
-sizes.large=Large
-sizes.x-large=X-Large
-error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
-delete=Delete
-username=Username
-password=Password
-welcome=Welcome
-property=Property
-black=Black
-white=White
-red=Red
-green=Green
-blue=Blue
-custom=Custom...
-WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
+sizes.small=Маленький
+sizes.medium=Середина
+sizes.large=Большой
+sizes.x-large=очень большой
+error.pdfPassword=Документ PDF имеет пароль, и пароль не был предоставлен или был неверным
+delete=Удалить
+username=Имя пользователя
+password=Пароль
+welcome=Добро пожаловать
+property=Свойство
+black=Чёрный
+white=Белый
+red=Красный
+green=Зеленый
+blue=Синий
+custom=Обычай...
+WorkInProgess=Работа продолжается, может не работать или глючить, пожалуйста, сообщайте о любых проблемах!
poweredBy=Powered by
-yes=Yes
-no=No
-changedCredsMessage=Credentials changed!
-notAuthenticatedMessage=User not authenticated.
-userNotFoundMessage=User not found.
-incorrectPasswordMessage=Current password is incorrect.
-usernameExistsMessage=New Username already exists.
+yes=Да
+no=Нет
+changedCredsMessage=Учетные данные изменены!
+notAuthenticatedMessage=Пользователь не прошел проверку подлинности.
+userNotFoundMessage=Пользователь не найден.
+incorrectPasswordMessage=Текущий пароль неверен.
+usernameExistsMessage=Новое имя пользователя уже существует.
+invalidUsernameMessage=Недопустимое имя пользователя, Имя пользователя должно содержать только буквы алфавита и цифры.
+deleteCurrentUserMessage=Невозможно удалить пользователя, вошедшего в систему.
+deleteUsernameExistsMessage=Имя пользователя не существует и не может быть удалено.
+downgradeCurrentUserMessage=Невозможно понизить роль текущего пользователя
+downgradeCurrentUserLongMessage=Невозможно понизить роль текущего пользователя. Следовательно, текущий пользователь не будет отображаться.
+error=Ошибка
+oops=Ой!
+help=Помощь
+goHomepage=Перейти на главную страницу
+joinDiscord=Присоединиться к нашему серверу Discord
+seeDockerHub=Посмотреть в Docker Hub
+visitGithub=Посетить репозиторий на GitHub
+donate=Пожертвовать
+color=Цвет
+sponsor=Спонсор
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
-pipeline.uploadButton=Upload Custom
-pipeline.configureButton=Configure
-pipeline.defaultOption=Custom
-pipeline.submitButton=Submit
+pipeline.header=Меню конвейерной обработки (Бета)
+pipeline.uploadButton=Загрузить Пользовательский
+pipeline.configureButton=Настройка
+pipeline.defaultOption=Пользовательский
+pipeline.submitButton=Отправить
+pipeline.help=Справка по конвейерной обработке
+pipeline.scanHelp=Справка по сканированию папок
######################
# 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
+pipelineOptions.header=Настройка конвейерной обработки
+pipelineOptions.pipelineNameLabel=Название конвейера
+pipelineOptions.saveSettings=Сохранить настройки операции
+pipelineOptions.pipelineNamePrompt=Введите имя конвейера здесь
+pipelineOptions.selectOperation=Выбрать операцию
+pipelineOptions.addOperationButton=Добавить операцию
+pipelineOptions.pipelineHeader=Конвейер:
+pipelineOptions.saveButton=Скачать
+pipelineOptions.validateButton=Проверить
@@ -94,72 +114,78 @@ navbar.settings=Настройки
#############
settings.title=Настройки
settings.update=Доступно обновление
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=Версия приложения:
settings.downloadOption.title=Выберите вариант загрузки (для загрузки одного файла без zip):
settings.downloadOption.1=Открыть в том же окне
settings.downloadOption.2=Открыть в новом окне
settings.downloadOption.3=Загрузить файл
settings.zipThreshold=Zip-файлы, когда количество загруженных файлов превышает
-settings.signOut=Sign Out
-settings.accountSettings=Account Settings
+settings.signOut=Выйти
+settings.accountSettings=Настройки аккаунта
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
+
+changeCreds.title=Изменить учетные данные
+changeCreds.header=Обновите данные вашей учетной записи
+changeCreds.changePassword=Вы используете предустановленные учетные данные для входа. Пожалуйста, введите новый пароль
+changeCreds.newUsername=Новое имя пользователя
+changeCreds.oldPassword=Текущий пароль
+changeCreds.newPassword=Новый пароль
+changeCreds.confirmNewPassword=Подтвердите новый пароль
+changeCreds.submit=Отправить изменения
-changeCreds.title=Change Credentials
-changeCreds.header=Update Your Account Details
-changeCreds.changeUserAndPassword=You are using default login credentials. Please enter a new password (and username if wanted)
-changeCreds.newUsername=New Username
-changeCreds.oldPassword=Current Password
-changeCreds.newPassword=New Password
-changeCreds.confirmNewPassword=Confirm New Password
-changeCreds.submit=Submit Changes
+account.title=Настройки аккаунта
+account.accountSettings=Настройки аккаунта
+account.adminSettings=Настройки администратора - Просмотр и добавление пользователей
+account.userControlSettings=Настройки контроля пользователя
+account.changeUsername=Изменить имя пользователя
+account.newUsername=Новое имя пользователя
+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=Синхронизировать учетную запись <- Браузер
-
-account.title=Account Settings
-account.accountSettings=Account Settings
-account.adminSettings=Admin Settings - View and Add Users
-account.userControlSettings=User Control Settings
-account.changeUsername=Change Username
-account.newUsername=New Username
-account.password=Confirmation Password
-account.oldPassword=Old password
-account.newPassword=New Password
-account.changePassword=Change Password
-account.confirmNewPassword=Confirm New Password
-account.signOut=Sign Out
-account.yourApiKey=Your API Key
-account.syncTitle=Sync browser settings with Account
-account.settingsCompare=Settings Comparison:
-account.property=Property
-account.webBrowserSettings=Web Browser Setting
-account.syncToBrowser=Sync Account -> Browser
-account.syncToAccount=Sync Account <- Browser
-
-
-adminUserSettings.title=User Control Settings
-adminUserSettings.header=Admin User Control Settings
-adminUserSettings.admin=Admin
-adminUserSettings.user=User
-adminUserSettings.addUser=Add New User
-adminUserSettings.roles=Roles
-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
+adminUserSettings.title=Настройки контроля пользователя
+adminUserSettings.header=Настройки контроля пользователя администратора
+adminUserSettings.admin=Администратор
+adminUserSettings.user=Пользователь
+adminUserSettings.addUser=Добавить нового пользователя
+adminUserSettings.usernameInfo=Имя пользователя должно содержать только буквы и цифры, без пробелов и специальных символов.
+adminUserSettings.roles=Роли
+adminUserSettings.role=Роль
+adminUserSettings.actions=Действия
+adminUserSettings.apiUser=Ограниченный пользователь API
+adminUserSettings.extraApiUser=Дополнительный ограниченный пользователь API
+adminUserSettings.webOnlyUser=Только веб-пользователь
+adminUserSettings.demoUser=Демо-пользователь (без настраиваемых параметров)
+adminUserSettings.internalApiUser=Внутренний пользователь API
+adminUserSettings.forceChange=Просить пользователя изменить пароль при входе в систему
+adminUserSettings.submit=Сохранить пользователя
+adminUserSettings.changeUserRole=Изменить роль пользователя
#############
# HOME-PAGE #
#############
home.desc=Ваш локальный универсальный магазин для всех ваших потребностей в PDF.
-home.searchBar=Search for features...
+home.searchBar=Поиск функций...
-home.viewPdf.title=View PDF
-home.viewPdf.desc=View, annotate, add text or images
+home.viewPdf.title=Просмотр PDF
+home.viewPdf.desc=Просмотр, аннотация, добавление текста или изображений
viewPdf.tags=view,read,annotate,text,image
home.multiTool.title=Мультиинструмент PDF
@@ -365,58 +391,70 @@ home.showJS.title=Показать Javascript
home.showJS.desc=Ищет и отображает любой JS, внедренный в PDF-файл.
showJS.tags=JS
-home.autoRedact.title=Auto Redact
-home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
+home.autoRedact.title=Автоматическое редактирование
+home.autoRedact.desc=Автоматическое затемнение (чернение) текста в PDF на основе входного текста
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
-home.tableExtraxt.title=PDF to CSV
-home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
+home.tableExtraxt.title=PDF в CSV
+home.tableExtraxt.desc=Извлекает таблицы из PDF и преобразует их в 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
+home.autoSizeSplitPDF.title=Автоматическое разделение по размеру/количеству
+home.autoSizeSplitPDF.desc=Разделяет один PDF на несколько документов на основе размера, количества страниц или количества документов
autoSizeSplitPDF.tags=pdf,split,document,organization
-home.overlay-pdfs.title=Overlay PDFs
-home.overlay-pdfs.desc=Overlays PDFs on-top of another PDF
+home.overlay-pdfs.title=Наложение PDF
+home.overlay-pdfs.desc=Наложение одного PDF поверх другого 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
+home.split-by-sections.title=Разделение PDF по секциям
+home.split-by-sections.desc=Разделение каждой страницы PDF на более мелкие горизонтальные и вертикальные секции
split-by-sections.tags=Section Split, Divide, Customize
-home.AddStampRequest.title=Add Stamp to PDF
-home.AddStampRequest.desc=Add text or add image stamps at set locations
+home.AddStampRequest.title=Добавить печать на PDF
+home.AddStampRequest.desc=Добавление текстовой или изображенческой печати в заданные места
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF в книгу/комикс
+home.PDFToBook.desc=Конвертирует PDF в формат книги/комикса с помощью calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Книга в PDF
+home.BookToPDF.desc=Конвертирует форматы книги/комикса в PDF с помощью calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
# #
###########################
#login
-login.title=Sign in
-login.signin=Sign in
-login.rememberme=Remember me
-login.invalid=Invalid username or password.
-login.locked=Your account has been locked.
-login.signinTitle=Please sign in
+login.title=Вход
+login.header=Вход
+login.signin=Войти
+login.rememberme=Запомнить меня
+login.invalid=Недействительное имя пользователя или пароль.
+login.locked=Ваша учетная запись заблокирована.
+login.signinTitle=Пожалуйста, войдите
+login.ssoSignIn=Вход через единый вход
+login.oauth2AutoCreateDisabled=OAUTH2 Автоматическое создание пользователя отключено
#auto-redact
-autoRedact.title=Auto Redact
-autoRedact.header=Auto Redact
-autoRedact.colorLabel=Colour
-autoRedact.textsToRedactLabel=Text to Redact (line-separated)
-autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
-autoRedact.useRegexLabel=Use Regex
-autoRedact.wholeWordSearchLabel=Whole Word Search
-autoRedact.customPaddingLabel=Custom Extra Padding
-autoRedact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
-autoRedact.submitButton=Submit
+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
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Преобразовать в одну страницу
pageExtracter.title=Извлечь страницы
pageExtracter.header=Извлечь страницы
pageExtracter.submit=Извлечь
+pageExtracter.placeholder=(например 1,2,8 или 4,7,12-16 или 2n-1)
#getPdfInfo
@@ -467,37 +506,37 @@ HTMLToPDF.header=HTML в PDF
HTMLToPDF.help=Принимает файлы HTML и ZIP-файлы, содержащие html/css/изображения и т. д.
HTMLToPDF.submit=Конвертировать
HTMLToPDF.credit=Использует WeasyPrint
-HTMLToPDF.zoom=Zoom level for displaying the website.
-HTMLToPDF.pageWidth=Width of the page in centimeters. (Blank to default)
-HTMLToPDF.pageHeight=Height of the page in centimeters. (Blank to default)
-HTMLToPDF.marginTop=Top margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginBottom=Bottom margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginLeft=Left margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginRight=Right margin of the page in millimeters. (Blank to default)
-HTMLToPDF.printBackground=Render the background of websites.
-HTMLToPDF.defaultHeader=Enable Default Header (Name and page number)
-HTMLToPDF.cssMediaType=Change the CSS media type of the page.
-HTMLToPDF.none=None
-HTMLToPDF.print=Print
-HTMLToPDF.screen=Screen
+HTMLToPDF.zoom=Уровень масштабирования для отображения веб-сайта.
+HTMLToPDF.pageWidth=Ширина страницы в сантиметрах. (Пусто - по умолчанию)
+HTMLToPDF.pageHeight=Высота страницы в сантиметрах. (Пусто - по умолчанию)
+HTMLToPDF.marginTop=Верхний отступ страницы в миллиметрах. (Пусто - по умолчанию)
+HTMLToPDF.marginBottom=Нижний отступ страницы в миллиметрах. (Пусто - по умолчанию)
+HTMLToPDF.marginLeft=Левый отступ страницы в миллиметрах. (Пусто - по умолчанию)
+HTMLToPDF.marginRight=Правый отступ страницы в миллиметрах. (Пусто - по умолчанию)
+HTMLToPDF.printBackground=Визуализировать фон веб-сайтов.
+HTMLToPDF.defaultHeader=Включить заголовок по умолчанию (Имя и номер страницы)
+HTMLToPDF.cssMediaType=Изменить тип медиа CSS страницы.
+HTMLToPDF.none=Нет
+HTMLToPDF.print=Печать
+HTMLToPDF.screen=Экран
#AddStampRequest
-AddStampRequest.header=Stamp PDF
-AddStampRequest.title=Stamp PDF
-AddStampRequest.stampType=Stamp Type
-AddStampRequest.stampText=Stamp Text
-AddStampRequest.stampImage=Stamp Image
-AddStampRequest.alphabet=Alphabet
-AddStampRequest.fontSize=Font/Image Size
-AddStampRequest.rotation=Rotation
-AddStampRequest.opacity=Opacity
-AddStampRequest.position=Position
-AddStampRequest.overrideX=Override X Coordinate
-AddStampRequest.overrideY=Override Y Coordinate
-AddStampRequest.customMargin=Custom Margin
-AddStampRequest.customColor=Custom Text Color
-AddStampRequest.submit=Submit
+AddStampRequest.header=Штамповать PDF
+AddStampRequest.title=Штамповать PDF
+AddStampRequest.stampType=Тип штампа
+AddStampRequest.stampText=Текст штампа
+AddStampRequest.stampImage=Изображение штампа
+AddStampRequest.alphabet=Алфавит
+AddStampRequest.fontSize=Размер шрифта/изображения
+AddStampRequest.rotation=Поворот
+AddStampRequest.opacity=Прозрачность
+AddStampRequest.position=Позиция
+AddStampRequest.overrideX=Переопределить координату X
+AddStampRequest.overrideY=Переопределить координату Y
+AddStampRequest.customMargin=Настроенный отступ
+AddStampRequest.customColor=Настроенный цвет текста
+AddStampRequest.submit=Отправить
#sanitizePDF
@@ -520,9 +559,9 @@ addPageNumbers.selectText.3=Позиция
addPageNumbers.selectText.4=Стартовый номер
addPageNumbers.selectText.5=Страницы для нумерации
addPageNumbers.selectText.6=Свой текст
-addPageNumbers.customTextDesc=Custom Text
-addPageNumbers.numberPagesDesc=Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc
-addPageNumbers.customNumberDesc=Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}
+addPageNumbers.customTextDesc=Пользовательский текст
+addPageNumbers.numberPagesDesc=Какие страницы нумеровать, по умолчанию 'все', также принимает 1-5 или 2,5,9 и т.д.
+addPageNumbers.customNumberDesc=По умолчанию {n}, также можно использовать 'Страница {n} из {total}', 'Текст-{n}', '{filename}-{n}'
addPageNumbers.submit=Добавить номера страниц
@@ -563,14 +602,14 @@ autoSplitPDF.submit=Отравить
#pipeline
-pipeline.title=Pipeline
+pipeline.title=Пайплайн
#pageLayout
pageLayout.title=Многостраничный макет
pageLayout.header=Многостраничный макет
pageLayout.pagesPerSheet=Страниц на одном листе:
-pageLayout.addBorder=Add Borders
+pageLayout.addBorder=Добавить границы
pageLayout.submit=Отправить
@@ -586,11 +625,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.jksNote=Примечание: Если ваш тип сертификата не указан ниже, пожалуйста, преобразуйте его в файл хранилища Java Keystore (.jks), используя утилиту командной строки keytool. Затем выберите опцию .jks файла ниже.
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.selectJKS=Выберите файл хранилища Java Keystore (.jks или .keystore):
certSign.certType=Тип сертификата
certSign.password=Введите пароль от хранилища ключей или личного ключа (если есть):
certSign.showSig=Показать подпись
@@ -611,9 +650,9 @@ removeBlanks.submit=Удалить Пустые
#removeAnnotations
-removeAnnotations.title=Remove Annotations
-removeAnnotations.header=Remove Annotations
-removeAnnotations.submit=Remove
+removeAnnotations.title=Удалить аннотации
+removeAnnotations.header=Удалить аннотации
+removeAnnotations.submit=Удалить
#compare
@@ -623,6 +662,18 @@ compare.document.1=Документ 1
compare.document.2=Документ 2
compare.submit=Сравнить
+#BookToPDF
+BookToPDF.title=Книги и комиксы в PDF
+BookToPDF.header=Конвертировать книгу в PDF
+BookToPDF.credit=Используется Calibre
+BookToPDF.submit=Конвертировать
+
+#PDFToBook
+PDFToBook.title=PDF в книгу
+PDFToBook.header=PDF в книгу
+PDFToBook.selectText.1=Формат
+PDFToBook.credit=Используется Calibre
+PDFToBook.submit=Конвертировать
#sign
sign.title=Подпись
@@ -643,6 +694,7 @@ repair.submit=Ремонт
#flatten
flatten.title=Сглаживание
flatten.header=Сглаживание PDF ов
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Сгладить
@@ -717,8 +769,8 @@ addImage.submit=Добавить изображение
#merge
merge.title=Объединить
merge.header=Объединение нескольких PDF-файлов (2+)
-merge.sortByName=Sort by name
-merge.sortByDate=Sort by date
+merge.sortByName=Сортировка по имени
+merge.sortByDate=Сортировка по дате
merge.submit=Объединить
@@ -726,21 +778,34 @@ merge.submit=Объединить
pdfOrganiser.title=Организатор страниц
pdfOrganiser.header=Организатор PDF-страниц
pdfOrganiser.submit=Переупорядочить страницы
+pdfOrganiser.mode=Режим
+pdfOrganiser.mode.1=Пользовательский порядок страниц
+pdfOrganiser.mode.2=Обратный порядок
+pdfOrganiser.mode.3=Сортировка дуплекса
+pdfOrganiser.mode.4=Сортировка брошюры
+pdfOrganiser.mode.5=Сортировка брошюры со стежкой по боковой стороне
+pdfOrganiser.mode.6=Разделение на чётные и нечётные страницы
+pdfOrganiser.mode.7=Удалить первую
+pdfOrganiser.mode.8=Удалить последнюю
+pdfOrganiser.mode.9=Удалить первую и последнюю
+pdfOrganiser.placeholder=(например, 1,3,2 или 4-8,2,10-12 или 2n-1)
#multiTool
multiTool.title=Мультиинструмент PDF
multiTool.header=Мультиинструмент PDF
+multiTool.uploadPrompts=Пожалуйста, загрузите PDF
#view pdf
-viewPdf.title=View PDF
-viewPdf.header=View PDF
+viewPdf.title=Просмотреть PDF
+viewPdf.header=Просмотреть PDF
#pageRemover
pageRemover.title=Удаление страниц
pageRemover.header=Удаление PDF-страниц
pageRemover.pagesToDelete=Страницы для удаления (введите список номеров страниц через запятую):
pageRemover.submit=Удалить страницы
+pageRemover.placeholder=(например, 1,2,6 или 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Выберите угол поворота (кратный 90
rotate.submit=Повернуть
-#merge
+#split-pdfs
split.title=Разделить PDF
split.header=Разделить PDF
split.desc.1=Выбранные вами числа — это номера страниц, на которых вы хотите сделать разделение.
-split.desc.2=Таким образом, выбор 1,3,7-8 разделит 10-страничный документ на 6 отдельных PDF-файлов с:
-split.desc.3=Документ #1: Page 1
-split.desc.4=Документ #2: Page 2 and 3
-split.desc.5=Документ #3: Page 4, 5 and 6
-split.desc.6=Документ #4: Page 7
-split.desc.7=Документ #5: Page 8
-split.desc.8=Документ #6: Page 9 and 10
+split.desc.2=Таким образом, выбор 1,3,7-9 разделит 10-страничный документ на 6 отдельных PDF-файлов с:
+split.desc.3=Документ #1: Страница 1
+split.desc.4=Документ #2: Страница 2 и 3
+split.desc.5=Документ #3: Страница 4, 5, 6 aиnd 7
+split.desc.6=Документ #4: Страница 8
+split.desc.7=Документ #5: Страница 9
+split.desc.8=Документ #6: Страница 10
split.splitPages=Введите страницы для разделения:
split.submit=Разделить
@@ -769,10 +834,10 @@ split.submit=Разделить
imageToPDF.title=Изображение в PDF
imageToPDF.header=Изображение в PDF
imageToPDF.submit=Конвертировать
-imageToPDF.selectLabel=Image Fit Options
-imageToPDF.fillPage=Fill Page
-imageToPDF.fitDocumentToImage=Fit Page to Image
-imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
+imageToPDF.selectLabel=Выберите режим отображения изображения
+imageToPDF.fillPage=Заполнение страницы
+imageToPDF.fitDocumentToImage=Подогнать документ под изображение
+imageToPDF.maintainAspectRatio=Сохранить пропорции
imageToPDF.selectText.2=Автоматический поворот PDF
imageToPDF.selectText.3=Многофайловая логика (включена только при работе с несколькими изображениями)
imageToPDF.selectText.4=Объединить в один PDF
@@ -809,9 +874,9 @@ addPassword.selectText.10=Предотвратить модификацию
addPassword.selectText.11=Запретить модификацию аннотаций
addPassword.selectText.12=Запретить печать
addPassword.selectText.13=Запретить печать разных форматов
-addPassword.selectText.14=Owner Password
-addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
-addPassword.selectText.16=Restricts the opening of the document itself
+addPassword.selectText.14=Владельческий пароль
+addPassword.selectText.15=Ограничивает то, что можно сделать с документом после его открытия (не поддерживается всеми программами чтения)
+addPassword.selectText.16=Ограничивает открытие самого документа
addPassword.submit=Шифровать
@@ -825,9 +890,11 @@ watermark.selectText.4=Поворот (0-360):
watermark.selectText.5=widthSpacer (пробел между каждым водяным знаком по горизонтали):
watermark.selectText.6=heightSpacer (пробел между каждым водяным знаком по вертикали):
watermark.selectText.7=Непрозрачность (0% - 100%):
-watermark.selectText.8=Watermark Type:
-watermark.selectText.9=Watermark Image:
+watermark.selectText.8=Тип водяного знака:
+watermark.selectText.9=Изображение водяного знака:
watermark.submit=Добавить водяной знак
+watermark.type.1=Текст
+watermark.type.2=Изображение
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF в PDF/A
pdfToPDFA.header=PDF в PDF/A
pdfToPDFA.credit=Этот сервис использует OCRmyPDF для преобразования PDF/A
pdfToPDFA.submit=Конвертировать
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Конвертировать
#PDFToHTML
PDFToHTML.title=PDF в HTML
PDFToHTML.header=PDF в HTML
-PDFToHTML.credit=Этот сервис использует LibreOffice для преобразования файлов.
+PDFToHTML.credit=Этот сервис использует pdftohtml для преобразования файлов.
PDFToHTML.submit=Конвертировать
@@ -919,54 +988,77 @@ PDFToXML.credit=Этот сервис использует LibreOffice для п
PDFToXML.submit=Конвертировать
#PDFToCSV
-PDFToCSV.title=PDF ? CSV
-PDFToCSV.header=PDF ? CSV
-PDFToCSV.prompt=Choose page to extract table
-PDFToCSV.submit=???????
+PDFToCSV.title=PDF в CSV
+PDFToCSV.header=PDF в CSV
+PDFToCSV.prompt=Выберите страницу для извлечения таблицы
+PDFToCSV.submit=Извлечь
#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
+split-by-size-or-count.title=Разделить PDF по размеру или количеству
+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=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
+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=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
+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
+split-by-sections.merge=Объединить в один PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
-licenses.nav=Licenses
-licenses.title=3rd Party Licenses
-licenses.header=3rd Party Licenses
-licenses.module=Module
-licenses.version=Version
-licenses.license=License
+licenses.nav=Лицензии
+licenses.title=Лицензии от третьих сторон
+licenses.header=Лицензии от третьих сторон
+licenses.module=Модуль
+licenses.version=Версия
+licenses.license=Лицензия
+# error
+error.sorry=Извините за проблему!
+error.needHelp=Нужна помощь / Нашли проблему?
+error.contactTip=Если у вас все еще есть проблемы, не стесняйтесь обращаться к нам за помощью. Вы можете отправить заявку на нашей странице GitHub или связаться с нами через Discord:
+error.404.head=404 - Страница не найдена | Ой, мы запутались в коде!
+error.404.1=Мы не можем найти страницу, которую вы ищете.
+error.404.2=Произошла ошибка
+error.github=Отправить заявку на GitHub
+error.showStack=Показать стек вызовов
+error.copyStack=Скопировать стек вызовов
+error.githubSubmit=GitHub - Отправить заявку
+error.discordSubmit=Discord - Отправить запрос в поддержку
+
diff --git a/src/main/resources/messages_sr-Latn-RS.properties b/src/main/resources/messages_sr_LATN_RS.properties
similarity index 89%
rename from src/main/resources/messages_sr-Latn-RS.properties
rename to src/main/resources/messages_sr_LATN_RS.properties
index 1cd0eec3..708dc2d8 100644
--- a/src/main/resources/messages_sr-Latn-RS.properties
+++ b/src/main/resources/messages_sr_LATN_RS.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -17,9 +17,11 @@ true=Tačno
false=Netačno
unknown=Nepoznato
save=Sačuvaj
+saveToBrowser=Save to Browser
close=Zatvori
filesSelected=odabrani fajlovi
noFavourites=Nema dodatih favorita
+downloadComplete=Download Complete
bored=Da li ti je dosadno dok čekaš?
alphabet=Alfabet
downloadPdf=Skini PDF
@@ -52,6 +54,22 @@ notAuthenticatedMessage=Korisnik nije autentifikovan.
userNotFoundMessage=Korisnik nije pronađen.
incorrectPasswordMessage=Trenutna šifra je netačna.
usernameExistsMessage=Novi korisnik već postoji
+invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
+deleteCurrentUserMessage=Cannot delete currently logged in user.
+deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
+downgradeCurrentUserMessage=Nije moguće degradirati ulogu trenutnog korisnika
+downgradeCurrentUserLongMessage=Nije moguće unazaditi ulogu trenutnog korisnika. Dakle, trenutni korisnik neće biti prikazan.
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
###############
@@ -62,6 +80,8 @@ pipeline.uploadButton=Postavi prilagođeno
pipeline.configureButton=Konfiguriši
pipeline.defaultOption=Prilagođeno
pipeline.submitButton=Pošalji
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
######################
# Pipeline Options #
@@ -94,6 +114,7 @@ navbar.settings=Podešavanja
#############
settings.title=Podešavanja
settings.update=Dostupno ažuriranje
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
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
@@ -102,12 +123,13 @@ settings.downloadOption.3=Preuzmi fajl
settings.zipThreshold=Zipuj fajlove kada pređe broj preuzetih fajlova
settings.signOut=Odjava
settings.accountSettings=Podešavanja naloga
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
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.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=Novo korisničko ime
changeCreds.oldPassword=Trenutna lozinka
changeCreds.newPassword=Nova lozinka
@@ -142,14 +164,18 @@ adminUserSettings.header=Podešavanja kontrole korisnika za administratora
adminUserSettings.admin=Administrator
adminUserSettings.user=Korisnik
adminUserSettings.addUser=Dodaj novog korisnika
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.roles=Uloge
adminUserSettings.role=Uloga
adminUserSettings.actions=Akcije
adminUserSettings.apiUser=Korisnik s ograničenim API pristupom
+adminUserSettings.extraApiUser=Additional Limited API User
adminUserSettings.webOnlyUser=Korisnik samo za web
adminUserSettings.demoUser=Demo korisnik (Bez prilagođenih podešavanja)
+adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Prisili korisnika da promeni korisničko ime/lozinku pri prijavi
adminUserSettings.submit=Sačuvaj korisnika
+adminUserSettings.changeUserRole=Promenite ulogu korisnika
#############
# HOME-PAGE #
@@ -392,6 +418,15 @@ home.AddStampRequest.desc=Add text or add image stamps at set locations
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Prijavite se
+login.header=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
+login.ssoSignIn=Prijavite se putem jedinstvene prijave
+login.oauth2AutoCreateDisabled=OAUTH2 automatsko kreiranje korisnika je onemogućeno
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Konvertuj u Jednu Stranicu
pageExtracter.title=Izdvajanje stranica
pageExtracter.header=Izdvajanje stranica
pageExtracter.submit=Izdvoji
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -623,6 +662,18 @@ compare.document.1=Dokument 1
compare.document.2=Dokument 2
compare.submit=Uporedi
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
#sign
sign.title=Potpiši
@@ -643,6 +694,7 @@ repair.submit=Popravi
#flatten
flatten.title=Ravnanje
flatten.header=Ravnanje PDF fajlova
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Ravnanje
@@ -726,11 +778,23 @@ merge.submit=Spajanje
pdfOrganiser.title=Organizator stranica
pdfOrganiser.header=Organizator stranica u PDF-u
pdfOrganiser.submit=Preuredi stranice
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=PDF Multi Alatka
multiTool.header=PDF Multi Alatka
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
viewPdf.title=Prikaz
@@ -741,6 +805,7 @@ 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
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Izaberite ugao rotacije (u višestrukim od 90 stepeni):
rotate.submit=Rotiraj
-#merge
+#split-pdfs
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.2=Na primer, izbor 1,3,7-9 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.desc.5=Dokument #3: Stranice 4, 5, 6 i 7
+split.desc.6=Dokument #4: Stranica 8
+split.desc.7=Dokument #5: Stranica 9
+split.desc.8=Dokument #6: Stranice 10
split.splitPages=Unesite stranice za razdvajanje:
split.submit=Razdvoji
@@ -828,6 +893,8 @@ watermark.selectText.7=Opačitost (0% - 100%):
watermark.selectText.8=Tip vodenog žiga:
watermark.selectText.9=Slika vodenog žiga:
watermark.submit=Dodaj vodeni žig
+watermark.type.1=Text
+watermark.type.2=Image
#Change permissions
@@ -879,6 +946,8 @@ 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
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Konvertuj
#PDFToHTML
PDFToHTML.title=PDF u HTML
PDFToHTML.header=PDF u HTML
-PDFToHTML.credit=Ova usluga koristi LibreOffice za konverziju fajlova.
+PDFToHTML.credit=Ova usluga koristi pdftohtml za konverziju fajlova.
PDFToHTML.submit=Konvertuj
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Izaberite stranicu za ekstrakciju tabele
PDFToCSV.submit=Izvuci
#split-by-size-or-count
+split-by-size-or-count.title=Razdvoji PDF po veličini ili broju
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
@@ -959,6 +1029,15 @@ 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
+split-by-sections.merge=Merge Into One PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Version
licenses.license=License
+# error
+error.sorry=Sorry for the issue!
+error.needHelp=Need help / Found an issue?
+error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
+error.404.head=404 - Page Not Found | Oops, we tripped in the code!
+error.404.1=We can't seem to find the page you're looking for.
+error.404.2=Something went wrong
+error.github=Submit a ticket on GitHub
+error.showStack=Show Stack Trace
+error.copyStack=Copy Stack Trace
+error.githubSubmit=GitHub - Submit a ticket
+error.discordSubmit=Discord - Submit Support post
+
diff --git a/src/main/resources/messages_sv_SE.properties b/src/main/resources/messages_sv_SE.properties
index 5908b41c..f621c73c 100644
--- a/src/main/resources/messages_sv_SE.properties
+++ b/src/main/resources/messages_sv_SE.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -17,9 +17,11 @@ true=True
false=Falskt
unknown=Okänt
save=Spara
+saveToBrowser=Save to Browser
close=Stäng
filesSelected=filer valda
noFavourites=Inga favoriter har lagts till
+downloadComplete=Download Complete
bored=Utråkad att vänta?
alphabet=Alfabet
downloadPdf=Ladda ner PDF
@@ -52,16 +54,34 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
+invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers.
+deleteCurrentUserMessage=Cannot delete currently logged in user.
+deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
+downgradeCurrentUserMessage=Kan inte nedgradera nuvarande användares roll
+downgradeCurrentUserLongMessage=Kan inte nedgradera nuvarande användares roll. Därför kommer den aktuella användaren inte att visas.
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
+pipeline.header=Pipeline Menu (Beta)
pipeline.uploadButton=Upload Custom
pipeline.configureButton=Configure
pipeline.defaultOption=Custom
pipeline.submitButton=Submit
+pipeline.help=Pipeline Help
+pipeline.scanHelp=Folder Scanning Help
######################
# Pipeline Options #
@@ -94,6 +114,7 @@ navbar.settings=Inställningar
#############
settings.title=Inställningar
settings.update=Uppdatering tillgänglig
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=Appversion:
settings.downloadOption.title=Välj nedladdningsalternativ (för nedladdning av en fil utan zip):
settings.downloadOption.1=Öppnas i samma fönster
@@ -102,12 +123,13 @@ settings.downloadOption.3=Ladda ner fil
settings.zipThreshold=Zip-filer när antalet nedladdade filer överskrider
settings.signOut=Sign Out
settings.accountSettings=Account Settings
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=Change Credentials
changeCreds.header=Update Your Account Details
-changeCreds.changeUserAndPassword=You are using default login credentials. Please enter a new password (and username if wanted)
+changeCreds.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=New Username
changeCreds.oldPassword=Current Password
changeCreds.newPassword=New Password
@@ -142,14 +164,18 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
+adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
adminUserSettings.actions=Actions
adminUserSettings.apiUser=Limited API User
+adminUserSettings.extraApiUser=Additional 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.internalApiUser=Internal API User
+adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User
+adminUserSettings.changeUserRole=Ändra användarens roll
#############
# HOME-PAGE #
@@ -392,6 +418,15 @@ home.AddStampRequest.desc=Add text or add image stamps at set locations
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.PDFToBook.title=PDF to Book
+home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Book to PDF
+home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
###########################
# #
# WEB PAGES #
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Sign in
+login.header=Sign in
login.signin=Sign in
login.rememberme=Remember me
login.invalid=Invalid username or password.
login.locked=Your account has been locked.
login.signinTitle=Please sign in
+login.ssoSignIn=Logga in via enkel inloggning
+login.oauth2AutoCreateDisabled=OAUTH2 Auto-Create User inaktiverad
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Convert To Single Page
pageExtracter.title=Extract Pages
pageExtracter.header=Extract Pages
pageExtracter.submit=Extract
+pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
#getPdfInfo
@@ -623,6 +662,18 @@ compare.document.1=Dokument 1
compare.document.2=Dokument 2
compare.submit=Jämför
+#BookToPDF
+BookToPDF.title=Books and Comics to PDF
+BookToPDF.header=Book to PDF
+BookToPDF.credit=Uses Calibre
+BookToPDF.submit=Convert
+
+#PDFToBook
+PDFToBook.title=PDF to Book
+PDFToBook.header=PDF to Book
+PDFToBook.selectText.1=Format
+PDFToBook.credit=Uses Calibre
+PDFToBook.submit=Convert
#sign
sign.title=Signera
@@ -643,6 +694,7 @@ repair.submit=Reparera
#flatten
flatten.title=Platta till
flatten.header=Placera PDF-filer
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Platta till
@@ -726,11 +778,23 @@ merge.submit=Slå samman
pdfOrganiser.title=Sidorganisatör
pdfOrganiser.header=PDF-sidorganisatör
pdfOrganiser.submit=Ordna om sidor
+pdfOrganiser.mode=Mode
+pdfOrganiser.mode.1=Custom Page Order
+pdfOrganiser.mode.2=Reverse Order
+pdfOrganiser.mode.3=Duplex Sort
+pdfOrganiser.mode.4=Booklet Sort
+pdfOrganiser.mode.5=Side Stitch Booklet Sort
+pdfOrganiser.mode.6=Odd-Even Split
+pdfOrganiser.mode.7=Remove First
+pdfOrganiser.mode.8=Remove Last
+pdfOrganiser.mode.9=Remove First and Last
+pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=PDF-multiverktyg
multiTool.header=PDF Multi-verktyg
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
viewPdf.title=View PDF
@@ -741,6 +805,7 @@ pageRemover.title=Sidborttagare
pageRemover.header=PDF Sidborttagning
pageRemover.pagesToDelete=Sidor att radera (Ange en kommaseparerad lista med sidnummer) :
pageRemover.submit=Ta bort sidor
+pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Välj rotationsvinkel (i multipler av 90 grader):
rotate.submit=Rotera
-#merge
+#split-pdfs
split.title=Dela upp PDF
split.header=Dela upp PDF
split.desc.1=Siffrorna du väljer är sidnumret du vill göra en split på
-split.desc.2=Som sådan skulle ett val av 1,3,7-8 dela upp ett 10-sidigt dokument i 6 separata PDF-filer med:
+split.desc.2=Som sådan skulle ett val av 1,3,7-9 dela upp ett 10-sidigt dokument i 6 separata PDF-filer med:
split.desc.3=Dokument #1: Sida 1
split.desc.4=Dokument #2: Sida 2 och 3
-split.desc.5=Dokument #3: Sida 4, 5 och 6
-split.desc.6=Dokument #4: Sida 7
-split.desc.7=Dokument #5: Sida 8
-split.desc.8=Dokument #6: Sida 9 och 10
+split.desc.5=Dokument #3: Sida 4, 5, 6 och 7
+split.desc.6=Dokument #4: Sida 8
+split.desc.7=Dokument #5: Sida 9
+split.desc.8=Dokument #6: Sida 10
split.splitPages=Ange sidor att dela på:
split.submit=Dela
@@ -828,6 +893,8 @@ watermark.selectText.7=Opacitet (0% - 100%):
watermark.selectText.8=Watermark Type:
watermark.selectText.9=Watermark Image:
watermark.submit=Lägg till vattenstämpel
+watermark.type.1=Text
+watermark.type.2=Image
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF till PDF/A
pdfToPDFA.header=PDF till PDF/A
pdfToPDFA.credit=Denna tjänst använder OCRmyPDF för PDF/A-konvertering
pdfToPDFA.submit=Konvertera
+pdfToPDFA.tip=Currently does not work for multiple inputs at once
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Konvertera
#PDFToHTML
PDFToHTML.title=PDF till HTML
PDFToHTML.header=PDF till HTML
-PDFToHTML.credit=Denna tjänst använder LibreOffice för filkonvertering.
+PDFToHTML.credit=Denna tjänst använder pdftohtml för filkonvertering.
PDFToHTML.submit=Konvertera
@@ -925,6 +994,7 @@ PDFToCSV.prompt=Choose page to extract table
PDFToCSV.submit=Navvit
#split-by-size-or-count
+split-by-size-or-count.title=Split PDF 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
@@ -959,6 +1029,15 @@ 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
+split-by-sections.merge=Merge Into One PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
@@ -970,3 +1049,16 @@ licenses.version=Version
licenses.license=License
+# error
+error.sorry=Sorry for the issue!
+error.needHelp=Need help / Found an issue?
+error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
+error.404.head=404 - Page Not Found | Oops, we tripped in the code!
+error.404.1=We can't seem to find the page you're looking for.
+error.404.2=Something went wrong
+error.github=Submit a ticket on GitHub
+error.showStack=Show Stack Trace
+error.copyStack=Copy Stack Trace
+error.githubSubmit=GitHub - Submit a ticket
+error.discordSubmit=Discord - Submit Support post
+
diff --git a/src/main/resources/messages_tr_TR.properties b/src/main/resources/messages_tr_TR.properties
index 618e967e..8484e555 100644
--- a/src/main/resources/messages_tr_TR.properties
+++ b/src/main/resources/messages_tr_TR.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -11,15 +11,17 @@ imgPrompt=Resim(leri) seçin
genericSubmit=Gönder
processTimeWarning=Uyarı: Bu işlem, dosya boyutuna bağlı olarak bir dakikaya kadar sürebilir.
pageOrderPrompt=Özel Sayfa Sırası (Virgülle ayrılmış sayfa numaraları veya 2n+1 gibi bir fonksiyon girin) :
-pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
+pageSelectionPrompt=Özel Sayfa Seçimi (1,5,6 sayfa numaralarının virgülle ayrılmış bir listesini veya 2n+1 gibi bir fonksiyon girin) :
goToPage=Git
true=Doğru
false=Yanlış
unknown=Bilinmeyen
save=Kaydet
+saveToBrowser=Tarayıcıya Kaydet
close=Kapat
filesSelected=dosya seçildi
noFavourites=Favori eklenmedi
+downloadComplete=İndirme Tamamlandı
bored=Sıkıldınız mı?
alphabet=Alfabe
downloadPdf=PDF İndir
@@ -43,38 +45,56 @@ red=Kırmızı
green=Yeşil
blue=Mavi
custom=Özel
-WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
-poweredBy=Powered by
-yes=Yes
-no=No
+WorkInProgess=Çalışmalar devam ediyor, Çalışmayabilir veya hatalı olabilir, Lütfen herhangi bir sorunu bildirin!
+poweredBy=Tarafından desteklenmektedir
+yes=Evet
+no=Hayır
changedCredsMessage=Bilgiler değiştirildi!
notAuthenticatedMessage=Kullanıcı doğrulanmadı.
userNotFoundMessage=Kullanıcı bulunamadı.
incorrectPasswordMessage=Mevcut şifre yanlış.
usernameExistsMessage=Yeni Kullanıcı Adı zaten var.
+invalidUsernameMessage=Geçersiz kullanıcı adı, Kullanıcı adı yalnızca alfabe karakterleri ve sayılar içermelidir.
+deleteCurrentUserMessage=Şu anda oturum açmış olan kullanıcı silinemiyor.
+deleteUsernameExistsMessage=Kullanıcı adı mevcut değil ve silinemez.
+downgradeCurrentUserMessage=Mevcut kullanıcının rolü düşürülemiyor
+downgradeCurrentUserLongMessage=Mevcut kullanıcının rolü düşürülemiyor. Bu nedenle, mevcut kullanıcı gösterilmeyecektir.
+error=Hata
+oops=Tüh!
+help=Yardım
+goHomepage=Anasayfa'ya git
+joinDiscord=Discord sunucumuza katılın
+seeDockerHub=Docker Hub'a bakın
+visitGithub=Github Deposunu Ziyaret Edin
+donate=Bağış Yapın
+color=Renk
+sponsor=Bağış
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
-pipeline.uploadButton=Upload Custom
-pipeline.configureButton=Configure
-pipeline.defaultOption=Custom
-pipeline.submitButton=Submit
+pipeline.header=Çoklu İşlemler Menü (Beta)
+pipeline.uploadButton=Upload edin
+pipeline.configureButton=Yapılandır
+pipeline.defaultOption=Özel
+pipeline.submitButton=Gönder
+pipeline.help=Çoklu İşlemler Yardım
+pipeline.scanHelp=Klasör Tarama Yardımı
######################
# 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
+pipelineOptions.header=Çoklu İşlemler Yapılandırma
+pipelineOptions.pipelineNameLabel=Çoklu İşlemler İsim
+pipelineOptions.saveSettings=Ayarları Kaydet
+pipelineOptions.pipelineNamePrompt=Buraya isim girin
+pipelineOptions.selectOperation=İşlem Seçin
+pipelineOptions.addOperationButton=İşlem ekle
+pipelineOptions.pipelineHeader=Çoklu İşlemler:
+pipelineOptions.saveButton=İndir
+pipelineOptions.validateButton=Doğrula
@@ -94,6 +114,7 @@ navbar.settings=Ayarlar
#############
settings.title=Ayarlar
settings.update=Güncelleme mevcut
+settings.updateAvailable={0} mevcut kurulu sürümdür. Yeni bir sürüm ({1}) mevcuttur.
settings.appVersion=Uygulama Sürümü:
settings.downloadOption.title=İndirme seçeneği seçin (Zip olmayan tek dosya indirmeler için):
settings.downloadOption.1=Aynı pencerede aç
@@ -102,12 +123,13 @@ settings.downloadOption.3=Dosyayı indir
settings.zipThreshold=İndirilen dosya sayısı şu değeri aştığında zip dosyası oluştur:
settings.signOut=Oturumu Kapat
settings.accountSettings=Hesap Ayarları
-
-
+settings.bored.help=Paskalya yumurtası oyunu etkinleştirir
+settings.cacheInputs.name=Form girdilerini kaydet
+settings.cacheInputs.help=Gelecekteki çalıştırmalar için önceden kullanılan girdileri saklamayı etkinleştirin
changeCreds.title=Giriş Bilgilerini Değiştir
changeCreds.header=Hesap Detaylarınızı Güncelleyin
-changeCreds.changeUserAndPassword=Varsayılan giriş bilgilerini kullanıyorsunuz. Lütfen yeni bir şifre (ve istenirse kullanıcı adı) girin
+changeCreds.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=Yeni Kullanıcı Adı
changeCreds.oldPassword=Mevcut Şifre
changeCreds.newPassword=Yeni Şifre
@@ -142,25 +164,29 @@ adminUserSettings.header=Yönetici Kullanıcı Kontrol Ayarları
adminUserSettings.admin=Yönetici
adminUserSettings.user=Kullanıcı
adminUserSettings.addUser=Yeni Kullanıcı Ekle
+adminUserSettings.usernameInfo=Kullanıcı adı yalnızca harf ve rakamlardan oluşmalı, boşluk veya özel karakter içermemelidir.
adminUserSettings.roles=Roller
adminUserSettings.role=Rol
adminUserSettings.actions=Eylemler
adminUserSettings.apiUser=Sınırlı API Kullanıcısı
+adminUserSettings.extraApiUser=Ek Sınırlı API Kullanıcısı
adminUserSettings.webOnlyUser=Sadece Web Kullanıcısı
-adminUserSettings.demoUser=Demo User (No custom settings)
+adminUserSettings.demoUser=Demo Kullanıcısı (Özel ayar yok)
+adminUserSettings.internalApiUser=Dahili API Kullanıcısı
adminUserSettings.forceChange=Kullanıcının girişte kullanıcı adı/şifre değiştirmesini zorla
adminUserSettings.submit=Kullanıcıyı Kaydet
+adminUserSettings.changeUserRole=Kullanıcı rolünü değiştir
#############
# HOME-PAGE #
#############
home.desc=Yerel olarak barındırılan tüm PDF ihtiyaçlarınız için tek durak noktanız.
-home.searchBar=Search for features...
+home.searchBar=Özellikleri arayın...
-home.viewPdf.title=View PDF
-home.viewPdf.desc=View, annotate, add text or images
-viewPdf.tags=view,read,annotate,text,image
+home.viewPdf.title=PDF Görüntüle
+home.viewPdf.desc=Görüntüleyin, açıklama ekleyin, metin veya resim ekleyin
+viewPdf.tags=görüntüle,oku,açıklama ekle,metin,görüntü
home.multiTool.title=PDF Çoklu Araç
home.multiTool.desc=Birleştir, Döndür, Yeniden Düzenle ve Sayfaları Kaldır
@@ -284,9 +310,9 @@ home.removeBlanks.title=Boş Sayfaları Kaldır
home.removeBlanks.desc=Bir belgeden boş sayfaları tespit eder ve kaldırır
removeBlanks.tags=temizle,sadeleştir,içeriksiz,düzenle
-home.removeAnnotations.title=Remove Annotations
-home.removeAnnotations.desc=Removes all comments/annotations from a PDF
-removeAnnotations.tags=comments,highlight,notes,markup,remove
+home.removeAnnotations.title=Ek Açıklamaları Kaldır
+home.removeAnnotations.desc=PDF'deki tüm yorumları/açıklamaları kaldırır
+removeAnnotations.tags=yorumlar,vurgulama,notlar,işaretleme,kaldırma
home.compare.title=Karşılaştır
home.compare.desc=2 PDF Belgesi arasındaki farkları karşılaştırır ve gösterir
@@ -304,8 +330,8 @@ home.scalePages.title=Sayfa boyutunu/ölçeğini ayarla
home.scalePages.desc=Bir sayfanın ve/veya içeriğinin boyutunu/ölçeğini değiştirir
scalePages.tags=boyutlandır,değiştir,boyut,uyarla
-home.pipeline.title=Hattı (İleri Seviye)
-home.pipeline.desc=Hattı betikleri tanımlayarak PDF'lere birden fazla işlemi çalıştır
+home.pipeline.title=Çoklu İşlemler (İleri Seviye)
+home.pipeline.desc=Çoklu İşlemler tanımlayarak PDF'lere birden fazla işlemi çalıştır
pipeline.tags=otomatikleştir,sıralı,betikli,toplu-işlem
home.add-page-numbers.title=Sayfa Numaraları Ekle
@@ -369,27 +395,36 @@ home.autoRedact.title=Otomatik Karartma
home.autoRedact.desc=Giriş metnine dayanarak bir PDF'teki metni Otomatik Karartır (Redakte)
autoRedact.tags=Karart,Gizle,karartma,siyah,markör,gizli
-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.tableExtraxt.title=PDF'den CSV'ye
+home.tableExtraxt.desc=PDF'den Tabloları çıkarır ve CSV'ye dönüştürür
+tableExtraxt.tags=CSV, Tablo Çıkarma, ayıklama, dönüştürme
-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.autoSizeSplitPDF.title=Boyut/Sayıya Göre Otomatik Bölme
+home.autoSizeSplitPDF.desc=Tek bir PDF'yi boyut, sayfa sayısı veya belge sayısına göre birden fazla belgeye bölün
+autoSizeSplitPDF.tags=pdf,bölme,belge,organizasyon
-home.overlay-pdfs.title=Overlay PDFs
-home.overlay-pdfs.desc=Overlays PDFs on-top of another PDF
-overlay-pdfs.tags=Overlay
+home.overlay-pdfs.title=PDF'leri Bindirme
+home.overlay-pdfs.desc=PDF'leri başka bir PDF'nin üzerine bindirir
+overlay-pdfs.tags=Bindirme
-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
+home.split-by-sections.title=PDF'yi Bölümlere Ayırma
+home.split-by-sections.desc=PDF'nin her sayfasını daha küçük yatay ve dikey bölümlere ayırın
+split-by-sections.tags=Bölümlere Ayırma, Bölme, Özelleştirme
-home.AddStampRequest.title=Add Stamp to PDF
-home.AddStampRequest.desc=Add text or add image stamps at set locations
-AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.AddStampRequest.title=PDF'ye Damga Ekleme
+home.AddStampRequest.desc=Belirlenen konumlara metin veya resim damgaları ekleyin
+AddStampRequest.tags=Damga, Görüntü ekle, Görüntüyü ortala, Filigran, PDF, Göm, Özelleştir
+
+
+home.PDFToBook.title=PDF'den Kitaba
+home.PDFToBook.desc=Calibre kullanarak PDF'yi Kitap/Komik formatlarına dönüştürür
+PDFToBook.tags=Kitap,Çizgi Roman,Calibre,Dönüştür,manga,amazon,kindle,epub,mobi,azw3,docx,rtf,txt,html,lit,fb2,pdb,lrf
+
+home.BookToPDF.title=Kitaptan PDF'ye
+home.BookToPDF.desc=calibre kullanarak Kitap/Karikatür formatlarını PDF'ye dönüştürür
+BookToPDF.tags=Kitap,Çizgi Roman,Calibre,Dönüştür,manga,amazon,kindle,epub,mobi,azw3,docx,rtf,txt,html,lit,fb2,pdb,lrf
###########################
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=Giriş Yap
+login.header=Giriş Yap
login.signin=Giriş Yap
login.rememberme=Beni hatırla
login.invalid=Geçersiz kullanıcı adı veya şifre.
login.locked=Hesabınız kilitlendi.
login.signinTitle=Lütfen giriş yapınız.
+login.ssoSignIn=Tek Oturum Açma ile Giriş Yap
+login.oauth2AutoCreateDisabled=OAUTH2 Otomatik Oluşturma Kullanıcı Devre Dışı Bırakıldı
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=Tek Sayfaya Dönüştür
pageExtracter.title=Sayfaları Çıkar
pageExtracter.header=Sayfaları Çıkar
pageExtracter.submit=Çıkar
+pageExtracter.placeholder=(örneğin 1,2,8 veya 4,7,12-16 ya da 2n-1)
#getPdfInfo
@@ -467,37 +506,37 @@ HTMLToPDF.header=HTML'den PDF'e
HTMLToPDF.help=HTML dosyalarını ve html/css/görsel vb. içeren ZIP'leri kabul eder
HTMLToPDF.submit=Dönüştür
HTMLToPDF.credit=WeasyPrint Kullanıyor
-HTMLToPDF.zoom=Zoom level for displaying the website.
-HTMLToPDF.pageWidth=Width of the page in centimeters. (Blank to default)
-HTMLToPDF.pageHeight=Height of the page in centimeters. (Blank to default)
-HTMLToPDF.marginTop=Top margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginBottom=Bottom margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginLeft=Left margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginRight=Right margin of the page in millimeters. (Blank to default)
-HTMLToPDF.printBackground=Render the background of websites.
-HTMLToPDF.defaultHeader=Enable Default Header (Name and page number)
-HTMLToPDF.cssMediaType=Change the CSS media type of the page.
-HTMLToPDF.none=None
-HTMLToPDF.print=Print
-HTMLToPDF.screen=Screen
+HTMLToPDF.zoom=Web sitesini görüntülemek için yakınlaştırma düzeyi.
+HTMLToPDF.pageWidth=Sayfanın santimetre cinsinden genişliği. (Varsayılan olarak boş)
+HTMLToPDF.pageHeight=Sayfanın santimetre cinsinden yüksekliği. (Varsayılan olarak boş)
+HTMLToPDF.marginTop=Sayfanın milimetre cinsinden üst kenar boşluğu. (Varsayılan olarak boş)
+HTMLToPDF.marginBottom=Sayfanın milimetre cinsinden alt kenar boşluğu. (Varsayılan olarak boş)
+HTMLToPDF.marginLeft=Sayfanın milimetre cinsinden sol kenar boşluğu. (Varsayılan olarak boş)
+HTMLToPDF.marginRight=Sayfanın milimetre cinsinden sağ kenar boşluğu. (Varsayılan olarak boş)
+HTMLToPDF.printBackground=Web sitelerinin arka planını oluşturun.
+HTMLToPDF.defaultHeader=Varsayılan Üstbilgiyi Etkinleştir (Ad ve sayfa numarası)
+HTMLToPDF.cssMediaType=Sayfanın CSS ortam türünü değiştirin.
+HTMLToPDF.none=Hiçbiri
+HTMLToPDF.print=Yazdır
+HTMLToPDF.screen=Ekran
#AddStampRequest
-AddStampRequest.header=Stamp PDF
-AddStampRequest.title=Stamp PDF
-AddStampRequest.stampType=Stamp Type
-AddStampRequest.stampText=Stamp Text
-AddStampRequest.stampImage=Stamp Image
-AddStampRequest.alphabet=Alphabet
-AddStampRequest.fontSize=Font/Image Size
-AddStampRequest.rotation=Rotation
-AddStampRequest.opacity=Opacity
-AddStampRequest.position=Position
-AddStampRequest.overrideX=Override X Coordinate
-AddStampRequest.overrideY=Override Y Coordinate
-AddStampRequest.customMargin=Custom Margin
-AddStampRequest.customColor=Custom Text Color
-AddStampRequest.submit=Submit
+AddStampRequest.header=Damga PDF
+AddStampRequest.title=Damga PDF
+AddStampRequest.stampType=Damga Türü
+AddStampRequest.stampText=Damga Metni
+AddStampRequest.stampImage=Damga Resmi
+AddStampRequest.alphabet=Alfabe
+AddStampRequest.fontSize=Yazı Tipi/Görüntü Boyutu
+AddStampRequest.rotation=Döndürme
+AddStampRequest.opacity=Opaklık
+AddStampRequest.position=Konum
+AddStampRequest.overrideX=X Koordinatını geçersiz kıl
+AddStampRequest.overrideY=Y Koordinatını Geçersiz Kıl
+AddStampRequest.customMargin=Özel Kenar Boşluğu
+AddStampRequest.customColor=Özel Metin Rengi
+AddStampRequest.submit=Gönder
#sanitizePDF
@@ -563,7 +602,7 @@ autoSplitPDF.submit=Gönder
#pipeline
-pipeline.title=Pipeline
+pipeline.title=Çoklu İşlemler
#pageLayout
@@ -586,11 +625,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.jksNote=Note: Sertifika türünüz aşağıda listelenmemişse, lütfen keytool komut satırı aracını kullanarak sertifikanızı bir Java Keystore (.jks) dosyasına dönüştürün. Ardından, aşağıdaki .jks dosyası seçeneğini seçin.
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.selectJKS=Java Keystore Dosyanızı (.jks veya .keystore) seçin:
certSign.certType=Sertifika Türü
certSign.password=Anahtar Deposu veya Özel Anahtar Şifrenizi Girin (Varsa):
certSign.showSig=İmzayı Göster
@@ -611,9 +650,9 @@ removeBlanks.submit=Boşları Kaldır
#removeAnnotations
-removeAnnotations.title=Remove Annotations
-removeAnnotations.header=Remove Annotations
-removeAnnotations.submit=Remove
+removeAnnotations.title=Ek Açıklamaları Kaldır
+removeAnnotations.header=Ek Açıklamaları Kaldır
+removeAnnotations.submit=Kaldır
#compare
@@ -623,6 +662,18 @@ compare.document.1=Belge 1
compare.document.2=Belge 2
compare.submit=Karşılaştır
+#BookToPDF
+BookToPDF.title=Kitapları ve Çizgi Romanları PDF'e Dönüştürme
+BookToPDF.header=Kitaptan PDF'ye
+BookToPDF.credit=Kalibre Kullanır
+BookToPDF.submit=Dönüştür
+
+#PDFToBook
+PDFToBook.title=PDF'den Kitaba
+PDFToBook.header=PDF'den Kitaba
+PDFToBook.selectText.1=Format biçimi
+PDFToBook.credit=Kalibre Kullanır
+PDFToBook.submit=Dönüştür
#sign
sign.title=İmzala
@@ -643,6 +694,7 @@ repair.submit=Onar
#flatten
flatten.title=Düzleştir
flatten.header=PDF'leri Düzleştir
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Düzleştir
@@ -726,21 +778,34 @@ merge.submit=Birleştir
pdfOrganiser.title=Sayfa Organizatörü
pdfOrganiser.header=PDF Sayfa Organizatörü
pdfOrganiser.submit=Sayfaları Yeniden Düzenle
+pdfOrganiser.mode=Mod
+pdfOrganiser.mode.1=Özel Sayfa Düzeni
+pdfOrganiser.mode.2=Ters Sıralama
+pdfOrganiser.mode.3=Çift Taraflı Sıralama
+pdfOrganiser.mode.4=Kitapçık Sıralama
+pdfOrganiser.mode.5=Yandan Dikişli Kitapçık Sıralama
+pdfOrganiser.mode.6=Tek-Çift Ayrımı
+pdfOrganiser.mode.7=İlk Önce Kaldır
+pdfOrganiser.mode.8=Sonuncuyu Kaldır
+pdfOrganiser.mode.9=İlk ve Sonu Kaldır
+pdfOrganiser.placeholder=(örn. 1,3,2 veya 4-8,2,10-12 veya 2n-1)
#multiTool
multiTool.title=PDF Çoklu Araç
multiTool.header=PDF Çoklu Araç
+multiTool.uploadPrompts=Lütfen PDF Yükleyin
#view pdf
-viewPdf.title=View PDF
-viewPdf.header=View PDF
+viewPdf.title=PDF Görüntüle
+viewPdf.header=PDF Görüntüle
#pageRemover
pageRemover.title=Sayfa Silici
pageRemover.header=PDF Sayfa silici
pageRemover.pagesToDelete=Silinmesi gereken sayfalar (Virgülle ayrılmış sayfa numaraları listesi girin):
pageRemover.submit=Sayfaları Sil
+pageRemover.placeholder=(örn. 1,2,6 veya 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=Döndürme açısını seçin (90 derecenin katları olarak):
rotate.submit=Döndür
-#merge
+#split-pdfs
split.title=PDF Ayır
split.header=PDF Ayır
split.desc.1=Seçtiğiniz numaralar, bir ayrım yapmak istediğiniz sayfa numarasıdır
-split.desc.2=Bu nedenle, 1,3,7-8 seçmek 10 sayfalı bir belgeyi şunlarla 6 ayrı PDF'e böler:
+split.desc.2=Bu nedenle, 1,3,7-9 seçmek 10 sayfalı bir belgeyi şunlarla 6 ayrı PDF'e böler:
split.desc.3=Belge #1: Sayfa 1
split.desc.4=Belge #2: Sayfa 2 ve 3
-split.desc.5=Belge #3: Sayfa 4, 5 ve 6
-split.desc.6=Belge #4: Sayfa 7
-split.desc.7=Belge #5: Sayfa 8
-split.desc.8=Belge #6: Sayfa 9 ve 10
+split.desc.5=Belge #3: Sayfa 4, 5, 6 ve 7
+split.desc.6=Belge #4: Sayfa 8
+split.desc.7=Belge #5: Sayfa 9
+split.desc.8=Belge #6: Sayfa 10
split.splitPages=Ayrılacak sayfaları girin:
split.submit=Ayır
@@ -828,6 +893,8 @@ watermark.selectText.7=Opaklık (0% - 100%):
watermark.selectText.8=Filigran Türü:
watermark.selectText.9=Filigran Resmi:
watermark.submit=Filigran Ekle
+watermark.type.1=Metin
+watermark.type.2=Resim
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF'den PDF/A'ya
pdfToPDFA.header=PDF'den PDF/A'ya
pdfToPDFA.credit=Bu hizmet PDF/A dönüşümü için OCRmyPDF kullanır
pdfToPDFA.submit=Dönüştür
+pdfToPDFA.tip=Şu anda aynı anda birden fazla giriş için çalışmıyor
+pdfToPDFA.outputFormat=Çıkış formatı
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=Dönüştür
#PDFToHTML
PDFToHTML.title=PDF'den HTML'e
PDFToHTML.header=PDF'den HTML'e
-PDFToHTML.credit=Bu hizmet dosya dönüşümü için LibreOffice kullanır.
+PDFToHTML.credit=Bu hizmet dosya dönüşümü için pdftohtml kullanır.
PDFToHTML.submit=Dönüştür
@@ -919,54 +988,77 @@ PDFToXML.credit=Bu hizmet dosya dönüşümü için LibreOffice kullanır.
PDFToXML.submit=Dönüştür
#PDFToCSV
-PDFToCSV.title=PDF to CSV
-PDFToCSV.header=PDF to CSV
-PDFToCSV.prompt=Choose page to extract table
-PDFToCSV.submit=Extract
+PDFToCSV.title=PDF'den CSV'ye
+PDFToCSV.header=PDF'den CSV'ye
+PDFToCSV.prompt=Tabloyu çıkarmak için sayfa seçin
+PDFToCSV.submit=Çıkart
#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
+split-by-size-or-count.title=PDF'yi Boyuta veya Sayıya Göre Bölme
+split-by-size-or-count.header=PDF'yi Boyuta veya Sayıya Göre Bölme
+split-by-size-or-count.type.label=Bölme Türünü Seçin
+split-by-size-or-count.type.size=Boyuta Göre
+split-by-size-or-count.type.pageCount=Sayfa Sayısına Göre
+split-by-size-or-count.type.docCount=Belge Sayısına Göre
+split-by-size-or-count.value.label=Değer Girin
+split-by-size-or-count.value.placeholder=Boyutu (örn. 2MB veya 3KB) veya sayıyı (örn. 5) girin
+split-by-size-or-count.submit=Gönder
#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
+overlay-pdfs.header=PDF Dosyalarını Bindirme
+overlay-pdfs.baseFile.label=Temel PDF Dosyasını Seçin
+overlay-pdfs.overlayFiles.label=İkinci PDF Dosyalarını Seçin
+overlay-pdfs.mode.label=Bindirme Modunu Seçin
+overlay-pdfs.mode.sequential=Sıralı Bindirme
+overlay-pdfs.mode.interleaved=Serpiştirilmiş Bindirme
+overlay-pdfs.mode.fixedRepeat=Sabit Tekrar Bindirme
+overlay-pdfs.counts.label=Bindirme Sayıları (Sabit Tekrar Modu için)
+overlay-pdfs.counts.placeholder=Virgülle ayrılmış sayıları girin (örn. 2,3,1)
+overlay-pdfs.position.label=Bindirme Konumunu Seçin
+overlay-pdfs.position.foreground=Ön plan
+overlay-pdfs.position.background=Arka plan
+overlay-pdfs.submit=Gönder
#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
+split-by-sections.title=PDF'yi Bölümlere Ayırma
+split-by-sections.header=PDF'yi Bölümlere Ayırma
+split-by-sections.horizontal.label=Yatay Bölümler
+split-by-sections.vertical.label=Dikey Bölümler
+split-by-sections.horizontal.placeholder=Yatay bölme sayısını girin
+split-by-sections.vertical.placeholder=Dikey bölme sayısını girin
+split-by-sections.submit=PDF'yi Böl
+split-by-sections.merge=Bir PDF'de Birleştirin
+
+
+#printFile
+printFile.title=Dosya Yazdır
+printFile.header=Dosyayı Yazıcıya Yazdır
+printFile.selectText.1=Yazdırılacak Dosyayı Seçin
+printFile.selectText.2=Yazıcı Adını Girin
+printFile.submit=Yazdır
#licenses
-licenses.nav=Licenses
-licenses.title=3rd Party Licenses
-licenses.header=3rd Party Licenses
-licenses.module=Module
-licenses.version=Version
-licenses.license=License
+licenses.nav=Lisanslar
+licenses.title=3. Taraf Lisansları
+licenses.header=3. Taraf Lisansları
+licenses.module=Modül
+licenses.version=Versiyon
+licenses.license=Lisans
+# error
+error.sorry=Sorun için özür dileriz!
+error.needHelp=Yardıma mı ihtiyacınız var / Bir sorun mu buldunuz?
+error.contactTip=Hala sorun yaşıyorsanız, yardım için bize ulaşmaktan çekinmeyin. GitHub sayfamızdan bir bilet gönderebilir veya Discord üzerinden bizimle iletişime geçebilirsiniz:
+error.404.head=404 - Sayfa Bulunamadı | Tüh, kodda takıldık!
+error.404.1=Aradığınız sayfayı bulamıyoruz.
+error.404.2=Bir şeyler ters gitti
+error.github=GitHub üzerinden bir hata bildirin
+error.showStack=Yığın İzlemesini Göster
+error.copyStack=Yığın İzini Kopyala
+error.githubSubmit=GitHub - Hata gönderin
+error.discordSubmit=Discord - Destek gönderisi gönderin
+
diff --git a/src/main/resources/messages_uk_UA.properties b/src/main/resources/messages_uk_UA.properties
new file mode 100644
index 00000000..1ace290c
--- /dev/null
+++ b/src/main/resources/messages_uk_UA.properties
@@ -0,0 +1,1064 @@
+###########
+# Generic #
+###########
+# the direction that the language is written (ltr=left to right, rtl = right to left)
+language.direction=ltr
+
+pdfPrompt=Оберіть PDF(и)
+multiPdfPrompt=Оберіть PDFи (2+)
+multiPdfDropPrompt=Оберіть (або перетягніть) всі необхідні PDFи
+imgPrompt=Оберіть зображення(я)
+genericSubmit=Надіслати
+processTimeWarning=Увага: Цей процес може тривати до хвилини в залежності від розміру файлу.
+pageOrderPrompt=Порядок сторінок (введіть список номерів сторінок через кому):
+pageSelectionPrompt=Користувацький вибір сторінки (введіть список номерів сторінок через кому 1,5,6 або функції типу 2n+1) :
+goToPage=Вперед
+true=Правда
+false=Брехня
+unknown=Невідомо
+save=Зберегти
+saveToBrowser=Зберегти в браузері
+close=Закрити
+filesSelected=файлів обрано
+noFavourites=Немає вибраного
+downloadComplete=Завантаження завершено
+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=Робота триває, може не працювати або глючити, будь ласка, повідомляйте про будь-які проблеми!
+poweredBy=Працює на
+yes=Так
+no=Ні
+changedCredsMessage=Облікові дані змінено!
+notAuthenticatedMessage=Користувач не пройшов перевірку автентичності.
+userNotFoundMessage=Користувача не знайдено.
+incorrectPasswordMessage=Поточний пароль невірний.
+usernameExistsMessage=Нове ім'я користувача вже існує.
+invalidUsernameMessage=Недійсне ім'я користувача, Ім'я користувача повинно містити тільки літери алфавіту та цифри.
+deleteCurrentUserMessage=Неможливо видалити користувача, який увійшов в систему.
+deleteUsernameExistsMessage=Ім'я користувача не існує і не може бути видалено.
+downgradeCurrentUserMessage=Неможливо понизити роль поточного користувача
+downgradeCurrentUserLongMessage=Неможливо понизити роль поточного користувача. Отже, поточний користувач не відображатиметься.
+error=Error
+oops=Oops!
+help=Help
+goHomepage=Go to Homepage
+joinDiscord=Join our Discord server
+seeDockerHub=See Docker Hub
+visitGithub=Visit Github Repository
+donate=Donate
+color=Color
+sponsor=Sponsor
+
+
+
+###############
+# Pipeline #
+###############
+pipeline.header=Меню конвеєрної обробки (Бета)
+pipeline.uploadButton=Завантажити Користувацький
+pipeline.configureButton=Налаштування
+pipeline.defaultOption=Користувацький
+pipeline.submitButton=Надіслати
+pipeline.help=Довідка з конвеєрної обробки
+pipeline.scanHelp=Довідка зі сканування папок
+
+######################
+# Pipeline Options #
+######################
+pipelineOptions.header=Налаштування конвеєрної обробки
+pipelineOptions.pipelineNameLabel=Назва конвеєра
+pipelineOptions.saveSettings=Зберегти налаштування операції
+pipelineOptions.pipelineNamePrompt=Введіть назву конвеєра тут
+pipelineOptions.selectOperation=Вибрати операцію
+pipelineOptions.addOperationButton=Додати операцію
+pipelineOptions.pipelineHeader=Конвеєр:
+pipelineOptions.saveButton=Завантажити
+pipelineOptions.validateButton=Перевірити
+
+
+
+
+#############
+# NAVBAR #
+#############
+navbar.convert=Конвертувати
+navbar.security=Безпека
+navbar.other=Інше
+navbar.darkmode=Темний режим
+navbar.pageOps=Операції зі сторінкою
+navbar.settings=Налаштування
+
+#############
+# SETTINGS #
+#############
+settings.title=Налаштування
+settings.update=Доступне оновлення
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
+settings.appVersion=Версія додатку:
+settings.downloadOption.title=Виберіть варіант завантаження (для завантаження одного файлу без zip):
+settings.downloadOption.1=Відкрити в тому ж вікні
+settings.downloadOption.2=Відкрити в новому вікні
+settings.downloadOption.3=Завантажити файл
+settings.zipThreshold=Zip-файли, коли кількість завантажених файлів перевищує
+settings.signOut=Вийти
+settings.accountSettings=Налаштування акаунта
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
+
+changeCreds.title=Змінити облікові дані
+changeCreds.header=Оновіть дані вашого облікового запису
+changeCreds.changePassword=Ви використовуєте заводські облікові дані для входу. Будь ласка, введіть новий пароль
+changeCreds.newUsername=Нове ім'я користувача
+changeCreds.oldPassword=Поточний пароль
+changeCreds.newPassword=Новий пароль
+changeCreds.confirmNewPassword=Підтвердіть новий пароль
+changeCreds.submit=Надіслати зміни
+
+
+
+account.title=Налаштування акаунта
+account.accountSettings=Налаштування акаунта
+account.adminSettings=Налаштування адміністратора - Перегляд і додавання користувачів
+account.userControlSettings=Налаштування контролю користувача
+account.changeUsername=Змінити ім'я користувача
+account.newUsername=Нове ім'я користувача
+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.usernameInfo=Ім'я користувача має містити тільки літери та цифри, без пробілів та спеціальних символів.
+adminUserSettings.roles=Ролі
+adminUserSettings.role=Роль
+adminUserSettings.actions=Дії
+adminUserSettings.apiUser=Обмежений користувач API
+adminUserSettings.extraApiUser=Додатковий обмежений користувач API
+adminUserSettings.webOnlyUser=Тільки веб-користувач
+adminUserSettings.demoUser=Демо-користувач (без налаштованих параметрів)
+adminUserSettings.internalApiUser=Внутрішній користувач API
+adminUserSettings.forceChange=Примусити користувача змінити пароль при вході в систему
+adminUserSettings.submit=Зберегти користувача
+adminUserSettings.changeUserRole=Змінити роль користувача
+
+#############
+# HOME-PAGE #
+#############
+home.desc=Ваш локальний універсальний магазин для всіх ваших потреб у PDF.
+home.searchBar=Пошук функцій...
+
+
+home.viewPdf.title=Перегляд PDF
+home.viewPdf.desc=Перегляд, анотація, додавання тексту або зображень
+viewPdf.tags=view,read,annotate,text,image
+
+home.multiTool.title=Мультіінструмент PDF
+home.multiTool.desc=Об'єднання, поворот, зміна порядку та видалення сторінок
+multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side
+
+home.merge.title=Об'єднати
+home.merge.desc=Легко об'єднуйте кілька PDF-файлів у один.
+merge.tags=merge,Page operations,Back end,server side
+
+home.split.title=Розділити
+home.split.desc=Розділіть PDF-файли на кілька документів
+split.tags=Page operations,divide,Multi Page,cut,server side
+
+home.rotate.title=Повернути
+home.rotate.desc=Легко повертайте ваші PDF-файли.
+rotate.tags=server side
+
+
+home.imageToPdf.title=Зображення в PDF
+home.imageToPdf.desc=Перетворення зображення (PNG, JPEG, GIF) в PDF.
+imageToPdf.tags=conversion,img,jpg,picture,photo
+
+home.pdfToImage.title=PDF в зображення
+home.pdfToImage.desc=Перетворення PDF в зображення. (PNG, JPEG, GIF)
+pdfToImage.tags=conversion,img,jpg,picture,photo
+
+home.pdfOrganiser.title=Реорганізація
+home.pdfOrganiser.desc=Видалення/перестановка сторінок у будь-якому порядку
+pdfOrganiser.tags=duplex,even,odd,sort,move
+
+
+home.addImage.title=Додати зображення
+home.addImage.desc=Додає зображення у вказане місце в PDF (в розробці)
+addImage.tags=img,jpg,picture,photo
+
+home.watermark.title=Додати водяний знак
+home.watermark.desc=Додайте свій водяний знак до документа PDF.
+watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo
+
+home.permissions.title=Змінити дозволи
+home.permissions.desc=Змініть дозволи вашого документа PDF
+permissions.tags=read,write,edit,print
+
+
+home.removePages.title=Видалення
+home.removePages.desc=Видаліть непотрібні сторінки з документа PDF.
+removePages.tags=Remove pages,delete pages
+
+home.addPassword.title=Додати пароль
+home.addPassword.desc=Зашифруйте документ PDF паролем.
+addPassword.tags=secure,security
+
+home.removePassword.title=Видалити пароль
+home.removePassword.desc=Зніміть захист паролем з вашого документа PDF.
+removePassword.tags=secure,Decrypt,security,unpassword,delete password
+
+home.compressPdfs.title=Стиснути
+home.compressPdfs.desc=Стискайте PDF-файли, щоб зменшити їх розмір.
+compressPdfs.tags=squish,small,tiny
+
+
+home.changeMetadata.title=Змінити метадані
+home.changeMetadata.desc=Змінити/видалити/додати метадані з документа PDF
+changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
+
+home.fileToPDF.title=Конвертувати файл в PDF
+home.fileToPDF.desc=Конвертуйте майже будь-який файл в PDF (DOCX, PNG, XLS, PPT, TXT та інші)
+fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
+
+home.ocr.title=OCR/Очищення сканування
+home.ocr.desc=Очищення сканування та виявлення тексту на зображеннях у файлі PDF та повторне додавання його як текст.
+ocr.tags=recognition,text,image,scan,read,identify,detection,editable
+
+
+home.extractImages.title=Витягнути зображення
+home.extractImages.desc=Витягує всі зображення з PDF і зберігає їх у zip
+extractImages.tags=picture,photo,save,archive,zip,capture,grab
+
+home.pdfToPDFA.title=PDF в PDF/A
+home.pdfToPDFA.desc=Перетворення PDF в PDF/A для довготривалого зберігання
+pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
+
+home.PDFToWord.title=PDF в Word
+home.PDFToWord.desc=Перетворення PDF в формати Word (DOC, DOCX та ODT)
+PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
+
+home.PDFToPresentation.title=PDF в презентацію
+home.PDFToPresentation.desc=Перетворення PDF в формати презентацій (PPT, PPTX та ODP)
+PDFToPresentation.tags=slides,show,office,microsoft
+
+home.PDFToText.title=PDF в Text/RTF
+home.PDFToText.desc=Перетворення PDF в текстовий або RTF формат
+PDFToText.tags=richformat,richtextformat,rich text format
+
+home.PDFToHTML.title=PDF в HTML
+home.PDFToHTML.desc=Перетворення PDF в формат HTML
+PDFToHTML.tags=web content,browser friendly
+
+
+home.PDFToXML.title=PDF в XML
+home.PDFToXML.desc=Перетворення PDF в формат XML
+PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
+
+home.ScannerImageSplit.title=Виявлення/розділення відсканованих фотографій
+home.ScannerImageSplit.desc=Розділяє кілька фотографій з фото/PDF
+ScannerImageSplit.tags=separate,auto-detect,scans,multi-photo,organize
+
+home.sign.title=Підпис
+home.sign.desc=Додає підпис до PDF за допомогою малюнка, тексту або зображення
+sign.tags=authorize,initials,drawn-signature,text-sign,image-signature
+
+home.flatten.title=Згладжування
+home.flatten.desc=Видалення всіх інтерактивних елементів та форм з PDF
+flatten.tags=static,deactivate,non-interactive,streamline
+
+home.repair.title=Ремонт
+home.repair.desc=Намагається відновити пошкоджений/зламаний PDF
+repair.tags=fix,restore,correction,recover
+
+home.removeBlanks.title=Видалити порожні сторінки
+home.removeBlanks.desc=Виявляє та видаляє порожні сторінки з документа
+removeBlanks.tags=cleanup,streamline,non-content,organize
+
+home.removeAnnotations.title=Видалити анотації
+home.removeAnnotations.desc=Видаляє всі коментарі/анотації з PDF
+removeAnnotations.tags=comments,highlight,notes,markup,remove
+
+home.compare.title=Порівняння
+home.compare.desc=Порівнює та показує різницю між двома PDF-документами
+compare.tags=differentiate,contrast,changes,analysis
+
+home.certSign.title=Підписати сертифікатом
+home.certSign.desc=Підписати PDF сертифікатом/ключем (PEM/P12)
+certSign.tags=authenticate,PEM,P12,official,encrypt
+
+home.pageLayout.title=Об'єднати сторінки
+home.pageLayout.desc=Об'єднання кількох сторінок документа PDF в одну сторінку
+pageLayout.tags=merge,composite,single-view,organize
+
+home.scalePages.title=Змінити розмір/масштаб сторінки
+home.scalePages.desc=Змінити розмір/масштаб сторінки та/або її вмісту.
+scalePages.tags=resize,modify,dimension,adapt
+
+home.pipeline.title=Конвеєр (розширений)
+home.pipeline.desc=Виконуйте кілька дій з PDF-файлами, визначаючи сценарії конвеєрної обробки.
+pipeline.tags=automate,sequence,scripted,batch-process
+
+home.add-page-numbers.title=Додати номера сторінок
+home.add-page-numbers.desc=Додає номера сторінок по всьому документу в заданому місці
+add-page-numbers.tags=paginate,label,organize,index
+
+home.auto-rename.title=Автоматичне перейменування PDF-файлу
+home.auto-rename.desc=Автоматичне перейменування файлу PDF на основі його виявленого заголовку
+auto-rename.tags=auto-detect,header-based,organize,relabel
+
+home.adjust-contrast.title=Налаштування кольорів/контрастності
+home.adjust-contrast.desc=Налаштування контрастності, насиченості та яскравості файлу PDF
+adjust-contrast.tags=color-correction,tune,modify,enhance
+
+home.crop.title=Обрізати PDF-файл
+home.crop.desc=Обрізати PDF-файл, щоб зменшити його розмір (текст залишається!)
+crop.tags=trim,shrink,edit,shape
+
+home.autoSplitPDF.title=Автоматичне розділення сторінок
+home.autoSplitPDF.desc=Автоматичне розділення відсканованого PDF-файлу за допомогою фізичного роздільника відсканованих сторінок QR-коду
+autoSplitPDF.tags=QR-based,separate,scan-segment,organize
+
+home.sanitizePdf.title=Санітарна обробка
+home.sanitizePdf.desc=Видалення скриптів та інших елементів з PDF-файлів
+sanitizePdf.tags=clean,secure,safe,remove-threats
+
+home.URLToPDF.title=URL/сайт у PDF
+home.URLToPDF.desc=Конвертує будь-який http(s)URL у PDF
+URLToPDF.tags=web-capture,save-page,web-to-doc,archive
+
+home.HTMLToPDF.title=HTML у PDF
+home.HTMLToPDF.desc=Конвертує будь-який HTML-файл або zip-файл у PDF.
+HTMLToPDF.tags=markup,web-content,transformation,convert
+
+
+home.MarkdownToPDF.title=Markdown у PDF
+home.MarkdownToPDF.desc=Конвертує будь-який файл Markdown у PDF
+MarkdownToPDF.tags=markup,web-content,transformation,convert
+
+
+home.getPdfInfo.title=Отримати ВСЮ інформацію у форматі PDF
+home.getPdfInfo.desc=Збирає будь-яку можливу інформацію у PDF-файлах.
+getPdfInfo.tags=infomation,data,stats,statistics
+
+
+home.extractPage.title=Видобути сторінку(и)
+home.extractPage.desc=Видобуває обрані сторінки з PDF
+extractPage.tags=extract
+
+
+home.PdfToSinglePage.title=PDF на одну велику сторінку
+home.PdfToSinglePage.desc=Об'єднує всі сторінки PDF в одну велику сторінку.
+PdfToSinglePage.tags=single page
+
+
+home.showJS.title=Показати Javascript
+home.showJS.desc=Шукає та відображає будь-який JS, вбудований у PDF-файл.
+showJS.tags=JS
+
+home.autoRedact.title=Автоматичне редагування
+home.autoRedact.desc=Автоматичне затемнення (чорніння) тексту в PDF на основі вхідного тексту
+autoRedact.tags=Redact,Hide,black out,black,marker,hidden
+
+home.tableExtraxt.title=PDF у CSV
+home.tableExtraxt.desc=Видобуває таблиці з PDF та перетворює їх у CSV
+tableExtraxt.tags=CSV,Table Extraction,extract,convert
+
+
+home.autoSizeSplitPDF.title=Автоматичне розділення за розміром/кількістю
+home.autoSizeSplitPDF.desc=Розділяє один PDF на кілька документів на основі розміру, кількості сторінок або кількості документів
+autoSizeSplitPDF.tags=pdf,split,document,organization
+
+
+home.overlay-pdfs.title=Накладення PDF
+home.overlay-pdfs.desc=Накладення одного PDF поверх іншого PDF
+overlay-pdfs.tags=Overlay
+
+home.split-by-sections.title=Розділення PDF за секціями
+home.split-by-sections.desc=Розділення кожної сторінки PDF на менші горизонтальні та вертикальні секції
+split-by-sections.tags=Section Split, Divide, Customize
+
+home.AddStampRequest.title=Додати печатку на PDF
+home.AddStampRequest.desc=Додавання текстової або зображення печатки у вказані місця
+AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+
+
+home.PDFToBook.title=PDF у книгу/комікс
+home.PDFToBook.desc=Конвертує PDF у формат книги/комікса за допомогою calibre
+PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+home.BookToPDF.title=Книга у PDF
+home.BookToPDF.desc=Конвертує формати книги/комікса у PDF за допомогою calibre
+BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
+
+
+###########################
+# #
+# WEB PAGES #
+# #
+###########################
+#login
+login.title=Вхід
+login.header=Вхід
+login.signin=Увійти
+login.rememberme=Запам'ятати мене
+login.invalid=Недійсне ім'я користувача або пароль.
+login.locked=Ваш обліковий запис заблоковано.
+login.signinTitle=Будь ласка, увійдіть
+login.ssoSignIn=Увійти через єдиний вхід
+login.oauth2AutoCreateDisabled=Автоматичне створення користувача OAUTH2 ВИМКНЕНО
+
+
+#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=Видобути
+pageExtracter.placeholder=(наприклад 1,2,8 або 4,7,12-16 або 2n-1)
+
+
+#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 та ZIP-файли, що містять html/css/зображення тощо.
+HTMLToPDF.submit=Конвертувати
+HTMLToPDF.credit=Використовує WeasyPrint
+HTMLToPDF.zoom=Рівень масштабування для відображення веб-сайту.
+HTMLToPDF.pageWidth=Ширина сторінки в сантиметрах. (Порожньо - за замовчуванням)
+HTMLToPDF.pageHeight=Висота сторінки в сантиметрах. (Порожньо - за замовчуванням)
+HTMLToPDF.marginTop=Верхній відступ сторінки в міліметрах. (Порожньо - за замовчуванням)
+HTMLToPDF.marginBottom=Нижній відступ сторінки в міліметрах. (Порожньо - за замовчуванням)
+HTMLToPDF.marginLeft=Лівий відступ сторінки в міліметрах. (Порожньо - за замовчуванням)
+HTMLToPDF.marginRight=Правий відступ сторінки в міліметрах. (Порожньо - за замовчуванням)
+HTMLToPDF.printBackground=Відтворити фон веб-сайтів.
+HTMLToPDF.defaultHeader=Включити заголовок за замовчуванням (Ім'я та номер сторінки)
+HTMLToPDF.cssMediaType=Змінити тип медіа CSS сторінки.
+HTMLToPDF.none=Немає
+HTMLToPDF.print=Друк
+HTMLToPDF.screen=Екран
+
+
+#AddStampRequest
+AddStampRequest.header=Поставити печатку на PDF
+AddStampRequest.title=Поставити печатку на PDF
+AddStampRequest.stampType=Тип печатки
+AddStampRequest.stampText=Текст печатки
+AddStampRequest.stampImage=Зображення печатки
+AddStampRequest.alphabet=Алфавіт
+AddStampRequest.fontSize=Розмір шрифту/зображення
+AddStampRequest.rotation=Обертання
+AddStampRequest.opacity=Прозорість
+AddStampRequest.position=Позиція
+AddStampRequest.overrideX=Перевизначити координату X
+AddStampRequest.overrideY=Перевизначити координату Y
+AddStampRequest.customMargin=Користувацький відступ
+AddStampRequest.customColor=Користувацький колір тексту
+AddStampRequest.submit=Надіслати
+
+
+#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=Дезінфекція
+
+
+#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=Друк, вставка, сканування, завантаження і дозвольте нам автоматично розділити ваші документи. Не потребує ручного сортування.
+autoSplitPDF.selectText.1=Друк кількох окремих аркушів (підійде чорно-білий варіант).
+autoSplitPDF.selectText.2=Скануйте всі документи одночасно, вставляючи між ними роздільний аркуш.
+autoSplitPDF.selectText.3=Завантажте один великий відсканований PDF-файл, і нехай Stirling PDF зробить все інше.
+autoSplitPDF.selectText.4=Роздільні сторінки автоматично виявляються і видаляються, забезпечуючи акуратний кінцевий документ.
+autoSplitPDF.formPrompt=Надіслати PDF-файл, що містить роздільні сторінки Stirling-PDF:
+autoSplitPDF.duplexMode=Дуплексний режим (сканування спереду і ззаду)
+autoSplitPDF.dividerDownload1=Завантажити 'Auto Splitter Divider (minimal).pdf'
+autoSplitPDF.dividerDownload2=Завантажити 'Auto Splitter Divider (with instructions).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=Підпишіть PDF своїм сертифікатом (робота в процесі)
+certSign.selectPDF=Виберіть файл PDF для підпису:
+certSign.jksNote=Примітка: Якщо ваш тип сертифіката не зазначений нижче, будь ласка, конвертуйте його в файл сховища Java Keystore (.jks), використовуючи утиліту командного рядка keytool. Потім виберіть опцію файлу .jks нижче.
+certSign.selectKey=Виберіть файл закритого ключа (формат PKCS#8, може бути .pem або .der):
+certSign.selectCert=Виберіть файл сертифіката (формат X.509, може бути .pem або .der):
+certSign.selectP12=Виберіть файл сховища ключів PKCS#12 (.p12 або .pfx) (необов'язково, якщо він наданий, він повинен містити ваш закритий ключ і сертифікат):
+certSign.selectJKS=Виберіть файл сховища Java Keystore (.jks або .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=Поріг для визначення того, наскільки білим має бути білий піксель
+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=Порівняти
+
+#BookToPDF
+BookToPDF.title=Книги та комікси в PDF
+BookToPDF.header=Конвертувати книгу в PDF
+BookToPDF.credit=Використовується Calibre
+BookToPDF.submit=Конвертувати
+
+#PDFToBook
+PDFToBook.title=PDF в книгу
+PDFToBook.header=PDF в книгу
+PDFToBook.selectText.1=Формат
+PDFToBook.credit=Використовується Calibre
+PDFToBook.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.flattenOnlyForms=Flatten only forms
+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 (Optical Character Recognition) Розпізнавання тексту
+ocr.selectText.1=Виберіть мови, які повинні бути виявлені у PDF-файлі (перелічені ті, які виявлені на даний момент):
+ocr.selectText.2=Створіть текстовий файл, що містить текст OCR, разом із PDF-файлом, обробленим OCR.
+ocr.selectText.3=Правильні сторінки були відскановані під перекошеним кутом шляхом повороту їх на місце
+ocr.selectText.4=Очистіть сторінку, щоб зменшити шанси, що OCR знайде текст на фоновому шумі. (без зміни виходу)
+ocr.selectText.5=Очистіть сторінку, щоб зменшити шанси, що OCR знайде текст на фоновому шумі, підтримує очищення виводу.
+ocr.selectText.6=Ігнорує сторінки з інтерактивним текстом, розпізнає лише сторінки з зображеннями
+ocr.selectText.7=Примусове розпізнавання символів, буде розпізнавати кожну сторінку, видаляючи всі елементи початкового тексту
+ocr.selectText.8=Звичайний (буде помилка, якщо PDF містить текст)
+ocr.selectText.9=Додаткові налаштування
+ocr.selectText.10=Режим OCR
+ocr.selectText.11=Видалити зображення після OCR (видаляє ВСІ зображення, корисно лише в тому випадку, якщо вони є частиною етапу перетворення)
+ocr.selectText.12=Тип рендеру (розширений)
+ocr.help=Прочитайте цю документацію про те, як використовувати це для інших мов і/або використовувати не в докері.
+ocr.credit=Цей сервіс використовує OCRmyPDF та Tesseract для OCR.
+ocr.submit=Обробка PDF з OCR
+
+
+#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 (наприклад, 25 МБ, 10,8 МБ, 25 КБ)
+compress.submit=Стиснути
+
+
+#Add image
+addImage.title=Додати зображення
+addImage.header=Додати зображення в PDF
+addImage.everyPage=Кожна сторінка?
+addImage.upload=Додати зображення
+addImage.submit=Додати зображення
+
+
+#merge
+merge.title=Об'єднати
+merge.header=Об'єднання кількох PDF-файлів (2+)
+merge.sortByName=Сортування за ім'ям
+merge.sortByDate=Сортування за датою
+merge.submit=Об'єднати
+
+
+#pdfOrganiser
+pdfOrganiser.title=Організатор сторінок
+pdfOrganiser.header=Організатор PDF-сторінок
+pdfOrganiser.submit=Переупорядкувати сторінки
+pdfOrganiser.mode=Режим
+pdfOrganiser.mode.1=Користувацький порядок сторінок
+pdfOrganiser.mode.2=Зворотній порядок
+pdfOrganiser.mode.3=Сортування дуплексом
+pdfOrganiser.mode.4=Сортування брошурою
+pdfOrganiser.mode.5=Сортування брошурою зі степлером з боку
+pdfOrganiser.mode.6=Розділення на парні та непарні сторінки
+pdfOrganiser.mode.7=Видалити першу
+pdfOrganiser.mode.8=Видалити останню
+pdfOrganiser.mode.9=Видалити першу та останню
+pdfOrganiser.placeholder=(наприклад, 1,3,2 або 4-8,2,10-12 або 2n-1)
+
+
+#multiTool
+multiTool.title=Мультіінструмент PDF
+multiTool.header=Мультіінструмент PDF
+multiTool.uploadPrompts=Будь ласка, завантажте PDF
+
+#view pdf
+viewPdf.title=Переглянути PDF
+viewPdf.header=Переглянути PDF
+
+#pageRemover
+pageRemover.title=Видалення сторінок
+pageRemover.header=Видалення сторінок PDF
+pageRemover.pagesToDelete=Сторінки для видалення (введіть список номерів сторінок через кому):
+pageRemover.submit=Видалити сторінки
+pageRemover.placeholder=(наприклад, 1,2,6 або 1-10,15-30)
+
+
+#rotate
+rotate.title=Повернути PDF
+rotate.header=Повернути PDF
+rotate.selectAngle=Виберіть кут повороту (кратний 90 градусам):
+rotate.submit=Повернути
+
+
+#split-pdfs
+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=Додати водяний знак
+watermark.type.1=Текст
+watermark.type.2=Зображення
+
+
+#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.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=Конвертувати
+pdfToPDFA.tip=Наразі не працює для кількох вхідних файлів одночасно
+pdfToPDFA.outputFormat=Output format
+
+
+#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 в Text/RTF
+PDFToText.header=PDF в Text/RTF
+PDFToText.selectText.1=Формат вихідного файлу
+PDFToText.credit=Цей сервіс використовує LibreOffice для перетворення файлів.
+PDFToText.submit=Конвертувати
+
+
+#PDFToHTML
+PDFToHTML.title=PDF в HTML
+PDFToHTML.header=PDF в HTML
+PDFToHTML.credit=Цей сервіс використовує pdftohtml для перетворення файлів.
+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.title=Розділити PDF за розміром або кількістю
+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=Виберіть файл(и) для накладення
+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
+split-by-sections.merge=Об'єднати в один PDF
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
+
+
+#licenses
+licenses.nav=Ліцензії
+licenses.title=Ліцензії від третіх сторін
+licenses.header=Ліцензії від третіх сторін
+licenses.module=Модуль
+licenses.version=Версія
+licenses.license=Ліцензія
+
+
+# error
+error.sorry=Вибачте за незручності!
+error.needHelp=Потрібна допомога / Знайшли проблему?
+error.contactTip=Якщо у вас досі виникають проблеми, не соромтеся звертатися до нас за допомогою. Ви можете надіслати запит на нашій сторінці GitHub або зв'язатися з нами через Discord:
+error.404.head=404 - Сторінку не знайдено | Ой, ми заплуталися в коді!
+error.404.1=Ми не можемо знайти сторінку, яку ви шукаєте.
+error.404.2=Щось пішло не так
+error.github=Надіслати запит на GitHub
+error.showStack=Показати стек викликів
+error.copyStack=Скопіювати стек викликів
+error.githubSubmit=GitHub - Надіслати запит
+error.discordSubmit=Discord - Надіслати повідомлення підтримки
+
diff --git a/src/main/resources/messages_zh_CN.properties b/src/main/resources/messages_zh_CN.properties
index ea994fbb..ca04fc36 100644
--- a/src/main/resources/messages_zh_CN.properties
+++ b/src/main/resources/messages_zh_CN.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -11,16 +11,18 @@ imgPrompt=选择图像
genericSubmit=提交
processTimeWarning=警告:此过程可能需要多达一分钟,具体时间取决于文件大小
pageOrderPrompt=页面顺序(输入逗号分隔的页码列表):
-pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
+pageSelectionPrompt=自定义页面选择(输入以逗号分隔的页码列表 1,5,6 或 2n+1 等函数):
goToPage=到
true=对
false=错
unknown=未知
save=保存
+saveToBrowser=保存到浏览器
close=关闭
filesSelected=选中的文件
noFavourites=没有添加收藏夹
-bored=无聊等待吗?
+downloadComplete=下载完成
+bored=等待时觉得无聊?
alphabet=字母表
downloadPdf=下载PDF
text=文本
@@ -30,51 +32,69 @@ pageNum=页码
sizes.small=小型尺寸
sizes.medium=中型尺寸
sizes.large=大型尺寸
-sizes.x-large=稍大型尺寸
+sizes.x-large=超大型尺寸
error.pdfPassword=PDF 文档有密码,未提供密码或密码不正确
delete=删除
username=用户名
password=密码
welcome=欢迎
property=资产
-black=Black
-white=White
-red=Red
-green=Green
-blue=Blue
-custom=Custom...
-WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
+black=黑色
+white=白色
+red=红色
+green=绿色
+blue=蓝色
+custom=自定义...
+WorkInProgess=工作正在进行中,可能无法工作或有错误,请报告任何问题!
poweredBy=Powered by
-yes=Yes
-no=No
+yes=是
+no=否
changedCredsMessage=凭证已更改!
notAuthenticatedMessage=用户未经过身份验证。
userNotFoundMessage=未找到用户。
incorrectPasswordMessage=当前密码不正确。
usernameExistsMessage=新用户名已存在。
+invalidUsernameMessage=用户名无效,用户名只能由字母字符和数字组成。
+deleteCurrentUserMessage=无法删除当前登录的用户。
+deleteUsernameExistsMessage=用户名不存在,无法删除。
+downgradeCurrentUserMessage=无法降级当前用户的角色
+downgradeCurrentUserLongMessage=无法降级当前用户的角色。因此,当前用户将不会显示。
+error=错误
+oops=哎呀!
+help=帮助
+goHomepage=返回主页
+joinDiscord=加入我们的Discord服务器
+seeDockerHub=查看Docker Hub
+visitGithub=访问Github仓库
+donate=捐款
+color=颜色
+sponsor=赞助
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
-pipeline.uploadButton=Upload Custom
-pipeline.configureButton=Configure
-pipeline.defaultOption=Custom
-pipeline.submitButton=Submit
+pipeline.header=流水线菜单 (Beta)
+pipeline.uploadButton=上传自定义流水线
+pipeline.configureButton=配置
+pipeline.defaultOption=自定义
+pipeline.submitButton=提交
+pipeline.help=工作流帮助
+pipeline.scanHelp=文件夹扫描帮助
######################
# 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
+pipelineOptions.header=流水线配置
+pipelineOptions.pipelineNameLabel=流水线名称
+pipelineOptions.saveSettings=保存设置
+pipelineOptions.pipelineNamePrompt=请输入流水线名称
+pipelineOptions.selectOperation=选择操作
+pipelineOptions.addOperationButton=添加操作
+pipelineOptions.pipelineHeader=流水线:
+pipelineOptions.saveButton=下载
+pipelineOptions.validateButton=验证
@@ -94,6 +114,7 @@ navbar.settings=设置
#############
settings.title=设置
settings.update=可更新
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=应用程序版本:
settings.downloadOption.title=选择下载选项(单个文件非压缩文件):
settings.downloadOption.1=在同一窗口打开
@@ -102,12 +123,13 @@ settings.downloadOption.3=下载文件
settings.zipThreshold=当下载的文件数量超过限制时,将文件压缩。
settings.signOut=登出
settings.accountSettings=帐号设定
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=更改凭证
changeCreds.header=更新您的账户详情
-changeCreds.changeUserAndPassword=您正在使用默认登录凭据。请输入新密码(如果需要,还可以输入新用户名)
+changeCreds.changePassword=您正在使用默认登录凭证,请输入新密码
changeCreds.newUsername=新用户名
changeCreds.oldPassword=当前密码
changeCreds.newPassword=新密码
@@ -142,19 +164,23 @@ adminUserSettings.header=管理员用户控制设置
adminUserSettings.admin=管理员
adminUserSettings.user=用户
adminUserSettings.addUser=添加新用户
+adminUserSettings.usernameInfo=用户名只能由字母和数字组成,不能包含空格或特殊字符。
adminUserSettings.roles=角色
adminUserSettings.role=角色
adminUserSettings.actions=操作
-adminUserSettings.apiUser=有限 API 用户
+adminUserSettings.apiUser=受限制的 API 用户
+adminUserSettings.extraApiUser=额外受限制的 API 用户
adminUserSettings.webOnlyUser=仅限 Web 用户
-adminUserSettings.demoUser=Demo User (No custom settings)
+adminUserSettings.demoUser=演示用户(无自定义设置)
+adminUserSettings.internalApiUser=内部API用户
adminUserSettings.forceChange=强制用户在登录时更改用户名/密码
adminUserSettings.submit=保存用户
+adminUserSettings.changeUserRole=更改用户角色
#############
# HOME-PAGE #
#############
-home.desc=CZL一站式服务,满足您的所有PDF需求。
+home.desc=本地部署的一站式服务,满足您的所有PDF需求。
home.searchBar=搜索您需要的功能...
@@ -228,7 +254,7 @@ changeMetadata.tags=标题、作者、日期、创建、时间、发布者、制
home.fileToPDF.title=将文件转换为PDF文件
home.fileToPDF.desc=将几乎所有文件转换为PDF(DOCX、PNG、XLS、PPT、TXT等)。
-fileToPDF.tags=转换、格式、文档、图片、幻灯片、文本、转换、办公室、文档、Word、Excel、PowerPoint
+fileToPDF.tags=转换、格式、文档、图片、幻灯片、文本、转换、Office、Docs、Word、Excel、PowerPoint
home.ocr.title=运行OCR/清理扫描
home.ocr.desc=清理和识别PDF中的图像文本,并将其转换为可编辑文本。
@@ -239,17 +265,17 @@ home.extractImages.title=提取图像
home.extractImages.desc=从PDF中提取所有图像并保存到压缩包中。
extractImages.tags=图片、照片、保存、归档、压缩包、截取、抓取
-home.pdfToPDFA.title=PDF To PDF/A
+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、转换、格式、办公、Microsoft、文档
+PDFToWord.tags=doc、docx、odt、word、转换、格式、Office、Microsoft、文档
home.PDFToPresentation.title=PDF转演示文稿
home.PDFToPresentation.desc=将PDF转换为演示文稿格式(PPT、PPTX和ODP)。
-PDFToPresentation.tags=幻灯片、展示、办公、Microsoft
+PDFToPresentation.tags=幻灯片、展示、Office、Microsoft
home.PDFToText.title=PDF转RTF(文本)
home.PDFToText.desc=将PDF转换为文本或RTF格式。
@@ -268,7 +294,7 @@ home.ScannerImageSplit.title=检测/分割扫描图像
home.ScannerImageSplit.desc=从一张照片或PDF中分割出多张照片。
ScannerImageSplit.tags=分离、自动检测、扫描、多张照片、整理
-home.sign.title=标志
+home.sign.title=签名
home.sign.desc=通过绘图、文字或图像向PDF添加签名
sign.tags=授权、缩写、手绘签名、文本签名、图像签名
@@ -304,8 +330,8 @@ home.scalePages.title=调整页面尺寸/缩放
home.scalePages.desc=调整页面及/或其内容的尺寸/缩放
scalePages.tags=调整大小、修改、尺寸、适应
-home.pipeline.title=管道(高级版)
-home.pipeline.desc=通过定义管道脚本在PDF上运行多个操作
+home.pipeline.title=流水线(高级版)
+home.pipeline.desc=通过定义流水线脚本在PDF上运行多个操作
pipeline.tags=自动化、顺序、脚本化、批处理
home.add-page-numbers.title=添加页码
@@ -367,9 +393,9 @@ showJS.tags=JavaScript
home.autoRedact.title=自动删除
home.autoRedact.desc=根据输入文本自动删除(覆盖)PDF中的文本
-autoRedact.tags=Redact,Hide,black out,black,marker,hidden
+autoRedact.tags=脱敏、隐藏、涂黑、标记、不可见
-home.tableExtraxt.title=PDF to CSV
+home.tableExtraxt.title=PDF转CSV
home.tableExtraxt.desc=从PDF中提取表格并将其转换为CSV
tableExtraxt.tags=CSV、表格提取、提取、转换
@@ -387,9 +413,18 @@ home.split-by-sections.title=拆分PDF成小块
home.split-by-sections.desc=将PDF的每一页分割成更小的水平和垂直的部分
split-by-sections.tags=章节拆分、分割、自定义
-home.AddStampRequest.title=Add Stamp to PDF
-home.AddStampRequest.desc=Add text or add image stamps at set locations
-AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.AddStampRequest.title=添加图章
+home.AddStampRequest.desc=在指定位置添加文本或图片图章
+AddStampRequest.tags=图章、添加图片、图片居中、水印、PDF、嵌入、自定义
+
+
+home.PDFToBook.title=PDF转电子书
+home.PDFToBook.desc=使用Calibre将PDF转换成电子书/漫画
+PDFToBook.tags=电子书、漫画、Calibre、转换、日本漫画、亚马逊、kindle
+
+home.BookToPDF.title=电子书转PDF
+home.BookToPDF.desc=使用Calibre将电子书/漫画转换成PDF
+BookToPDF.tags=电子书、漫画、Calibre、转换、日本漫画、亚马逊、kindle
###########################
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=登录
+login.header=登录
login.signin=登录
login.rememberme=记住我
login.invalid=用户名或密码无效。
login.locked=您的账户已被锁定。
login.signinTitle=请登录
+login.ssoSignIn=通过单点登录登录
+login.oauth2AutoCreateDisabled=OAUTH2自动创建用户已禁用
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=转为单页
pageExtracter.title=提取页面
pageExtracter.header=提取页面
pageExtracter.submit=提取
+pageExtracter.placeholder=(例如 1,2,8 或 4,7,12-16 或 2n-1)
#getPdfInfo
@@ -450,7 +489,7 @@ MarkdownToPDF.title=Markdown转PDF
MarkdownToPDF.header=Markdown转PDF
MarkdownToPDF.submit=转换
MarkdownToPDF.help=正在努力中
-MarkdownToPDF.credit=使用WeasyPrint
+MarkdownToPDF.credit=此服务使用WeasyPrint进行文件转换。
@@ -458,7 +497,7 @@ MarkdownToPDF.credit=使用WeasyPrint
URLToPDF.title=URL转PDF
URLToPDF.header=URL转PDF
URLToPDF.submit=转换
-URLToPDF.credit=使用WeasyPrint
+URLToPDF.credit=此服务使用WeasyPrint进行文件转换。
#html-to-pdf
@@ -466,38 +505,38 @@ HTMLToPDF.title=HTML转PDF
HTMLToPDF.header=HTML转PDF
HTMLToPDF.help=接受HTML文件和包含所需的html/css/images等的ZIP文件
HTMLToPDF.submit=转换
-HTMLToPDF.credit=使用WeasyPrint
-HTMLToPDF.zoom=Zoom level for displaying the website.
-HTMLToPDF.pageWidth=Width of the page in centimeters. (Blank to default)
-HTMLToPDF.pageHeight=Height of the page in centimeters. (Blank to default)
-HTMLToPDF.marginTop=Top margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginBottom=Bottom margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginLeft=Left margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginRight=Right margin of the page in millimeters. (Blank to default)
-HTMLToPDF.printBackground=Render the background of websites.
-HTMLToPDF.defaultHeader=Enable Default Header (Name and page number)
-HTMLToPDF.cssMediaType=Change the CSS media type of the page.
-HTMLToPDF.none=None
-HTMLToPDF.print=Print
-HTMLToPDF.screen=Screen
+HTMLToPDF.credit=此服务使用WeasyPrint进行文件转换。
+HTMLToPDF.zoom=网站显示缩放级别
+HTMLToPDF.pageWidth=页面宽度-以厘米为单位(填空则使用默认值)
+HTMLToPDF.pageHeight=页面高度-以厘米为单位(填空则使用默认值)
+HTMLToPDF.marginTop=页面上边距-以毫米为单位(填空则使用默认值)
+HTMLToPDF.marginBottom=页面下边距-以毫米为单位(填空则使用默认值)
+HTMLToPDF.marginLeft=页面左上边距-以毫米为单位(填空则使用默认值)
+HTMLToPDF.marginRight=页面右边距-以毫米为单位(填空则使用默认值)
+HTMLToPDF.printBackground=页面背景渲染
+HTMLToPDF.defaultHeader=启用默认页头(文件名称和页码)
+HTMLToPDF.cssMediaType=更换页面的CSS media type.
+HTMLToPDF.none=无
+HTMLToPDF.print=打印
+HTMLToPDF.screen=屏幕
#AddStampRequest
-AddStampRequest.header=Stamp PDF
-AddStampRequest.title=Stamp PDF
-AddStampRequest.stampType=Stamp Type
-AddStampRequest.stampText=Stamp Text
-AddStampRequest.stampImage=Stamp Image
-AddStampRequest.alphabet=Alphabet
-AddStampRequest.fontSize=Font/Image Size
-AddStampRequest.rotation=Rotation
-AddStampRequest.opacity=Opacity
-AddStampRequest.position=Position
-AddStampRequest.overrideX=Override X Coordinate
-AddStampRequest.overrideY=Override Y Coordinate
-AddStampRequest.customMargin=Custom Margin
-AddStampRequest.customColor=Custom Text Color
-AddStampRequest.submit=Submit
+AddStampRequest.header=添加图章
+AddStampRequest.title=添加图章
+AddStampRequest.stampType=图章类型
+AddStampRequest.stampText=图章文字
+AddStampRequest.stampImage=图章图片
+AddStampRequest.alphabet=字母表
+AddStampRequest.fontSize=字体/图片大小
+AddStampRequest.rotation=旋转角度
+AddStampRequest.opacity=透明度
+AddStampRequest.position=定位
+AddStampRequest.overrideX=覆盖 X 坐标
+AddStampRequest.overrideY=覆盖 Y 坐标
+AddStampRequest.customMargin=自定义外边距
+AddStampRequest.customColor=自定义文本颜色
+AddStampRequest.submit=提交
#sanitizePDF
@@ -586,11 +625,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.jksNote=注意:如果您的证书类型未在下面列出,请使用 keytool 命令行工具将其转换为 Java Keystore (.jks) 文件。 然后,选择下面的 .jks 文件选项。
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.selectJKS=选择你的 Java Keystore 文件 (.jks 或 .keystore):
certSign.certType=证书类型
certSign.password=输入您的密钥库或私钥密码(如果有):
certSign.showSig=显示签名
@@ -611,9 +650,9 @@ removeBlanks.submit=删除空白
#removeAnnotations
-removeAnnotations.title=Remove Annotations
-removeAnnotations.header=Remove Annotations
-removeAnnotations.submit=Remove
+removeAnnotations.title=删除标注
+removeAnnotations.header=删除标注
+removeAnnotations.submit=删除
#compare
@@ -623,6 +662,18 @@ compare.document.1=文档 1
compare.document.2=文档 2
compare.submit=比较
+#BookToPDF
+BookToPDF.title=电子书和漫画转换成PDF
+BookToPDF.header=电子书转PDF
+BookToPDF.credit=此服务使用Calibre进行文件转换。
+BookToPDF.submit=转换
+
+#PDFToBook
+PDFToBook.title=PDF转电子书
+PDFToBook.header=PDF转电子书
+PDFToBook.selectText.1=格式
+PDFToBook.credit=此服务使用Calibre进行文件转换。
+PDFToBook.submit=转换
#sign
sign.title=签名
@@ -643,6 +694,7 @@ repair.submit=修复
#flatten
flatten.title=展平
flatten.header=展平 PDF
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=展平
@@ -689,7 +741,7 @@ extractImages.submit=提取
#File to PDF
fileToPDF.title=文件转换为PDF
fileToPDF.header=将任何文件转换为PDF。
-fileToPDF.credit=本服务使用LibreOffice和Unoconv进行文件转换。
+fileToPDF.credit=此服务使用LibreOffice和Unoconv进行文件转换。
fileToPDF.supportedFileTypes=支持的文件类型应该包括以下几种,但是,对于支持的格式的完整更新列表,请参考LibreOffice文档。
fileToPDF.submit=转换为 PDF
@@ -708,7 +760,7 @@ compress.submit=压缩
#Add image
addImage.title=添加图像
-addImage.header=添加图片到PDF(正在进行中)
+addImage.header=添加图片到PDF
addImage.everyPage=每一页?
addImage.upload=添加图片
addImage.submit=添加图片
@@ -726,21 +778,34 @@ merge.submit=合并
pdfOrganiser.title=页面排序
pdfOrganiser.header=PDF页面排序
pdfOrganiser.submit=重新排列页面
+pdfOrganiser.mode=模式
+pdfOrganiser.mode.1=自定义页面顺序
+pdfOrganiser.mode.2=反向顺序
+pdfOrganiser.mode.3=双面排序
+pdfOrganiser.mode.4=小册子排序
+pdfOrganiser.mode.5=侧装订小册子排序
+pdfOrganiser.mode.6=奇偶拆分
+pdfOrganiser.mode.7=删除第一页
+pdfOrganiser.mode.8=删除最后一页
+pdfOrganiser.mode.9=删除第一页和最后一页
+pdfOrganiser.placeholder=(例如 1,3,2 或 4-8,2,10-12 或 2n-1)
#multiTool
multiTool.title=PDF多功能工具
multiTool.header=PDF多功能工具
+multiTool.uploadPrompts=上传PDF
#view pdf
-viewPdf.title=View PDF
-viewPdf.header=View PDF
+viewPdf.title=浏览PDF
+viewPdf.header=浏览PDF
#pageRemover
pageRemover.title=删除页面
pageRemover.header=PDF页面移除器
pageRemover.pagesToDelete=要删除的页面(输入一个用逗号分隔的页码列表):
pageRemover.submit=删除页面
+pageRemover.placeholder=(例如 1,2,6 或 1-10,15-30)
#rotate
@@ -750,14 +815,14 @@ rotate.selectAngle=选择旋转角度(以90度的倍数):
rotate.submit=旋转
-#merge
+#split-pdfs
split.title=拆分PDF
split.header=拆分PDF
split.desc.1=选择希望进行分割的页数
-split.desc.2=如选择1,3,7-8将把一个10页的文件分割成6个独立的PDF:
+split.desc.2=如选择1,3,7-9将把一个10页的文件分割成6个独立的PDF:
split.desc.3=文档 #1:第1页
split.desc.4=文档 #2:第2页和第3页
-split.desc.5=文档 #3:第4页、第5页和第6页
+split.desc.5=文档 #3:第4页、第5页、第6页和第7页
split.desc.6=文档 #4:第7页
split.desc.7=文档 #5:第8页
split.desc.8=文档 #6:第9页和第10页
@@ -780,7 +845,7 @@ imageToPDF.selectText.5=转换为独立的PDF文件
#pdfToImage
-pdfToImage.title=PDF to Image
+pdfToImage.title=PDF转图片
pdfToImage.header=PDF转图片
pdfToImage.selectText=图像格式
pdfToImage.singleOrMultiple=图像结果类型
@@ -828,6 +893,8 @@ watermark.selectText.7=透明度(0% - 100%):
watermark.selectText.8=水印类型:
watermark.selectText.9=水印图片:
watermark.submit=添加水印
+watermark.type.1=文字
+watermark.type.2=图片
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=将PDF转换为PDF/A
pdfToPDFA.header=PDF转换为PDF/A
pdfToPDFA.credit=此服务使用OCRmyPDF进行PDF/A转换
pdfToPDFA.submit=转换
+pdfToPDFA.tip=目前不支持上传多个
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -893,7 +962,7 @@ PDFToWord.submit=转换
PDFToPresentation.title=PDF转换为演示文稿
PDFToPresentation.header=将PDF转为演示文稿
PDFToPresentation.selectText.1=输出文件格式
-PDFToPresentation.credit=该服务使用LibreOffice进行文件转换。
+PDFToPresentation.credit=此服务使用LibreOffice进行文件转换。
PDFToPresentation.submit=转换
@@ -901,14 +970,14 @@ PDFToPresentation.submit=转换
PDFToText.title=PDF to RTF (Text)
PDFToText.header=将PDF转换成文本/RTF
PDFToText.selectText.1=输出文件格式
-PDFToText.credit=该服务使用LibreOffice进行文件转换。
+PDFToText.credit=此服务使用LibreOffice进行文件转换。
PDFToText.submit=转换
#PDFToHTML
PDFToHTML.title=PDF To HTML
PDFToHTML.header=将PDF转换成HTML
-PDFToHTML.credit=此服务使用LibreOffice进行文件转换。
+PDFToHTML.credit=此服务使用pdftohtml进行文件转换。
PDFToHTML.submit=转换
@@ -925,6 +994,7 @@ PDFToCSV.prompt=选择需要提取表格的页面
PDFToCSV.submit=提取
#split-by-size-or-count
+split-by-size-or-count.title=按照大小或数目拆分PDF
split-by-size-or-count.header=按照大小或数目拆分PDF
split-by-size-or-count.type.label=选择拆分类型
split-by-size-or-count.type.size=按照大小
@@ -959,14 +1029,36 @@ split-by-sections.vertical.label=垂直分割
split-by-sections.horizontal.placeholder=输入水平分割数
split-by-sections.vertical.placeholder=输入垂直分割数
split-by-sections.submit=分割PDF
+split-by-sections.merge=是否合并为一个pdf
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
-licenses.nav=Licenses
-licenses.title=3rd Party Licenses
-licenses.header=3rd Party Licenses
-licenses.module=Module
-licenses.version=Version
-licenses.license=License
+licenses.nav=许可证
+licenses.title=第三方许可证
+licenses.header=第三方许可证
+licenses.module=模块
+licenses.version=版本
+licenses.license=许可证
+# error
+error.sorry=对此问题感到抱歉!
+error.needHelp=需要帮助 / 发现问题?
+error.contactTip=如果你仍然遇到问题,不要犹豫,向我们寻求帮助。你可以在我们的GitHub页面上提交工单,或者通过Discord与我们联系:
+error.404.head=404 - 页面未找到 | 哎呀,我们在代码中触发了错误!
+error.404.1=我们似乎找不到你寻找的页面。
+error.404.2=出了些问题
+error.github=在GitHub上提交工单
+error.showStack=显示堆栈跟踪
+error.copyStack=复制堆栈跟踪
+error.githubSubmit=GitHub - 提交工单
+error.discordSubmit=Discord - 提交支持帖子
+
diff --git a/src/main/resources/messages_zh_TW.properties b/src/main/resources/messages_zh_TW.properties
index 2122d9f0..8391da55 100644
--- a/src/main/resources/messages_zh_TW.properties
+++ b/src/main/resources/messages_zh_TW.properties
@@ -1,4 +1,4 @@
-###########
+###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -11,15 +11,17 @@ imgPrompt=選擇圖片
genericSubmit=送出
processTimeWarning=警告:此過程可能需要長達一分鐘,具體取決於檔案大小
pageOrderPrompt=自訂頁面順序(輸入以逗號分隔的頁碼或函式,如 2n+1):
-pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
+pageSelectionPrompt=自訂頁面選擇(輸入以逗號分隔的頁碼 1、5、6 或 2n+1 等函數的清單):
goToPage=前往
true=是
false=否
unknown=未知
save=儲存
+saveToBrowser=儲存到瀏覽器
close=關閉
filesSelected=已選擇的檔案
noFavourites=未新增收藏
+downloadComplete=下載完成
bored=等待時覺得無聊?
alphabet=字母表
downloadPdf=下載 PDF
@@ -43,38 +45,56 @@ red=紅色
green=綠色
blue=藍色
custom=自訂...
-WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
+WorkInProgess=工作正在進行中,可能無法工作或有問題,請報告任何問題!
poweredBy=Powered by
-yes=Yes
-no=No
+yes=是
+no=否
changedCredsMessage=憑證已變更!
notAuthenticatedMessage=使用者未認證。
userNotFoundMessage=找不到使用者。
incorrectPasswordMessage=目前密碼不正確。
usernameExistsMessage=新使用者名稱已存在。
+invalidUsernameMessage=使用者名無效,使用者名只能包含字母字元和數位。
+deleteCurrentUserMessage=無法刪除目前登錄的使用者。
+deleteUsernameExistsMessage=使用者名不存在,無法刪除。
+downgradeCurrentUserMessage=無法降級目前使用者的角色
+downgradeCurrentUserLongMessage=無法降級目前使用者的角色。因此,不會顯示目前的使用者。
+error=錯誤
+oops=哎呀!
+help=幫助
+goHomepage=前往首頁
+joinDiscord=加入我們的Discord服務器
+seeDockerHub=查看Docker Hub
+visitGithub=訪問Github存儲庫
+donate=捐贈
+color=顏色
+sponsor=贊助
+
###############
# Pipeline #
###############
-pipeline.header=Pipeline Menu (Alpha)
-pipeline.uploadButton=Upload Custom
-pipeline.configureButton=Configure
-pipeline.defaultOption=Custom
-pipeline.submitButton=Submit
+pipeline.header=管道選單(測試版)
+pipeline.uploadButton=上傳自定義
+pipeline.configureButton=配置
+pipeline.defaultOption=自訂
+pipeline.submitButton=送出
+pipeline.help=管道説明
+pipeline.scanHelp=資料夾掃描説明
######################
# 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
+pipelineOptions.header=管道配置
+pipelineOptions.pipelineNameLabel=管道名稱
+pipelineOptions.saveSettings=保存操作設置
+pipelineOptions.pipelineNamePrompt=在此處輸入管道名稱
+pipelineOptions.selectOperation=選擇操作
+pipelineOptions.addOperationButton=添加操作
+pipelineOptions.pipelineHeader=管道:
+pipelineOptions.saveButton=下載
+pipelineOptions.validateButton=驗證
@@ -94,6 +114,7 @@ navbar.settings=設定
#############
settings.title=設定
settings.update=有更新可用
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
settings.appVersion=應用版本:
settings.downloadOption.title=選擇下載選項(對於單一檔案非壓縮下載):
settings.downloadOption.1=在同一視窗中開啟
@@ -102,12 +123,13 @@ settings.downloadOption.3=下載檔案
settings.zipThreshold=當下載的檔案數量超過時,壓縮檔案
settings.signOut=登出
settings.accountSettings=帳戶設定
-
-
+settings.bored.help=Enables easter egg game
+settings.cacheInputs.name=Save form inputs
+settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=變更憑證
changeCreds.header=更新您的帳戶詳細資訊
-changeCreds.changeUserAndPassword=您正在使用預設的登入憑證。請輸入新的密碼(如果需要,也可以輸入使用者名稱)
+changeCreds.changePassword=您使用的是預設登錄認證。請輸入新密碼
changeCreds.newUsername=新使用者名稱
changeCreds.oldPassword=目前密碼
changeCreds.newPassword=新密碼
@@ -142,14 +164,18 @@ adminUserSettings.header=管理使用者控制設定
adminUserSettings.admin=管理員
adminUserSettings.user=使用者
adminUserSettings.addUser=新增使用者
+adminUserSettings.usernameInfo=使用者名只能包含字母和數位,不能包含空格或特殊字元。
adminUserSettings.roles=角色
adminUserSettings.role=角色
adminUserSettings.actions=操作
adminUserSettings.apiUser=受限制的 API 使用者
+adminUserSettings.extraApiUser=其他受限 API 使用者
adminUserSettings.webOnlyUser=僅使用網頁的使用者
adminUserSettings.demoUser=示範用途的使用者(無自訂設定)
+adminUserSettings.internalApiUser=內部 API 使用者
adminUserSettings.forceChange=強制使用者在登入時修改使用者名稱/密碼
adminUserSettings.submit=儲存
+adminUserSettings.changeUserRole=更改使用者身份
#############
# HOME-PAGE #
@@ -387,9 +413,18 @@ home.split-by-sections.title=依區段分割 PDF
home.split-by-sections.desc=將 PDF 的每一頁分割為較小的水平和垂直區段
split-by-sections.tags=區段分割, 劃分, 自訂
-home.AddStampRequest.title=Add Stamp to PDF
-home.AddStampRequest.desc=Add text or add image stamps at set locations
-AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
+home.AddStampRequest.title=將圖章添加到 PDF
+home.AddStampRequest.desc=在設置位置添加文字或添加圖像圖章
+AddStampRequest.tags=圖章,添加圖片,中心圖像,浮水印,PDF,嵌入,自訂
+
+
+home.PDFToBook.title=PDF 轉電子書
+home.PDFToBook.desc=使用 calibre 將 PDF 轉換為書籍/漫畫格式
+PDFToBook.tags=電子書,漫畫,Calibre,轉換,日本漫畫,亞馬遜,kindle
+
+home.BookToPDF.title=電子書轉 PDF
+home.BookToPDF.desc=使用 calibre 將書籍/漫畫格式轉換為 PDF
+BookToPDF.tags=電子書,漫畫,Calibre,轉換,日本漫畫,亞馬遜,kindle
###########################
@@ -399,11 +434,14 @@ AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Cust
###########################
#login
login.title=登入
+login.header=登入
login.signin=登入
login.rememberme=記住我
login.invalid=使用者名稱或密碼無效。
login.locked=您的帳戶已被鎖定。
login.signinTitle=請登入
+login.ssoSignIn=透過織網單一簽入
+login.oauth2AutoCreateDisabled=OAUTH2自動建立使用者已停用
#auto-redact
@@ -436,6 +474,7 @@ pdfToSinglePage.submit=轉換為單一頁面
pageExtracter.title=提取頁面
pageExtracter.header=提取頁面
pageExtracter.submit=提取
+pageExtracter.placeholder=(例如 1,2,8 或 4,7,12-16 或 2n-1)
#getPdfInfo
@@ -450,7 +489,7 @@ MarkdownToPDF.title=Markdown 轉 PDF
MarkdownToPDF.header=Markdown 轉 PDF
MarkdownToPDF.submit=轉換
MarkdownToPDF.help=正在進行中
-MarkdownToPDF.credit=使用 WeasyPrint
+MarkdownToPDF.credit=此服務使用 WeasyPrint 進行轉換
@@ -458,7 +497,7 @@ MarkdownToPDF.credit=使用 WeasyPrint
URLToPDF.title=URL 轉 PDF
URLToPDF.header=URL 轉 PDF
URLToPDF.submit=轉換
-URLToPDF.credit=使用 WeasyPrint
+URLToPDF.credit=此服務使用 WeasyPrint 進行轉換
#html-to-pdf
@@ -466,38 +505,38 @@ HTMLToPDF.title=HTML 轉 PDF
HTMLToPDF.header=HTML 轉 PDF
HTMLToPDF.help=接受 HTML 文件和包含所需 html/css/images 等的 ZIP
HTMLToPDF.submit=轉換
-HTMLToPDF.credit=使用 WeasyPrint
-HTMLToPDF.zoom=Zoom level for displaying the website.
-HTMLToPDF.pageWidth=Width of the page in centimeters. (Blank to default)
-HTMLToPDF.pageHeight=Height of the page in centimeters. (Blank to default)
-HTMLToPDF.marginTop=Top margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginBottom=Bottom margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginLeft=Left margin of the page in millimeters. (Blank to default)
-HTMLToPDF.marginRight=Right margin of the page in millimeters. (Blank to default)
-HTMLToPDF.printBackground=Render the background of websites.
-HTMLToPDF.defaultHeader=Enable Default Header (Name and page number)
-HTMLToPDF.cssMediaType=Change the CSS media type of the page.
-HTMLToPDF.none=None
-HTMLToPDF.print=Print
-HTMLToPDF.screen=Screen
+HTMLToPDF.credit=此服務使用 WeasyPrint 進行轉換
+HTMLToPDF.zoom=用於顯示網站的縮放級別。
+HTMLToPDF.pageWidth=頁面寬度-以釐米為單位(填空則使用預設值)
+HTMLToPDF.pageHeight=頁面高度-以釐米為單位(填空則使用預設值)
+HTMLToPDF.marginTop=頁面的上邊距-以毫米為單位(填空則使用預設值)
+HTMLToPDF.marginBottom=頁面的下邊距-以毫米為單位(填空則使用預設值)
+HTMLToPDF.marginLeft=頁面的左邊距-以毫米為單位(填空則使用預設值)
+HTMLToPDF.marginRight=頁面的右邊距-以毫米為單位(填空則使用預設值)
+HTMLToPDF.printBackground=渲染網站的背景。
+HTMLToPDF.defaultHeader=啟用預設標頭(名稱和頁碼)
+HTMLToPDF.cssMediaType=更改頁面的 CSS 媒體類型。
+HTMLToPDF.none=無
+HTMLToPDF.print=列印
+HTMLToPDF.screen=螢幕
#AddStampRequest
-AddStampRequest.header=Stamp PDF
-AddStampRequest.title=Stamp PDF
-AddStampRequest.stampType=Stamp Type
-AddStampRequest.stampText=Stamp Text
-AddStampRequest.stampImage=Stamp Image
-AddStampRequest.alphabet=Alphabet
-AddStampRequest.fontSize=Font/Image Size
-AddStampRequest.rotation=Rotation
-AddStampRequest.opacity=Opacity
-AddStampRequest.position=Position
-AddStampRequest.overrideX=Override X Coordinate
-AddStampRequest.overrideY=Override Y Coordinate
-AddStampRequest.customMargin=Custom Margin
-AddStampRequest.customColor=Custom Text Color
-AddStampRequest.submit=Submit
+AddStampRequest.header=圖章 PDF
+AddStampRequest.title=圖章 PDF
+AddStampRequest.stampType=圖章類型
+AddStampRequest.stampText=圖章文字
+AddStampRequest.stampImage=圖章圖片
+AddStampRequest.alphabet=字母表
+AddStampRequest.fontSize=字體/圖像大小
+AddStampRequest.rotation=旋轉
+AddStampRequest.opacity=透明度
+AddStampRequest.position=位置
+AddStampRequest.overrideX=覆蓋 X 座標
+AddStampRequest.overrideY=覆蓋 Y 座標
+AddStampRequest.customMargin=自訂邊緣
+AddStampRequest.customColor=自訂文字顏色
+AddStampRequest.submit=送出
#sanitizePDF
@@ -522,7 +561,7 @@ addPageNumbers.selectText.5=要編號的頁面
addPageNumbers.selectText.6=自訂文字
addPageNumbers.customTextDesc=自訂文字
addPageNumbers.numberPagesDesc=要編號的頁面,預設為 '全部',也可使用 1-5 或 2,5,9 等格式
-addPageNumbers.customNumberDesc=預設為 {n},也接受 '頁面 {n} 共 {total}','文字-{n}','{filename}-{n}
+addPageNumbers.customNumberDesc=預設為 {n},也接受 '頁面 {n} 共 {total}','文字-{n}','{filename}-{n}'
addPageNumbers.submit=新增頁碼
@@ -586,11 +625,11 @@ scalePages.submit=送出
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.jksNote=注意:如果您的證書類型未在下面列出,請使用keytool命令行工具將其轉換為Java Keystore (.jks) 檔。 然後,選擇下面的 .jks 文件選項。
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.selectJKS=選擇你的 Java Keystore 檔 (.jks 或 .keystore):
certSign.certType=憑證類型
certSign.password=輸入您的金鑰庫或私鑰密碼(如果有):
certSign.showSig=顯示簽章
@@ -623,6 +662,18 @@ compare.document.1=文件 1
compare.document.2=文件 2
compare.submit=比較
+#BookToPDF
+BookToPDF.title=電子書和漫畫轉 PDF
+BookToPDF.header=電子書轉 PDF
+BookToPDF.credit=此服務使用 Calibre 進行轉換
+BookToPDF.submit=轉換
+
+#PDFToBook
+PDFToBook.title=PDF 轉電子書
+PDFToBook.header=PDF 轉電子書
+PDFToBook.selectText.1=格式
+PDFToBook.credit=此服務使用 Calibre 進行轉換
+PDFToBook.submit=轉換
#sign
sign.title=簽章
@@ -643,6 +694,7 @@ repair.submit=修復
#flatten
flatten.title=平坦化
flatten.header=PDF 平坦化
+flatten.flattenOnlyForms=Flatten only forms
flatten.submit=平坦化
@@ -726,11 +778,23 @@ merge.submit=合併
pdfOrganiser.title=頁面整理
pdfOrganiser.header=PDF 頁面整理
pdfOrganiser.submit=重新排列頁面
+pdfOrganiser.mode=模式
+pdfOrganiser.mode.1=自定義頁面順序
+pdfOrganiser.mode.2=反向順序
+pdfOrganiser.mode.3=雙工排序
+pdfOrganiser.mode.4=摺頁冊排序
+pdfOrganiser.mode.5=側裝訂摺頁冊排序
+pdfOrganiser.mode.6=奇偶拆分
+pdfOrganiser.mode.7=刪除第一頁
+pdfOrganiser.mode.8=刪除最後一頁
+pdfOrganiser.mode.9=刪除第一頁和最後一頁
+pdfOrganiser.placeholder=(例如 1,3,2 或 4-8,2,10-12 或 2n-1)
#multiTool
multiTool.title=PDF 多工具
multiTool.header=PDF 多工具
+multiTool.uploadPrompts=Please Upload PDF
#view pdf
viewPdf.title=檢視 PDF
@@ -741,6 +805,7 @@ pageRemover.title=頁面移除
pageRemover.header=PDF 頁面移除
pageRemover.pagesToDelete=要刪除的頁面(輸入以逗號分隔的頁碼):
pageRemover.submit=刪除頁面
+pageRemover.placeholder=(例如 1,2,6 或 1-10,15-30)
#rotate
@@ -750,17 +815,17 @@ rotate.selectAngle=選擇旋轉角度(以 90 度的倍數):
rotate.submit=旋轉
-#merge
+#split-pdfs
split.title=分割 PDF
split.header=分割 PDF
split.desc.1=您選擇的數字是您希望進行分割的頁碼
-split.desc.2=因此,選擇 1,3,7-8 將會將一個 10 頁的文件分割為 6 個單獨的 PDF,包括:
+split.desc.2=因此,選擇 1,3,7-9 將會將一個 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.desc.5=文件 #3:頁面 4、5、6 和 7
+split.desc.6=文件 #4:頁面 8
+split.desc.7=文件 #5:頁面 9
+split.desc.8=文件 #6:頁面 10
split.splitPages=輸入要分割的頁面:
split.submit=分割
@@ -828,6 +893,8 @@ watermark.selectText.7=不透明度(0% - 100%):
watermark.selectText.8=浮水印類型:
watermark.selectText.9=浮水印影像:
watermark.submit=新增浮水印
+watermark.type.1=文字
+watermark.type.2=圖片
#Change permissions
@@ -879,6 +946,8 @@ pdfToPDFA.title=PDF 轉 PDF/A
pdfToPDFA.header=PDF 轉 PDF/A
pdfToPDFA.credit=此服務使用 OCRmyPDF 進行 PDF/A 轉換
pdfToPDFA.submit=轉換
+pdfToPDFA.tip=目前不支援上傳多個
+pdfToPDFA.outputFormat=Output format
#PDFToWord
@@ -908,7 +977,7 @@ PDFToText.submit=轉換
#PDFToHTML
PDFToHTML.title=PDF 轉 HTML
PDFToHTML.header=PDF 轉 HTML
-PDFToHTML.credit=此服務使用 LibreOffice 進行檔案轉換。
+PDFToHTML.credit=此服務使用 pdftohtml 進行檔案轉換。
PDFToHTML.submit=轉換
@@ -925,6 +994,7 @@ PDFToCSV.prompt=選擇要提取表格的頁面
PDFToCSV.submit=提取
#split-by-size-or-count
+split-by-size-or-count.title=依大小或數量分割 PDF
split-by-size-or-count.header=依大小或數量分割 PDF
split-by-size-or-count.type.label=選擇分割類型
split-by-size-or-count.type.size=依大小
@@ -959,14 +1029,36 @@ split-by-sections.vertical.label=垂直劃分
split-by-sections.horizontal.placeholder=輸入水平劃分的數量
split-by-sections.vertical.placeholder=輸入垂直劃分的數量
split-by-sections.submit=分割 PDF
+split-by-sections.merge=是否合併為一個pdf
+
+
+#printFile
+printFile.title=Print File
+printFile.header=Print File to Printer
+printFile.selectText.1=Select File to Print
+printFile.selectText.2=Enter Printer Name
+printFile.submit=Print
#licenses
-licenses.nav=Licenses
-licenses.title=3rd Party Licenses
-licenses.header=3rd Party Licenses
-licenses.module=Module
-licenses.version=Version
-licenses.license=License
+licenses.nav=許可證
+licenses.title=第三方許可證
+licenses.header=第三方許可證
+licenses.module=模組
+licenses.version=版本
+licenses.license=許可證
+# error
+error.sorry=對於這個問題,我們感到抱歉!
+error.needHelp=需要幫助/發現了一個問題?
+error.contactTip=如果你仍然遇到問題,請不要猶豫,隨時向我們尋求幫助。你可以在我們的GitHub頁面提交工單,或通過Discord與我們聯繋:
+error.404.head=404 - 找不到頁面 | 哎呀,我們在代碼中走錯了路!
+error.404.1=我們好像找不到你正在尋找的頁面。
+error.404.2=出了點錯誤
+error.github=在GitHub上提交工單
+error.showStack=顯示堆疊追蹤
+error.copyStack=複製堆疊追蹤
+error.githubSubmit=GitHub - 提交工單
+error.discordSubmit=Discord - 提交支援帖子
+
diff --git a/src/main/resources/settings.yml.template b/src/main/resources/settings.yml.template
index 5869bc4e..45f1762d 100644
--- a/src/main/resources/settings.yml.template
+++ b/src/main/resources/settings.yml.template
@@ -7,19 +7,24 @@ security:
csrfDisabled: true
loginAttemptCount: 5 # lock user account after 5 tries
loginResetTimeMinutes : 120 # lock account for 2 hours after x attempts
+ #oauth2:
+ # enabled: false # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work)
+ # issuer: "" # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point
+ # clientId: "" # Client ID from your provider
+ # clientSecret: "" # Client Secret from your provider
+ # autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users
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:
- bookAndHtmlFormatsInstalled: 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)
-
-#ui:
-# appName: exampleAppName # Application's visible name
-# homeDescription: I am a description # Short description or tagline shown on homepage.
-# appNameNavbar: navbarName # Name displayed on the navigation bar
+ showUpdate: true # see when a new update is available
+ showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
+
+ui:
+ appName: null # Application's visible name
+ homeDescription: null # Short description or tagline shown on homepage.
+ appNameNavbar: null # Name displayed on the navigation bar
endpoints:
toRemove: [] # List endpoints to disable (e.g. ['img-to-pdf', 'remove-pages'])
@@ -27,3 +32,7 @@ endpoints:
metrics:
enabled: true # 'true' to enable Info APIs (`/api/*`) endpoints, 'false' to disable
+
+# Automatically Generated Settings (Do Not Edit Directly)
+AutomaticallyGenerated:
+ key: example
\ No newline at end of file
diff --git a/src/main/resources/static/3rdPartyLicenses.json b/src/main/resources/static/3rdPartyLicenses.json
index c03dd84c..97025001 100644
--- a/src/main/resources/static/3rdPartyLicenses.json
+++ b/src/main/resources/static/3rdPartyLicenses.json
@@ -3,69 +3,69 @@
{
"moduleName": "ch.qos.logback:logback-classic",
"moduleUrl": "http://www.qos.ch",
- "moduleVersion": "1.4.14",
+ "moduleVersion": "1.5.3",
"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",
+ "moduleVersion": "1.5.3",
"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",
+ "moduleVersion": "2.15.4",
"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",
+ "moduleVersion": "2.15.4",
"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",
+ "moduleVersion": "2.15.4",
"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",
+ "moduleVersion": "2.15.4",
"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",
+ "moduleVersion": "2.15.4",
"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",
+ "moduleVersion": "2.15.4",
"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",
+ "moduleVersion": "2.15.4",
"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"
+ "moduleVersion": "2.15.4"
},
{
"moduleName": "com.fasterxml:classmate",
@@ -74,6 +74,20 @@
"moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
},
+ {
+ "moduleName": "com.fathzer:javaluator",
+ "moduleUrl": "http://javaluator.fathzer.com",
+ "moduleVersion": "3.0.3",
+ "moduleLicense": "GNU Lesser General Public License v3 (LGPL-v3)",
+ "moduleLicenseUrl": "http://www.gnu.org/licenses/lgpl-3.0.html"
+ },
+ {
+ "moduleName": "com.github.stephenc.jcip:jcip-annotations",
+ "moduleUrl": "http://stephenc.github.com/jcip-annotations",
+ "moduleVersion": "1.0-1",
+ "moduleLicense": "Apache 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",
@@ -84,7 +98,7 @@
{
"moduleName": "com.google.zxing:core",
"moduleUrl": "https://github.com/zxing/zxing/core",
- "moduleVersion": "3.5.2",
+ "moduleVersion": "3.5.3",
"moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
},
@@ -102,6 +116,34 @@
"moduleLicense": "LGPL",
"moduleLicenseUrl": "http://www.martiansoftware.com/jsap/license.html"
},
+ {
+ "moduleName": "com.nimbusds:content-type",
+ "moduleUrl": "https://connect2id.com",
+ "moduleVersion": "2.2",
+ "moduleLicense": "The Apache Software License, Version 2.0",
+ "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
+ },
+ {
+ "moduleName": "com.nimbusds:lang-tag",
+ "moduleUrl": "https://connect2id.com/",
+ "moduleVersion": "1.7",
+ "moduleLicense": "The Apache Software License, Version 2.0",
+ "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
+ },
+ {
+ "moduleName": "com.nimbusds:nimbus-jose-jwt",
+ "moduleUrl": "https://connect2id.com",
+ "moduleVersion": "9.24.4",
+ "moduleLicense": "The Apache Software License, Version 2.0",
+ "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
+ },
+ {
+ "moduleName": "com.nimbusds:oauth2-oidc-sdk",
+ "moduleUrl": "https://bitbucket.org/connect2id/oauth-2.0-sdk-with-openid-connect-extensions",
+ "moduleVersion": "9.43.3",
+ "moduleLicense": "Apache License, version 2.0",
+ "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.html"
+ },
{
"moduleName": "com.opencsv:opencsv",
"moduleUrl": "http://opencsv.sf.net",
@@ -214,35 +256,35 @@
{
"moduleName": "io.github.pixee:java-security-toolkit",
"moduleUrl": "https://github.com/pixee/java-security-toolkit",
- "moduleVersion": "1.1.2",
+ "moduleVersion": "1.1.3",
"moduleLicense": "MIT License",
"moduleLicenseUrl": "http://www.opensource.org/licenses/mit-license.php"
},
{
"moduleName": "io.micrometer:micrometer-commons",
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
- "moduleVersion": "1.12.2",
+ "moduleVersion": "1.12.4",
"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.2",
+ "moduleVersion": "1.12.4",
"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.2",
+ "moduleVersion": "1.12.4",
"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.2",
+ "moduleVersion": "1.12.4",
"moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
},
@@ -276,7 +318,7 @@
{
"moduleName": "jakarta.activation:jakarta.activation-api",
"moduleUrl": "https://www.eclipse.org",
- "moduleVersion": "2.1.2",
+ "moduleVersion": "2.1.3",
"moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception",
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
},
@@ -318,16 +360,30 @@
{
"moduleName": "jakarta.xml.bind:jakarta.xml.bind-api",
"moduleUrl": "https://www.eclipse.org",
- "moduleVersion": "4.0.1",
+ "moduleVersion": "4.0.2",
"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.11",
+ "moduleVersion": "1.14.12",
"moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
},
+ {
+ "moduleName": "net.minidev:accessors-smart",
+ "moduleUrl": "https://urielch.github.io/",
+ "moduleVersion": "2.5.0",
+ "moduleLicense": "The Apache Software License, Version 2.0",
+ "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
+ },
+ {
+ "moduleName": "net.minidev:json-smart",
+ "moduleUrl": "https://urielch.github.io/",
+ "moduleVersion": "2.5.0",
+ "moduleLicense": "The Apache Software License, Version 2.0",
+ "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
+ },
{
"moduleName": "org.antlr:antlr4-runtime",
"moduleUrl": "https://www.antlr.org/",
@@ -371,49 +427,49 @@
{
"moduleName": "org.apache.pdfbox:fontbox",
"moduleUrl": "https://pdfbox.apache.org",
- "moduleVersion": "3.0.1",
+ "moduleVersion": "3.0.2",
"moduleLicense": "Apache-2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
},
{
"moduleName": "org.apache.pdfbox:pdfbox",
"moduleUrl": "https://pdfbox.apache.org",
- "moduleVersion": "3.0.1",
+ "moduleVersion": "3.0.2",
"moduleLicense": "Apache-2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
},
{
"moduleName": "org.apache.pdfbox:pdfbox-io",
"moduleUrl": "https://pdfbox.apache.org",
- "moduleVersion": "3.0.1",
+ "moduleVersion": "3.0.2",
"moduleLicense": "Apache-2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
},
{
"moduleName": "org.apache.pdfbox:xmpbox",
"moduleUrl": "https://pdfbox.apache.org",
- "moduleVersion": "3.0.1",
+ "moduleVersion": "3.0.2",
"moduleLicense": "Apache-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.18",
+ "moduleVersion": "10.1.19",
"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.18",
+ "moduleVersion": "10.1.19",
"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.18",
+ "moduleVersion": "10.1.19",
"moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
},
@@ -467,41 +523,41 @@
},
{
"moduleName": "org.commonmark:commonmark",
- "moduleVersion": "0.21.0",
+ "moduleVersion": "0.22.0",
"moduleLicense": "BSD 2-Clause License",
"moduleLicenseUrl": "https://opensource.org/licenses/BSD-2-Clause"
},
{
"moduleName": "org.commonmark:commonmark-ext-gfm-tables",
- "moduleVersion": "0.21.0",
+ "moduleVersion": "0.22.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",
+ "moduleVersion": "2.0.2",
"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",
+ "moduleVersion": "4.0.5",
"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",
+ "moduleVersion": "4.0.5",
"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",
+ "moduleVersion": "4.0.5",
"moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception",
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
},
@@ -522,7 +578,7 @@
{
"moduleName": "org.hibernate.orm:hibernate-core",
"moduleUrl": "https://www.hibernate.org/orm/6.4",
- "moduleVersion": "6.4.1.Final",
+ "moduleVersion": "6.4.4.Final",
"moduleLicense": "GNU Library General Public License v2.1 or later",
"moduleLicenseUrl": "https://www.opensource.org/licenses/LGPL-2.1"
},
@@ -533,52 +589,6 @@
"moduleLicense": "Public Domain",
"moduleLicenseUrl": "http://repository.jboss.org/licenses/cc0-1.0.txt"
},
- {
- "moduleName": "org.junit.jupiter:junit-jupiter",
- "moduleUrl": "https://junit.org/junit5/",
- "moduleVersion": "5.10.1",
- "moduleLicense": "Eclipse Public License v2.0",
- "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-v20.html"
- },
- {
- "moduleName": "org.junit.jupiter:junit-jupiter-api",
- "moduleUrl": "https://junit.org/junit5/",
- "moduleVersion": "5.10.1",
- "moduleLicense": "Eclipse Public License v2.0",
- "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-v20.html"
- },
- {
- "moduleName": "org.junit.jupiter:junit-jupiter-engine",
- "moduleUrl": "https://junit.org/junit5/",
- "moduleVersion": "5.10.1",
- "moduleLicense": "Eclipse Public License v2.0",
- "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-v20.html"
- },
- {
- "moduleName": "org.junit.jupiter:junit-jupiter-params",
- "moduleUrl": "https://junit.org/junit5/",
- "moduleVersion": "5.10.1",
- "moduleLicense": "Eclipse Public License v2.0",
- "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-v20.html"
- },
- {
- "moduleName": "org.junit.platform:junit-platform-commons",
- "moduleUrl": "https://junit.org/junit5/",
- "moduleVersion": "1.10.1",
- "moduleLicense": "Eclipse Public License v2.0",
- "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-v20.html"
- },
- {
- "moduleName": "org.junit.platform:junit-platform-engine",
- "moduleUrl": "https://junit.org/junit5/",
- "moduleVersion": "1.10.1",
- "moduleLicense": "Eclipse Public License v2.0",
- "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-v20.html"
- },
- {
- "moduleName": "org.junit:junit-bom",
- "moduleVersion": "5.10.1"
- },
{
"moduleName": "org.latencyutils:LatencyUtils",
"moduleUrl": "http://latencyutils.github.io/LatencyUtils/",
@@ -587,23 +597,23 @@
"moduleLicenseUrl": "http://creativecommons.org/publicdomain/zero/1.0/"
},
{
- "moduleName": "org.opentest4j:opentest4j",
- "moduleUrl": "https://github.com/ota4j-team/opentest4j",
- "moduleVersion": "1.3.0",
- "moduleLicense": "The Apache License, Version 2.0",
- "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
+ "moduleName": "org.ow2.asm:asm",
+ "moduleUrl": "http://asm.ow2.org",
+ "moduleVersion": "9.3",
+ "moduleLicense": "The Apache Software License, Version 2.0",
+ "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
},
{
"moduleName": "org.slf4j:jul-to-slf4j",
"moduleUrl": "http://www.slf4j.org",
- "moduleVersion": "2.0.11",
+ "moduleVersion": "2.0.12",
"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.11",
+ "moduleVersion": "2.0.12",
"moduleLicense": "MIT License",
"moduleLicenseUrl": "http://www.opensource.org/licenses/mit-license.php"
},
@@ -628,238 +638,266 @@
{
"moduleName": "org.springframework.boot:spring-boot",
"moduleUrl": "https://spring.io/projects/spring-boot",
- "moduleVersion": "3.2.2",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
+ "moduleLicense": "Apache License, Version 2.0",
+ "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
+ },
+ {
+ "moduleName": "org.springframework.boot:spring-boot-starter-oauth2-client",
+ "moduleUrl": "https://spring.io/projects/spring-boot",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
"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.2",
+ "moduleVersion": "3.2.4",
"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",
+ "moduleVersion": "6.2.3",
"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",
+ "moduleVersion": "6.2.3",
"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",
+ "moduleVersion": "6.2.3",
+ "moduleLicense": "Apache License, Version 2.0",
+ "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
+ },
+ {
+ "moduleName": "org.springframework.security:spring-security-oauth2-client",
+ "moduleUrl": "https://spring.io/projects/spring-security",
+ "moduleVersion": "6.2.3",
+ "moduleLicense": "Apache License, Version 2.0",
+ "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
+ },
+ {
+ "moduleName": "org.springframework.security:spring-security-oauth2-core",
+ "moduleUrl": "https://spring.io/projects/spring-security",
+ "moduleVersion": "6.2.3",
+ "moduleLicense": "Apache License, Version 2.0",
+ "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
+ },
+ {
+ "moduleName": "org.springframework.security:spring-security-oauth2-jose",
+ "moduleUrl": "https://spring.io/projects/spring-security",
+ "moduleVersion": "6.2.3",
"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",
+ "moduleVersion": "6.2.3",
"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.3",
+ "moduleVersion": "6.1.5",
"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.3",
+ "moduleVersion": "6.1.5",
"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.3",
+ "moduleVersion": "6.1.5",
"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.3",
+ "moduleVersion": "6.1.5",
"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.3",
+ "moduleVersion": "6.1.5",
"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.3",
+ "moduleVersion": "6.1.5",
"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.3",
+ "moduleVersion": "6.1.5",
"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.3",
+ "moduleVersion": "6.1.5",
"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.3",
+ "moduleVersion": "6.1.5",
"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.3",
+ "moduleVersion": "6.1.5",
"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.3",
+ "moduleVersion": "6.1.5",
"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",
+ "moduleVersion": "6.1.5",
"moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
},
diff --git a/src/main/resources/static/css/account.css b/src/main/resources/static/css/account.css
new file mode 100644
index 00000000..957fcd9f
--- /dev/null
+++ b/src/main/resources/static/css/account.css
@@ -0,0 +1,4 @@
+.buttons-container {
+ margin-top: 20px;
+ text-align: center;
+}
diff --git a/src/main/resources/static/css/add-image.css b/src/main/resources/static/css/add-image.css
new file mode 100644
index 00000000..5a735b42
--- /dev/null
+++ b/src/main/resources/static/css/add-image.css
@@ -0,0 +1,28 @@
+#box-drag-container {
+ position: relative;
+ margin: 20px 0;
+}
+#pdf-canvas {
+ box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
+ width: 100%;
+}
+.draggable-buttons-box {
+ position: absolute;
+ top: 0;
+ padding: 10px;
+ width: 100%;
+ display: flex;
+ gap: 5px;
+}
+.draggable-buttons-box > button {
+ z-index: 10;
+ background-color: rgba(13, 110, 253, 0.1);
+}
+.draggable-canvas {
+ border: 1px solid red;
+ position: absolute;
+ touch-action: none;
+ user-select: none;
+ top: 0px;
+ left: 0;
+}
diff --git a/src/main/resources/static/css/dark-mode.css b/src/main/resources/static/css/dark-mode.css
index 6f914fc3..b874f410 100644
--- a/src/main/resources/static/css/dark-mode.css
+++ b/src/main/resources/static/css/dark-mode.css
@@ -1,9 +1,11 @@
/* Dark Mode Styles */
-body, select, textarea {
- --body-background-color: 51, 51, 51;
- --base-font-color: 255, 255, 255;
- background-color: rgb(var(--body-background-color)) !important;
- color: rgb(var(--base-font-color)) !important;
+body,
+select,
+textarea {
+ --body-background-color: 51, 51, 51;
+ --base-font-color: 255, 255, 255;
+ background-color: rgb(var(--body-background-color)) !important;
+ color: rgb(var(--base-font-color)) !important;
}
.card {
background-color: rgb(var(--body-background-color)) !important;
@@ -11,11 +13,11 @@ body, select, textarea {
color: rgb(var(--base-font-color)) !important;
}
- a {
- color: #add8e6;
- }
- a:hover {
- color: #87ceeb; /* Slightly brighter blue on hover for accessibility */
+a {
+ color: #add8e6;
+}
+a:hover {
+ color: #87ceeb; /* Slightly brighter blue on hover for accessibility */
}
.dark-card {
@@ -36,7 +38,7 @@ body, select, textarea {
color: rgb(var(--base-font-color)) !important;
}
#support-section {
- background-color: #444 !important;
+ background-color: #444 !important;
}
#pages-container-wrapper {
@@ -47,89 +49,93 @@ body, select, textarea {
}
.favorite-icon img {
- filter: brightness(0) invert(1) !important;
+ filter: brightness(0) invert(1) !important;
}
table thead {
- background-color: #333 !important;
- border: 1px solid #444;
+ background-color: #333 !important;
+ border: 1px solid #444;
}
-table th, table td {
- border: 1px solid #444 !important;
- color: white;
+table th,
+table td {
+ border: 1px solid #444 !important;
+ color: white;
}
.btn {
- background-color: #444 !important;
- border: none;
- color: #fff !important;
+ background-color: #444 !important;
+ border: none;
+ color: #fff !important;
}
.btn-primary {
- background-color: #007bff !important;
- border: none;
- color: #fff !important;
+ background-color: #007bff !important;
+ border: none;
+ color: #fff !important;
}
.btn-secondary {
- background-color: #6c757d !important;
- border: none;
- color: #fff !important;
+ background-color: #6c757d !important;
+ border: none;
+ color: #fff !important;
}
.btn-info {
- background-color: #17a2b8 !important;
- border: none;
- color: #fff !important;
+ background-color: #17a2b8 !important;
+ border: none;
+ color: #fff !important;
}
.btn-danger {
- background-color: #dc3545 !important;
- border: none;
- color: #fff !important;
+ background-color: #dc3545 !important;
+ border: none;
+ color: #fff !important;
}
.btn-warning {
- background-color: #ffc107 !important;
- border: none;
- color: #000 !important;
+ background-color: #ffc107 !important;
+ border: none;
+ color: #000 !important;
}
.btn-outline-secondary {
- color: #fff !important;
- border-color: #fff;
+ color: #fff !important;
+ border-color: #fff;
}
.btn-outline-secondary:hover {
- background-color: #444 !important;
- color: #007bff !important;
- border-color: #007bff;
+ background-color: #444 !important;
+ color: #007bff !important;
+ border-color: #007bff;
}
.blackwhite-icon {
- filter: brightness(0) invert(1);
+ filter: brightness(0) invert(1);
}
hr {
- border-color: rgba(255, 255, 255, 0.6); /* semi-transparent white */
- background-color: rgba(255, 255, 255, 0.6); /* for some browsers that might use background instead of border for */
+ border-color: rgba(255, 255, 255, 0.6); /* semi-transparent white */
+ background-color: rgba(255, 255, 255, 0.6); /* for some browsers that might use background instead of border for */
}
.modal-content {
- color: #fff !important;
- border-color: #fff;
+ color: #fff !important;
+ border-color: #fff;
}
-#global-buttons-container input {
- background-color: #323948;
- caret-color: #ffffff;
- color: #ffffff;
+.global-buttons-container input {
+ background-color: #323948;
+ caret-color: #ffffff;
+ color: #ffffff;
}
-#global-buttons-container input::placeholder {
- color: #ffffff;
+.global-buttons-container input::placeholder {
+ color: #ffffff;
}
-#global-buttons-container input:disabled::-webkit-input-placeholder { /* WebKit browsers */
- color: #6E6865;
+.global-buttons-container input:disabled::-webkit-input-placeholder {
+ /* WebKit browsers */
+ color: #6e6865;
}
-#global-buttons-container input:disabled:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
- color: #6E6865;
+.global-buttons-container input:disabled:-moz-placeholder {
+ /* Mozilla Firefox 4 to 18 */
+ color: #6e6865;
}
-#global-buttons-container input:disabled::-moz-placeholder { /* Mozilla Firefox 19+ */
- color: #6E6865;
+.global-buttons-container input:disabled::-moz-placeholder {
+ /* Mozilla Firefox 19+ */
+ color: #6e6865;
}
-#global-buttons-container input:disabled:-ms-input-placeholder { /* Internet Explorer 10+ */
- color: #6E6865;
+.global-buttons-container input:disabled:-ms-input-placeholder {
+ /* Internet Explorer 10+ */
+ color: #6e6865;
}
-
diff --git a/src/main/resources/static/css/dragdrop.css b/src/main/resources/static/css/dragdrop.css
index e75a0d06..7758bdd9 100644
--- a/src/main/resources/static/css/dragdrop.css
+++ b/src/main/resources/static/css/dragdrop.css
@@ -1,78 +1,78 @@
#drag-container {
- position: fixed;
- display:flex;
- inset: 0;
- pointer-events: none;
- z-index: 10000;
- visibility: hidden;
+ position: fixed;
+ display: flex;
+ inset: 0;
+ pointer-events: none;
+ z-index: 10000;
+ visibility: hidden;
}
#drag-container:not(:empty) {
- visibility: visible;
+ visibility: visible;
}
#drag-container .dragged-img {
- position: fixed;
- max-width: 200px;
- max-height: 200px;
- box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.58);
- transform-origin: top left;
+ position: fixed;
+ max-width: 200px;
+ max-height: 200px;
+ box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.58);
+ transform-origin: top left;
}
.drag-manager_dragging {
- width: 0px;
- visibility: hidden;
+ width: 0px;
+ visibility: hidden;
}
.drag-manager_draghover {
- width: 375px !important;
+ width: 375px !important;
}
.drag-manager_draghover .insert-file-button-container {
- display: none !important;
+ display: none !important;
}
.drag-manager_draghover .button-container {
- visibility: hidden !important;
+ visibility: hidden !important;
}
-html[lang-direction=ltr] .drag-manager_draghover img {
- left: calc(50% + 62.5px) !important;
+html[dir="ltr"] .drag-manager_draghover img {
+ left: calc(50% + 62.5px) !important;
}
-html[lang-direction=rtl] .drag-manager_draghover img {
- left: 125px
+html[dir="rtl"] .drag-manager_draghover img {
+ left: 125px;
}
.drag-manager_dragging-container .hide-on-drag {
- display: none !important;
+ display: none !important;
}
.drag-manager_endpoint {
- width: 80px;
- height: 100%;
- background-color: #FFFFFF10;
- transition: width 0.1s;
- animation: end-drop-expand .3s ease;
- display: flex;
- align-items: center;
- justify-content: center;
+ width: 80px;
+ height: 100%;
+ background-color: #ffffff10;
+ transition: width 0.1s;
+ animation: end-drop-expand 0.3s ease;
+ display: flex;
+ align-items: center;
+ justify-content: center;
}
.drag-manager_endpoint svg {
- width: 50px;
- height: 50px;
+ width: 50px;
+ height: 50px;
}
.drag-manager_endpoint.drag-manager_draghover {
- width: 150px !important;
+ width: 150px !important;
}
@keyframes end-drop-expand {
- from {
- width: 0;
- }
- to {
- width: 80px;
- }
-}
\ No newline at end of file
+ from {
+ width: 0;
+ }
+ to {
+ width: 80px;
+ }
+}
diff --git a/src/main/resources/static/css/error.css b/src/main/resources/static/css/error.css
new file mode 100644
index 00000000..5cc37b61
--- /dev/null
+++ b/src/main/resources/static/css/error.css
@@ -0,0 +1,88 @@
+h1 {
+ text-align: center;
+ margin-top: 10%;
+}
+
+p {
+ text-align: center;
+ margin-top: 2em;
+}
+
+.button:hover {
+ background-color: #005b7f;
+}
+
+.features-container {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(21rem, 3fr));
+ gap: 25px 30px;
+}
+
+.feature-card {
+ border: 1px solid rgba(0, 0, 0, 0.125);
+ border-radius: 0.25rem;
+ padding: 1.25rem;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+}
+
+.feature-card .card-text {
+ flex: 1;
+}
+
+#support-section {
+ background-color: #f9f9f9;
+ padding: 4rem;
+ margin-top: 1rem;
+ text-align: center;
+}
+
+#support-section h1 {
+ margin-top: 0;
+}
+
+#support-section p {
+ margin-top: 0;
+}
+
+#button-group {
+ display: flex;
+ justify-content: center;
+ flex-wrap: wrap;
+}
+
+#github-button,
+#discord-button {
+ display: inline-block;
+ padding: 1rem 2rem;
+ margin: 1rem;
+ background-color: #008cba;
+ color: #fff;
+ font-size: 1.2rem;
+ text-align: center;
+ text-decoration: none;
+ border-radius: 3rem;
+ transition: all 0.3s ease-in-out;
+}
+
+#github-button:hover,
+#discord-button:hover,
+.home-button:hover {
+ background-color: #005b7f;
+}
+
+.home-button {
+ display: block;
+ width: 200px;
+ height: 50px;
+ margin: 2em auto;
+ background-color: #008cba;
+ color: white;
+ text-align: center;
+ line-height: 50px;
+ text-decoration: none;
+ font-weight: bold;
+ border-radius: 25px;
+ transition: all 0.3s ease-in-out;
+}
diff --git a/src/main/resources/static/css/errorBanner.css b/src/main/resources/static/css/errorBanner.css
index 69a940b3..75618731 100644
--- a/src/main/resources/static/css/errorBanner.css
+++ b/src/main/resources/static/css/errorBanner.css
@@ -1,94 +1,97 @@
#errorContainer {
- margin: 20px; /* adjust this value as needed */
+ margin: 20px; /* adjust this value as needed */
}
#helpModalDialog {
- width: 90%;
- max-width: 800px;
+ width: 90%;
+ max-width: 800px;
}
#helpModal h1 {
- text-align: center;
- margin-top: 10%;
+ text-align: center;
+ margin-top: 10%;
}
#helpModal p {
- text-align: center;
- margin-top: 2em;
+ text-align: center;
+ margin-top: 2em;
}
#helpModal .button:hover {
- background-color: #005b7f;
+ background-color: #005b7f;
}
#helpModal .features-container {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(21rem, 3fr));
- gap: 25px 30px;
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(21rem, 3fr));
+ gap: 25px 30px;
}
#helpModal .feature-card {
- border: 1px solid rgba(0, 0, 0, .125);
- border-radius: 0.25rem;
- padding: 1.25rem;
- display: flex;
- flex-direction: column;
- align-items: flex-start;
+ border: 1px solid rgba(0, 0, 0, 0.125);
+ border-radius: 0.25rem;
+ padding: 1.25rem;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
}
#helpModal .feature-card .card-text {
- flex: 1;
+ flex: 1;
}
#support-section {
- background-color: #f9f9f9;
- padding: 4rem;
- margin-top: 1rem;
- text-align: center;
+ background-color: #f9f9f9;
+ padding: 4rem;
+ margin-top: 1rem;
+ text-align: center;
}
#support-section h1 {
- margin-top: 0;
+ margin-top: 0;
}
#support-section p {
- margin-top: 0;
+ margin-top: 0;
}
#button-group {
- display: flex;
- justify-content: center;
- flex-wrap: wrap;
+ display: flex;
+ justify-content: center;
+ flex-wrap: wrap;
}
-#github-button, #discord-button {
- display: inline-block;
- padding: 1rem 2rem;
- margin: 1rem;
- background-color: #008CBA;
- color: #fff;
- font-size: 1.2rem;
- text-align: center;
- text-decoration: none;
- border-radius: 3rem;
- transition: all 0.3s ease-in-out;
+#github-button,
+#discord-button {
+ display: inline-block;
+ padding: 1rem 2rem;
+ margin: 1rem;
+ background-color: #008cba;
+ color: #fff;
+ font-size: 1.2rem;
+ text-align: center;
+ text-decoration: none;
+ border-radius: 3rem;
+ transition: all 0.3s ease-in-out;
}
-#github-button:hover, #discord-button:hover, #home-button:hover {
- background-color: #005b7f;
+#github-button:hover,
+#discord-button:hover,
+.home-button:hover {
+ background-color: #005b7f;
}
-#home-button {
- display: block;
- width: 200px;
- height: 50px;
- margin: 2em auto;
- background-color: #008CBA;
- color: white;
- text-align: center;
- line-height: 50px;
- text-decoration: none;
- font-weight: bold;
- border-radius: 25px;
- transition: all 0.3s ease-in-out;
-}
\ No newline at end of file
+.home-button {
+ display: block;
+ width: 200px;
+ height: 50px;
+ margin: 2em auto;
+ background-color: #008cba;
+ color: white;
+ text-align: center;
+ line-height: 50px;
+ text-decoration: none;
+ font-weight: bold;
+ border-radius: 25px;
+ transition: all 0.3s ease-in-out;
+}
diff --git a/src/main/resources/static/css/fileSelect.css b/src/main/resources/static/css/fileSelect.css
index 2cd2c682..e8f12979 100644
--- a/src/main/resources/static/css/fileSelect.css
+++ b/src/main/resources/static/css/fileSelect.css
@@ -1,10 +1,10 @@
.custom-file-label {
- padding-right: 90px;
+ padding-right: 90px;
}
.selected-files {
- margin-top: 10px;
- max-height: 150px;
- overflow-y: auto;
- white-space: pre-wrap;
-}
\ No newline at end of file
+ margin-top: 10px;
+ max-height: 150px;
+ overflow-y: auto;
+ white-space: pre-wrap;
+}
diff --git a/src/main/resources/static/css/footer.css b/src/main/resources/static/css/footer.css
new file mode 100644
index 00000000..f6cf093d
--- /dev/null
+++ b/src/main/resources/static/css/footer.css
@@ -0,0 +1,20 @@
+#footer {
+ display: flex;
+ flex-direction: column; /* Stack children vertically */
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+}
+
+.footer-center {
+ display: flex;
+ align-items: center; /* Center children horizontally */
+ flex-grow: 1;
+}
+
+.footer-powered-by {
+ margin-top: auto; /* Pushes the text to the bottom */
+ color: grey;
+ text-align: center; /* Centers the text inside the div */
+ width: 100%; /* Full width to center the text properly */
+}
diff --git a/src/main/resources/static/css/game.css b/src/main/resources/static/css/game.css
index 01b93e94..fc2f7262 100644
--- a/src/main/resources/static/css/game.css
+++ b/src/main/resources/static/css/game.css
@@ -1,49 +1,54 @@
#game-container {
- position: relative;
- width: 100vh;
- height: 0;
- padding-bottom: 75%; /* 4:3 aspect ratio */
- background-color: transparent;
- margin: auto;
- overflow: hidden;
- border: 2px solid black; /* Add border */
+ position: relative;
+ width: 100vh;
+ height: 0;
+ padding-bottom: 75%; /* 4:3 aspect ratio */
+ background-color: transparent;
+ margin: auto;
+ overflow: hidden;
+ border: 2px solid black; /* Add border */
}
-.pdf, .player, .projectile {
- position: absolute;
+.pdf,
+.player,
+.projectile {
+ position: absolute;
}
.pdf {
- width: 50px;
- height: 50px;
+ width: 50px;
+ height: 50px;
}
.player {
- width: 50px;
- height: 50px;
+ width: 50px;
+ height: 50px;
}
.projectile {
- background-color: black !important;
- width: 5px;
- height: 10px;
+ background-color: black !important;
+ width: 5px;
+ height: 10px;
}
-#score, #level, #lives, #high-score {
- color: black;
- font-family: sans-serif;
- position: absolute;
- font-size: calc(14px + 0.25vw); /* Reduced font size */
+#score,
+#level,
+#lives,
+#high-score {
+ color: black;
+ font-family: sans-serif;
+ position: absolute;
+ font-size: calc(14px + 0.25vw); /* Reduced font size */
}
#score {
- top: 10px;
- left: 10px;
+ top: 10px;
+ left: 10px;
}
#lives {
- top: 10px;
- left: calc(7vw); /* Adjusted position */
+ top: 10px;
+ left: calc(9vw); /* Adjusted position */
}
#high-score {
- top: 10px;
- left: calc(14vw); /* Adjusted position */
+ top: 10px;
+ left: calc(14vw); /* Adjusted position */
}
#level {
- top: 10px;
- right: 10px;
-}
\ No newline at end of file
+ top: 10px;
+ right: 10px;
+}
diff --git a/src/main/resources/static/css/general.css b/src/main/resources/static/css/general.css
index 934074ca..72edf184 100644
--- a/src/main/resources/static/css/general.css
+++ b/src/main/resources/static/css/general.css
@@ -1,20 +1,20 @@
#page-container {
- min-height: 100vh;
- display: flex;
- flex-direction: column;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
}
#content-wrap {
- flex: 1;
+ flex: 1;
}
#footer {
- bottom: 0;
- width: 100%;
+ bottom: 0;
+ width: 100%;
}
.navbar {
- height: auto; /* Adjusts height automatically based on content */
- white-space: nowrap; /* Prevents wrapping of navbar contents */
+ height: auto; /* Adjusts height automatically based on content */
+ white-space: nowrap; /* Prevents wrapping of navbar contents */
}
/* TODO enable later
.navbar .container {
@@ -25,70 +25,70 @@
margin-right: auto;
}*/
-html[lang-direction=ltr] * {
- direction: ltr;
+html[dir="ltr"] * {
+ direction: ltr;
}
-html[lang-direction=rtl] * {
- direction: rtl;
- text-align: right;
+html[dir="rtl"] * {
+ direction: rtl;
+ text-align: right;
}
.ignore-rtl {
- direction: ltr !important;
- text-align: left !important;
+ direction: ltr !important;
+ text-align: left !important;
}
.align-top {
- position: absolute;
- top: 0;
+ position: absolute;
+ top: 0;
}
.align-center-right {
- position: absolute;
- right: 0;
- top: 50%;
+ position: absolute;
+ right: 0;
+ top: 50%;
}
.align-center-left {
- position: absolute;
- left: 0;
- top: 50%;
+ position: absolute;
+ left: 0;
+ top: 50%;
}
.align-bottom {
- position: absolute;
- bottom: 0;
+ position: absolute;
+ bottom: 0;
}
.btn-group > label:first-of-type {
- border-top-left-radius: 0.25rem !important;
- border-bottom-left-radius: 0.25rem !important;
+ border-top-left-radius: 0.25rem !important;
+ border-bottom-left-radius: 0.25rem !important;
}
-html[lang-direction="rtl"] input.form-check-input {
- position: relative;
- margin-left: 0px;
+html[dir="rtl"] input.form-check-input {
+ position: relative;
+ margin-left: 0px;
}
-html[lang-direction="rtl"] label.form-check-label {
- display: inline;
+html[dir="rtl"] label.form-check-label {
+ display: inline;
}
.margin-auto-parent {
- width: 100%;
- display: flex;
+ width: 100%;
+ display: flex;
}
.margin-center {
- margin: 0 auto;
+ margin: 0 auto;
}
#pdf-canvas {
- box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
- width: 100%;
+ box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
+ width: 100%;
}
.fixed-shadow-canvas {
- box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
- width: 100%;
+ box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
+ width: 100%;
}
.shadow-canvas {
- box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
+ box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
}
.hidden {
- display: none;
-}
\ No newline at end of file
+ display: none;
+}
diff --git a/src/main/resources/static/css/home.css b/src/main/resources/static/css/home.css
index fe184637..ff8d1cf7 100644
--- a/src/main/resources/static/css/home.css
+++ b/src/main/resources/static/css/home.css
@@ -1,64 +1,62 @@
#searchBar {
- background-image: url('../images/search.svg');
- background-position: 16px 16px;
- background-repeat: no-repeat;
- width: 100%;
- font-size: 16px;
- margin-bottom: 12px;
- padding: 12px 20px 12px 40px;
- border: 1px solid #ddd;
-
-
+ background-image: url("../images/search.svg");
+ background-position: 16px 16px;
+ background-repeat: no-repeat;
+ width: 100%;
+ font-size: 16px;
+ margin-bottom: 12px;
+ padding: 12px 20px 12px 40px;
+ border: 1px solid #ddd;
}
.dark-mode-search {
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' hei… 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z'/%3E%3C/svg%3E") !important;
- color: #f8f9fa !important;
- background-color: #212529 !important;
- border-color: #343a40 !important;
- }
-
-
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' hei… 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z'/%3E%3C/svg%3E") !important;
+ color: #f8f9fa !important;
+ background-color: #212529 !important;
+ border-color: #343a40 !important;
+}
.features-container {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(15rem, 3fr));
- gap: 25px 30px;
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(15rem, 3fr));
+ gap: 25px 30px;
}
.feature-card {
- border: 2px solid rgba(0, 0, 0, .25);
- border-radius: 0.25rem;
- padding: 1.25rem;
- display: flex;
- flex-direction: column;
- align-items: flex-start;
- background: rgba(13, 110, 253, 0.05);
- transition: transform 0.3s, border 0.3s;
- transform-origin: center center;
- outline: 2px solid transparent;
+ border: 2px solid rgba(0, 0, 0, 0.25);
+ border-radius: 0.25rem;
+ padding: 1.25rem;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ background: rgba(13, 110, 253, 0.05);
+ transition:
+ transform 0.3s,
+ border 0.3s;
+ transform-origin: center center;
+ outline: 2px solid transparent;
}
.feature-card a {
- text-decoration: none;
- color: inherit;
- display: flex;
- flex-direction: column;
- width: 100%;
- height: 100%;
+ text-decoration: none;
+ color: inherit;
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ height: 100%;
}
.feature-card .card-text {
- flex: 1;
+ flex: 1;
}
.feature-card:hover {
- outline: 1px solid rgba(0, 0, 0, .5);
- cursor: pointer;
- transform: scale(1.1);
+ outline: 1px solid rgba(0, 0, 0, 0.5);
+ cursor: pointer;
+ transform: scale(1.1);
}
.feature-card:hover .card-title {
- text-decoration: underline;
+ text-decoration: underline;
}
.card-title.text-primary {
color: #000; /* Replace with your desired shade of blue */
@@ -67,27 +65,62 @@
.home-card-icon {
width: 30px;
height: 30px;
- transform: translateY(-5px);
+ transform: translateY(-5px);
}
.home-card-icon-colour {
-filter: invert(0.2) sepia(2) saturate(50) hue-rotate(190deg);
+ filter: invert(0.2) sepia(2) saturate(50) hue-rotate(190deg);
}
.favorite-icon {
- display: none;
- position: absolute;
- top: 10px;
- right: 10px;
+ display: none;
+ position: absolute;
+ top: 10px;
+ right: 10px;
}
/* Only show the favorite icons when the parent card is being hovered over */
.feature-card:hover .favorite-icon {
- display: block;
+ display: block;
}
.favorite-icon img {
- filter: brightness(0);
+ filter: brightness(0);
}
.jumbotron {
- padding: 3rem 3rem; /* Reduce vertical padding */
+ padding: 3rem 3rem; /* Reduce vertical padding */
+}
+
+.lookatme {
+ opacity: 1;
+ position: relative;
+ display: inline-block;
+}
+
+.lookatme::after {
+ color: #e33100;
+ text-shadow: 0 0 5px #e33100;
+ /* in the html, the data-lookatme-text attribute must */
+ /* contain the same text as the .lookatme element */
+ content: attr(data-lookatme-text);
+ padding: inherit;
+ position: absolute;
+ inset: 0 0 0 0;
+ z-index: 1;
+ /* 20 steps / 2 seconds = 10fps */
+ -webkit-animation: 2s infinite Pulse steps(20);
+ animation: 2s infinite Pulse steps(20);
+}
+
+@keyframes Pulse {
+ from {
+ opacity: 0;
+ }
+
+ 50% {
+ opacity: 1;
+ }
+
+ to {
+ opacity: 0;
+ }
}
diff --git a/src/main/resources/static/css/imageHighlighter.css b/src/main/resources/static/css/imageHighlighter.css
index 231895d6..397c0c54 100644
--- a/src/main/resources/static/css/imageHighlighter.css
+++ b/src/main/resources/static/css/imageHighlighter.css
@@ -1,40 +1,43 @@
-
#image-highlighter {
- position: fixed;
- display:flex;
- inset: 0;
- z-index: 10000;
- background-color: rgba(0, 0, 0, 0);
- visibility: hidden;
- align-items: center;
- justify-content: center;
- transition: visbility 0.1s linear, background-color 0.1s linear;
+ position: fixed;
+ display: flex;
+ inset: 0;
+ z-index: 10000;
+ background-color: rgba(0, 0, 0, 0);
+ visibility: hidden;
+ align-items: center;
+ justify-content: center;
+ transition:
+ visbility 0.1s linear,
+ background-color 0.1s linear;
}
#image-highlighter > * {
- max-width: 80vw;
- max-height: 80vh;
- animation: image-highlight .1s linear;
- transition: transform .1s linear, opacity .1s linear;
+ max-width: 80vw;
+ max-height: 80vh;
+ animation: image-highlight 0.1s linear;
+ transition:
+ transform 0.1s linear,
+ opacity 0.1s linear;
}
#image-highlighter > *.remove {
- transform: scale(0.8) !important;
- opacity: 0 !important;
+ transform: scale(0.8) !important;
+ opacity: 0 !important;
}
#image-highlighter:not(:empty) {
- background-color: rgba(0, 0, 0, 0.37);
- visibility: visible;
+ background-color: rgba(0, 0, 0, 0.37);
+ visibility: visible;
}
@keyframes image-highlight {
- from {
- transform: scale(0.8);
- opacity: 0;
- }
- to {
- transform: scale(1);
- opacity: 1;
- }
-}
\ No newline at end of file
+ from {
+ transform: scale(0.8);
+ opacity: 0;
+ }
+ to {
+ transform: scale(1);
+ opacity: 1;
+ }
+}
diff --git a/src/main/resources/static/css/licenses.css b/src/main/resources/static/css/licenses.css
new file mode 100644
index 00000000..79abdc34
--- /dev/null
+++ b/src/main/resources/static/css/licenses.css
@@ -0,0 +1,9 @@
+td a {
+ text-decoration: none;
+}
+
+td a:hover,
+td a:focus {
+ text-decoration: underline;
+ /* Adds underline on hover/focus for clarity */
+}
diff --git a/src/main/resources/static/css/light-mode.css b/src/main/resources/static/css/light-mode.css
index 08efbf4c..f7e79b90 100644
--- a/src/main/resources/static/css/light-mode.css
+++ b/src/main/resources/static/css/light-mode.css
@@ -1,24 +1,23 @@
/* Dark Mode Styles */
body {
- --body-background-color: 255, 255, 255;
- --base-font-color: 33, 37, 41;
+ --body-background-color: 255, 255, 255;
+ --base-font-color: 33, 37, 41;
}
-
-#global-buttons-container input {
- background-color: #ffffff;
- /*caret-color: #ffffff;*/
- /*color: #ffffff;*/
+.global-buttons-container input {
+ background-color: #ffffff;
+ /*caret-color: #ffffff;*/
+ /*color: #ffffff;*/
}
-/*#global-buttons-container input:disabled::-webkit-input-placeholder { !* WebKit browsers *!*/
+/*.global-buttons-container input:disabled::-webkit-input-placeholder { !* WebKit browsers *!*/
/* color: #98A0AB;*/
/*}*/
-/*#global-buttons-container input:disabled:-moz-placeholder { !* Mozilla Firefox 4 to 18 *!*/
+/*.global-buttons-container input:disabled:-moz-placeholder { !* Mozilla Firefox 4 to 18 *!*/
/* color: #98A0AB;*/
/*}*/
-/*#global-buttons-container input:disabled::-moz-placeholder { !* Mozilla Firefox 19+ *!*/
+/*.global-buttons-container input:disabled::-moz-placeholder { !* Mozilla Firefox 19+ *!*/
/* color: #98A0AB;*/
/*}*/
-/*#global-buttons-container input:disabled:-ms-input-placeholder { !* Internet Explorer 10+ *!*/
+/*.global-buttons-container input:disabled:-ms-input-placeholder { !* Internet Explorer 10+ *!*/
/* color: #98A0AB;*/
/*}*/
diff --git a/src/main/resources/static/css/login.css b/src/main/resources/static/css/login.css
new file mode 100644
index 00000000..743ee606
--- /dev/null
+++ b/src/main/resources/static/css/login.css
@@ -0,0 +1,111 @@
+html,
+body {
+ height: 100%;
+}
+
+body {
+ display: flex;
+ align-items: center;
+ padding-top: 40px;
+ padding-bottom: 40px;
+ background-color: #f5f5f5;
+}
+
+.form-signin {
+ width: 100%;
+ max-width: 330px;
+ padding: 15px;
+ margin: auto;
+}
+
+.form-signin .checkbox {
+ font-weight: 400;
+}
+
+.form-signin .form-floating:focus-within {
+ z-index: 2;
+}
+
+.form-signin input[type="text"] {
+ margin-bottom: -1px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+
+.form-signin input[type="password"] {
+ margin-bottom: 10px;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+.container-flex {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ width: 100%; /* Set width to 100% */
+ align-items: center; /* Center its children horizontally */
+}
+.footer-bottom {
+ margin-top: auto;
+}
+body.light-mode input:-webkit-autofill,
+body.light-mode input:-webkit-autofill:hover,
+body.light-mode input:-webkit-autofill:focus,
+body.light-mode input:-webkit-autofill:active {
+ -webkit-text-fill-color: #212529; /* Dark font color */
+ -webkit-box-shadow: 0 0 0 1000px #f8f9fa inset; /* Light background color */
+}
+
+/* Dark Mode */
+body.dark-mode input:-webkit-autofill,
+body.dark-mode input:-webkit-autofill:hover,
+body.dark-mode input:-webkit-autofill:focus,
+body.dark-mode input:-webkit-autofill:active {
+ -webkit-text-fill-color: #f8f9fa; /* Light font color */
+ -webkit-box-shadow: 0 0 0 1000px #212529 inset; /* Dark background color */
+}
+/* Light Mode */
+body.light-mode .form-floating > input:focus + label {
+ color: #212529 !important; /* Dark text for light background */
+}
+
+/* Dark Mode */
+body.dark-mode .form-floating > input:focus + label {
+ color: #fff !important; /* Light text for dark background */
+}
+
+body.light-mode .form-floating > label {
+ color: #212529 !important; /* Dark text for light background */
+}
+
+body.dark-mode .form-floating > label {
+ color: #fff !important; /* Light text for dark background */
+}
+
+/* Removing default styles for ul and li */
+ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+li {
+ list-style: none;
+}
+
+/* Positioning the container of these elements to the top right */
+.your-container-class {
+ position: absolute;
+ top: 0;
+ right: 0;
+ display: flex;
+}
+
+/* Styling for the dropdown */
+.dropdown-menu {
+ min-width: 200px; /* or whatever width you prefer */
+}
+
+.navbar-icon {
+ width: 40px;
+ height: 40px;
+}
diff --git a/src/main/resources/static/css/merge.css b/src/main/resources/static/css/merge.css
index 866e2e8c..dc3c7657 100644
--- a/src/main/resources/static/css/merge.css
+++ b/src/main/resources/static/css/merge.css
@@ -1,4 +1,4 @@
- .list-group-item {
+.list-group-item {
display: flex;
justify-content: space-between;
align-items: center;
@@ -25,5 +25,4 @@
.move-down span {
font-weight: bold;
font-size: 1.2em;
-
}
diff --git a/src/main/resources/static/css/multi-tool.css b/src/main/resources/static/css/multi-tool.css
new file mode 100644
index 00000000..50e038ce
--- /dev/null
+++ b/src/main/resources/static/css/multi-tool.css
@@ -0,0 +1,119 @@
+.multi-tool-container {
+ max-width: 95vw;
+ margin: 0 auto;
+}
+
+.global-buttons-container {
+ display: flex;
+ gap: 10px;
+ align-items: start;
+
+ background-color: rgba(13, 110, 253, 0.1);
+ border: 1px solid rgba(0, 0, 0, 0.25);
+ backdrop-filter: blur(2px);
+
+ top: 10px;
+ z-index: 10;
+ padding: 10px;
+ border-radius: 8px;
+}
+.global-buttons-container > * {
+ padding: 0.6rem 0.75rem;
+}
+
+.global-buttons-container svg {
+ width: 20px;
+ height: 20px;
+}
+#export-button {
+ margin-left: auto;
+}
+
+#pages-container-wrapper {
+ --background-color: rgba(0, 0, 0, 0.025);
+ --scroll-bar-color: #f1f1f1;
+ --scroll-bar-thumb: #888;
+ --scroll-bar-thumb-hover: #555;
+ background-color: var(--background-color);
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ padding: 10px 25px;
+ border-radius: 10px;
+ overflow-y: hidden;
+ overflow-x: auto;
+ min-height: 275px;
+ margin: 0 0 30px 0;
+}
+
+#pages-container {
+ margin: auto;
+ gap: 0px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+/* width */
+#pages-container-wrapper::-webkit-scrollbar {
+ width: 10px;
+ height: 10px;
+}
+
+/* Track */
+#pages-container-wrapper::-webkit-scrollbar-track {
+ background: var(--scroll-bar-color);
+}
+
+/* Handle */
+#pages-container-wrapper::-webkit-scrollbar-thumb {
+ border-radius: 10px;
+ background: var(--scroll-bar-thumb);
+}
+
+/* Handle on hover */
+#pages-container-wrapper::-webkit-scrollbar-thumb:hover {
+ background: var(--scroll-bar-thumb-hover);
+}
+
+.page-container {
+ height: 250px;
+ display: flex;
+ align-items: center;
+ flex-direction: column-reverse;
+ aspect-ratio: 1;
+ text-align: center;
+ position: relative;
+ user-select: none;
+ transition: width 1s linear;
+}
+
+.page-container img {
+ /* max-width: calc(100% - 15px); */
+ max-height: calc(100% - 15px);
+ max-width: 237px;
+ display: block;
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ translate: -50% -50%;
+ box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
+ border-radius: 4px;
+ transition: rotate 0.3s;
+}
+
+#add-pdf-button {
+ margin: 0 auto;
+}
+
+.page-number {
+ position: absolute;
+ top: 5px;
+ right: 5px;
+ color: white;
+ background-color: #007bff; /* Primary blue color */
+ padding: 3px 6px;
+ border-radius: 4px;
+ font-size: 12px;
+ z-index: 2;
+}
diff --git a/src/main/resources/static/css/navbar.css b/src/main/resources/static/css/navbar.css
index 5bb99a5e..f46c44a6 100644
--- a/src/main/resources/static/css/navbar.css
+++ b/src/main/resources/static/css/navbar.css
@@ -1,80 +1,116 @@
-
-
#navbarSearch {
- top: 100%;
- right: 0;
+ top: 100%;
+ right: 0;
+ transition: all 0.3s;
+ max-height: 0;
+ overflow: hidden;
+}
+
+#navbarSearch.show {
+ max-height: 300px; /* Adjust this to your desired max height */
}
#searchForm {
- width: 200px; /* Adjust this value as needed */
+ width: 200px; /* Adjust this value as needed */
}
/* Style the search results to match the navbar */
#searchResults {
- max-height: 200px; /* Adjust this value as needed */
- overflow-y: auto;
- width: 100%;
+ max-height: 200px; /* Adjust this value as needed */
+ overflow-y: auto;
+ width: 100%;
+ max-width: 300px; /* Adjust to your preferred width */
+ transition: height 0.3s ease; /* Smooth height transition */
}
#searchResults .dropdown-item {
- display: flex;
- align-items: center;
- white-space: nowrap;
- height: 50px; /* Fixed height */
- overflow: hidden; /* Hide overflow */
+ display: flex;
+ align-items: center;
+ white-space: nowrap;
+ height: 50px; /* Fixed height */
+ overflow: hidden; /* Hide overflow */
}
#searchResults .icon {
- margin-right: 10px;
+ margin-right: 10px;
}
#searchResults .icon-text {
- display: inline;
- overflow: hidden; /* Hide overflow */
- text-overflow: ellipsis; /* Add ellipsis for long text */
+ display: inline;
+ overflow: hidden; /* Hide overflow */
+ text-overflow: ellipsis; /* Add ellipsis for long text */
}
+#search-icon i {
+ font-size: 24px; /* Adjust this to your desired size */
+ transition: color 0.3s;
+}
+#search-icon:hover i {
+ color: #666; /* Adjust this to your hover color */
+}
+
+.search-input {
+ transition:
+ border 0.3s,
+ box-shadow 0.3s;
+}
+
+.search-input:focus {
+ border-color: #666; /* Adjust this to your focus color */
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* Adjust this to your desired shadow */
+}
+
+/* Set a fixed height and styling for each search result item */
+.search-results a {
+ display: flex;
+ align-items: center;
+ gap: 10px; /* space between icon and text */
+ height: 40px; /* Adjust based on your design */
+ overflow: hidden; /* Prevent content from overflowing */
+ white-space: nowrap; /* Prevent text from wrapping to next line */
+ text-overflow: ellipsis; /* Truncate text if it's too long */
+}
.main-icon {
- width: 36px;
- height: 36px;
- vertical-align: middle;
- transform: translateY(-2px);
+ width: 36px;
+ height: 36px;
+ vertical-align: middle;
+ transform: translateY(-2px);
}
.icon {
- width: 16px;
- height: 16px;
- vertical-align: middle;
- transform: translateY(-2px);
+ width: 16px;
+ height: 16px;
+ vertical-align: middle;
+ transform: translateY(-2px);
}
-.icon+.icon {
- margin-left: -4px;
+.icon + .icon {
+ margin-left: -4px;
}
.icon-text {
- margin-left: 4px;
+ margin-left: 4px;
}
.nav-item-separator {
- position: relative;
- margin: 0 4px; /* Adjust the margin as needed */
+ position: relative;
+ margin: 0 4px; /* Adjust the margin as needed */
}
.nav-item-separator::before {
- content: '';
- position: absolute;
- left: 0;
- top: 10%; /* Adjust the top and bottom margins as needed */
- bottom: 10%;
- width: 1px;
- background-color: #ccc; /* Adjust the color as needed */
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 10%; /* Adjust the top and bottom margins as needed */
+ bottom: 10%;
+ width: 1px;
+ background-color: #ccc; /* Adjust the color as needed */
}
.navbar-icon {
- width: 20px;
- height: 20px;
- transform: translateY(-2px);
-}
\ No newline at end of file
+ width: 20px;
+ height: 20px;
+ transform: translateY(-2px);
+}
diff --git a/src/main/resources/static/css/pdfActions.css b/src/main/resources/static/css/pdfActions.css
index 98c29dbe..455de860 100644
--- a/src/main/resources/static/css/pdfActions.css
+++ b/src/main/resources/static/css/pdfActions.css
@@ -1,87 +1,85 @@
-
.pdf-actions_button-container {
- z-index: 2;
- display:flex;
- opacity: 0;
- transition: opacity 0.1s linear;
+ z-index: 2;
+ display: flex;
+ opacity: 0;
+ transition: opacity 0.1s linear;
}
.pdf-actions_container:hover .pdf-actions_button-container {
- opacity: 1;
+ opacity: 1;
}
.pdf-actions_button-container > * {
- padding: 0.25rem 0.5rem;
- margin: 3px;
- display: block;
+ padding: 0.25rem 0.5rem;
+ margin: 3px;
+ display: block;
}
.pdf-actions_container svg {
- width: 16px;
- height: 16px;
+ width: 16px;
+ height: 16px;
}
.pdf-actions_container:nth-child(1) .pdf-actions_move-left-button {
- display: none;
+ display: none;
}
.pdf-actions_container:last-child .pdf-actions_move-right-button {
- display: none;
+ display: none;
}
/* "insert pdf" buttons that appear on the right when hover */
.pdf-actions_insert-file-button-container {
- translate: 0 -50%;
- width: 80px;
- height: 100%;
+ translate: 0 -50%;
+ width: 80px;
+ height: 100%;
- z-index: 1;
- opacity: 0;
- transition: opacity 0.2s;
+ z-index: 1;
+ opacity: 0;
+ transition: opacity 0.2s;
}
.pdf-actions_insert-file-button-container.left {
- left: -20px;
+ left: -20px;
}
.pdf-actions_insert-file-button-container.right {
- right: -20px;
+ right: -20px;
}
-html[lang-direction=ltr] .pdf-actions_insert-file-button-container.right {
- display:none;
+html[dir="ltr"] .pdf-actions_insert-file-button-container.right {
+ display: none;
}
-html[lang-direction=rtl] .pdf-actions_insert-file-button-container.left {
- display:none;
+html[dir="rtl"] .pdf-actions_insert-file-button-container.left {
+ display: none;
}
.pdf-actions_insert-file-button-container.left .pdf-actions_insert-file-button {
- left: 0;
- translate: 0 -50%;
+ left: 0;
+ translate: 0 -50%;
}
.pdf-actions_insert-file-button-container.right .pdf-actions_insert-file-button {
- right: 0;
- translate: 0 -50%;
+ right: 0;
+ translate: 0 -50%;
}
-html[lang-direction=ltr] .pdf-actions_container:last-child > .pdf-actions_insert-file-button-container.right {
- display: block;
+html[dir="ltr"] .pdf-actions_container:last-child > .pdf-actions_insert-file-button-container.right {
+ display: block;
}
-
-html[lang-direction=rtl] .pdf-actions_container:last-child > .pdf-actions_insert-file-button-container.left {
- display: block;
+html[dir="rtl"] .pdf-actions_container:last-child > .pdf-actions_insert-file-button-container.left {
+ display: block;
}
.pdf-actions_insert-file-button-container:hover {
- opacity: 1;
- transition: opacity 0.05s;
+ opacity: 1;
+ transition: opacity 0.05s;
}
.pdf-actions_insert-file-button {
- position: absolute;
- top: 50%;
- right: 50%;
- translate: 50% -50%;
- aspect-ratio: 1;
- border-radius: 100px;
-}
\ No newline at end of file
+ position: absolute;
+ top: 50%;
+ right: 50%;
+ translate: 50% -50%;
+ aspect-ratio: 1;
+ border-radius: 100px;
+}
diff --git a/src/main/resources/static/css/pipeline.css b/src/main/resources/static/css/pipeline.css
new file mode 100644
index 00000000..9468333b
--- /dev/null
+++ b/src/main/resources/static/css/pipeline.css
@@ -0,0 +1,21 @@
+.btn-margin {
+ margin-right: 2px;
+}
+
+.bordered-box {
+ border: 1px solid #ddd;
+ padding: 20px;
+ margin: 20px;
+ width: 70%;
+}
+
+.center-element {
+ width: 80%;
+ text-align: center;
+ margin: auto;
+}
+
+.element-margin {
+ margin: 10px 0;
+ /* Adjust this value to increase/decrease the margin as needed */
+}
diff --git a/src/main/resources/static/css/rainbow-mode.css b/src/main/resources/static/css/rainbow-mode.css
index 2c58adf5..921423a5 100644
--- a/src/main/resources/static/css/rainbow-mode.css
+++ b/src/main/resources/static/css/rainbow-mode.css
@@ -1,37 +1,113 @@
/* Rainbow Mode Styles */
body {
- background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%);
- color: #fff !important;
- --body-background-color: 255, 255, 255;
- --base-font-color: 33, 37, 41;
+ background: linear-gradient(
+ 90deg,
+ rgba(255, 0, 0, 1) 0%,
+ rgba(255, 154, 0, 1) 10%,
+ rgba(208, 222, 33, 1) 20%,
+ rgba(79, 220, 74, 1) 30%,
+ rgba(63, 218, 216, 1) 40%,
+ rgba(47, 201, 226, 1) 50%,
+ rgba(28, 127, 238, 1) 60%,
+ rgba(95, 21, 242, 1) 70%,
+ rgba(186, 12, 248, 1) 80%,
+ rgba(251, 7, 217, 1) 90%,
+ rgba(255, 0, 0, 1) 100%
+ );
+ color: #fff !important;
+ --body-background-color: 255, 255, 255;
+ --base-font-color: 33, 37, 41;
}
.dark-card {
- background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%) !important;
- color: white !important;
+ background: linear-gradient(
+ 90deg,
+ rgba(255, 0, 0, 1) 0%,
+ rgba(255, 154, 0, 1) 10%,
+ rgba(208, 222, 33, 1) 20%,
+ rgba(79, 220, 74, 1) 30%,
+ rgba(63, 218, 216, 1) 40%,
+ rgba(47, 201, 226, 1) 50%,
+ rgba(28, 127, 238, 1) 60%,
+ rgba(95, 21, 242, 1) 70%,
+ rgba(186, 12, 248, 1) 80%,
+ rgba(251, 7, 217, 1) 90%,
+ rgba(255, 0, 0, 1) 100%
+ ) !important;
+ color: white !important;
}
.jumbotron {
- background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%);
- color: #fff !important;
+ background: linear-gradient(
+ 90deg,
+ rgba(255, 0, 0, 1) 0%,
+ rgba(255, 154, 0, 1) 10%,
+ rgba(208, 222, 33, 1) 20%,
+ rgba(79, 220, 74, 1) 30%,
+ rgba(63, 218, 216, 1) 40%,
+ rgba(47, 201, 226, 1) 50%,
+ rgba(28, 127, 238, 1) 60%,
+ rgba(95, 21, 242, 1) 70%,
+ rgba(186, 12, 248, 1) 80%,
+ rgba(251, 7, 217, 1) 90%,
+ rgba(255, 0, 0, 1) 100%
+ );
+ color: #fff !important;
}
.list-group {
- background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%) !important;
- color: fff !important;
+ background: linear-gradient(
+ 90deg,
+ rgba(255, 0, 0, 1) 0%,
+ rgba(255, 154, 0, 1) 10%,
+ rgba(208, 222, 33, 1) 20%,
+ rgba(79, 220, 74, 1) 30%,
+ rgba(63, 218, 216, 1) 40%,
+ rgba(47, 201, 226, 1) 50%,
+ rgba(28, 127, 238, 1) 60%,
+ rgba(95, 21, 242, 1) 70%,
+ rgba(186, 12, 248, 1) 80%,
+ rgba(251, 7, 217, 1) 90%,
+ rgba(255, 0, 0, 1) 100%
+ ) !important;
+ color: fff !important;
}
.list-group-item {
- background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%) !important;
- color: fff !important;
+ background: linear-gradient(
+ 90deg,
+ rgba(255, 0, 0, 1) 0%,
+ rgba(255, 154, 0, 1) 10%,
+ rgba(208, 222, 33, 1) 20%,
+ rgba(79, 220, 74, 1) 30%,
+ rgba(63, 218, 216, 1) 40%,
+ rgba(47, 201, 226, 1) 50%,
+ rgba(28, 127, 238, 1) 60%,
+ rgba(95, 21, 242, 1) 70%,
+ rgba(186, 12, 248, 1) 80%,
+ rgba(251, 7, 217, 1) 90%,
+ rgba(255, 0, 0, 1) 100%
+ ) !important;
+ color: fff !important;
}
#support-section {
- background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%, rgba(255,0,0,1) 100%) !important;
+ background: linear-gradient(
+ 90deg,
+ rgba(255, 0, 0, 1) 0%,
+ rgba(255, 154, 0, 1) 10%,
+ rgba(208, 222, 33, 1) 20%,
+ rgba(79, 220, 74, 1) 30%,
+ rgba(63, 218, 216, 1) 40%,
+ rgba(47, 201, 226, 1) 50%,
+ rgba(28, 127, 238, 1) 60%,
+ rgba(95, 21, 242, 1) 70%,
+ rgba(186, 12, 248, 1) 80%,
+ rgba(251, 7, 217, 1) 90%,
+ rgba(255, 0, 0, 1) 100%
+ ) !important;
}
-
#pages-container-wrapper {
--background-color: rgba(255, 255, 255, 0.046) !important;
--scroll-bar-color: #4c4c4c !important;
--scroll-bar-thumb: #d3d3d3 !important;
--scroll-bar-thumb-hover: #ffffff !important;
}
-
diff --git a/src/main/resources/static/css/rotate-pdf.css b/src/main/resources/static/css/rotate-pdf.css
new file mode 100644
index 00000000..57a30024
--- /dev/null
+++ b/src/main/resources/static/css/rotate-pdf.css
@@ -0,0 +1,29 @@
+#pdf-preview {
+ margin: 0 auto;
+ display: block;
+ max-width: calc(100% - 30px);
+ max-height: calc(100% - 30px);
+ box-shadow: 0 0 4px rgba(100, 100, 100, 0.25);
+ transition: rotate 0.3s;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ translate: -50% -50%;
+}
+
+#previewContainer {
+ aspect-ratio: 1;
+ width: 100%;
+ border: 1px solid rgba(0, 0, 0, 0.125);
+ border-radius: 0.25rem;
+ margin: 1rem 0;
+ padding: 15px;
+ display: block;
+ overflow: hidden;
+ position: relative;
+}
+
+.buttonContainer {
+ display: flex;
+ justify-content: space-around;
+}
diff --git a/src/main/resources/static/css/sign.css b/src/main/resources/static/css/sign.css
new file mode 100644
index 00000000..c6ae3374
--- /dev/null
+++ b/src/main/resources/static/css/sign.css
@@ -0,0 +1,39 @@
+select#font-select,
+select#font-select option {
+ height: 60px; /* Adjust as needed */
+ font-size: 30px; /* Adjust as needed */
+}
+
+.drawing-pad-container {
+ text-align: center;
+}
+
+#drawing-pad-canvas {
+ background: rgba(125, 125, 125, 0.2);
+ width: 100%;
+ height: 300px;
+}
+#box-drag-container {
+ position: relative;
+ margin: 20px 0;
+}
+.draggable-buttons-box {
+ position: absolute;
+ top: 0;
+ padding: 10px;
+ width: 100%;
+ display: flex;
+ gap: 5px;
+}
+.draggable-buttons-box > button {
+ z-index: 10;
+ background-color: rgba(13, 110, 253, 0.1);
+}
+.draggable-canvas {
+ border: 1px solid red;
+ position: absolute;
+ touch-action: none;
+ user-select: none;
+ top: 0px;
+ left: 0;
+}
diff --git a/src/main/resources/static/css/split-pdf-by-sections.css b/src/main/resources/static/css/split-pdf-by-sections.css
new file mode 100644
index 00000000..7520c10e
--- /dev/null
+++ b/src/main/resources/static/css/split-pdf-by-sections.css
@@ -0,0 +1,10 @@
+.pdf-visual-aid {
+ width: 150px; /* Adjust as needed */
+ height: 200px; /* Adjust as needed */
+ border: 1px solid black; /* Represents the PDF page */
+ position: relative;
+}
+.line {
+ position: absolute;
+ background-color: red; /* Line color */
+}
diff --git a/src/main/resources/static/css/stamp.css b/src/main/resources/static/css/stamp.css
new file mode 100644
index 00000000..9fed6178
--- /dev/null
+++ b/src/main/resources/static/css/stamp.css
@@ -0,0 +1,41 @@
+.a4container {
+ position: relative;
+ width: 50%;
+ aspect-ratio: 0.707;
+ border: 1px solid #ddd;
+ box-sizing: border-box;
+ background-color: white;
+}
+
+.pageNumber {
+ position: absolute;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-size: 1em;
+ color: #333;
+ cursor: pointer;
+ background-color: #ccc;
+ width: 15%;
+ height: 15%;
+ transform: translate(-50%, -50%);
+}
+
+.pageNumber:hover {
+ background-color: #eee;
+}
+
+#myForm {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin-top: 20px;
+}
+
+.selectedPosition {
+ background-color: #0a0;
+}
+
+.selectedPosition.selectedHovered {
+ background-color: #006600;
+}
diff --git a/src/main/resources/static/css/tab-container.css b/src/main/resources/static/css/tab-container.css
index f6609de4..cf048650 100644
--- a/src/main/resources/static/css/tab-container.css
+++ b/src/main/resources/static/css/tab-container.css
@@ -1,26 +1,24 @@
-
.tab-group {
-
}
.tab-container {
- display: none;
+ display: none;
}
.tab-container.active {
- display: block;
- border: 1px solid rgba(var(--base-font-color), 0.25);
- padding: 15px;
+ display: block;
+ border: 1px solid rgba(var(--base-font-color), 0.25);
+ padding: 15px;
}
.tab-buttons > button {
- margin-bottom: -1px;
- background: 0 0;
- border: 1px solid transparent;
- color: rgb(var(--base-font-color));
+ margin-bottom: -1px;
+ background: 0 0;
+ border: 1px solid transparent;
+ color: rgb(var(--base-font-color));
- border-top-left-radius: 0.25rem;
- border-top-right-radius: 0.25rem;
+ border-top-left-radius: 0.25rem;
+ border-top-right-radius: 0.25rem;
}
.tab-buttons > button.active {
- background-color: rgb(var(--body-background-color));
- border-color: rgba(var(--base-font-color), 0.25) rgba(var(--base-font-color), 0.25) rgb(var(--body-background-color));
-}
\ No newline at end of file
+ background-color: rgb(var(--body-background-color));
+ border-color: rgba(var(--base-font-color), 0.25) rgba(var(--base-font-color), 0.25) rgb(var(--body-background-color));
+}
diff --git a/src/main/resources/static/images/flags/pt_pt.svg b/src/main/resources/static/images/flags/pt_pt.svg
new file mode 100644
index 00000000..445cf7f5
--- /dev/null
+++ b/src/main/resources/static/images/flags/pt_pt.svg
@@ -0,0 +1,57 @@
+
diff --git a/src/main/resources/static/images/flags/ua.svg b/src/main/resources/static/images/flags/ua.svg
new file mode 100644
index 00000000..a339eb1b
--- /dev/null
+++ b/src/main/resources/static/images/flags/ua.svg
@@ -0,0 +1,6 @@
+
diff --git a/src/main/resources/static/images/update.svg b/src/main/resources/static/images/update.svg
new file mode 100644
index 00000000..3edc4c67
--- /dev/null
+++ b/src/main/resources/static/images/update.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/main/resources/static/js/cacheFormInputs.js b/src/main/resources/static/js/cacheFormInputs.js
new file mode 100644
index 00000000..e61b4449
--- /dev/null
+++ b/src/main/resources/static/js/cacheFormInputs.js
@@ -0,0 +1,82 @@
+document.addEventListener("DOMContentLoaded", function() {
+
+ var cacheInputs = localStorage.getItem("cacheInputs") || "disabled";
+ if (cacheInputs !== "enabled") {
+ return; // Stop execution if caching is not enabled
+ }
+
+ // Function to generate a key based on the form's action attribute
+ function generateStorageKey(form) {
+ const action = form.getAttribute('action');
+ if (!action || action.length < 3) {
+ return null; // Not a valid action, return null to skip processing
+ }
+ return 'formData_' + encodeURIComponent(action);
+ }
+
+ // Function to save form data to localStorage
+ function saveFormData(form) {
+ const formKey = generateStorageKey(form);
+ if (!formKey) return; // Skip if no valid key
+
+ const formData = {};
+ const elements = form.elements;
+ for (let i = 0; i < elements.length; i++) {
+ const element = elements[i];
+ // Skip elements without names, passwords, files, hidden fields, and submit/reset buttons
+ if (!element.name ||
+ element.type === 'password' ||
+ element.type === 'file' ||
+ //element.type === 'hidden' ||
+ element.type === 'submit' ||
+ element.type === 'reset') {
+ continue;
+ }
+ // Handle checkboxes: store only if checked
+ if (element.type === 'checkbox') {
+ if (element.checked) {
+ formData[element.name] = element.value;
+ } else {
+ continue; // Skip unchecked boxes
+ }
+ } else {
+ // Skip saving empty values
+ if (element.value === "" || element.value == null) {
+ continue;
+ }
+ formData[element.name] = element.value;
+ }
+ }
+ localStorage.setItem(formKey, JSON.stringify(formData));
+ }
+
+ // Function to load form data from localStorage
+ function loadFormData(form) {
+ const formKey = generateStorageKey(form);
+ if (!formKey) return; // Skip if no valid key
+
+ const savedData = localStorage.getItem(formKey);
+ if (savedData) {
+ const formData = JSON.parse(savedData);
+ for (const key in formData) {
+ if (formData.hasOwnProperty(key) && form.elements[key]) {
+ const element = form.elements[key];
+ if (element.type === 'checkbox') {
+ element.checked = true;
+ } else {
+ element.value = formData[key];
+ }
+ }
+ }
+ }
+ }
+
+ // Attach event listeners and load data for all forms
+ const forms = document.querySelectorAll('form');
+ forms.forEach(form => {
+ form.addEventListener('submit', function(event) {
+ saveFormData(form);
+ });
+ loadFormData(form);
+ });
+});
diff --git a/src/main/resources/static/js/darkmode.js b/src/main/resources/static/js/darkmode.js
index d3c62266..cb119a8a 100644
--- a/src/main/resources/static/js/darkmode.js
+++ b/src/main/resources/static/js/darkmode.js
@@ -1,5 +1,5 @@
-var toggleCount = 0
-var lastToggleTime = Date.now()
+var toggleCount = 0;
+var lastToggleTime = Date.now();
var elements = {
lightModeStyles: null,
@@ -11,18 +11,18 @@ var elements = {
navbar: null,
navIcons: null,
navDropdownMenus: null,
-}
+};
function getElements() {
- elements.lightModeStyles = document.getElementById("light-mode-styles")
- elements.darkModeStyles = document.getElementById("dark-mode-styles")
- elements.rainbowModeStyles = document.getElementById("rainbow-mode-styles")
- elements.darkModeIcon = document.getElementById("dark-mode-icon")
- elements.searchBar = document.getElementById("searchBar")
- elements.formControls = document.querySelectorAll(".form-control")
- elements.navbar = document.querySelectorAll("nav.navbar")
- elements.navIcons = document.querySelectorAll("nav .icon, .navbar-icon")
- elements.navDropdownMenus = document.querySelectorAll("nav .dropdown-menu")
+ elements.lightModeStyles = document.getElementById("light-mode-styles");
+ elements.darkModeStyles = document.getElementById("dark-mode-styles");
+ elements.rainbowModeStyles = document.getElementById("rainbow-mode-styles");
+ elements.darkModeIcon = document.getElementById("dark-mode-icon");
+ elements.searchBar = document.getElementById("searchBar");
+ elements.formControls = document.querySelectorAll(".form-control");
+ elements.navbar = document.querySelectorAll("nav.navbar");
+ elements.navIcons = document.querySelectorAll("nav .icon, .navbar-icon");
+ elements.navDropdownMenus = document.querySelectorAll(".dropdown-menu");
}
function setMode(mode) {
var event = new CustomEvent("modeChanged", { detail: mode });
@@ -48,22 +48,22 @@ function setMode(mode) {
elements.searchBar.classList.add("dark-mode-search");
}
if (elements && elements.formControls) {
- elements.formControls.forEach(input => input.classList.add("bg-dark", "text-white"));
+ elements.formControls.forEach((input) => input.classList.add("bg-dark", "text-white"));
}
if (elements && elements.navbar) {
- elements.navbar.forEach(navElement => {
+ elements.navbar.forEach((navElement) => {
navElement.classList.remove("navbar-light", "bg-light");
navElement.classList.add("navbar-dark", "bg-dark");
});
}
if (elements && elements.navDropdownMenus) {
- elements.navDropdownMenus.forEach(menu => menu.classList.add("dropdown-menu-dark"));
+ elements.navDropdownMenus.forEach((menu) => menu.classList.add("dropdown-menu-dark"));
}
if (elements && elements.navIcons) {
- elements.navIcons.forEach(icon => (icon.style.filter = "invert(1)"));
+ elements.navIcons.forEach((icon) => (icon.style.filter = "invert(1)"));
}
var tables = document.querySelectorAll(".table");
- tables.forEach(table => {
+ tables.forEach((table) => {
table.classList.add("table-dark");
});
if (jumbotron) {
@@ -78,22 +78,22 @@ function setMode(mode) {
elements.searchBar.classList.remove("dark-mode-search");
}
if (elements && elements.formControls) {
- elements.formControls.forEach(input => input.classList.remove("bg-dark", "text-white"));
+ elements.formControls.forEach((input) => input.classList.remove("bg-dark", "text-white"));
}
if (elements && elements.navbar) {
- elements.navbar.forEach(navElement => {
+ elements.navbar.forEach((navElement) => {
navElement.classList.remove("navbar-dark", "bg-dark");
navElement.classList.add("navbar-light", "bg-light");
});
}
if (elements && elements.navDropdownMenus) {
- elements.navDropdownMenus.forEach(menu => menu.classList.remove("dropdown-menu-dark"));
+ elements.navDropdownMenus.forEach((menu) => menu.classList.remove("dropdown-menu-dark"));
}
if (elements && elements.navIcons) {
- elements.navIcons.forEach(icon => (icon.style.filter = "none"));
+ elements.navIcons.forEach((icon) => (icon.style.filter = "none"));
}
var tables = document.querySelectorAll(".table-dark");
- tables.forEach(table => {
+ tables.forEach((table) => {
table.classList.remove("table-dark");
});
if (jumbotron) {
@@ -108,43 +108,43 @@ function setMode(mode) {
}
function toggleDarkMode() {
- var currentTime = Date.now()
+ var currentTime = Date.now();
if (currentTime - lastToggleTime < 1000) {
- toggleCount++
+ toggleCount++;
} else {
- toggleCount = 1
+ toggleCount = 1;
}
- lastToggleTime = currentTime
+ lastToggleTime = currentTime;
if (toggleCount >= 18) {
- localStorage.setItem("dark-mode", "rainbow")
- setMode("rainbow")
+ localStorage.setItem("dark-mode", "rainbow");
+ setMode("rainbow");
} else if (localStorage.getItem("dark-mode") == "on") {
- localStorage.setItem("dark-mode", "off")
- setMode("off")
+ localStorage.setItem("dark-mode", "off");
+ setMode("off");
} else {
- localStorage.setItem("dark-mode", "on")
- setMode("on")
+ localStorage.setItem("dark-mode", "on");
+ setMode("on");
}
}
document.addEventListener("DOMContentLoaded", function () {
- getElements()
+ getElements();
- var currentMode = localStorage.getItem("dark-mode")
+ var currentMode = localStorage.getItem("dark-mode");
if (currentMode === "on" || currentMode === "off" || currentMode === "rainbow") {
- setMode(currentMode)
+ setMode(currentMode);
} else if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
- setMode("on")
+ setMode("on");
} else {
- setMode("off")
+ setMode("off");
}
var darkModeToggle = document.getElementById("dark-mode-toggle");
if (darkModeToggle !== null) {
- darkModeToggle.addEventListener("click", function (event) {
- event.preventDefault();
- toggleDarkMode();
- });
- }
-})
+ darkModeToggle.addEventListener("click", function (event) {
+ event.preventDefault();
+ toggleDarkMode();
+ });
+ }
+});
diff --git a/src/main/resources/static/js/downloader.js b/src/main/resources/static/js/downloader.js
index 8971f98e..c955bb1b 100644
--- a/src/main/resources/static/js/downloader.js
+++ b/src/main/resources/static/js/downloader.js
@@ -1,242 +1,265 @@
function showErrorBanner(message, stackTrace) {
- const errorContainer = document.getElementById("errorContainer");
- errorContainer.style.display = "block"; // Display the banner
- document.querySelector("#errorContainer .alert-heading").textContent = "Error";
- document.querySelector("#errorContainer p").textContent = message;
- document.querySelector("#traceContent").textContent = stackTrace;
+ const errorContainer = document.getElementById("errorContainer");
+ errorContainer.style.display = "block"; // Display the banner
+ document.querySelector("#errorContainer .alert-heading").textContent = "Error";
+ document.querySelector("#errorContainer p").textContent = message;
+ document.querySelector("#traceContent").textContent = stackTrace;
}
let firstErrorOccurred = false;
-$(document).ready(function() {
- $('form').submit(async function(event) {
- event.preventDefault();
- firstErrorOccurred = false;
- const url = this.action;
- const files = $('#fileInput-input')[0].files;
- const formData = new FormData(this);
+$(document).ready(function () {
+ $("form").submit(async function (event) {
+ event.preventDefault();
+ firstErrorOccurred = false;
+ const url = this.action;
+ const files = $("#fileInput-input")[0].files;
+ const formData = new FormData(this);
- // Remove empty file entries
- for (let [key, value] of formData.entries()) {
- if (value instanceof File && !value.name) {
- formData.delete(key);
- }
+ // Remove empty file entries
+ for (let [key, value] of formData.entries()) {
+ if (value instanceof File && !value.name) {
+ formData.delete(key);
+ }
+ }
+ const override = $("#override").val() || "";
+ const originalButtonText = $("#submitBtn").text();
+ $("#submitBtn").text("Processing...");
+ console.log(override);
+
+ // Set a timeout to show the game button if operation takes more than 5 seconds
+ const timeoutId = setTimeout(() => {
+ var boredWaiting = localStorage.getItem("boredWaiting") || "disabled";
+ const showGameBtn = document.getElementById("show-game-btn");
+ if (boredWaiting === "enabled" && showGameBtn) {
+ showGameBtn.style.display = "block";
+ }
+ }, 5000);
+
+ try {
+ if (remoteCall === true) {
+ if (override === "multi" || (!multiple && files.length > 1 && override !== "single")) {
+ await submitMultiPdfForm(url, files);
+ } else {
+ await handleSingleDownload(url, formData);
}
- const override = $('#override').val() || '';
- const originalButtonText = $('#submitBtn').text();
- $('#submitBtn').text('Processing...');
- console.log(override);
- try {
- if(remoteCall === true) {
- if (override === 'multi' || (!multiple && files.length > 1) && override !== 'single' ) {
- await submitMultiPdfForm(url, files);
- } else {
- await handleSingleDownload(url, formData);
- }
- }
- $('#submitBtn').text(originalButtonText);
- } catch (error) {
- handleDownloadError(error);
- $('#submitBtn').text(originalButtonText);
- console.error(error);
- }
- });
+ }
+ clearTimeout(timeoutId);
+ $("#submitBtn").text(originalButtonText);
+
+ // After process finishes, check for boredWaiting and gameDialog open status
+ const boredWaiting = localStorage.getItem("boredWaiting") || "disabled";
+ const gameDialog = document.getElementById('game-container-wrapper');
+ if (boredWaiting === "enabled" && gameDialog && gameDialog.open) {
+ // Display a green banner at the bottom of the screen saying "Download complete"
+ let downloadCompleteText = "Download Complete";
+ if(window.downloadCompleteText){
+ downloadCompleteText = window.downloadCompleteText;
+ }
+ $("body").append('
'+ downloadCompleteText + '
');
+ setTimeout(function() {
+ $("#download-complete-banner").fadeOut("slow", function() {
+ $(this).remove(); // Remove the banner after fading out
+ });
+ }, 5000); // Banner will fade out after 5 seconds
+ }
+
+ } catch (error) {
+ clearTimeout(timeoutId);
+ handleDownloadError(error);
+ $("#submitBtn").text(originalButtonText);
+ console.error(error);
+ }
+ });
});
+async function handleSingleDownload(url, formData, isMulti = false, isZip = false) {
+ try {
+ const response = await fetch(url, { method: "POST", body: formData });
+ const contentType = response.headers.get("content-type");
+ if (!response.ok) {
+ if (contentType && contentType.includes("application/json")) {
+ console.error("Throwing error banner, response was not okay");
+ return handleJsonResponse(response);
+ }
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
-async function handleSingleDownload(url, formData, isMulti = false , isZip = false) {
- try {
- const response = await fetch(url, { method: 'POST', body: formData });
- const contentType = response.headers.get('content-type');
+ const contentDisposition = response.headers.get("Content-Disposition");
+ let filename = getFilenameFromContentDisposition(contentDisposition);
- if (!response.ok) {
- if (contentType && contentType.includes('application/json')) {
- return handleJsonResponse(response);
- console.error('Throwing error banner, response was not okay');
- }
- throw new Error(`HTTP error! status: ${response.status}`);
- }
-
- const contentDisposition = response.headers.get('Content-Disposition');
- let filename = getFilenameFromContentDisposition(contentDisposition);
-
- const blob = await response.blob();
- if (contentType.includes('application/pdf') || contentType.includes('image/')) {
- return handleResponse(blob, filename, !isMulti, isZip);
- } else {
- return handleResponse(blob, filename, false, isZip);
- }
- } catch (error) {
- console.error('Error in handleSingleDownload:', error);
- throw error; // Re-throw the error if you want it to be handled higher up.
- }
+ const blob = await response.blob();
+ if (contentType.includes("application/pdf") || contentType.includes("image/")) {
+ return handleResponse(blob, filename, !isMulti, isZip);
+ } else {
+ return handleResponse(blob, filename, false, isZip);
+ }
+ } catch (error) {
+ console.error("Error in handleSingleDownload:", error);
+ throw error; // Re-throw the error if you want it to be handled higher up.
+ }
}
function getFilenameFromContentDisposition(contentDisposition) {
- let filename;
+ let filename;
- if (contentDisposition && contentDisposition.indexOf('attachment') !== -1) {
- filename = decodeURIComponent(contentDisposition.split('filename=')[1].replace(/"/g, '')).trim();
- } else {
- // If the Content-Disposition header is not present or does not contain the filename, use a default filename
- filename = 'download';
- }
+ if (contentDisposition && contentDisposition.indexOf("attachment") !== -1) {
+ filename = decodeURIComponent(contentDisposition.split("filename=")[1].replace(/"/g, "")).trim();
+ } else {
+ // If the Content-Disposition header is not present or does not contain the filename, use a default filename
+ filename = "download";
+ }
- return filename;
+ return filename;
}
-
-
async function handleJsonResponse(response) {
- const json = await response.json();
- const errorMessage = JSON.stringify(json, null, 2);
- if (errorMessage.toLowerCase().includes('the password is incorrect') || errorMessage.toLowerCase().includes('Password is not provided') || errorMessage.toLowerCase().includes('PDF contains an encryption dictionary')) {
- if (!firstErrorOccurred) {
- firstErrorOccurred = true;
- alert(pdfPasswordPrompt);
- }
- } else {
- showErrorBanner(json.error + ':' + json.message, json.trace);
- }
+ const json = await response.json();
+ const errorMessage = JSON.stringify(json, null, 2);
+ if (
+ errorMessage.toLowerCase().includes("the password is incorrect") ||
+ errorMessage.toLowerCase().includes("Password is not provided") ||
+ errorMessage.toLowerCase().includes("PDF contains an encryption dictionary")
+ ) {
+ if (!firstErrorOccurred) {
+ firstErrorOccurred = true;
+ alert(pdfPasswordPrompt);
+ }
+ } else {
+ showErrorBanner(json.error + ":" + json.message, json.trace);
+ }
}
-
async function handleResponse(blob, filename, considerViewOptions = false, isZip = false) {
- if (!blob) return;
- const downloadOption = localStorage.getItem('downloadOption');
- if (considerViewOptions) {
- if (downloadOption === 'sameWindow') {
- const url = URL.createObjectURL(blob);
- window.location.href = url;
- return;
- } else if (downloadOption === 'newWindow') {
- const url = URL.createObjectURL(blob);
- window.open(url, '_blank');
- return;
- }
- }
- if(!isZip){
- downloadFile(blob, filename);
- }
- return { filename, blob };
+ if (!blob) return;
+ const downloadOption = localStorage.getItem("downloadOption");
+ if (considerViewOptions) {
+ if (downloadOption === "sameWindow") {
+ const url = URL.createObjectURL(blob);
+ window.location.href = url;
+ return;
+ } else if (downloadOption === "newWindow") {
+ const url = URL.createObjectURL(blob);
+ window.open(url, "_blank");
+ return;
+ }
+ }
+ if (!isZip) {
+ downloadFile(blob, filename);
+ }
+ return { filename, blob };
}
function handleDownloadError(error) {
- const errorMessage = error.message;
- showErrorBanner(errorMessage);
+ const errorMessage = error.message;
+ showErrorBanner(errorMessage);
}
let urls = []; // An array to hold all the URLs
function downloadFile(blob, filename) {
- if (!(blob instanceof Blob)) {
- console.error('Invalid blob passed to downloadFile function');
- return;
- }
- const url = URL.createObjectURL(blob);
- const a = document.createElement('a');
- a.href = url;
- a.download = filename;
- a.click();
- urls.push(url); // Store the URL so it doesn't get garbage collected too soon
+ if (!(blob instanceof Blob)) {
+ console.error("Invalid blob passed to downloadFile function");
+ return;
+ }
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = filename;
+ a.click();
+ urls.push(url); // Store the URL so it doesn't get garbage collected too soon
- return { filename, blob };
+ return { filename, blob };
}
-
-
async function submitMultiPdfForm(url, files) {
- const zipThreshold = parseInt(localStorage.getItem('zipThreshold'), 10) || 4;
- const zipFiles = files.length > zipThreshold;
- let jszip = null;
- // Show the progress bar
- $('#progressBarContainer').show();
- // Initialize the progress bar
+ const zipThreshold = parseInt(localStorage.getItem("zipThreshold"), 10) || 4;
+ const zipFiles = files.length > zipThreshold;
+ let jszip = null;
+ // Show the progress bar
+ $(".progressBarContainer").show();
+ // Initialize the progress bar
- let progressBar = $('#progressBar');
- progressBar.css('width', '0%');
- progressBar.attr('aria-valuenow', 0);
- progressBar.attr('aria-valuemax', files.length);
+ let progressBar = $(".progressBar");
+ progressBar.css("width", "0%");
+ progressBar.attr("aria-valuenow", 0);
+ progressBar.attr("aria-valuemax", files.length);
- if (zipFiles) {
- jszip = new JSZip();
- }
+ if (zipFiles) {
+ jszip = new JSZip();
+ }
+ // Get the form with the method attribute set to POST
+ let postForm = document.querySelector('form[method="POST"]');
- // Get the form with the method attribute set to POST
- let postForm = document.querySelector('form[method="POST"]');
-
- // Get existing form data
- let formData;
- if (postForm) {
- formData = new FormData($(postForm)[0]); // Convert the form to a jQuery object and get the raw DOM element
- } else {
- console.log("No form with POST method found.");
- }
- //Remove file to reuse parameters for other runs
- formData.delete('fileInput');
- // Remove empty file entries
- for (let [key, value] of formData.entries()) {
- if (value instanceof File && !value.name) {
- formData.delete(key);
- }
+ // Get existing form data
+ let formData;
+ if (postForm) {
+ formData = new FormData($(postForm)[0]); // Convert the form to a jQuery object and get the raw DOM element
+ } else {
+ console.log("No form with POST method found.");
+ }
+ //Remove file to reuse parameters for other runs
+ formData.delete("fileInput");
+ // Remove empty file entries
+ for (let [key, value] of formData.entries()) {
+ if (value instanceof File && !value.name) {
+ formData.delete(key);
}
- const CONCURRENCY_LIMIT = 8;
- const chunks = [];
- for (let i = 0; i < Array.from(files).length; i += CONCURRENCY_LIMIT) {
- chunks.push(Array.from(files).slice(i, i + CONCURRENCY_LIMIT));
- }
+ }
+ const CONCURRENCY_LIMIT = 8;
+ const chunks = [];
+ for (let i = 0; i < Array.from(files).length; i += CONCURRENCY_LIMIT) {
+ chunks.push(Array.from(files).slice(i, i + CONCURRENCY_LIMIT));
+ }
- for (const chunk of chunks) {
- const promises = chunk.map(async file => {
- let fileFormData = new FormData();
- fileFormData.append('fileInput', file);
- console.log(fileFormData);
- // Add other form data
- for (let pair of formData.entries()) {
- fileFormData.append(pair[0], pair[1]);
- console.log(pair[0]+ ', ' + pair[1]);
- }
+ for (const chunk of chunks) {
+ const promises = chunk.map(async (file) => {
+ let fileFormData = new FormData();
+ fileFormData.append("fileInput", file);
+ console.log(fileFormData);
+ // Add other form data
+ for (let pair of formData.entries()) {
+ fileFormData.append(pair[0], pair[1]);
+ console.log(pair[0] + ", " + pair[1]);
+ }
- try {
- const downloadDetails = await handleSingleDownload(url, fileFormData, true, zipFiles);
- console.log(downloadDetails);
- if (zipFiles) {
- jszip.file(downloadDetails.filename, downloadDetails.blob);
- } else {
- //downloadFile(downloadDetails.blob, downloadDetails.filename);
- }
- updateProgressBar(progressBar, Array.from(files).length);
- } catch (error) {
- handleDownloadError(error);
- console.error(error);
- }
- });
- await Promise.all(promises);
+ try {
+ const downloadDetails = await handleSingleDownload(url, fileFormData, true, zipFiles);
+ console.log(downloadDetails);
+ if (zipFiles) {
+ jszip.file(downloadDetails.filename, downloadDetails.blob);
+ } else {
+ //downloadFile(downloadDetails.blob, downloadDetails.filename);
+ }
+ updateProgressBar(progressBar, Array.from(files).length);
+ } catch (error) {
+ handleDownloadError(error);
+ console.error(error);
+ }
+ });
+ await Promise.all(promises);
+ }
- }
-
- if (zipFiles) {
- try {
- const content = await jszip.generateAsync({ type: "blob" });
- downloadFile(content, "files.zip");
- } catch (error) {
- console.error('Error generating ZIP file: ' + error);
- }
- }
- progressBar.css('width', '100%');
- progressBar.attr('aria-valuenow', Array.from(files).length);
+ if (zipFiles) {
+ try {
+ const content = await jszip.generateAsync({ type: "blob" });
+ downloadFile(content, "files.zip");
+ } catch (error) {
+ console.error("Error generating ZIP file: " + error);
+ }
+ }
+ progressBar.css("width", "100%");
+ progressBar.attr("aria-valuenow", Array.from(files).length);
}
-
-
function updateProgressBar(progressBar, files) {
- let progress = ((progressBar.attr('aria-valuenow') / files.length) * 100) + (100 / files.length);
- progressBar.css('width', progress + '%');
- progressBar.attr('aria-valuenow', parseInt(progressBar.attr('aria-valuenow')) + 1);
+ let progress = (progressBar.attr("aria-valuenow") / files.length) * 100 + 100 / files.length;
+ progressBar.css("width", progress + "%");
+ progressBar.attr("aria-valuenow", parseInt(progressBar.attr("aria-valuenow")) + 1);
}
-window.addEventListener('unload', () => {
- for (const url of urls) {
- URL.revokeObjectURL(url);
- }
+window.addEventListener("unload", () => {
+ for (const url of urls) {
+ URL.revokeObjectURL(url);
+ }
});
diff --git a/src/main/resources/static/js/draggable-utils.js b/src/main/resources/static/js/draggable-utils.js
index 2263e540..6064e398 100644
--- a/src/main/resources/static/js/draggable-utils.js
+++ b/src/main/resources/static/js/draggable-utils.js
@@ -1,282 +1,357 @@
const DraggableUtils = {
+ boxDragContainer: document.getElementById("box-drag-container"),
+ pdfCanvas: document.getElementById("pdf-canvas"),
+ nextId: 0,
+ pdfDoc: null,
+ pageIndex: 0,
+ documentsMap: new Map(),
+ lastInteracted: null,
- boxDragContainer: document.getElementById('box-drag-container'),
- pdfCanvas: document.getElementById('pdf-canvas'),
- nextId: 0,
- pdfDoc: null,
- pageIndex: 0,
- documentsMap: new Map(),
-
- init() {
- interact('.draggable-canvas')
- .draggable({
- listeners: {
- move: (event) => {
- const target = event.target;
- const x = (parseFloat(target.getAttribute('data-bs-x')) || 0) + event.dx;
- const y = (parseFloat(target.getAttribute('data-bs-y')) || 0) + event.dy;
-
- target.style.transform = `translate(${x}px, ${y}px)`;
- target.setAttribute('data-bs-x', x);
- target.setAttribute('data-bs-y', y);
-
- this.onInteraction(target);
- },
- },
- })
- .resizable({
- edges: { left: true, right: true, bottom: true, top: true },
- listeners: {
+ init() {
+ interact(".draggable-canvas")
+ .draggable({
+ listeners: {
move: (event) => {
- var target = event.target
- var x = (parseFloat(target.getAttribute('data-bs-x')) || 0)
- var y = (parseFloat(target.getAttribute('data-bs-y')) || 0)
+ const target = event.target;
+ const x = (parseFloat(target.getAttribute("data-bs-x")) || 0)
+ + event.dx;
+ const y = (parseFloat(target.getAttribute("data-bs-y")) || 0)
+ + event.dy;
- // check if control key is pressed
- if (event.ctrlKey) {
- const aspectRatio = target.offsetWidth / target.offsetHeight;
- // preserve aspect ratio
- let width = event.rect.width;
- let height = event.rect.height;
+ target.style.transform = `translate(${x}px, ${y}px)`;
+ target.setAttribute("data-bs-x", x);
+ target.setAttribute("data-bs-y", y);
- if (Math.abs(event.deltaRect.width) >= Math.abs(event.deltaRect.height)) {
- height = width / aspectRatio;
- } else {
- width = height * aspectRatio;
- }
-
- event.rect.width = width;
- event.rect.height = height;
- }
-
- target.style.width = event.rect.width + 'px'
- target.style.height = event.rect.height + 'px'
-
- // translate when resizing from top or left edges
- x += event.deltaRect.left
- y += event.deltaRect.top
-
- target.style.transform = 'translate(' + x + 'px,' + y + 'px)'
-
- target.setAttribute('data-bs-x', x)
- target.setAttribute('data-bs-y', y)
- target.textContent = Math.round(event.rect.width) + '\u00D7' + Math.round(event.rect.height)
-
- this.onInteraction(target);
+ this.onInteraction(target);
+ //update the last interacted element
+ this.lastInteracted = event.target;
},
- },
+ },
+ })
+ .resizable({
+ edges: { left: true, right: true, bottom: true, top: true },
+ listeners: {
+ move: (event) => {
+ var target = event.target;
+ var x = parseFloat(target.getAttribute("data-bs-x")) || 0;
+ var y = parseFloat(target.getAttribute("data-bs-y")) || 0;
- modifiers: [
- interact.modifiers.restrictSize({
- min: { width: 5, height: 5 },
- }),
- ],
- inertia: true,
- });
- },
- onInteraction(target) {
- this.boxDragContainer.appendChild(target);
- },
+ // check if control key is pressed
+ if (event.ctrlKey) {
+ const aspectRatio = target.offsetWidth / target.offsetHeight;
+ // preserve aspect ratio
+ let width = event.rect.width;
+ let height = event.rect.height;
- createDraggableCanvas() {
- const createdCanvas = document.createElement('canvas');
- createdCanvas.id = `draggable-canvas-${this.nextId++}`;
- createdCanvas.classList.add("draggable-canvas");
-
- const x = 0;
- const y = 20;
- createdCanvas.style.transform = `translate(${x}px, ${y}px)`;
- createdCanvas.setAttribute('data-bs-x', x);
- createdCanvas.setAttribute('data-bs-y', y);
-
- createdCanvas.onclick = e => this.onInteraction(e.target);
-
- this.boxDragContainer.appendChild(createdCanvas);
- return createdCanvas;
- },
- createDraggableCanvasFromUrl(dataUrl) {
- return new Promise((resolve) => {
- var myImage = new Image();
- myImage.src = dataUrl;
- myImage.onload = () => {
- var createdCanvas = this.createDraggableCanvas();
-
- createdCanvas.width = myImage.width;
- createdCanvas.height = myImage.height;
-
- const imgAspect = myImage.width / myImage.height;
- const pdfAspect = this.boxDragContainer.offsetWidth / this.boxDragContainer.offsetHeight;
-
- var scaleMultiplier;
- if (imgAspect > pdfAspect) {
- scaleMultiplier = this.boxDragContainer.offsetWidth / myImage.width;
- } else {
- scaleMultiplier = this.boxDragContainer.offsetHeight / myImage.height;
- }
-
- var newWidth = createdCanvas.width;
- var newHeight = createdCanvas.height;
- if (scaleMultiplier < 1) {
- newWidth = newWidth * scaleMultiplier;
- newHeight = newHeight * scaleMultiplier;
- }
-
- createdCanvas.style.width = newWidth+"px";
- createdCanvas.style.height = newHeight+"px";
-
- var myContext = createdCanvas.getContext("2d");
- myContext.drawImage(myImage,0,0);
- resolve(createdCanvas);
+ if (Math.abs(event.deltaRect.width) >= Math.abs(
+ event.deltaRect.height)) {
+ height = width / aspectRatio;
+ } else {
+ width = height * aspectRatio;
}
- })
- },
- deleteAllDraggableCanvases() {
- this.boxDragContainer.querySelectorAll(".draggable-canvas").forEach(el => el.remove());
- },
- deleteDraggableCanvas(element) {
- if (element) {
- element.remove();
- }
- },
- getLastInteracted() {
- return this.boxDragContainer.querySelector(".draggable-canvas:last-of-type");
- },
- storePageContents() {
- var pagesMap = this.documentsMap.get(this.pdfDoc);
- if (!pagesMap) {
- pagesMap = {};
+ event.rect.width = width;
+ event.rect.height = height;
+ }
+
+ target.style.width = event.rect.width + "px";
+ target.style.height = event.rect.height + "px";
+
+ // translate when resizing from top or left edges
+ x += event.deltaRect.left;
+ y += event.deltaRect.top;
+
+ target.style.transform = "translate(" + x + "px," + y + "px)";
+
+ target.setAttribute("data-bs-x", x);
+ target.setAttribute("data-bs-y", y);
+ target.textContent = Math.round(event.rect.width) + "\u00D7"
+ + Math.round(event.rect.height);
+
+ this.onInteraction(target);
+ },
+ },
+
+ modifiers: [
+ interact.modifiers.restrictSize({
+ min: {width: 5, height: 5},
+ }),
+ ],
+ inertia: true,
+ });
+ //Arrow key Support for Add-Image and Sign pages
+ if(window.location.pathname.endsWith('sign') || window.location.pathname.endsWith('add-image')) {
+ window.addEventListener('keydown', (event) => {
+ //Check for last interacted element
+ if (!this.lastInteracted){
+ return;
+ }
+ // Get the currently selected element
+ const target = this.lastInteracted;
+
+ // Step size relatively to the elements size
+ const stepX = target.offsetWidth * 0.05;
+ const stepY = target.offsetHeight * 0.05;
+
+ // Get the current x and y coordinates
+ let x = (parseFloat(target.getAttribute('data-bs-x')) || 0);
+ let y = (parseFloat(target.getAttribute('data-bs-y')) || 0);
+
+ // Check which key was pressed and update the coordinates accordingly
+ switch (event.key) {
+ case 'ArrowUp':
+ y -= stepY;
+ event.preventDefault(); // Prevent the default action
+ break;
+ case 'ArrowDown':
+ y += stepY;
+ event.preventDefault();
+ break;
+ case 'ArrowLeft':
+ x -= stepX;
+ event.preventDefault();
+ break;
+ case 'ArrowRight':
+ x += stepX;
+ event.preventDefault();
+ break;
+ default:
+ return; // Listen only to arrow keys
}
- const elements = [...this.boxDragContainer.querySelectorAll(".draggable-canvas")];
- const draggablesData = elements.map(el => {return{element:el, offsetWidth:el.offsetWidth, offsetHeight:el.offsetHeight}});
- elements.forEach(el => this.boxDragContainer.removeChild(el));
+ // Update position
+ target.style.transform = `translate(${x}px, ${y}px)`;
+ target.setAttribute('data-bs-x', x);
+ target.setAttribute('data-bs-y', y);
- pagesMap[this.pageIndex] = draggablesData;
- pagesMap[this.pageIndex+"-offsetWidth"] = this.pdfCanvas.offsetWidth;
- pagesMap[this.pageIndex+"-offsetHeight"] = this.pdfCanvas.offsetHeight;
+ DraggableUtils.onInteraction(target);
+ });
+ }
+ },
- this.documentsMap.set(this.pdfDoc, pagesMap);
- },
- loadPageContents() {
- var pagesMap = this.documentsMap.get(this.pdfDoc);
- this.deleteAllDraggableCanvases();
- if (!pagesMap) {
- return;
- }
+ onInteraction(target) {
+ this.boxDragContainer.appendChild(target);
+ },
- const draggablesData = pagesMap[this.pageIndex];
- if (draggablesData) {
- draggablesData.forEach(draggableData => this.boxDragContainer.appendChild(draggableData.element));
- }
+ createDraggableCanvas() {
+ const createdCanvas = document.createElement("canvas");
+ createdCanvas.id = `draggable-canvas-${this.nextId++}`;
+ createdCanvas.classList.add("draggable-canvas");
- this.documentsMap.set(this.pdfDoc, pagesMap);
- },
+ const x = 0;
+ const y = 20;
+ createdCanvas.style.transform = `translate(${x}px, ${y}px)`;
+ createdCanvas.setAttribute("data-bs-x", x);
+ createdCanvas.setAttribute("data-bs-y", y);
- async renderPage(pdfDocument, pageIdx) {
- this.pdfDoc = pdfDocument ? pdfDocument : this.pdfDoc;
- this.pageIndex = pageIdx;
+ //Click element in order to enable arrow keys
+ createdCanvas.addEventListener('click', () => {
+ this.lastInteracted = createdCanvas;
+ });
- // persist
- const page = await this.pdfDoc.getPage(this.pageIndex+1);
+ createdCanvas.onclick = (e) => this.onInteraction(e.target);
- // set the canvas size to the size of the page
- if (page.rotate == 90 || page.rotate == 270) {
- this.pdfCanvas.width = page.view[3];
- this.pdfCanvas.height = page.view[2];
+ this.boxDragContainer.appendChild(createdCanvas);
+
+ //Enable Arrow keys directly after the element is created
+ this.lastInteracted = createdCanvas;
+
+ return createdCanvas;
+ },
+ createDraggableCanvasFromUrl(dataUrl) {
+ return new Promise((resolve) => {
+ var myImage = new Image();
+ myImage.src = dataUrl;
+ myImage.onload = () => {
+ var createdCanvas = this.createDraggableCanvas();
+
+ createdCanvas.width = myImage.width;
+ createdCanvas.height = myImage.height;
+
+ const imgAspect = myImage.width / myImage.height;
+ const pdfAspect = this.boxDragContainer.offsetWidth / this.boxDragContainer.offsetHeight;
+
+ var scaleMultiplier;
+ if (imgAspect > pdfAspect) {
+ scaleMultiplier = this.boxDragContainer.offsetWidth / myImage.width;
} else {
- this.pdfCanvas.width = page.view[2];
- this.pdfCanvas.height = page.view[3];
+ scaleMultiplier = this.boxDragContainer.offsetHeight / myImage.height;
}
- // render the page onto the canvas
- var renderContext = {
- canvasContext: this.pdfCanvas.getContext("2d"),
- viewport: page.getViewport({ scale: 1 })
+ var newWidth = createdCanvas.width;
+ var newHeight = createdCanvas.height;
+ if (scaleMultiplier < 1) {
+ newWidth = newWidth * scaleMultiplier;
+ newHeight = newHeight * scaleMultiplier;
+ }
+
+ createdCanvas.style.width = newWidth + "px";
+ createdCanvas.style.height = newHeight + "px";
+
+ var myContext = createdCanvas.getContext("2d");
+ myContext.drawImage(myImage, 0, 0);
+ resolve(createdCanvas);
+ };
+ });
+ },
+ deleteAllDraggableCanvases() {
+ this.boxDragContainer.querySelectorAll(".draggable-canvas").forEach((el) => el.remove());
+ },
+ deleteDraggableCanvas(element) {
+ if (element) {
+ //Check if deleted element is the last interacted
+ if (this.lastInteracted === element) {
+ // If it is, set lastInteracted to null
+ this.lastInteracted = null;
+ }
+ element.remove();
+ }
+ },
+ getLastInteracted() {
+ return this.boxDragContainer.querySelector(".draggable-canvas:last-of-type");
+ },
+
+ storePageContents() {
+ var pagesMap = this.documentsMap.get(this.pdfDoc);
+ if (!pagesMap) {
+ pagesMap = {};
+ }
+
+ const elements = [...this.boxDragContainer.querySelectorAll(".draggable-canvas")];
+ const draggablesData = elements.map((el) => {
+ return {
+ element: el,
+ offsetWidth: el.offsetWidth,
+ offsetHeight: el.offsetHeight,
+ };
+ });
+ elements.forEach((el) => this.boxDragContainer.removeChild(el));
+
+ pagesMap[this.pageIndex] = draggablesData;
+ pagesMap[this.pageIndex + "-offsetWidth"] = this.pdfCanvas.offsetWidth;
+ pagesMap[this.pageIndex + "-offsetHeight"] = this.pdfCanvas.offsetHeight;
+
+ this.documentsMap.set(this.pdfDoc, pagesMap);
+ },
+ loadPageContents() {
+ var pagesMap = this.documentsMap.get(this.pdfDoc);
+ this.deleteAllDraggableCanvases();
+ if (!pagesMap) {
+ return;
+ }
+
+ const draggablesData = pagesMap[this.pageIndex];
+ if (draggablesData) {
+ draggablesData.forEach((draggableData) => this.boxDragContainer.appendChild(draggableData.element));
+ }
+
+ this.documentsMap.set(this.pdfDoc, pagesMap);
+ },
+
+ async renderPage(pdfDocument, pageIdx) {
+ this.pdfDoc = pdfDocument ? pdfDocument : this.pdfDoc;
+ this.pageIndex = pageIdx;
+
+ // persist
+ const page = await this.pdfDoc.getPage(this.pageIndex + 1);
+
+ // set the canvas size to the size of the page
+ if (page.rotate == 90 || page.rotate == 270) {
+ this.pdfCanvas.width = page.view[3];
+ this.pdfCanvas.height = page.view[2];
+ } else {
+ this.pdfCanvas.width = page.view[2];
+ this.pdfCanvas.height = page.view[3];
+ }
+
+ // render the page onto the canvas
+ var renderContext = {
+ canvasContext: this.pdfCanvas.getContext("2d"),
+ viewport: page.getViewport({ scale: 1 }),
+ };
+ await page.render(renderContext).promise;
+
+ //return pdfCanvas.toDataURL();
+ },
+ async incrementPage() {
+ if (this.pageIndex < this.pdfDoc.numPages - 1) {
+ this.storePageContents();
+ await this.renderPage(this.pdfDoc, this.pageIndex + 1);
+ this.loadPageContents();
+ }
+ },
+ async decrementPage() {
+ if (this.pageIndex > 0) {
+ this.storePageContents();
+ await this.renderPage(this.pdfDoc, this.pageIndex - 1);
+ this.loadPageContents();
+ }
+ },
+
+ parseTransform(element) {},
+ async getOverlayedPdfDocument() {
+ const pdfBytes = await this.pdfDoc.getData();
+ const pdfDocModified = await PDFLib.PDFDocument.load(pdfBytes, {
+ ignoreEncryption: true,
+ });
+ this.storePageContents();
+
+ const pagesMap = this.documentsMap.get(this.pdfDoc);
+ for (let pageIdx in pagesMap) {
+ if (pageIdx.includes("offset")) {
+ continue;
+ }
+ console.log(typeof pageIdx);
+
+ const page = pdfDocModified.getPage(parseInt(pageIdx));
+ const draggablesData = pagesMap[pageIdx];
+ const offsetWidth = pagesMap[pageIdx + "-offsetWidth"];
+ const offsetHeight = pagesMap[pageIdx + "-offsetHeight"];
+
+ for (const draggableData of draggablesData) {
+ // embed the draggable canvas
+ const draggableElement = draggableData.element;
+ const response = await fetch(draggableElement.toDataURL());
+ const draggableImgBytes = await response.arrayBuffer();
+ const pdfImageObject = await pdfDocModified.embedPng(draggableImgBytes);
+
+ // calculate the position in the pdf document
+ const tansform = draggableElement.style.transform.replace(/[^.,-\d]/g, "");
+ const transformComponents = tansform.split(",");
+ const draggablePositionPixels = {
+ x: parseFloat(transformComponents[0]),
+ y: parseFloat(transformComponents[1]),
+ width: draggableData.offsetWidth,
+ height: draggableData.offsetHeight,
+ };
+ const draggablePositionRelative = {
+ x: draggablePositionPixels.x / offsetWidth,
+ y: draggablePositionPixels.y / offsetHeight,
+ width: draggablePositionPixels.width / offsetWidth,
+ height: draggablePositionPixels.height / offsetHeight,
+ };
+ const draggablePositionPdf = {
+ x: draggablePositionRelative.x * page.getWidth(),
+ y: draggablePositionRelative.y * page.getHeight(),
+ width: draggablePositionRelative.width * page.getWidth(),
+ height: draggablePositionRelative.height * page.getHeight(),
};
- await page.render(renderContext).promise;
- //return pdfCanvas.toDataURL();
- },
- async incrementPage() {
- if (this.pageIndex < this.pdfDoc.numPages-1) {
- this.storePageContents();
- await this.renderPage(this.pdfDoc, this.pageIndex+1);
- this.loadPageContents();
- }
- },
- async decrementPage() {
- if (this.pageIndex > 0) {
- this.storePageContents();
- await this.renderPage(this.pdfDoc, this.pageIndex-1);
- this.loadPageContents();
- }
- },
+ // draw the image
+ page.drawImage(pdfImageObject, {
+ x: draggablePositionPdf.x,
+ y: page.getHeight() - draggablePositionPdf.y - draggablePositionPdf.height,
+ width: draggablePositionPdf.width,
+ height: draggablePositionPdf.height,
+ });
+ }
+ }
- parseTransform(element) {
-
- },
- async getOverlayedPdfDocument() {
- const pdfBytes = await this.pdfDoc.getData();
- const pdfDocModified = await PDFLib.PDFDocument.load(pdfBytes, { ignoreEncryption: true });
- this.storePageContents();
-
- const pagesMap = this.documentsMap.get(this.pdfDoc);
- for (let pageIdx in pagesMap) {
- if (pageIdx.includes("offset")) {
- continue;
- }
- console.log(typeof pageIdx);
-
- const page = pdfDocModified.getPage(parseInt(pageIdx));
- const draggablesData = pagesMap[pageIdx];
- const offsetWidth = pagesMap[pageIdx+"-offsetWidth"];
- const offsetHeight = pagesMap[pageIdx+"-offsetHeight"];
-
- for (const draggableData of draggablesData) {
- // embed the draggable canvas
- const draggableElement = draggableData.element;
- const response = await fetch(draggableElement.toDataURL());
- const draggableImgBytes = await response.arrayBuffer();
- const pdfImageObject = await pdfDocModified.embedPng(draggableImgBytes);
-
- // calculate the position in the pdf document
- const tansform = draggableElement.style.transform.replace(/[^.,-\d]/g, '');
- const transformComponents = tansform.split(",");
- const draggablePositionPixels = {
- x: parseFloat(transformComponents[0]),
- y: parseFloat(transformComponents[1]),
- width: draggableData.offsetWidth,
- height: draggableData.offsetHeight,
- };
- const draggablePositionRelative = {
- x: draggablePositionPixels.x / offsetWidth,
- y: draggablePositionPixels.y / offsetHeight,
- width: draggablePositionPixels.width / offsetWidth,
- height: draggablePositionPixels.height / offsetHeight,
- }
- const draggablePositionPdf = {
- x: draggablePositionRelative.x * page.getWidth(),
- y: draggablePositionRelative.y * page.getHeight(),
- width: draggablePositionRelative.width * page.getWidth(),
- height: draggablePositionRelative.height * page.getHeight(),
- }
-
- // draw the image
- page.drawImage(pdfImageObject, {
- x: draggablePositionPdf.x,
- y: page.getHeight() - draggablePositionPdf.y - draggablePositionPdf.height,
- width: draggablePositionPdf.width,
- height: draggablePositionPdf.height,
- });
- }
- }
-
- this.loadPageContents();
- return pdfDocModified;
- },
-}
+ this.loadPageContents();
+ return pdfDocModified;
+ },
+};
document.addEventListener("DOMContentLoaded", () => {
- DraggableUtils.init();
+ DraggableUtils.init();
});
diff --git a/src/main/resources/static/js/errorBanner.js b/src/main/resources/static/js/errorBanner.js
index 9d151407..727a854f 100644
--- a/src/main/resources/static/js/errorBanner.js
+++ b/src/main/resources/static/js/errorBanner.js
@@ -1,50 +1,50 @@
var traceVisible = false;
function toggletrace() {
- var traceDiv = document.getElementById("trace");
- if (!traceVisible) {
- traceDiv.style.maxHeight = "500px";
- traceVisible = true;
- } else {
- traceDiv.style.maxHeight = "0px";
- traceVisible = false;
- }
- adjustContainerHeight();
+ var traceDiv = document.getElementById("trace");
+ if (!traceVisible) {
+ traceDiv.style.maxHeight = "500px";
+ traceVisible = true;
+ } else {
+ traceDiv.style.maxHeight = "0px";
+ traceVisible = false;
+ }
+ adjustContainerHeight();
}
function copytrace() {
- var flip = false
- if (!traceVisible) {
- toggletrace()
- flip = true
- }
- var traceContent = document.getElementById("traceContent");
- var range = document.createRange();
- range.selectNode(traceContent);
- window.getSelection().removeAllRanges();
- window.getSelection().addRange(range);
- document.execCommand("copy");
- window.getSelection().removeAllRanges();
- if (flip) {
- toggletrace()
- }
+ var flip = false;
+ if (!traceVisible) {
+ toggletrace();
+ flip = true;
+ }
+ var traceContent = document.getElementById("traceContent");
+ var range = document.createRange();
+ range.selectNode(traceContent);
+ window.getSelection().removeAllRanges();
+ window.getSelection().addRange(range);
+ document.execCommand("copy");
+ window.getSelection().removeAllRanges();
+ if (flip) {
+ toggletrace();
+ }
}
function dismissError() {
- var errorContainer = document.getElementById("errorContainer");
- errorContainer.style.display = "none";
- errorContainer.style.height = "0";
+ var errorContainer = document.getElementById("errorContainer");
+ errorContainer.style.display = "none";
+ errorContainer.style.height = "0";
}
function adjustContainerHeight() {
- var errorContainer = document.getElementById("errorContainer");
- var traceDiv = document.getElementById("trace");
- if (traceVisible) {
- errorContainer.style.height = errorContainer.scrollHeight - traceDiv.scrollHeight + traceDiv.offsetHeight + "px";
- } else {
- errorContainer.style.height = "auto";
- }
+ var errorContainer = document.getElementById("errorContainer");
+ var traceDiv = document.getElementById("trace");
+ if (traceVisible) {
+ errorContainer.style.height = errorContainer.scrollHeight - traceDiv.scrollHeight + traceDiv.offsetHeight + "px";
+ } else {
+ errorContainer.style.height = "auto";
+ }
}
function showHelp() {
- $('#helpModal').modal('show');
-}
\ No newline at end of file
+ $("#helpModal").modal("show");
+}
diff --git a/src/main/resources/static/js/favourites.js b/src/main/resources/static/js/favourites.js
index 08c6f183..dbecd013 100644
--- a/src/main/resources/static/js/favourites.js
+++ b/src/main/resources/static/js/favourites.js
@@ -1,45 +1,45 @@
function updateFavoritesDropdown() {
- var dropdown = document.querySelector('#favoritesDropdown');
+ var dropdown = document.querySelector("#favoritesDropdown");
- // Check if dropdown exists
- if (!dropdown) {
- console.error('Dropdown element with ID "favoritesDropdown" not found!');
- return; // Exit the function
+ // Check if dropdown exists
+ if (!dropdown) {
+ console.error('Dropdown element with ID "favoritesDropdown" not found!');
+ return; // Exit the function
+ }
+ dropdown.innerHTML = ""; // Clear the current favorites
+
+ var hasFavorites = false;
+
+ for (var i = 0; i < localStorage.length; i++) {
+ var key = localStorage.key(i);
+ if (localStorage.getItem(key) === "favorite") {
+ // Find the corresponding navbar entry
+ var navbarEntry = document.querySelector(`a[href='${key}']`);
+ if (navbarEntry) {
+ // Create a new dropdown entry
+ var dropdownItem = document.createElement("a");
+ dropdownItem.className = "dropdown-item";
+ dropdownItem.href = navbarEntry.href;
+ dropdownItem.innerHTML = navbarEntry.innerHTML;
+ dropdown.appendChild(dropdownItem);
+ hasFavorites = true;
+ } else {
+ console.warn(`Navbar entry not found for key: ${key}`);
+ }
}
- dropdown.innerHTML = ''; // Clear the current favorites
+ }
- var hasFavorites = false;
-
- for (var i = 0; i < localStorage.length; i++) {
- var key = localStorage.key(i);
- if (localStorage.getItem(key) === 'favorite') {
- // Find the corresponding navbar entry
- var navbarEntry = document.querySelector(`a[href='${key}']`);
- if (navbarEntry) {
- // Create a new dropdown entry
- var dropdownItem = document.createElement('a');
- dropdownItem.className = 'dropdown-item';
- dropdownItem.href = navbarEntry.href;
- dropdownItem.innerHTML = navbarEntry.innerHTML;
- dropdown.appendChild(dropdownItem);
- hasFavorites = true;
- } else {
- console.warn(`Navbar entry not found for key: ${key}`);
- }
- }
- }
-
- // Show or hide the default item based on whether there are any favorites
- if (!hasFavorites) {
- var defaultItem = document.createElement('a');
- defaultItem.className = 'dropdown-item';
- defaultItem.textContent = noFavourites;
- dropdown.appendChild(defaultItem);
- }
+ // Show or hide the default item based on whether there are any favorites
+ if (!hasFavorites) {
+ var defaultItem = document.createElement("a");
+ defaultItem.className = "dropdown-item";
+ defaultItem.textContent = noFavourites;
+ dropdown.appendChild(defaultItem);
+ }
}
// Ensure that the DOM content has been fully loaded before calling the function
-document.addEventListener('DOMContentLoaded', function() {
- console.log('DOMContentLoaded event fired');
- updateFavoritesDropdown();
+document.addEventListener("DOMContentLoaded", function () {
+ console.log("DOMContentLoaded event fired");
+ updateFavoritesDropdown();
});
diff --git a/src/main/resources/static/js/fileInput.js b/src/main/resources/static/js/fileInput.js
index 610ae723..001c8f24 100644
--- a/src/main/resources/static/js/fileInput.js
+++ b/src/main/resources/static/js/fileInput.js
@@ -1,104 +1,112 @@
-document.addEventListener('DOMContentLoaded', function() {
- document.querySelectorAll('.custom-file-chooser').forEach(setupFileInput);
+document.addEventListener("DOMContentLoaded", function () {
+ document.querySelectorAll(".custom-file-chooser").forEach(setupFileInput);
});
function setupFileInput(chooser) {
- const elementId = chooser.getAttribute('data-bs-element-id');
- const filesSelected = chooser.getAttribute('data-bs-files-selected');
- const pdfPrompt = chooser.getAttribute('data-bs-pdf-prompt');
+ const elementId = chooser.getAttribute("data-bs-element-id");
+ const filesSelected = chooser.getAttribute("data-bs-files-selected");
+ const pdfPrompt = chooser.getAttribute("data-bs-pdf-prompt");
- let allFiles = [];
- let overlay;
- let dragCounter = 0;
+ let allFiles = [];
+ let overlay;
+ let dragCounter = 0;
- const dragenterListener = function() {
- dragCounter++;
- if (!overlay) {
- overlay = document.createElement('div');
- overlay.style.position = 'fixed';
- overlay.style.top = 0;
- overlay.style.left = 0;
- overlay.style.width = '100%';
- overlay.style.height = '100%';
- overlay.style.background = 'rgba(0, 0, 0, 0.5)';
- overlay.style.color = '#fff';
- overlay.style.zIndex = '1000';
- overlay.style.display = 'flex';
- overlay.style.alignItems = 'center';
- overlay.style.justifyContent = 'center';
- overlay.style.pointerEvents = 'none';
- overlay.innerHTML = '
-
-
-
-
+
\ No newline at end of file
diff --git a/src/main/resources/templates/extract-page.html b/src/main/resources/templates/extract-page.html
index 77cc7496..9d97b3b4 100644
--- a/src/main/resources/templates/extract-page.html
+++ b/src/main/resources/templates/extract-page.html
@@ -1,33 +1,33 @@
-
+
+
+
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
+
-
+
\ No newline at end of file
diff --git a/src/main/resources/templates/fragments/card.html b/src/main/resources/templates/fragments/card.html
index 1d8193cd..3f5517d6 100644
--- a/src/main/resources/templates/fragments/card.html
+++ b/src/main/resources/templates/fragments/card.html
@@ -1,12 +1,12 @@
-